/******************************************************************************
 * @file     main.c
 * @brief    Main program body
 * @version  V4.0.0
 * @date     30-July-2026
 *
 * @note
 * Copyright (C) 2022 Spintrol Electronic Technology (Shanghai) Co., Ltd.. All rights reserved.
 *
 * @attention
 * THIS SOFTWARE JUST PROVIDES CUSTOMERS WITH CODING INFORMATION REGARDING
 * THEIR PRODUCTS, WHICH AIMS AT SAVING TIME FOR THEM. SPINTROL SHALL NOT BE
 * LIABLE FOR THE USE OF THE SOFTWARE. SPINTROL DOES NOT GUARANTEE THE
 * CORRECTNESS OF THIS SOFTWARE AND RESERVES THE RIGHT TO MODIFY THE SOFTWARE
 * WITHOUT NOTIFICATION.
 *
 ******************************************************************************/

#include<stdio.h>
#include<stdlib.h>

#if defined(SPC1158)
#include "spc1158.h"
#elif defined(SPD1148)
#include "spd1148.h"
#elif defined(SPD1178)
#include "spd1178.h"
#elif defined(SPD1188)
#include "spd1188.h"
#elif defined(SPD1163)
#include "spd1163.h"
#else
#include "spc1168.h"
#endif

#if defined(SPD1148)
    #define               SDA_GPIO                   GPIO_31
    #define               SCL_GPIO                   GPIO_30
    #define               SDA_GPIO_FUNC              GPIO31_I2C_SDA
    #define               SCL_GPIO_FUNC              GPIO30_I2C_SCL
#elif defined(SPD1163)
    #define               SDA_GPIO                   GPIO_38
    #define               SCL_GPIO                   GPIO_39
    #define               SDA_GPIO_FUNC              GPIO38_I2C_SDA
    #define               SCL_GPIO_FUNC              GPIO39_I2C_SCL
#else
    #define               SDA_GPIO                   GPIO_13
    #define               SCL_GPIO                   GPIO_12
    #define               SDA_GPIO_FUNC              GPIO13_I2C_SDA
    #define               SCL_GPIO_FUNC              GPIO12_I2C_SCL
#endif

#define               DEBUG_INFO                 1                         /* The controlling flag of printf info*/
#define               SLAVE_TRANSMIT             0                         /* 1: slave transmit 0: slave receive */

#define               T_BUFFER_SIZE              128
#define               I2C_Slave_ADDR             0x10                      /* IIC Slave ADDR Must be greater than 0xF when in High speed mode*/
#define               I2C_SPEED                  2000000

uint32_t              gu32BuffSize               = T_BUFFER_SIZE;
uint8_t               gau8TxBuf[T_BUFFER_SIZE];
uint8_t               gau8RxBuf[T_BUFFER_SIZE];
ErrorStatus           estatus;
uint32_t              gu32_cnt_i2c_stop_isr;

static ErrorStatus Check_Receive_Data(void)
{
    int i;
    uint8_t u8Data = 0;

    /*To check the datum sent and received are the same*/
    for(i = 0; i < gu32BuffSize; i++)
    {
        if (gau8RxBuf[i] != u8Data)
        {
            #if DEBUG_INFO
            printf("[Error]@%4d: TX(0x%02X) != RX(0x%02X)\n", __LINE__, u8Data, gau8RxBuf[i]);
            #endif

            return ERROR;
        }
        else
        {
            #if DEBUG_INFO
            printf("%3d: TX(0x%02X) == RX(0x%02X)\n", i, u8Data, gau8RxBuf[i]);
            #endif
        }

        u8Data++;
    }

    return SUCCESS;
}


