/* USER CODE BEGIN Header */
/* you can remove the copyright */

/*
 *  Copyright 2020-2023 Yuntu Microelectronics co.,ltd
 *  All rights reserved.
 *
 *  YUNTU Confidential. This software is owned or controlled by YUNTU and may only be
 *  used strictly in accordance with the applicable license terms. By expressly
 *  accepting such terms or by downloading, installing, activating and/or otherwise
 *  using the software, you are agreeing that you have read, and that you agree to
 *  comply with and are bound by, such license terms. If you do not agree to be
 *  bound by the applicable license terms, then you may not retain, install,
 *  activate or otherwise use the software. The production use license in
 *  Section 2.3 is expressly granted for this software.
 *
 * @file main.c
 * @brief
 *
 */

/* USER CODE END Header */
#include "Mcal.h"
/* Includes ------------------------------------------------------------------*/

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define TRANSFER_SIZE           8U

#define I2C_TRANS_IN_ASYNCMODE  0U
#define I2C_TRANS_IN_SYNCMODE   1U

#define I2C_TX_MODE     (I2C_TRANS_IN_SYNCMODE)
#define I2C_RX_MODE     (I2C_TRANS_IN_ASYNCMODE)
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
#define CDDI2C_START_SEC_VAR_INIT_UNSPECIFIED_NO_CACHEABLE
#include "CddI2c_MemMap.h"
CDDI2C_VAR uint8  WriteToEepromBuffer[8] = {0x0, 0x18, 0x20, 0x31, 0x47, 0x5, 0x6, 0x7};
#define CDDI2C_STOP_SEC_VAR_INIT_UNSPECIFIED_NO_CACHEABLE
#include "CddI2c_MemMap.h"

#define CDDI2C_START_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "CddI2c_MemMap.h"
CDDI2C_VAR uint8  ReadFromEepromBuffer[7];
#define CDDI2C_STOP_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "CddI2c_MemMap.h"

uint8 SlaveRxBuffer[TRANSFER_SIZE] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
uint8 SlaveTxBuffer[TRANSFER_SIZE] = {0xa5, 0x71, 0x62, 0x53, 0x44, 0x35, 0x26, 0x17};
uint8 MasterRxBuffer[TRANSFER_SIZE] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
uint8 MasterTxBuffer[TRANSFER_SIZE] = {0x5a, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};

CddI2c_RequestType I2c0MasterTx =
{
    /* Slave address */
    .SlaveAddress = 0x50,
    /*10 bit address*/
    .BitsSlaveAddressIs10 = FALSE,
    /*high speed */
    .HighSpeedMode = FALSE,
    /* expect Nack */
    .ExpectNack = FALSE,
    /*repeated start */
    .RepeatedStart = FALSE,
    /*buffer size */
    .BufferSize = 8U,
    /*Data direction */
    .DataDirection = I2C_SEND_DATA,
    /*Buffer*/
    .DataBuffer = WriteToEepromBuffer
};

CddI2c_RequestType I2c0MasterRx =
{
    /* Slave address */
    .SlaveAddress = 0x50,
    /*10 bit address*/
    .BitsSlaveAddressIs10 = FALSE,
    /*high speed */
    .HighSpeedMode = FALSE,
    /* expect Nack */
    .ExpectNack = FALSE,
    /*repeated start */
    .RepeatedStart = FALSE,
    /*buffer size */
    .BufferSize = 7U,
    /*Data direction */
    .DataDirection = I2C_RECEIVE_DATA,
    /*Buffer*/
    .DataBuffer = ReadFromEepromBuffer
};

CddI2c_RequestType I2c1MasterSend =
{
    /* Slave address */
    .SlaveAddress = 0x21U,
    /*10 bit address*/
    .BitsSlaveAddressIs10 = FALSE,
    /*high speed */
    .HighSpeedMode = FALSE,
    /* expect Nack */
    .ExpectNack = FALSE,
    /*repeated start */
    .RepeatedStart = FALSE,
    /*buffer size */
    .BufferSize = 8U,
    /*Data direction */
    .DataDirection = I2C_SEND_DATA,
    /*Buffer*/
    .DataBuffer = MasterTxBuffer
};

