/**
  *****************************************************************************************************
  * @file    main.c
  * @author  Kiwi Software Team
  * @brief   This example code demonstrates how SCI IIC works.
  *
  * 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 "kpm32xx_demoboard_ddl.h"


#define __MAXIMUM_RD_LENGTH__       8
static volatile uint8_t gRecvCont = 0;
static volatile uint8_t gTranCont = 0;
volatile uint32_t i2cTxCmplt = 0;
volatile uint32_t i2cRxCmplt = 0;
static volatile uint8_t txClptFlg = 0;

uint8_t wrBuf[] = {0x34, 0x33, 0x34, 0x35, 0x36, 0x37, 0x77, 0x22};
uint8_t rdBuf[__MAXIMUM_RD_LENGTH__] = {0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A};


/** Called once when one frame data is received */
void DDL_SCIIIC_OneFrmRxCpltCallback(SCI_Type *SCIx)
{
	if (gRecvCont == __MAXIMUM_RD_LENGTH__)
	{
		/* Clear Transaction Complete Flag */
		WRITE_REG(SCIx->CLR, SCI_CLR_RXEND);

		rdBuf[gRecvCont] = SCIx->RXD;
		gRecvCont ++;
		{
			/* Now, disable all interrupt */
            DDL_SCIIIC_IntDisable(SCIx, SCI_IE_TXBUFEMPT | SCI_IE_RXEND | SCI_IE_OVRERR | SCI_IE_PRTERR | SCI_IE_FRMERR);

			/* Force termination */
			__DDL_SCII2C_STP_GENERATE(SCIx);
            i2cRxCmplt = 1;
		}
	}
	else
	{
		WRITE_REG(SCIx->CLR, SCI_CLR_TXBUFEMPT);

		if (SCIx->ST & SCI_ST_RXBUFFUL)
		{
			rdBuf[gRecvCont] = SCIx->RXD;
			gRecvCont ++;
			WRITE_REG(SCIx->CLR, SCI_CLR_RXBUFFUL);
		}

		if (gRecvCont <= (__MAXIMUM_RD_LENGTH__-2))
		{
			SCIx->TXD = __I2C_08BIT_DUMMY_DATA__;
		}

		if (gRecvCont == (__MAXIMUM_RD_LENGTH__-1))
		{
		    WRITE_REG(SCIx->CLR, SCI_CLR_RXEND);
			__DDL_SCII2C_INTRENABLE(SCIx, SCI_IE_RXEND);
			__DDL_SCII2C_INTRDISABLE(SCIx, SCI_IE_TXBUFEMPT);
			/* Generate NACK signal for the last byte when reading */
			__DDL_SCII2C_NACK_GENERATE(SCIx);
		}
	}
}


/** Called once when one frame of data has been sent-out */
void DDL_SCIIIC_OneFrmTxCpltCallback(SCI_Type *SCIx)
{
	if (gTranCont == 0U)
	{
		/* Clear Transaction Complete Flag */
		WRITE_REG(SCIx->CLR, SCI_CLR_TXBUFEMPT);
		WRITE_REG(SCIx->CLR, SCI_CLR_TXEND);
		if (!(txClptFlg))
		{
			__DDL_SCII2C_INTRENABLE(SCIx, SCI_IE_TXEND);
			__DDL_SCII2C_INTRDISABLE(SCIx, SCI_IE_TXBUFEMPT);
		}

		if (txClptFlg)
		{
			/* Now, disable all interrupt */
            DDL_SCIIIC_IntDisable(SCIx, SCI_IE_TXEND | SCI_IE_TXBUFEMPT | SCI_IE_OVRERR | SCI_IE_PRTERR | SCI_IE_FRMERR);
			/* Force termination */
			__DDL_SCII2C_STP_GENERATE(SCIx);
            i2cTxCmplt = 1;
		}

		txClptFlg = 1;
	}
	else
	{
		txClptFlg = 0;
		/* Clear Transaction Complete Flag */
		WRITE_REG(SCIx->CLR, SCI_CLR_TXBUFEMPT);
		SCIx->TXD = wrBuf[__MAXIMUM_RD_LENGTH__ - gTranCont];
		gTranCont--;
	}
}


