/*
 * twi_master.c
 *
 *  Created on: Oct, 2010
 *      Author: fouedjio
 */
#include <stdint.h>
#include <stdio.h>
#include <string.h> 
#include <math.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/iocan128.h>
#include <avr/iocanxx.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include "api_define.h"
#include "api_global.h"
#include "twi_master.h"
#include "api.h"


/****************************************************************************
  TWI State codes
****************************************************************************/
// General TWI Master staus codes                      
#define TWI_START				0x08  // START has been transmitted  
#define TWI_REP_START				0x10  // Repeated START has been transmitted
#define TWI_ARB_LOST				0x38  // Arbitration lost

// TWI Master Transmitter staus codes                      
#define TWI_MTX_ADR_ACK				0x18  // SLA+W has been tramsmitted and ACK received
#define TWI_MTX_ADR_NACK			0x20  // SLA+W has been tramsmitted and NACK received 
#define TWI_MTX_DATA_ACK			0x28  // Data byte has been tramsmitted and ACK received
#define TWI_MTX_DATA_NACK			0x30  // Data byte has been tramsmitted and NACK received 

// TWI Master Receiver staus codes  
#define TWI_MRX_ADR_ACK				0x40  // SLA+R has been tramsmitted and ACK received
#define TWI_MRX_ADR_NACK			0x48  // SLA+R has been tramsmitted and NACK received
#define TWI_MRX_DATA_ACK			0x50  // Data byte has been received and ACK tramsmitted
#define TWI_MRX_DATA_NACK			0x58  // Data byte has been received and NACK tramsmitted

// TWI Slave Transmitter staus codes
#define TWI_STX_ADR_ACK				0xA8  // Own SLA+R has been received; ACK has been returned
#define TWI_STX_ADR_ACK_M_ARB_LOST	0xB0  // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
#define TWI_STX_DATA_ACK			0xB8  // Data byte in TWDR has been transmitted; ACK has been received
#define TWI_STX_DATA_NACK			0xC0  // Data byte in TWDR has been transmitted; NOT ACK has been received
#define TWI_STX_DATA_ACK_LAST_BYTE	0xC8  // Last data byte in TWDR has been transmitted (TWEA = �0�); ACK has been received

// TWI Slave Receiver staus codes
#define TWI_SRX_ADR_ACK				0x60  // Own SLA+W has been received ACK has been returned
#define TWI_SRX_ADR_ACK_M_ARB_LOST	0x68  // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
#define TWI_SRX_GEN_ACK				0x70  // General call address has been received; ACK has been returned
#define TWI_SRX_GEN_ACK_M_ARB_LOST	0x78  // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_ACK		0x80  // Previously addressed with own SLA+W; data has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_NACK		0x88  // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
#define TWI_SRX_GEN_DATA_ACK		0x90  // Previously addressed with general call; data has been received; ACK has been returned
#define TWI_SRX_GEN_DATA_NACK		0x98  // Previously addressed with general call; data has been received; NOT ACK has been returned
#define TWI_SRX_STOP_RESTART		0xA0  // A STOP condition or repeated START condition has been received while still addressed as Slave

// TWI Miscellaneous status codes
#define TWI_NO_STATE		        0xF8  // No relevant state information available; TWINT = �0�
#define TWI_BUS_ERROR			0x00  // Bus error due to an illegal START or STOP condition


/*
 * Public Function: Twim_Init
 * Purpose: Initialise the TWI Master Interface
 * Input Parameter:
 * uint16_t	TWI_Bitrate (Hz)
 * Return Value: uint8_t
 *	- FALSE:	Bitrate too high
 *	- TRUE:		Bitrate OK
*/
uint8_t Twim_Init (uint32_t TWI_Bitrate)
	{
/* Set TWI bitrate, if bitrate is too high, then error return*/
//	TWBR = ((F_CPU/TWI_Bitrate)-16)/2;
	TWBR = 42;	// flo
	
	if (TWBR < 11) return FALSE;

	PORTB = (1<<PB5); // i2cmultilpexer: i2creset (aktive low) set to high flo

	TWCR = ((1<<TWEN)|(0<<TWIE)); // enable i2c interface, disable i2c interrupts flo

	return TRUE;
	}
