/* Light_Sensor_ISL29020.c
* Lichtmessung (alle 200ms) und Ausgabe der Lichtstärke in Lux in der Variablen "lux_value"
* Ein möglicher Übertragungsfehler (ERROR) wird durch eine LED an PB1 angezeigt
* CPU: ATmega88, FCPU = 8MHz
* I²C CLK Frequency = 62,5kHz, --> CLK Frequency = FCPU/(16 + 2*(TWBR)*Prescaler Value)
*/
#include <avr/io.h>
#include <util/delay.h>

#define START			0x08	// A START condition has been transmitted
#define R_START			0x10	// A REPEATED START condition has been transmitted
#define SLA_W			0x88	// Slave Address & Write 1000 1000
#define SLA_R			0x89	// Slave Address & Read 1000 1001
#define MT_SLA_ACK		0x18	// Master Transmit SLA + W has been transmitted & ACK has been received
#define MT_DATA_ACK		0x28	// Master Transmit Data byte has been transmitted & ACK has been received
#define MR_SLA_ACK		0x40	// Master Receive SLA + R has been transmitted & ACK has been received
#define MR_SLA_NACK		0x48	// Master Receive SLA + R has been transmitted & ACK has been received
#define MR_DATA_ACK		0x50	// Master Receive Data byte has been transmitted & ACK has been returned
#define MR_DATA_NACK	0x58	// Master Receive Data byte has been transmitted & NACK has been returned
#define BIT_RATE		56		// Set value for the bit rate register TWBR

void ERROR(void);				// Prototyping of function "ERROR"

/*** Function to send a START Condition ***/
void TWI_START(void)
{
	// Send a START condition
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
	// Wait for TWINT Flag set. This indicates that the START condition has been transmitted
	while (!(TWCR & (1<<TWINT)));
	// Check value of TWI statusregister. Mask prescaler bits. If status different from START go to ERROR if ((TWSR & 0xF8) != START)
	ERROR();
}

/*** Function to send the Slave Address with ACK in Master Transmit Mode ***/
void TWI_MT_SLA_ACK(void)
{
	// Load Slave Address + Write into TWDR Register
	TWDR = SLA_W;
	// Clear TWINT bit in TWCR to start transmission
	TWCR = (1<<TWINT) | (1<<TWEN);
	// Wait for TWINT Flag set. This indicates that the SLA+W has been transmitted, and ACK/NACK has been received.
	while (!(TWCR & (1<<TWINT)));
	// Check value of TWI status register. Mask prescaler bits. If status different from MT_SLA_ACK go to ERROR
	if ((TWSR & 0xF8) != MT_SLA_ACK)
	ERROR();
}

/*** Function to send 8Bit of data with ACK in Master Transmit Mode **/
void TWI_MT_DATA_ACK(uint8_t data)
{
	// Load DATA into TWDR register
	TWDR = data;
	// Clear TWINT bit in TWCR to start transmission
	TWCR = (1<<TWINT) | (1<<TWEN);
	// Wait for TWINT flag set. This indicates that the DATA has been transmitted, and ACK/NACK has been received.
	while (!(TWCR & (1<<TWINT)));
	// Check value of TWI status register. Mask prescaler bits. If status different from MT_DATA_ACK go to ERROR
	if ((TWSR & 0xF8) != MT_DATA_ACK)
	ERROR();
}

/*** Function to send a REPEATED START condition **/
void TWI_R_START(void)
{
	// Send a START condition
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
	// Wait for TWINT Flag set. This indicates that the START condition has been transmitted
	while (!(TWCR & (1<<TWINT)));
	// Check value of TWI statusregister. Mask prescaler bits. If status different from R_START go to ER-ROR
	if ((TWSR & 0xF8) != R_START)
	ERROR();
}

/*** Function to send the Slave Address in Master Receive Mode with Acknowledge **/
void TWI_MR_SLA_ACK(void)
{
	// Load Slave Address + Read into TWDR Register
	TWDR = SLA_R;
	// Clear TWINT bit in TWCR to start transmission
	TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
	// Wait for TWINT Flag set. This indicates that the SLA+W has been transmitted, and ACK/NACK has been received.
	while (!(TWCR & (1<<TWINT)));
	// Check value of TWI status register. Mask prescaler bits. If status different from MR_SLA_ACK go to ERROR
	if ((TWSR & 0xF8) != MR_SLA_ACK)
	ERROR();
}

