/**
  *****************************************************************************************************
  * @file    main.c
  * @author  Kiwi Software Team
  * @brief   This example code demonstrates how 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 __MAX_I2C_RDWR_DATA_LENGTH__       8
#define __I2C_SLAVE_ADDRESS__               0x50

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

static volatile uint8_t gi2cTxCmplt = 0;
static volatile uint8_t gi2cRxCmplt = 0;
uint32_t pTxBuffPtr = 0;
uint32_t txXferCount = 0;
uint32_t pRxBuffPtr = 0;
uint32_t rxXferCount = 0;

/**
  * @brief  This function is IIC callback.
  * @param  None
  * @retval None
  */
void DDL_I2C_CpltCallback(I2C_Type *I2Cx)
{
    static uint8_t masterflag;
	uint16_t i = 0;
	static uint16_t datacount;
	static uint8_t dataflag;
    if (((I2Cx->CTRL >> 12)&0x01) == 0)
	{
		if (I2Cx->INTSR & I2C_INTSR_ADDR)
		{
			/* Clear the address Interrupt Status */
			__DDL_I2C_CLEAR_ADDR_INTR(I2Cx);
		}

		if (I2Cx->INTSR & I2C_INTSR_DATA)
		{
			/* Clear the data Interrupt Status */
			__DDL_I2C_CLEAR_DATA_INTR(I2Cx);
		}

		if (I2Cx->DATACNT >= 8)
		{
			if (dataflag == 0)
			{
				for (i = 0;i < 8;i++)
				{
					I2Cx->DT = wrBuf[pTxBuffPtr];
					pTxBuffPtr ++;
					txXferCount--;
				}
				dataflag = 1;
				/* Open the fifothre Interrupt Ctrl */
				__DDL_I2C_INTENABLE(I2Cx, I2C_INTEN_FIFOTHRE);
				__DDL_I2C_WAIT_QUIT_SET(I2Cx);
			}
			datacount = txXferCount;


			if (I2Cx->INTSR & I2C_INTEN_FIFOTHRE)
			{
				if (txXferCount >= 6)
				{
					for (i = 0;i < 6;i++)
					{
						I2Cx->DT = wrBuf[pTxBuffPtr];
						pTxBuffPtr ++;
						txXferCount--;
					}
				}
				else
				{
					__DDL_I2C_INTDISABLE(I2Cx, I2C_INTEN_FIFOTHRE);
					for (i = 0;i < datacount;i++)
					{
						I2Cx->DT = wrBuf[pTxBuffPtr];
						pTxBuffPtr ++;
						txXferCount--;
					}
				}
			}
		}
		else
		{
			/* Close the fifothre Interrupt Ctrl */
			__DDL_I2C_INTDISABLE(I2Cx, I2C_INTEN_FIFOTHRE);
			for (i = 0;i < I2Cx->DATACNT;i++)
			{
				I2Cx->DT = wrBuf[pTxBuffPtr];
				pTxBuffPtr ++;
				txXferCount--;
			}
			__DDL_I2C_WAIT_QUIT_SET(I2Cx);
		}
		if (I2Cx->INTSR & I2C_INTSR_TCNTDONE)
		{
			__DDL_I2C_CLEAR_TCNTDONE_INTR(I2Cx);
			/* Generate One I2C Stop Signal*/
			__DDL_I2C_STP_GENERATE(I2Cx);
		}

		if (I2Cx->INTSR & I2C_INTSR_STP)
		{
			__DDL_I2C_CLEAR_STOP_INTR(I2Cx);
			__DDL_I2C_CLEAR_TCNTDONE_INTR(I2Cx);
			__DDL_I2C_COMM_QUIT_SET(I2Cx);
			__DDL_I2C_INTDISABLE(I2Cx, I2C_INTEN_FIFOTHRE);
			__DDL_I2C_CLEAR_FIFO(I2Cx);
			datacount = 0;
			dataflag = 0;
			/* Disable interrupts */
			__DDL_I2C_INTDISABLE(I2Cx, I2C_INTEN_STOPINT | I2C_INTEN_WTIMEN | I2C_INTEN_ADDRINT | I2C_INTEN_TCNTEN | I2C_INTEN_NACK);
			/*All-Data Sent-out*/
			gi2cTxCmplt = 1;
		}
	}
    else/* When I2C works as Master read*/
    {
		if (I2Cx->INTSR & I2C_INTSR_ADDR)
		{
			/* Clear the address Interrupt Status */
			__DDL_I2C_CLEAR_ADDR_INTR(I2Cx);
			__DDL_I2C_WAIT_QUIT_SET(I2Cx);
			__DDL_I2C_ACKGEN_ENABLE(I2Cx);
			return ;
		}
		/* data count less than 8*/
		if (I2Cx->INTSR & I2C_INTSR_TCNTDONE)
		{
			__DDL_I2C_CLEAR_TCNTDONE_INTR(I2Cx);
			if (!masterflag)
			{
				masterflag = 1;
				__DDL_I2C_WTIM_8OR9THCLK_CONFIG(I2Cx, I2C_INTOCUR_ON9TH_CLK);
				__DDL_I2C_NACK_GENERATE(I2Cx);
				__DDL_I2C_WAIT_QUIT_SET(I2Cx);
			}
			else
			{
				__DDL_I2C_STP_GENERATE(I2Cx);
				return ;
			}
			if ((I2Cx->DATACNT&0xFFFF) < 8)
			{
				for (i = 0;i < rxXferCount; i++)
				{
					/* Start first Data-Frame Transaction */
					rdBuf[pRxBuffPtr] = I2Cx->DT;
					pRxBuffPtr ++;
				}
			}
			else
			{
				for (i = 0;i < rxXferCount; i++)
				{
					/* Start first Data-Frame Transaction */
					rdBuf[pRxBuffPtr] = I2Cx->DT;
					pRxBuffPtr ++;
					datacount++;
				}
			}
		}
		if (I2Cx->INTSR & I2C_INTEN_FIFOTHRE)
		{
			for (i = 0;i < 6; i++)
			{
				/* Start first Data-Frame Transaction */
				rdBuf[pRxBuffPtr] = I2Cx->DT;
				pRxBuffPtr ++;
				datacount++;
				rxXferCount--;
			}
		}
		if (I2Cx->INTSR & I2C_INTSR_DATA)
		{
			/* Clear the address Interrupt Status */
			__DDL_I2C_CLEAR_DATA_INTR(I2Cx);
		}

		if (I2Cx->INTSR & I2C_INTSR_STP)
		{
			masterflag = 0;
			datacount = 0;
			__DDL_I2C_CLEAR_FIFO(I2Cx);
			__DDL_I2C_CLEAR_STOP_INTR(I2Cx);
			__DDL_I2C_INTDISABLE(I2Cx, I2C_INTEN_FIFOTHRE);
			/* Disable interrupts */
			__DDL_I2C_INTDISABLE(I2Cx, I2C_INTEN_STOPINT | I2C_INTEN_WTIMEN | I2C_INTEN_ADDRINT | I2C_INTEN_TCNTEN);
			gi2cRxCmplt = 1;
		}
    }
}


