/*
 * 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>

//All of the I2C API functions (For Example: HAL_I2C_Master_Transmit()) are being called from stm32f4xx_hal.h

//hi2c1 - The variable to the I2C handler which is needed later in the Write and Read I2C function.
//hi2c1 is defined in the stm32f4xx_hal.h and being called here via extern I2C_HandleTypeDef hi2c1;.
extern I2C_HandleTypeDef hi2c1;

//Master sends I2C write command via pointer *Data from the Sensor API.
//The function returns HAL_OK (=0) when there is no error and -1 when there is an error.
int WriteI2C_Bus(struct TransferData *Data)
{
	//Initialization of intial Error = 0
	int Error = 0;

	//Define an array of 3 Bytes to be sent as I2C Write Command as shown in Fig. 10 in the Datasheet Page 7
	uint8_t WData[3]={Data->RegisterAddress, Data->WData[0], Data->WData[1]};

	//Send I2C Write Command as shown in Fig. 10 in the Datasheet Page 7 with Error checking.
	/*Format defined by STM:
	*HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout).
	*HAL_I2C_Master_Transmit() is used for transmitting data to the I2C device. It takes following arguments:
	*
	*I2C_HandleTypeDef *hi2c - is the pointer to the i2c handler. hi2c1 is defined in the stm32f4xx_hal.h and being called here via extern I2C_HandleTypeDef *hi2c1;.
	*uint16_t DevAddress - is the Address of the I2C device (Need to be shifted by 1 to left since the input of function expects 8 bits).
	*uint8_t *pData  - is the pointer to the data to be transmitted.
	*uint16_t Size  - is the size of the transmitted data in bytes.
	*uint32_t Timeout - timeout in millisecond in case of any error.
	*Return Error.
	*/
	Error = HAL_I2C_Master_Transmit(&hi2c1, (Data->Slave_Address)<<1, WData, 3, 100);

	//Return -1 when there is error and return HAL_OK (= 0) when no error
	if (Error != HAL_OK)
	{
		return -1;
	}
	else
	{
		return HAL_OK;
	}
}

//Master sends I2C Read command and save the read data via pointer *Data.
//The function returns HAL_OK (=0) when no error and -1 when there is error.
int ReadI2C_Bus (struct TransferData *Data)
{
	//Initialization of intial Error = 0
	int Error = 0;

	//Send I2C Read Command as shown in Fig. 10 in the Datasheet Page 7 with Error checking.
	/*Format defined by STM:
	*HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c1, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout).
	*HAL_I2C_Mem_Read () is used for reading data from the I2C device. It has been used instead of HAL_I2C_Master_Receive() because it sends restart condition
	*while the latter which sends stop condition and thus not working. It takes following arguments:
	*
	*I2C_HandleTypeDef *hi2c - is the pointer to the i2c handler.
	*uint16_t DevAddress - is the Address of the I2C device (Need to be shifted by 1 to left since the input of function expects 8 bits).
	*uint16_t MemAddress - is the Internal memory address in the slave which is the register address.
	*uint16_t MemAddSize - the size of memory address (in Byte) which is the size of register address (In the case of Vishay's Sensor always 1 Byte).
	*uint8_t *pData  - is the pointer to the data to be received.
	*uint16_t Size  - is the size of the received data in bytes.
	*uint32_t Timeout - timeout in millisecond in case of any error.
	*Return Error.
	*
	*/
	Error = HAL_I2C_Mem_Read(&hi2c1, (Data->Slave_Address)<<1, Data->RegisterAddress, 1,Data->RData,2,100);

	//Return -1 when there is error and return HAL_OK (= 0) when no error
	if (Error !=HAL_OK)
	{
		return -1;
	}
	else
	{
		return HAL_OK;
	}
}

//Master sends I2C Gesture Read command and save the read data via pointer *Data.
//The function returns HAL_OK (=0) when no error and -1 when there is error.
int ReadI2C_Bus_Gesture_Mode(struct GestureTransferData *Data)
{
	//Initialization of intial Error = 0
	int Error = 0;

	//Send I2C Gesture Read Command as shown in the Application Note Page 19 with Error checking.
	/*Format defined by STM:
	*HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout).
	*HAL_I2C_Master_Receive () is used for reading data from the I2C device. It has been used instead of HAL_I2C_Mem_Read() because no restart condition is *needed.
	*It takes following arguments:
	*
	*I2C_HandleTypeDef *hi2c - is the pointer to the i2c handler. hi2c1 is defined in the stm32f4xx_hal.h and being called here via extern I2C_HandleTypeDef *hi2c1;.
	*uint16_t DevAddress - is the Address of the I2C device (Need to be shifted by 1 to left since the input of function expects 8 bits).
	*uint8_t *pData  - is the pointer to the data to be received.
	*uint16_t Size  - is the size of the received data in bytes (For Gesture Stream 6 Bytes are needed).
	*uint32_t Timeout - timeout in millisecond in case of any error.
	*Return Error.
	*
	*/
	Error = HAL_I2C_Master_Receive(&hi2c1,(Data->Slave_Address)<<1,Data->RData,6,100);

	//Return -1 when there is error and return HAL_OK (= 0) when no error
	if (Error != HAL_OK)
	{
		return -1;
	}
	else
	{
		return HAL_OK;
	}
}
