/*
 * I2C_Functions.c
 *
 * Created  : 9 November 2020
 * Modified : 6 May 2021
 * Author   : HWanyusof
 * Version	: 1.0
 */ 
 
#include "I2C_Functions.h"
#include <stdio.h>
#include <stdlib.h>

//Cypress specific I2C API call

//All of the I2C API functions (For Example: I2C_1_MasterSendStart()) are being called from project.h
//#include "project.h"

//Master sends I2C write command via pointer *Data from the Sensor API. 
//The function returns 0 when no error and -1 when there is error.
int WriteI2C_Bus(struct TransferData *Data) 
{
	//Initialization of intial Error loop counting = 0
	int i = 0;
	//Initialization of intial Error = 0
	int Error = 0;
  
	//Wait for Master to be ready.
	/*I2C_1_MasterStatus() returns the master’s communication status.
	*I2C_1_MODE_COMPLETE_XFER = 0x00.
	*As long as I2C_1_MasterStatus() returns nonzero value (means master is busy or there is error), the loop remains.
	*/
	while (I2C_1_MasterStatus()!= I2C_1_MODE_COMPLETE_XFER){}
	
	//Send I2C Write Command as shown in Fig. 10 in the Datasheet Page 7 with Error checking.
	//Step 1) Send Start condition, Slave Address and Write bit.
	/*Format defined by Cypress:
	*I2C_1_MasterSendStart(uint8_t SlaveAddress,uint8_t W_nR);.
	*uint8_t SlaveAddress - is the Address of the I2C device (7 Bits).
	*uint8_t W_nR - Write/Read Bit. Write I2C_1_WRITE_XFER_MODE for write and I2C_1_READ_XFER_MODE for read.
	*/
	I2C_1_MasterSendStart(Data->Slave_Address, I2C_1_WRITE_XFER_MODE);
	
	//Step 2) Send Register Address.
	/*Format defined by Cypress:
	*I2C_1_MasterWriteByte(uint8_t theByte);.
	*uint8_t theByte - is the Address of the Register to be written (1 Byte) for this case to fulfill I2C Write Command as shown in Fig. 10 in the Datasheet *Page 7.
	*/
	I2C_1_MasterWriteByte(Data->RegisterAddress);
	
	//Step 3) Send I2C Write data to the slave with error checking
	for(i=0;i<2;i++)
	{
		//Write data to be written to the above register address.
		/*Format defined by Cypress:
		*I2C_1_MasterWriteByte(uint8_t theByte);.
		*uint8_t theByte - is the Data to be written to the above register address (1 Byte for each loop) for this case to fulfill I2C Write Command as shown *in Fig. 10 in the Datasheet Page 7.
		*This function returns uint8_t error status. Expect I2C_1_MSTR_NO_ERROR (=0) for no error, otherwise, there is an error.
		*/
		Error = I2C_1_MasterWriteByte(Data->WData[i]);
		
		//Return -1 when there is error
		if(Error != I2C_1_MSTR_NO_ERROR)
		{
			return -1;
		}
	}
	
	//Step 4) Send Stop Condition
	I2C_1_MasterSendStop(); 
	
	//Wait for Master to finish communicating with the Sensor.
	/*I2C_1_MasterStatus() returns the master’s communication status.
	*I2C_1_MODE_COMPLETE_XFER = 0x00.
	*As long as I2C_1_MasterStatus() returns nonzero value (means master is busy or there is error), the loop remains.
	*/
	while(I2C_1_MasterStatus() != I2C_1_MODE_COMPLETE_XFER ){}
	
	//Clear the buffer
	I2C_1_MasterClearWriteBuf();
	
	return 0;
}

