
/*
 * FRAM_MB85RC256.c
 *
 *  Created on: Sep 24, 2019
 *      Author: nxa07657
 */

#include "Mcal.h"
#include "Siul2_Port_Ip.h"
#include "Siul2_Dio_Ip.h"
#include "Lpi2c_ip.h"
#include "IntCtrl_Ip.h"
#include "FRAM_MB85RC256.h"

extern void LPI2C0_Master_Slave_IRQHandler(void);

/*******************************************************************************************************************
 * Function   : void FRAM_MB85RC256_Init(void)
 * Description: initialize the FRAM MB85RC1MT via set its WP(Write Protection) pin to low(inactive)
 ******************************************************************************************************************/
Std_ReturnType FRAM_MB85RC256_Init(void)
{
	Std_ReturnType retCode;

	/* Initialize the I2C module for ACC communication  */
	retCode = Lpi2c_Ip_MasterInit(FRAM_I2C_INST, &FRAM_I2C_MasterConfig);

	/* Install LPI2C0 ISR and enable LPI2C0 IRQ */
	IntCtrl_Ip_InstallHandler(LPI2C0_IRQn, LPI2C0_Master_Slave_IRQHandler, NULL_PTR);
	IntCtrl_Ip_EnableIrq(LPI2C0_IRQn);

	/*disable the write protection*/
	FRAM_MB85RC256_WP_Disable();

	return retCode;
}

/*******************************************************************************************************************
 * Function   : void FRAM_MB85RC256_Init(void)
 * Description: de-initialize the FRAM MB85RC1MT via set its WP(Write Protection) pin to high(active)
 ******************************************************************************************************************/
void FRAM_MB85RC256_DeInit(void)
{
	/*Enable the write protection*/
	FRAM_MB85RC256_WP_Enable();
}

/*******************************************************************************************************************
 * Function   : Std_ReturnType FRAM_MB85RC256_ByteWrite(uint32_t address, uint8_t data)
 * Description: byte write the user data to FRAM MB85RC1MT memory,
 *              address[in]: the start address for the byte write;
 *              data[in]   :the data buffer need to write;
 *Return      : LPI2C_IP_SUCCESS_STATUS if success, or error status code
 ******************************************************************************************************************/
Std_ReturnType FRAM_MB85RC256_ByteWrite(uint32_t address, uint8_t data)
{
	Std_ReturnType ret = LPI2C_IP_SUCCESS_STATUS;
	uint8_t masterTxBuffer[3] = {0};

	uint32 bytesRemaining = 0;

	masterTxBuffer[0] = (address>>8)&0xFF;/*set target memory address high 8-bit*/
	masterTxBuffer[1] = address&0xFF;     /*set target memory address low 8-bit*/
	masterTxBuffer[2] = data;              /*set data*/

	/* check the LPI2C slave address */
	if(MB85RC256_DEVIC_Addr != FRAM_I2C_MasterConfig.SlaveAddress)
	{
		/*initialize the I2C interface for MB85RC256 FRAM communication by setting new slave address*/
		Lpi2c_Ip_MasterSetSlaveAddr(FRAM_I2C_INST, MB85RC256_DEVIC_Addr, FRAM_I2C_MasterConfig.Is10bitAddr);
	}

	/*transmit slave address + write and target address + data */
	ret = Lpi2c_Ip_MasterSendData(FRAM_I2C_INST,  masterTxBuffer, 3, true);
	
	/* wait for transfer complete */
    while(LPI2C_IP_BUSY_STATUS==Lpi2c_Ip_MasterGetTransferStatus(FRAM_I2C_INST, &bytesRemaining)){}

	return ret;
}

/*******************************************************************************************************************
 * Function   : Std_ReturnType FRAM_MB85RC256_PageWrite(uint32_t address, uint8_t *data, uint16_t length)
 * Description: page write the user data to FRAM MB85RC1MT memory,
 *              address[in]: the start address for the page write;
 *              *data[in]  : the data buffer need to write;
 *              leghth[in] : the length of byte need to write
 *Return      : LPI2C_IP_SUCCESS_STATUS if success, or error status code
 ******************************************************************************************************************/