/**
  * @brief  This function is implemented for IIC PinMux configuration.
  * @param  None
  * @retval None
  */
void I2C_PinMux_Config(void)
{
    DDL_GPIO_Config2AltFunc(GPIOA, GPIO_PIN_12, GPIOA12_AF0_SCI0_SCK_CTS);
    DDL_GPIO_Config2AltFunc(GPIOA, GPIO_PIN_10, GPIOA10_AF3_SCI0_TX_SDA_MOSI);
//    DDL_GPIO_OpenDrainConfig(GPIOA, GPIO_PIN_12, 0);
//    DDL_GPIO_OpenDrainConfig(GPIOA, GPIO_PIN_10, 0);
    SET_BIT(SYSCFG->PDPLUP[0], 0x1400);
}


/**
  * @brief  This function is implemented for system clock configuration.
  *         where:
  *         System Clock source            = PLL (HIRC)
  *         System Clock frequency         = 100MHz
  * @param  None
  * @retval None
  */
void SystemClock_Config(void)
{
	RCC_PLLInit_T pllInitStruct    = {0};
	RCC_ClkInit_T rccClkInitStruct = {0};

	DDL_RCC_PllStructInit(&pllInitStruct);
	/* FCLK : 100MHz */
	pllInitStruct.pllPrescaler  = 4;
	if (DDL_RCC_PllConfig(&pllInitStruct) != DDL_OK)
	{
		while(1) ;
	}

	/* Select PLL as system clock source */
	rccClkInitStruct.sysClkSource  = RCC_SYSCLKSOURCE_PLLCLK;
	rccClkInitStruct.sysClkDivider = 0;
	if (DDL_RCC_ClkSrcConfig(&rccClkInitStruct) != DDL_OK)
	{
		while(1) ;
	}
}



/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
	SCII2C_Init_T pSCII2CStruct;

    DDL_Init();
    SystemClock_Config();
	DDL_Delay(1000);

    DDL_SCI_Instance_Active(SCI0);
    I2C_PinMux_Config();
	DDL_SCII2C_StructInit(&pSCII2CStruct);

    pSCII2CStruct.mlsb        = SCII2C_MSB_FIRST;
	pSCII2CStruct.sdaHold     = SCII2C_HLDCNT_1_4;
	pSCII2CStruct.fastMode    = SCII2C_FASTMODE_DISABLE;
    /* 400000 baud */
	pSCII2CStruct.clkPres     = 2;
	pSCII2CStruct.brDiv1And2  = 0x1D << 16;

    DDL_SCII2C_Init(SCI0, &pSCII2CStruct);
    NVIC_SetPriority(SCI0_IRQn, __PREEMPT_INTRERRUPT_PRIORITY_0__);
	while(1)
	{
        gTranCont = __MAXIMUM_RD_LENGTH__;
        DDL_SCII2C_Master_Transmit_IT(SCI0, 0xA0, wrBuf, sizeof(wrBuf)/sizeof(uint8_t));
        while(i2cTxCmplt == 0);
		i2cTxCmplt = 0;
        DDL_Delay(100);
        gRecvCont = 0;
        DDL_SCII2C_Master_Receive_IT(SCI0, 0xA1, rdBuf, sizeof(rdBuf)/sizeof(uint8_t));
        while(i2cRxCmplt == 0);
		i2cRxCmplt = 0;
        if (memcmp(rdBuf, wrBuf, __MAXIMUM_RD_LENGTH__) != 0)
		{
			__asm volatile("bkpt 0");
		}

		memset(rdBuf, 0x5A, __MAXIMUM_RD_LENGTH__);
        DDL_Delay(500);
	}
}