//Master sends I2C Read command and save the read data via pointer *Data. 
//The function returns 0 upon completion.
int ReadI2C_Bus(struct TransferData *Data)
{
	//Initialization of intial Error = 0
	int Error = 0;
	
	//Wait for Master to be ready.
	/*I2C_1_MasterStatus() returns the master’s communication status.
	*I2C_1_MODE_COMPLETE_XFER = 0x00.
	*As long as I2C_1_MasterStatus() returns nonzero value (means master is busy or there is error), the loop remains.
	*/
	while (I2C_1_MasterStatus() != I2C_1_MODE_COMPLETE_XFER){}
	
	//Send I2C Read Command as shown in Fig. 10 in the Datasheet Page 7 with Error checking.
	//Step 1) Send Start condition, Slave Address and Write bit.
	/*I2C_1_MasterSendStart(uint8_t SlaveAddress,uint8_t W_nR);.
	*uint8_t SlaveAddress - is the Address of the I2C device (7 Bits).
	*uint8_t W_nR - Write/Read Bit. Write I2C_1_WRITE_XFER_MODE for write and I2C_1_READ_XFER_MODE for read
	*/
	I2C_1_MasterSendStart(Data->Slave_Address, I2C_1_WRITE_XFER_MODE);
	
	//Step 2) Send Register Address.
	/*I2C_1_MasterWriteByte(uint8_t theByte);.
	*uint8_t theByte - is the Address of the Register to be written (1 Byte) for this case to fulfill I2C Read Command as shown in Fig. 10 in the Datasheet *Page 7.
	*/
	I2C_1_MasterWriteByte(Data->RegisterAddress);
	
	//Step 3) Send Restart condition, Slave Address and Read bit.
	/*I2C_1_MasterSendRestart(uint8_t SlaveAddress,uint8_t W_nR);.
	*uint8_t SlaveAddress - is the Address of the I2C device (7 Bits).
	*uint8_t W_nR - Write/Read Bit. Write I2C_1_WRITE_XFER_MODE for write and I2C_1_READ_XFER_MODE for read.
	*This function returns uint8_t error status.
	*/
	Error = I2C_1_MasterSendRestart(Data->Slave_Address, I2C_1_READ_XFER_MODE);
		
	//Return -1 when there is error
	if(Error != I2C_1_MSTR_NO_ERROR)
	{
		return -1;
	}
	
	//Step 4) Read from the Data Register of the Sensor (2 Bytes array)
	/*I2C_1_MasterReadByte(uint8_t acknNak);.
	*The function returns 1 Byte of Data and the function expects acknowledge or no acknowledge from the Sensor .
	*uint8_t acknNak - The function read whether acknowledge (I2C_1_ACK_DATA) or no acknowledge (I2C_1_NAK_DATA)has been sent from the Sensor.
	*/
	Data->RData[0]  = I2C_1_MasterReadByte(I2C_1_ACK_DATA);
	Data->RData[1]  = I2C_1_MasterReadByte(I2C_1_NAK_DATA);

	//Step 5) Send Stop Condition
	I2C_1_MasterSendStop();
	
	//Wait for Master to finish communicating with the Sensor.
	/*I2C_1_MasterStatus() returns the master’s communication status.
	*I2C_1_MODE_COMPLETE_XFER = 0x00.
	*As long as I2C_1_MasterStatus() returns nonzero value (means master is busy or there is error), the loop remains.
	*/		
	while(I2C_1_MasterStatus() != I2C_1_MODE_COMPLETE_XFER ){}
	
	//Clear the buffer
	I2C_1_MasterClearReadBuf();
	
	return 0;
}

//Master sends I2C Gesture Read command and save the read data via pointer *Data. 
//The function returns 0 upon completion.
int ReadI2C_Bus_Gesture_Mode(struct GestureTransferData *Data)
{
	//Initialization of intial Error = 0
	int Error = 0;
	
	//Wait for Master to be ready.
	/*I2C_1_MasterStatus() returns the master’s communication status.
	*I2C_1_MODE_COMPLETE_XFER = 0x00.
	*As long as I2C_1_MasterStatus() returns nonzero value (means master is busy or there is error), the loop remains.
	*/
	while (I2C_1_MasterStatus() != I2C_1_MODE_COMPLETE_XFER){}
	
	//Send I2C Gesture Read Command as shown in the Application Note Page 19.
	//Step 1) Send Start condition, Slave Address and Read bit.
	/*I2C_1_MasterSendStart(uint8_t SlaveAddress,uint8_t W_nR);.
	*uint8_t SlaveAddress - is the Address of the I2C device (7 Bits).
	*uint8_t W_nR - Write/Read Bit. Write I2C_1_WRITE_XFER_MODE for write and I2C_1_READ_XFER_MODE for read.
	*This function returns uint8_t error status.
	*/
	Error = I2C_1_MasterSendStart(Data->Slave_Address, I2C_1_READ_XFER_MODE);
	
	//Return -1 when there is error
	if(Error != I2C_1_MSTR_NO_ERROR)
	{
		return -1;
	}
	
	//Step 2) Read from the Data Register of the Sensor (6 Bytes array).
	/*I2C_1_MasterReadByte(uint8_t acknNak);.
	*The function returns 1 Byte of Data and the function expects acknowledge or no acknowledge from the Sensor. 
	*uint8_t acknNak - The function read whether acknowledge (I2C_1_ACK_DATA) or no acknowledge (I2C_1_NAK_DATA)has been sent from the Sensor.
	*/
	Data->RData[0]  = I2C_1_MasterReadByte(I2C_1_ACK_DATA);
	Data->RData[1]  = I2C_1_MasterReadByte(I2C_1_ACK_DATA);
	Data->RData[2]  = I2C_1_MasterReadByte(I2C_1_ACK_DATA);
	Data->RData[3]  = I2C_1_MasterReadByte(I2C_1_ACK_DATA);
	Data->RData[4]  = I2C_1_MasterReadByte(I2C_1_ACK_DATA);
	Data->RData[5]  = I2C_1_MasterReadByte(I2C_1_NAK_DATA);
	
	//Step 3) Send Stop Condition
	I2C_1_MasterSendStop();
	
	//Wait for Master to finish communicating with the Sensor.
	/*I2C_1_MasterStatus() returns the master’s communication status.
	*I2C_1_MODE_COMPLETE_XFER = 0x00.
	*As long as I2C_1_MasterStatus() returns nonzero value (means master is busy or there is error), the loop remains.
	*/				
	while(I2C_1_MasterStatus() != I2C_1_MODE_COMPLETE_XFER ){}
	
	//Clear the buffer
	I2C_1_MasterClearReadBuf();
	
	return 0;
}