/*
 * xmegatwi.h
 * Author: Andrew Adamson
 * Provides polling based write routines to control a Two Wire Interface (I2C) port on the xMega
 */ 

#ifndef XMEGATWI_H
#define XMEGATWI_H

#define CPU_SPEED 2000000
#define BAUDRATE 400000
#define TWI_BAUD(F_SYS, F_TWI) ((F_SYS / (2 * F_TWI)) - 5)
#define TWI_BAUDSETTING TWI_BAUD(CPU_SPEED, BAUDRATE)

/*
* Configures and initialises the given TWIx controller
* Input: pointer to a TWI struct
*/
void twi_init(TWI_t * twiname) {
	//enable smartmode to send the ack immediately after the data
	twiname->MASTER.CTRLB = TWI_MASTER_SMEN_bm;
	//Set the Baud
	twiname->MASTER.BAUD = TWI_BAUDSETTING;
	//Enable the TWI master
	twiname->MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
	//Force the bus into idle mode
	twiname->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;

	return;
}

/*
* Sets the given TWI controller to write mode for given slave address
* Input: pointer to a TWI struct, 8-bit slave address
*/
//Can probably refactor this to make a generic "start" function
void i2c_startWrite(TWI_t * twiname, uint8_t address) {
	//Write the address (which should end in a zero for a write address)
	twiname->MASTER.ADDR = address & 0b11111110;
	//Poll for the write interrupt flag to be set
	while(!(twiname->MASTER.STATUS&TWI_MASTER_WIF_bm));
}

/*
* Puts a byte into the data register of the given TWI controller
* and waits for it to be sent to the slave
* Input: pointer to a TWI struct, 8-bit data value
*/
void i2c_write(TWI_t * twiname, uint8_t writeData) {
	//Write the data
	twiname->MASTER.DATA = writeData;
	//Poll for the write interrupt flag to be set
	while(!(twiname->MASTER.STATUS&TWI_MASTER_WIF_bm));
	return;
}

/*
* Puts a stop condition on the TWI bus to indicate communication has finished
* Input: pointer to a TWI struct
*/
void i2c_stop(TWI_t * twiname) {
	twiname->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
}
#endif /* XMEGATWI_H */