/**
  *****************************************************************************************************
  * @file    iic_user_drv.c
  * @author  Kiwi Software Team
  * @brief   This file provides simplified functions to manage the following
  *          functionalities of SCI IIC:
  *          + Transmit and receive data with interrupt mode
  * @note
  *          V1.0.0, 2022/08/03.
  *
  * Copyright (c) 2024, Kiwi Instruments Co,. Ltd.
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *
  *   3. Neither the name of the copyright holder nor the names of its contributors
  *      may be used to endorse or promote products derived from this software without
  *      specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************************************
  */

#include "main.h"
#include "string.h"
#include <stdlib.h>
#include "iic_user_drv.h"



/**
  * @brief  SCI I2C as master transmits an amount of data with interrupt.
  * @param  SCIx     Pointer to SCI IIC instance.
  *         slvAddr  slave address.
  *         pData    pointer to data buffer.
  *         size     the amount of data to be sent.
  *
  * @retval DDL status
  */
DDL_Status_T DDL_SCII2C_Master_Transmit_IT(SCI_Type *SCIx, uint16_t slvAddr, uint8_t *pData, uint16_t size)
{
    ASSERT_PARAM(pData != NULL);
	ASSERT_PARAM(size  != 0U);
	uint16_t tmp = 0;
	uint8_t  tmpAddr = 0;

	/* LSB: 0 indicates writing data to slave */
	tmpAddr = slvAddr & 0xFE;

	DDL_SCII2C_SetMode(SCIx, IIC_TX);

	/* Generate a Start Signal */
	__DDL_SCII2C_STT_GENERATE(SCIx);

	/*Till now, SCI is ready to transaction data-frame */
	/* First, send slave address */
	tmp = tmpAddr & 0xFFUL;
	SCIx->TXD = tmp;

	/* Enable transaction done interrupt, over-run must be enabled in Continuous-Transaction mode */
    DDL_SCIIIC_IntEnable(SCIx, SCI_IE_TXBUFEMPT | SCI_IE_OVRERR);
	NVIC_EnableIRQ(DDL_Get_SCIModule_IRQn(SCIx));

	return DDL_OK;
}


/**
  * @brief  SCI I2C as master receives an amount of data with interrupt.
  * @param  SCIx     Pointer to SCI IIC instance.
  *         slvAddr  slave address.
  *         pData    pointer to data buffer.
  *         size     the amount of data to receive.
  *
  * @retval DDL status
  */
DDL_Status_T DDL_SCII2C_Master_Receive_IT(SCI_Type *SCIx, uint16_t slvAddr, uint8_t *pData, uint16_t size)
{
    ASSERT_PARAM(pData != NULL);
	ASSERT_PARAM(size  != 0U);
    ASSERT_PARAM(SCIx != NULL);
	uint32_t  errFlags = SCI_ST_PRTERR | SCI_ST_FRMERR;
	uint8_t  tmpAddr = 0;
    uint8_t  addrFlag = 0;

	/* LSB: 0 indicates writing data to slave */
	tmpAddr = slvAddr | 0x1;
	addrFlag = 1;

	/* Construct a 'START' condition to start i2c transaction  */
	__DDL_SCII2C_STT_GENERATE(SCIx);
	__DDL_SCII2C_ACK_GENERATE(SCIx);

	while (addrFlag > 0 )
	{
		DDL_SCII2C_SetMode(SCIx, IIC_TX);
		SCIx->TXD = tmpAddr & 0xFFU;

		/* Should check the errors while CSI stay in receive mode */
		if (SCIx->ST & errFlags)
		{
            WRITE_REG(SCIx->CLR, errFlags);
		}

		/* Wait for transaction completes */
		while(!(SCIx->ST & SCI_ST_TXEND));
		/* Then clear the flag */
		WRITE_REG(SCIx->CLR, SCI_CLR_TXEND);

		addrFlag = 0;
	}

	DDL_SCII2C_SetMode(SCIx, IIC_RX);
	SCIx->TXD = __I2C_08BIT_DUMMY_DATA__;

    DDL_SCIIIC_IntEnable(SCIx, SCI_IE_TXBUFEMPT | SCI_IE_PRTERR | SCI_IE_FRMERR);
	NVIC_EnableIRQ(DDL_Get_SCIModule_IRQn(SCIx));
	return DDL_OK;
}


/**
  * @brief  Mutually configure IIC Tx and Rx .
  * @param  SCIx Pointer to SCI IIC instance.
  * @param  iicTxRx IIC Tx and Rx configuration.
  *
  * @retval None
  */
void DDL_SCII2C_SetMode(SCI_Type *SCIx, IicTxRx_T iicTxRx)
{
	/* For I2C, Tx and Rx may work the same time in User Application */
	if (iicTxRx == IIC_RX)
	{
		/* This will both SET Rx and CLEAR Tx mode */
		__DDL_SCII2C_SET_RX_MODE(SCIx);
		__DDL_SCII2C_CLEAR_TX_MODE(SCIx);
	}

	if (iicTxRx == IIC_TX)
	{
		/* This will both SET Tx and CLEAR Rx mode */
		__DDL_SCII2C_SET_TX_MODE(SCIx);
		__DDL_SCII2C_CLEAR_RX_MODE(SCIx);
	}
}