Std_ReturnType FRAM_MB85RC256_PageWrite(uint32_t address, uint8_t *data, uint16_t length)
{
	Std_ReturnType ret = LPI2C_IP_SUCCESS_STATUS;

	uint32 bytesRemaining = 0;

	data[0] = (address>>8)&0xFF;/*set target memory address high 8-bit*/
	data[1] = address&0xFF;     /*set target memory address low 8-bit*/

	/* check the LPI2C slave address */
	if(MB85RC256_DEVIC_Addr != FRAM_I2C_MasterConfig.SlaveAddress)
	{
		/*initialize the I2C interface for MB85RC256 FRAM communication by setting new slave address*/
		Lpi2c_Ip_MasterSetSlaveAddr(FRAM_I2C_INST, MB85RC256_DEVIC_Addr, FRAM_I2C_MasterConfig.Is10bitAddr);
	}

	/*transmit slave address + write and target memory address(2 bytes) and write several bytes(length) data afterward*/

	ret = Lpi2c_Ip_MasterSendData(FRAM_I2C_INST,  data, (length + 2), true);
	
	/* wait for transfer complete */
    while(LPI2C_IP_BUSY_STATUS==Lpi2c_Ip_MasterGetTransferStatus(FRAM_I2C_INST, &bytesRemaining)){}

	return ret;
}

/*******************************************************************************************************************
 * Function   : Std_ReturnType FRAM_MB85RC256_ReadByte(uint32_t address, uint8_t *data)
 * Description: byte read back the FRAM MB85RC1MT memory,
 *              address[in] : the start address for the byte read;
 *              *data[inout]: the buffer to store the read back data;
 *Return      : LPI2C_IP_SUCCESS_STATUS if success, or error status code
 ******************************************************************************************************************/
Std_ReturnType FRAM_MB85RC256_ReadByte(uint32_t address, uint8_t *data)
{
	Std_ReturnType ret = LPI2C_IP_SUCCESS_STATUS;
	uint8_t masterTxBuffer[2] = {0};

	uint32 bytesRemaining = 0;

	masterTxBuffer[0] = (address>>8)&0xFF;/*set target memory address high 8-bit*/
	masterTxBuffer[1] = address&0xFF;     /*set target memory address low 8-bit*/

	/* check the LPI2C slave address */
	if(MB85RC256_DEVIC_Addr != FRAM_I2C_MasterConfig.SlaveAddress)
	{
		/*initialize the I2C interface for MB85RC256 FRAM communication by setting new slave address*/
		Lpi2c_Ip_MasterSetSlaveAddr(FRAM_I2C_INST, MB85RC256_DEVIC_Addr, FRAM_I2C_MasterConfig.Is10bitAddr);
	}

	/*transmit slave address + write and target memory address, no STOP*/
	ret = Lpi2c_Ip_MasterSendData(FRAM_I2C_INST,  masterTxBuffer, 2, false);
	
	/* wait for transfer complete */
    while(LPI2C_IP_BUSY_STATUS==Lpi2c_Ip_MasterGetTransferStatus(FRAM_I2C_INST, &bytesRemaining)){}

    /*transmit slave address + read and read one byte data*/
	ret = Lpi2c_Ip_MasterReceiveData(FRAM_I2C_INST,  data, 1, true);
	
	/* wait for transfer complete */
    while(LPI2C_IP_BUSY_STATUS==Lpi2c_Ip_MasterGetTransferStatus(FRAM_I2C_INST, &bytesRemaining)){}

	return ret;
}

/*******************************************************************************************************************
 * Function   : Std_ReturnType FRAM_MB85RC256_ReadMultiByte(uint32_t address, uint8_t *data, uint16_t length)
 * Description: multi-byte read back the FRAM MB85RC1MT memory,
 *              address[in] : the start address for the multi-byte read;
 *              *data[inout]: the buffer to store the read back data;
 *              length[in]  : the length of byte  need to read
 *Return      : LPI2C_IP_SUCCESS_STATUS if success, or error status code
 ******************************************************************************************************************/
