//main master blink red led basic send with serial communication
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "USI_TWI_Master.h"
#include <avr/pgmspace.h>

#define SLAVE_ADDR  0x10

#define MESSAGEBUF_SIZE       4

#define TWI_GEN_CALL         0x00  // The General Call address is 0

// Sample TWI transmission commands
#define TWI_CMD_MASTER_WRITE 0x10
#define TWI_CMD_MASTER_READ  0x20

// Sample TWI transmission states, used in the main application.
#define SEND_DATA             0x01
#define REQUEST_DATA          0x02
#define READ_DATA_FROM_BUFFER 0x03

//definitions neil
#define output(directions,pin) (directions |= pin) // set port direction for output
#define input(directions,pin) (directions &= (~pin)) // set port direction for input
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define PWM_delay() _delay_us(25) // PWM delay

//serial communication
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define bit_delay_time 8.5 // bit delay for 115200 with overhead
#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
#define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay
#define char_delay() _delay_ms(10) // char delay

//definitions leds
#define led_porta PORTA
#define led_directiona DDRA
#define red (1 << PA7)
#define blue (1 << PA5)
#define led_portb PORTB
#define led_directionb DDRB
#define green (1 << PB2)

//definitions switch
#define input_port PORTA
#define input_direction DDRA
#define input_pin (1 << PA3)
#define input_pins PINA

//define serial communication
#define serial_port PORTA
#define serial_direction DDRA
#define serial_pins PINA
#define serial_pin_in (1 << PA0)
#define serial_pin_out (1 << PA1)

#define max_buffer 25

unsigned char TWI_Act_On_Failure_In_Last_Transmission ( unsigned char TWIerrorMsg )
{
	// A failure has occurred, use TWIerrorMsg to determine the nature of the failure
	// and take appropriate actions.
	// Se header file for a list of possible failures messages.
	 asm("nop");
	 return TWIerrorMsg;
}

void put_char(volatile unsigned char *port, unsigned char pin, char txchar) {
   // initialize serial communication
   // set clock divider to /1
   //
   CLKPR = (1 << CLKPCE);
   CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
   //
   // send character in txchar on port pin
   //    assumes line driver (inverts bits)
   //
   // start bit
   //
   clear(*port,pin);
   bit_delay();
   //
   // unrolled loop to write data bits
   //
   if bit_test(txchar,0)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,1)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,2)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,3)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,4)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,5)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,6)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,7)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   //
   // stop bit
   //
   set(*port,pin);
   bit_delay();
   //
   // char delay
   //
   bit_delay();
   }

void put_string(volatile unsigned char *port, unsigned char pin, char *str) {
   //
   // print a null-terminated string
   //
   static int index;
   index = 0;
   do {
      put_char(port, pin, str[index]);
      ++index;
      } while (str[index] != 0);
   }


int main(void) {
   //
   // main
   //
   //
   //
   //
   // initialize pins
   //
   set(serial_port, serial_pin_out);
   output(serial_direction, serial_pin_out);
   //
   //
   // initialize switch pins
   //
   set(input_port, input_pin); // turn on pull-up
   input(input_direction, input_pin);
   //
   //
   // intitialise things for I2C
  unsigned char TWI_targetSlaveAddress, temp, myCounter=0xFF;
  unsigned char messageBuf[MESSAGEBUF_SIZE];
   //  

// master init
  USI_TWI_Master_Initialise();
  
 sei();
  
  TWI_targetSlaveAddress   = 0x10;

  // This is a stk500 demo example. The buttons on PORTD are used to control different TWI operations.
   // main loop
   //
   // This is a stk500 demo example. The buttons on PORTD are used to control different TWI operations.
while (1)  {
      //
      // wait for button down
        if (0 == pin_test(input_pins,input_pin))  {
          temp = TRUE;
        // Send a Address Call, sending a command and data to the Slave          
          messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
          messageBuf[1] = TWI_CMD_MASTER_WRITE;             // The first byte is used for commands.
          messageBuf[2] = myCounter;                        // The second byte is used for the data.
          temp = USI_TWI_Start_Transceiver_With_Data( messageBuf, 3 );
      if (!temp)    // One of the operations failed.
      {             // Use TWI status information to detemine cause of failure and take appropriate actions. 
        TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) );  
       asm("nop"); // Put own code here.
      //print errors     
        if (0x00 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) ))
      {
          put_char(&serial_port, serial_pin_out, 'A');
      }
        if (0x01 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) )) 
      {
          put_char(&serial_port, serial_pin_out, 'B');
      }
        if (0x02 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) ))
      {
          put_char(&serial_port, serial_pin_out, 'C');
      }
        if (0x03 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) ))
      {
          put_char(&serial_port, serial_pin_out, 'D');
      }
        if (0x04 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) ))
      {
          put_char(&serial_port, serial_pin_out, 'E');
      }
        if (0x05 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) ))
      {
          put_char(&serial_port, serial_pin_out, 'F');
      }
        if (0x06 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) ))
      {
          put_char(&serial_port, serial_pin_out, 'G');
      }
        if (0x07 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) ))
      {
          put_char(&serial_port, serial_pin_out, 'H');
      }
        if (0x08 ==  TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) ))
      {
          put_char(&serial_port, serial_pin_out, 'I');
      }
     }      
      }
   }
} 