/*** Function to send the Slave Address in Master Receive Mode without Acknowledge **/
void TWI_MR_SLA_NACK(void)
{
	// Load Slave Address + Read into TWDR Register
	TWDR = SLA_R;
	// Clear TWINT bit in TWCR to start transmission
	TWCR = (1<<TWINT) | (1<<TWEN);
	// Wait for TWINT Flag set. This indicates that the SLA+W has been transmitted, and ACK/NACK has been received.
	while (!(TWCR & (1<<TWINT)));
	// Check value of TWI status register. Mask prescaler bits. If status different from MR_SLA_NACK go to ERROR
	if ((TWSR & 0xF8) != MR_SLA_NACK)
	ERROR();
}

/*** Function to read one Databyte in Master Receive Mode and send NACK ***/
uint8_t TWI_READ_DATABYTE_NACK(void)
{
	// Clear TWINT bit in TWCR to start transmission with NACK
	TWCR = (1<<TWINT) | (1<<TWEN);
	// Wait for TWINT flag set. This indicates that the DATA has been received
	while (!(TWCR & (1<<TWINT)));
	// Check value of TWI status register. Mask prescaler bits. If status different from MR_SLA_NACK go to ERROR
	if ((TWSR & 0xF8) != MR_DATA_NACK)
	ERROR();
	return TWDR; // Return the value of data register
}

/*** Function to read one Databyte in Master Receive Mode and send ACK ***/
uint8_t TWI_READ_DATABYTE_ACK(void)
{
	// Clear TWINT bit in TWCR to start transmission with ACK
	TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
	// Wait for TWINT flag set. This indicates that the DATA has been received
	while (!(TWCR & (1<<TWINT)));
	// Check value of TWI status register. Mask prescaler bits. If status different from MR_SLA_ACK go to ERROR
	if ((TWSR & 0xF8) != MR_DATA_ACK)
	ERROR();
	return TWDR; // Return the value of data register
}

/*** function to send a STOP condition ***/
void TWI_STOP(void)
{
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // Transmit STOP condition
}

/*** function to show a bus error ***/
void ERROR(void)
{
	PORTB |= (1<<PB1); // ERROR LED ON
}

uint8_t LSByte, MSByte;
uint16_t data_16bit, lux_value, high_byte, low_byte;

int main(void)
{
	DDRD = 0xFF;			// PORTD = output
	DDRC = 0x3F;			// PC0 ... PC5 = output
	DDRB = 0x03;			// PB0 and PB1 = output
	TWBR = BIT_RATE;		// Set the TWI clock-frequency in bit rate register
	TWI_START();			// Send START condition
	TWI_MT_SLA_ACK();		// Master Transmit Slave Address with Acknowledge
	TWI_MT_DATA_ACK(0x00);	// Transmit 0x00 for Register Command with Acknowledge
	TWI_MT_DATA_ACK(0xC3);	// Transmit 0xC3 (1100 0011) EN, Mode=1, Range4
	TWI_STOP();				// Send STOP condition
	_delay_ms(10);			// Delaytime between STOP and next START contition
	
	while(1)
	{
		TWI_START();			// Send START condition
		TWI_MT_SLA_ACK();		// Master Transmit Slave Address with ACK
		TWI_MT_DATA_ACK(0x01);	// Transmit 0x01 to start with Register 0x01 with ACK
		TWI_R_START();			// Send REPEATED START condition
		TWI_MR_SLA_ACK();		// Send the Slave Address in Master Receive Mode with ACK
		
		/* Read 2 Databytes in Burst Read Sequence */
		// Read one Databyte with ACK (tells the receiver more data will be received)
		LSByte = TWI_READ_DATABYTE_ACK();
		
		// Read one Databyte with NACK (tells the receiver no further data will be received)
		MSByte = TWI_READ_DATABYTE_NACK();
		
		TWI_STOP();							// Send STOP condition
		low_byte = LSByte;					// Store LSByte in low_byte
		high_byte = MSByte << 8;			// Shift MSByte 8 digits to left and store in high_byte
		lux_value = low_byte + high_byte;	// Store 16bit-result in lux_value
		_delay_ms(200);						// wait 200ms for new readout
	}
}