CddI2c_RequestType I2c1MasterReceive =
{
    /* Slave address */
    .SlaveAddress = 0x21U,
    /*10 bit address*/
    .BitsSlaveAddressIs10 = FALSE,
    /*high speed */
    .HighSpeedMode = FALSE,
    /* expect Nack */
    .ExpectNack = FALSE,
    /*repeated start */
    .RepeatedStart = FALSE,
    /*buffer size */
    .BufferSize = 8U,
    /*Data direction */
    .DataDirection = I2C_RECEIVE_DATA,
    /*Buffer*/
    .DataBuffer = MasterRxBuffer
};

/* USER CODE END PV */

/* Private function declare --------------------------------------------------*/
/* USER CODE BEGIN PFDC */
/* USER CODE END PFDC */
static void Board_Init(void);

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*uint8 buffer compare*/
boolean BufferCompare(uint8 const *Buffer1, uint8 const *Buffer2, uint32 Length)
{
    volatile boolean Result = TRUE;

    for (uint32 Index = 0; Index < Length; ++Index)
    {
        if (Buffer1[Index] != Buffer2[Index])
        {
            Result = FALSE;
            break;
        }
    }
    return Result;
}

void I2c_Callback(uint8 Event, uint8 Channel)
{
    switch (Event)
    {
        case I2C_EVENT_TX_REQ_SLAVE:
            (void)CddI2c_PrepareSlaveBuffer(Channel, SlaveTxBuffer, TRANSFER_SIZE, TRUE);
            break;
        case I2C_EVENT_RX_REQ_SLAVE:
            (void)CddI2c_PrepareSlaveBuffer(Channel, SlaveRxBuffer, TRANSFER_SIZE, FALSE);
            break;
        default:
            /*Do nothing*/
            break;
    }
}

void I2c_ErrorCallback(uint8 Event, uint8 Channel)
{
    (void)Event;
    (void)Channel;
    /*user code*/
}

/*Delay function*/
void Delay(uint32 DelayTime)
{
    while (DelayTime--)
    {
        __ASM("NOP");
    }
}

void I2C_Unlock()
{
    uint32 PortTemp = 0;
    PortTemp = *(volatile uint32 *)(0x4004800c);
    *(volatile uint32 *)(0x4004800c) = 0x157;
    *(volatile uint32 *)(0x40044014) |= (0x1 << 3);
    for (uint32 i = 0; i < 9; i++)
    {
        *(volatile uint32*)0x40044000 |= (0x1 << 3);
        Delay(100);
        *(volatile uint32*)0x40044000 &= ~(0x1 << 3);
        Delay(100);
    }
    *(volatile uint32 *)(0x4004800c) = PortTemp;
}