/**
  * @brief  This function is implemented for IIC PinMux configuration.
  * @param  None
  * @retval None
  */
void I2C_PinMux_Config(void)
{
    DDL_GPIO_Config2AltFunc(GPIOC, GPIO_PIN_3, GPIOC3_AF3_I2C0_SCL);
    DDL_GPIO_Config2AltFunc(GPIOC, GPIO_PIN_4, GPIOC4_AF3_I2C0_SDA);
    SET_BIT(SYSCFG->PDPLUP[1],0x18);
}


/**
  * @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)
{
    I2C_Init_T pI2CStruct;
    DDL_Init();
    SystemClock_Config();
	DDL_Delay(1000);

    /*So that I2C Module can be accessed */
	 __DDL_RCC_I2C0_ACTIVE();
	 __DDL_RCC_I2C0_CLK_RELEASE();
    I2C_PinMux_Config();


    DDL_I2C_StructInit(&pI2CStruct);
    pI2CStruct.prescaler = 1;
	pI2CStruct.widthHigh = 240;
	pI2CStruct.widthLow = 241;
    DDL_I2C_Init(I2C0, &pI2CStruct);
    NVIC_EnableIRQ(I2C0_IRQn);
    NVIC_SetPriority(I2C0_IRQn, 0);
	while(1)
	{
        txXferCount = __MAX_I2C_RDWR_DATA_LENGTH__;
        DDL_I2C_Master_Transmit_IT(I2C0, __I2C_SLAVE_ADDRESS__, wrBuf, __MAX_I2C_RDWR_DATA_LENGTH__);
		while(gi2cTxCmplt == 0);
		gi2cTxCmplt = 1;
        pTxBuffPtr = 0;

        DDL_Delay(100);
        rxXferCount = __MAX_I2C_RDWR_DATA_LENGTH__;

        DDL_SCII2C_Master_Receive_IT(I2C0, __I2C_SLAVE_ADDRESS__, rdBuf, __MAX_I2C_RDWR_DATA_LENGTH__);
        while(gi2cRxCmplt == 0);
		gi2cRxCmplt = 0;
        pRxBuffPtr = 0;

        DDL_Delay(100);
        if (memcmp(rdBuf, wrBuf, __MAX_I2C_RDWR_DATA_LENGTH__) != 0)
		{
			while(1);
		}
        memset(rdBuf, 0xAA, __MAX_I2C_RDWR_DATA_LENGTH__);

    }
}