void Slave_TxRX_data(I2C_REGS *I2Cx)
{
    int i;
    uint8_t u8Data = 0;
    uint32_t u32IsrCnt = 0;                                     /* Interrupt Check variable */

    if (SLAVE_TRANSMIT)
    {
        /* Generate random datum to transmit */
        for(i=0; i < gu32BuffSize; i++)
        {
            gau8TxBuf[i] = u8Data++;
            #if DEBUG_INFO
            printf("gau8TxBuf[%d] = 0x%x\n", i, gau8TxBuf[i]);
            #endif
        }

        printf("Slave Tx data...\n");
        estatus = I2C_SlaveWrite(I2C, gau8TxBuf, gu32BuffSize);
        if(estatus == ERROR)
        {
            return;
        }
    }
    else
    {
        printf("Slave Rx data...\n");

        /* Read the data had sent to the master just now back and put them into the 'gau8RxBuf' */
        I2C_SlaveRead(I2C, gau8RxBuf, gu32BuffSize);

        /*To check the datum sent and received are the same*/
        estatus = Check_Receive_Data();
        if(estatus == ERROR)
        {
            return;
        }
    }

    u32IsrCnt += gu32BuffSize;

    /* Wait for I2C INT done */
    Delay_Us(300);

    /*
     * Check interrupt counter, if the INT count is not equal the bytes we has sent, there
     * must be something wrong had happened.
     */
    if(gu32_cnt_i2c_stop_isr != u32IsrCnt)
    {
        #if DEBUG_INFO
        printf("[Error]@%4d: I2C ISR counter not right. expect %d, but is %d", __LINE__,
                                     u32IsrCnt, gu32_cnt_i2c_stop_isr);
        #endif
    }
    else
    {
        printf("Success\n");
    }
}


/*************************************************************************************************************************
*
* @brief      This example configures the I2C controller as a Slave in High Speed mode.
*             It enables the Stop Detect Interrupt to monitor the communication process.
*             Since the paired Master issues a STOP condition after every single byte sent, 
*             the Slave's Interrupt Service Routine (ISR) will increment a counter for each 
*             STOP detection. This allows the Slave to track the total number of received 
*             bytes via the cumulative interrupt count.
*
* @note
*             The slave device runs first, the master device runs later
*             This demo code is couple with the master demo code named "I2C_Master_High_Speed_Mode_Polling_TxRx".
*
*************************************************************************************************************************/


int main()
{
    FLASH_WALLOW();

#if defined(SPC1158)
    FLASH_SetTiming(100000000);
    /* Disable flash write access after flash operation had done */
    FLASH_WDIS();

    CLOCK_InitWithRCO(100000000UL);
#else
    FLASH_SetTiming(200000000);
    /* Disable flash write access after flash operation had done */
    FLASH_WDIS();

    CLOCK_InitWithRCO(200000000UL);
#endif

    Delay_Init();

    /*
     * Init the UART
     *
     * 1.Set the GPIO34/35 as UART FUNC
     *
     * 2.Enable the UART CLK
     *
     * 3.Set the rest para
     */
    GPIO_SetPinChannel(GPIO_34, GPIO34_UART_TXD);
    GPIO_SetPinChannel(GPIO_35, GPIO35_UART_RXD);
    CLOCK_EnableModule(UART_MODULE);
    UART_Init(UART, 38400);

    /* Config GPIO as I2C function */
    GPIO_SetPinChannel(SDA_GPIO, SDA_GPIO_FUNC);
    GPIO_SetPinChannel(SCL_GPIO, SCL_GPIO_FUNC);

    /*
     * Set Output Strength as 20mA, in case of many more
     * slaves are linking to the master.
     */
    GPIO_SetOutStrength(SDA_GPIO, GPIO_OUT_STRENGTH_20MA);
    GPIO_SetOutStrength(SCL_GPIO, GPIO_OUT_STRENGTH_20MA);

    /* Disable All INT */
    I2C_DisableAllInt(I2C);

    /* Enable CM4 INT Request */
    NVIC_EnableIRQ(I2C_IRQn);
    
    /* Enable the INT of detecting the STOP of I2C */
    I2C_EnableStopDetectInt(I2C);

    /* Clear All INT */
    I2C_ClearInt(I2C, I2C_INT_ALL);

    /* Init I2C as Slave and set the speed as 400K */
    estatus = I2C_SlaveInit(I2C, I2C_ADDR_7BIT, I2C_Slave_ADDR, I2C_SPEED, I2C_SPEED_HIGH);
    if (estatus == ERROR)
    {
        #if DEBUG_INFO
        printf("[IIC slave init FAIL] I2C clock is not fast enough to support the speed\n");
        #endif

        return 0;
    }

    /* Master start to transmit and receive data */
    Slave_TxRX_data(I2C);

    while (1)
    {

    }
}

void I2C_IRQHandler(void)
{
    volatile uint32_t u32Dummy;

    if (I2C_GetStopDetectIntRawFlag(I2C))
    {
        u32Dummy = I2C->I2CSTOPDETCLR.all;
        gu32_cnt_i2c_stop_isr ++ ;
    }
    else
    {
        #if DEBUG_INFO
        printf("[%s Error] Stop detect interrupt error\n", __func__);
        #endif
    }
}