/*EEPROM test on I2c0 bus*/
void Eeprom_Write_Read_Test(void)
{
    CddI2c_StatusType TempRav = I2C_CHN_UNINIT;

    /*write data to EEPROM in EVB with the I2C0 */
#if (I2C_TX_MODE == I2C_TRANS_IN_SYNCMODE)
    CddI2c_SyncModeTransfer(CddI2cConf_I2cChannel_I2cChannel_0, &I2c0MasterTx);

    TempRav = CddI2c_GetTransferStatus(CddI2cConf_I2cChannel_I2cChannel_0);
#else
    CddI2c_AsyncModeTransfer(CddI2cConf_I2cChannel_I2cChannel_0, &I2c0MasterTx);
    do
    {
        TempRav = CddI2c_GetTransferStatus(CddI2cConf_I2cChannel_I2cChannel_0);
    } while (I2C_CHN_COMPLETED != TempRav);
#endif

    /*delay 10ms*/
    Delay((uint32)1000000);

    /*Read data from EEPROM in EVB with the I2C0*/
#if (I2C_RX_MODE == I2C_TRANS_IN_ASYNCMODE)
    I2c0MasterTx.BufferSize = 1;
    CddI2c_SyncModeTransfer(CddI2cConf_I2cChannel_I2cChannel_0, &I2c0MasterTx);
    do
    {
        TempRav = CddI2c_GetTransferStatus(CddI2cConf_I2cChannel_I2cChannel_0);
    } while (I2C_CHN_COMPLETED != TempRav);

    CddI2c_SyncModeTransfer(CddI2cConf_I2cChannel_I2cChannel_0, &I2c0MasterRx);
    do
    {
        TempRav = CddI2c_GetTransferStatus(CddI2cConf_I2cChannel_I2cChannel_0);
    } while (I2C_CHN_COMPLETED != TempRav);
#else
    I2c0MasterTx.BufferSize = 1;
    CddI2c_SyncModeTransfer(CddI2cConf_I2cChannel_I2cChannel_0, &I2c0MasterTx);
    CddI2c_SyncModeTransfer(CddI2cConf_I2cChannel_I2cChannel_0, &I2c0MasterRx);

    TempRav = CddI2c_GetTransferStatus(CddI2cConf_I2cChannel_I2cChannel_0);

#endif
    /* Verify the recieve data is right or not*/
    while (BufferCompare(&WriteToEepromBuffer[1], &ReadFromEepromBuffer[0], 7) == FALSE);
}

/*I2c1 as master and I2c2 as slave communication test*/
void I2c1_Master_I2c2_Slave_Test(void)
{
    CddI2c_StatusType TempRav = I2C_CHN_UNINIT;

    /*master send and slave receive data*/
    CddI2c_StartListening(CddI2cConf_I2cChannel_I2cChannel_2);
    CddI2c_SyncModeTransfer(CddI2cConf_I2cChannel_I2cChannel_1, &I2c1MasterSend);

    // while (CddI2c_GetTransferStatus(CddI2cConf_I2cChannel_I2cChannel_2) != I2C_CHN_COMPLETED);
    // while (BufferCompare(&MasterTxBuffer[0], &SlaveRxBuffer[0], 8) == FALSE);

    /*master read 8B data from slave*/
    CddI2c_StartListening(CddI2cConf_I2cChannel_I2cChannel_2);
    CddI2c_SyncModeTransfer(CddI2cConf_I2cChannel_I2cChannel_1, &I2c1MasterReceive);
    // while (CddI2c_GetTransferStatus(CddI2cConf_I2cChannel_I2cChannel_2) != I2C_CHN_COMPLETED);

    // while (BufferCompare(&MasterRxBuffer[0], &SlaveTxBuffer[0], 8) == FALSE);
}
/* USER CODE END 0 */


/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
    /* USER CODE BEGIN 1 */
    volatile uint32 TestCount = 0;

    Mcu_Init(&Mcu_Config);
    Mcu_InitClock(0);
#if (MCU_NO_PLL == STD_OFF)
    while (MCU_PLL_LOCKED != Mcu_GetPllStatus())
    {
        /* Wait until PLL is locked */
    }
    Mcu_DistributePllClock();
#endif
    /* USER CODE END 1 */ 
    Board_Init();
    /* USER CODE BEGIN 2 */
    Eeprom_Write_Read_Test();
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */
        /* USER CODE BEGIN 3 */
        /*master send and slave receive data*/
        // for (uint32 loop = 0; loop < 100; loop++)
        {
            Eeprom_Write_Read_Test();
            // I2c1_Master_I2c2_Slave_Test();

            TestCount++;
            if (TestCount % 200 == 0U)
            {
                Dio_FlipChannel(DioConf_DioChannel_DioChannel_0);
            }
        }
    }

    CddI2c_DeInit();
    /* USER CODE END 3 */
}

static void Board_Init(void)
{
    Port_Init(&Port_Config);
    CddDma_Init(&CddDma_Config);
    CddI2c_Init(&CddI2c_Config);
    Platform_Init(NULL_PTR);
}

/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
