//	Author: Dingo_aus
//	Original Website: www.users.on.net/~symes
//	Document subject to copyright, permission must be granted by author before copying

#include <util/twi.h>
#include <avr/io.h>			//register defines
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdio.h>			//FILE access for UART1
#include <avr/delay.h>		//for software delays

#define F_CPU 8000000UL		//CPU clock 8 MHz

#define GPIO_0  PA0
#define SW1  	PA1
#define SW2  	PA2
#define SW3  	PA3
#define LED1  	PA4
#define LED2  	PA5
#define LED3  	PA6
#define LED4	PA7
#define GPIO_8  PC0
#define GPIO_9  PC1
#define GPIO_10 PC2
#define GPIO_11 PC3
#define GPIO_12 PC4
#define GPIO_13 PC5
#define GPIO_14 PC6
#define GPIO_15 PC7
#define outp(a, b) b = a

#define USART_BAUD 9600ul
#define USART_UBBR_VALUE ((F_CPU/(USART_BAUD<<4))-1)

#define SLA_W	0b10011110
#define SLA_R	0b10011111

#define 	TW_READ   1
#define 	TW_WRITE   0

void set_PORTA_xpin(char);
void clear_PORTA_xpin(char);
void send_TWI (void);

void I2C_init(int);
void TMR1_init(void);

int	i;
char DATA1;
char DATA2;






/*---------------------------------------------------
-				Interrupt handlers					-
---------------------------------------------------*/
//TIMER0
ISR(TIMER0_OVF_vect)
	{
	// user code here
	if(bit_is_clear(PINA, 5))
		{
		set_PORTA_xpin(5);
		}
	else
		{
		clear_PORTA_xpin(5);
		}
	}



//TWI
ISR(TWI_vect)
	{
	// user code here
	/*	The TWINT flag is set in the following situations:
 	• After the TWI has transmitted a START/REPEATED START condition
 	• After the TWI has transmitted SLA+R/W
 	• After the TWI has transmitted an address byte
 	• After the TWI has lost arbitration
 	• After the TWI has been addressed by own slave address or general call
 	• After the TWI has received a data byte
 	• After a STOP or REPEATED START has been received while still addressed as a slave
 	• When a bus error has occurred due to an illegal START or STOP condition		*/
	set_PORTA_xpin(4);

	switch (!(TWSR & 0xF8)) 
		{
		//A START condition has been transmitted
		case 0x08:
		TWDR = SLA_R; //Load SLA_R into TWDR Register.
		TWCR = (1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN); //Start transmit SLA_R

		break;

		//A repeated START condition has been transmitted
		case 0x10:

		break;

		//SLA+W has been transmitted;
		//ACK has been received
		case 0x18:

		break;

		//SLA+W has been transmitted;
		//NOT ACK has been received
		case 0x20:

		break;

		//Data byte has been transmitted;
		//ACK has been received
		case 0x28:

		break;

		//Data byte has been transmitted;
		//NOT ACK has been received
		case 0x30:

		break;

		//Arbitration lost in SLA+W or data bytes	or Arbitration lost in SLA+R or NOT ACK bit
		case 0x38:

		break;

		//SLA+R has been transmitted;
		//ACK has been received
		case 0x40:
		TWCR = (1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEA); //ACK will be transmitted transmit

		break;

		//SLA+R has been transmitted;
		//NOT ACK has been received
		case 0x48:

		break;

		//Data byte has been received;
		//ACK has been returned
		case 0x50:

		DATA1=TWDR;
		TWCR = (1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWEA);
		break;

		//Data byte has been received;
		//NOT ACK has been returned
		case 0x58:

		DATA2=TWDR;
		TWCR = (1<<TWINT)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWEA);
		break;

		default: set_PORTA_xpin(4); break;
		}
	}


//BADISR
ISR(BADISR_vect) 
	{
	// user code here
	}



/*---------------------------------------------------
-						MAIN						-
---------------------------------------------------*/
int main(void) 
		{

			//USART_vInit();
			//USART_vSendByte('A');

			//Initialize PORTA direvtion
			DDRA = 0b11110001;
			//DDRD = 0b00000011;
			

			TMR1_init();
			I2C_init(20);

			sei(); // enable interrupts
			
			_delay_us(1000);

			send_TWI();

			while (1) {

					if(bit_is_clear(PINA, 1))
						{
						set_PORTA_xpin(4);
						}
					else
						{
					//	clear_PORTA_xpin(4);
						}
				
				
			}

		}