/*
 * Public Function: Twim_Stop
 * Purpose: Stop the Twi Master
 * Input Parameter: None
 * Return Value: None
*/

void Twim_Stop (void)
	{
/*Send stop condition*/
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);

/* Wait until stop condition is executed and bus released*/
	while (TWCR & (1<<TWINT));
	}
		
	
/*

 * Public Function: Write_to_slave
 * Purpose: Write byte(s) to the slave.
 * It is implicitely assumed, that the slave will
 * accepts 8 bytes
 * Input Parameter: structure
 * Return Value: None

*/	
	
/*
void Write_to_slave( struct uartStruct *ptr_uartStruct )
      {
	 
	if (!Twim_Start (ptr_uartStruct->Adresse, TWIM_WRITE))
		{
		
			Twim_Stop ();	
			twi_errorCode = CommunicationError(ERRT,TWI_ERROR_Could_not_start_TWI_Bus_for_WRITE, 0, NULL, 0);
                        UART0_Send_Message_String(NULL,0);
	               
	    	}
	else
		{
		  for (uint8_t i=0;i<ptr_uartStruct->Uart_Length ;i++)
			{
		           Twim_Write (ptr_uartStruct->Uart_Data[i]);
				
			}
		  Twim_Stop ();
		  Delay_ms (1000);
		  snprintf_P(uart_message_string, BUFFER_SIZE - 1, PSTR("RECV %s"), READY);
	          UART0_Send_Message_String(NULL,0);
		  
		}
      }
      
*/
 /*
  * Public Function: Twim_Stop
  * Purpose: Read byte(s) from the slave
  * It is implicitely assumed, that the slave will send
  * 8 bytes
  * Input Parameter: structure
  * Return Value: None
 */   
 /*
  void Read_to_slave( struct uartStruct *ptr_uartStruct )
      {
	uint8_t i;
	if (!Twim_Start (ptr_uartStruct->Adresse, TWIM_READ))
	   {
		Twim_Stop ();
		twi_errorCode = CommunicationError(ERRT, TWI_ERROR_Could_not_start_TWI_Bus_for_READ, 0, NULL, 0);
 	   }
       else
 	  {
	   for (i=1;i<ptr_uartStruct->Uart_Length ;i++)
	       {
	        twiData[i] = Twim_ReadAck ();
	        snprintf_P(temp_twiString, BUFFER_SIZE - 1, PSTR("%x"), twiData[i]);
	        strncat(twiString, temp_twiString, BUFFER_SIZE - 1);
	        strncat_P(twiString, PSTR(" "), BUFFER_SIZE - 1);
		
 	       }
           clearString(temp_twiString, MAX_LENGTH_TWI_DATA); // clear the variable temp_twiString
	   twiData[ptr_uartStruct->Uart_Length] = Twim_ReadNack ();
	   Twim_Stop ();
 	   Delay_ms (1000);
	   snprintf_P(temp_twiString, BUFFER_SIZE - 1, PSTR("%x"), twiData[ptr_uartStruct->Uart_Length]);  
	   strncat(store_twiData, twiString, BUFFER_SIZE - 1);
	   strncat(store_twiData, temp_twiString, BUFFER_SIZE - 1); 
       snprintf_P(uart_message_string, BUFFER_SIZE - 1, PSTR("RECV %s"), store_twiData);
	   UART0_Send_Message_String(NULL,0);
	  }
 	clearString(temp_twiString, MAX_LENGTH_TWI_DATA); // clear the variable temp_twiString
	clearString(twiString, MAX_LENGTH_TWI_DATA); // clear the variable twiString
	clearString(store_twiData, MAX_LENGTH_TWI_DATA); // clear the variable store_twiData*
 	
      }
*/

/*
 * Public Function: TWIM_Start
 * Purpose: Start the TWI Master Interface
 * Input Parameter:
 	- uint8_t	Device address
 	- uint8_t	Type of required Operation:
			Twim_READ: Read data from the slave
			Twim_WRITE: Write data to the slave
 * Return Value: uint8_t
  	- TRUE:		OK, TWI Master accessible
 	- FALSE:	Error in starting TWI Master
*/


