#define START 		0x08
#define START_REP 	0x10
#define MT_SLA_ACK	0x18
#define MT_DATA_ACK 	0x28
#define MR_SLA_ACK  	0x40


unsigned char i2c_start (unsigned char address)		/* i2c_start */
{

 TWCR = (1<<TWINT)|(1<<TWSTA)|(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) != START)
 	return 0;

 TWDR = address;								//Load SLA_W into TWDR Register.
 TWCR = (1<<TWINT) | (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) != MT_SLA_ACK)				//Check value of TWI Status Register. Mask prescaler bits. If status different from
	return 0;									//MT_SLA_ACK go to ERROR

 return 1;
}

unsigned char i2c_start_rep (unsigned char address)
{TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);		//Start again
 while (!(TWCR & (1<<TWINT)));

 if ((TWSR & 0xF8) != START_REP)
 	return 0;
 
 TWDR = address;								//Load SLA_W into TWDR Register.
 TWCR = (1<<TWINT) | (1<<TWEN);

 while (!(TWCR & (1<<TWINT)));

 if ((TWSR & 0xF8) != MR_SLA_ACK)				//Check value of TWI Status Register. Mask prescaler bits. If status different from
	return 0;

 return 1;
}

void i2c_stop(void)
{TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

 while(TWCR & (1<<TWSTO));

}

unsigned char i2c_write (unsigned char data)
{TWDR = data;								//Load Pointer into TWDR Register. Clear
 TWCR = (1<<TWINT) | (1<<TWEN);				//TWINT bit in TWCR to start transmission of data

 while (!(TWCR & (1<<TWINT)));

 if ((TWSR & 0xF8) != MT_DATA_ACK)
	return 0;
 
 else return 1;
}

unsigned char i2c_read_ack(void)
{TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); 
 while (!(TWCR & (1<<TWINT)));

 return TWDR;
}

unsigned char i2c_read_nack(void)
{TWCR = (1<<TWINT) | (1<<TWEN); 
 while (!(TWCR & (1<<TWINT)));

 return TWDR;
}