/*-----------------------------------------------------------------
 -	 				 CPU Clock frequency
 -	SCL frequency =	---------------------
 -					16 + 2(TWBR) · 4^TWPS
 -
 -	TWBR = Value of the TWI Bit Rate Register
 -	TWPS = Value of the prescaler bits in the TWI Status Register
 -
 -	The TWDR contains the address or data bytes to be transmitted,
 -	or the address or data bytes received.
 -
 -	  TWPS1	  TWPS0	  PSValue
 -		0		0		1
 -		0		1		4
 -		1		0		16
 -		1		1		64
 -
 -
 -Temp IC: LM75 ADD: 1001111
 ---------------------------------------------------------------------*/

void I2C_init (int fr) 
	{
	//Setting Bitrate
	TWSR = 0;
	TWBR = ((int) (F_CPU/1000L / fr) - 16) / 2;

	TWCR = _BV(TWEN);
	TWCR = _BV(TWIE);

	}

void TMR1_init()
	{

	TIMSK = _BV(TOIE0); //Enable timer overflow interrupt

	TCNT0 = 0x00; //set timer counter initial value*/

	/*start timer without presscaler*/
	TCCR0 = 0b00000111; //set mode and prescaler
	OCR0 = 0xFF; //	set TOP va lue

	}


void send_TWI() 
	{
	TWCR = (1 << TWINT) | (1 << TWSTA) | (0 << TWSTO) | (1 << TWEN); //Send START condition
	TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
	}













set_PORTA_xpin(char x)
	{
	PORTA |= (1 << x);
	}

clear_PORTA_xpin(char x)
	{
	PORTA &= ~(1 << x);
	}

void USART_vInit(void)
	{
	// Set baud rate
	UBRR1H = ( uint8_t)(USART_UBBR_VALUE>>8);

	UBRR1L = (uint8_t)USART_UBBR_VALUE;

	// Set frame format to 8 data bits, no parity, 1 stop bit

	UCSR1C = (0 << USBS) | (1 << UCSZ1) | (1 << UCSZ0);

	// Enable receiver and transmitter

	UCSR1B = (1 << RXEN) | (1 << TXEN);

	}

	
	
	
void USART_vSendByte(uint8_t u8Data)
	{
	// Wait i f a byte is being transmitted
	while ((UCSR1A & (1 << UDRE)) == 0);
	// Transmit data
	UDR1 = u8Data;
	}



void TWIread() {

TWCR = (1 << TWINT) |(1 << TWSTA) | (0 << TWSTO) | (1 << TWEN); //Send START condition

		while (!(TWCR & (1 << TWINT)))
		; //Wait for TWINT flag set.
		//This indicates that the
		//START condition has been transmitted


		if ((TWSR & 0xF8) != TW_START) //Check value of TWI Status Register.
		ERROR(); //Mask prescaler bits. If status different
		//from START go to ERROR


		TWDR = SLA_R; //Load SLA_W into TWDR Register.
		TWCR = (1 << TWINT) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN); //Clear TWINT bit in TWCR to start
		//transmission of address


		while (!(TWCR & (1 << TWINT)))
		; //Wait for TWINT flag set.
		//This indicates that the SLA+W
		//has been transmitted, and ACK/NACK
		//has been received.


		if ((TWSR & 0xF8) != TW_MT_SLA_ACK) //Check value of TWI Status Register.
		ERROR(); //Mask prescaler bits.
		//If status different from
		//MT_SLA_ACK go to ERROR


		DATA1 = TWDR; //Load DATA into TWDR Register.
		//TWCR = (1<<TWINT)|(1<<TWEN);  				//Clear TWINT bit in TWCR to
		//Start receiving data						//start transmission of data


		while (!(TWCR & (1 << TWINT)))
		; //Wait for TWINT flag set.
		//This indicates that the DATA
		//has been transmitted, and ACK/NACK
		//has been received.

		DATA2 = TWDR;

		if ((TWSR & 0xF8) != TW_MT_DATA_ACK) //Check value of TWI Status Register.
		ERROR(); //Mask prescaler bits.
		//If status different from
		//MT_DATA_ACK go to ERROR


		TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); //Transmit STOP condition


	}

void ERROR() 
	{
	while (1)
		{
		}
	}