uint8_t Twim_Start (uint8_t Address, uint8_t TWIM_Type)
	{
	uint8_t twst;

// Send START condition
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(0<<TWIE);

// Wait until transmission completed
	while (!(TWCR & (1<<TWINT)));

// Check value of TWI Status Register. Mask prescaler bits
	twst = TWSR & 0xF8;
	if ((twst != TWI_START) && (twst != TWI_REP_START)) return FALSE;

// Send device address
	TWDR = (Address<<1) + TWIM_Type; // TWDR = ((ptr_uartStruct->Adresse)<<1) + TWIM_Type; flo
	TWCR = (1<<TWINT)|(1<<TWEN);
	
// Wait until transmission completed and ACK/NACK has been received
	while (!(TWCR & (1<<TWINT)));

// Check value of TWI Status Register. Mask prescaler bits.
	twst = TWSR & 0xF8;
	if ((twst != TWI_MTX_ADR_ACK) && (twst != TWI_MRX_ADR_ACK)) {
		snprintf_P(uart_message_string, BUFFER_SIZE - 1, PSTR("NO ACK WHILE STARTING TWI TRANSMITION"));
		UART0_Send_Message_String(NULL,0);
		return FALSE;
	}
	
	return TRUE;
	}

/*
* Public Function: Twim_Write
* Purpose: Write a byte to the slave
* Input Parameter:
 	- uint8_t	Byte to be sent
* Return Value: uint8_t
  	- TRUE:		OK, Byte sent
 	- FALSE:	Error in byte transmission
	
*/

uint8_t Twim_Write (uint8_t byte)
	{
	uint8_t   twst;
	
/* Send data to the previously addressed device*/
	TWDR = byte;
	TWCR = (1<<TWINT)|(1<<TWEN);
	
/*Wait until transmission completed*/
	while (!(TWCR & (1<<TWINT)));
	
/* Check value of TWI Status Register. Mask prescaler bits*/
	twst = TWSR & 0xF8;
	if (twst != TWI_MTX_DATA_ACK) {
		snprintf_P(uart_message_string, BUFFER_SIZE - 1, PSTR("TWI NO ACKNOWLEDGE WHILE SENDING DATA"));
		UART0_Send_Message_String(NULL,0);
		return FALSE;
	}

	return TRUE;
	}

 /*
  * Public Function: Twim_ReadAck
  * Purpose: Read a byte from the slave and request next byte
  * Input Parameter: None
  * Return Value: uint8_t
  	- uint8_t	Read byte
*/
uint8_t Twim_ReadAck (void)
	{
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
	while (!(TWCR & (1<<TWINT)));    

	return TWDR;
	}
	

/*
 * Public Function: Twim_ReadAck
 * Purpose: Read the last byte from the slave
 * Input Parameter: None
 * Return Value: uint8_t
  	- uint8_t	Read byte
*/
uint8_t Twim_ReadNack (void)
	{
	TWCR = (1<<TWINT)|(1<<TWEN);
	while(!(TWCR & (1<<TWINT)));
	
	return TWDR;
	}




// flo

void Twim_Write_Data(uint8_t Address, uint8_t twi_bytes_to_transceive, uint8_t twi_data[TWI_MAX_DATA_ELEMENTS])
{
	Twim_Start(Address, TWIM_WRITE);

	for(uint8_t i = 0; i < twi_bytes_to_transceive; i++)
	{
		Twim_Write(twi_data[i]);
	}

	Twim_Stop();
}


void Twim_Read_Data(uint8_t Address, uint8_t twi_bytes_to_transceive, uint8_t twi_data[TWI_MAX_DATA_ELEMENTS])
{
	Twim_Start(Address, TWIM_READ);

	for(uint8_t i = 0; i < (twi_bytes_to_transceive - 1); i++)
	{
		twi_data[i] = Twim_ReadAck();
	}

	twi_data[twi_bytes_to_transceive - 1] = Twim_ReadNack();

	Twim_Stop();
}



	