Std_ReturnType FRAM_MB85RC256_ReadMultiByte(uint32_t address, uint8_t *data, uint16_t length)
{
	Std_ReturnType ret = LPI2C_IP_SUCCESS_STATUS;
	uint8_t masterTxBuffer[2] = {0};

	uint32 bytesRemaining = 0;

	masterTxBuffer[0] = (address>>8)&0xFF;/*set target memory address high 8-bit*/
	masterTxBuffer[1] = address&0xFF;     /*set target memory address low 8-bit*/

	/* check the LPI2C slave address */
	if(MB85RC256_DEVIC_Addr != FRAM_I2C_MasterConfig.SlaveAddress)
	{
		/*initialize the I2C interface for MB85RC256 FRAM communication by setting new slave address*/
		Lpi2c_Ip_MasterSetSlaveAddr(FRAM_I2C_INST, MB85RC256_DEVIC_Addr, FRAM_I2C_MasterConfig.Is10bitAddr);
	}

	/*transmit slave address + write and target memory address, no STOP*/
	ret = Lpi2c_Ip_MasterSendData(FRAM_I2C_INST,  masterTxBuffer, 2, false);
	
	/* wait for transfer complete */
    while(LPI2C_IP_BUSY_STATUS==Lpi2c_Ip_MasterGetTransferStatus(FRAM_I2C_INST, &bytesRemaining)){}

    /*transmit slave address + read and read several bytes(length) data*/
	ret = Lpi2c_Ip_MasterReceiveData(FRAM_I2C_INST,  data, length, true);
	
	/* wait for transfer complete */
    while(LPI2C_IP_BUSY_STATUS==Lpi2c_Ip_MasterGetTransferStatus(FRAM_I2C_INST, &bytesRemaining)){}

	return ret;
}

/*******************************************************************************************************************
 * Function   : void FRAM_MB85RC256_Test(void)
 * Description: This a simple test function for FRAM MB85RC1MT write and read option
 *              The byte write & read and page write & read on both lower 64KB and higher 64KB address space.
 *
 ******************************************************************************************************************/
Std_ReturnType FRAM_MB85RC256_Test(void)
{
	Std_ReturnType ret = E_OK;
	uint8_t Write_Buffer[18];/*the 1st 2 bytes are reserved for FRAM memory address*/
	uint8_t Read_Bufeer[16];

	uint8_t Write_Byte;
	uint8_t Read_Byte;

	uint8_t i = 0;
	uint32_t FRAM_Addr = 0;/*set to lower 64KB address by default*/

	/*initialize the write buffer for test*/
	for(i=0;i<16;i++)
		Write_Buffer[i+2] = i;

	/**************test byte write & read on low 64KB FRAM  memory**************/
	Write_Byte = 0x55;

	FRAM_MB85RC256_ByteWrite(FRAM_Addr, Write_Byte);

	FRAM_MB85RC256_ReadByte(FRAM_Addr, &Read_Byte);

	if(Write_Byte != Read_Byte) /*verify*/
	{
		ret = E_NOT_OK;
		return ret;
	} else {
		ret = E_OK;
	}

	/**************test multiple bytes write & read on low 64KB FRAM  memory**************/

	FRAM_MB85RC256_PageWrite(FRAM_Addr,Write_Buffer, 16);

	FRAM_MB85RC256_ReadMultiByte(FRAM_Addr,Read_Bufeer, 16);

	/**verify the read back data**/
	for(i=0;i<16;i++)
	{
		if(Write_Buffer[i+2] != Read_Bufeer[i])
		{
			break;
		}
		else
		{
			Read_Bufeer[i] = 0;/*clean the read buffer */
		}
	}
	if(i<16){
		ret = E_NOT_OK;
	} else {
		ret = E_OK;
	}
	return ret;
}
