/******************************************************************************
 * @file     main.c
 * @brief    Main program body
 * @version  V1.8.0
 * @date     31-Dec-2021
 *
 * @note
 * Copyright (C) 2021 Spintrol Limited Corporation. 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"spc1168.h"
#include<stdio.h>
#include<stdlib.h>

#define             DEBUG_INFO              1               /* the contolling flag of printf info*/

#define             Tx_Full_INT_TH          0               /* threshold will thrigger Tx full INT */
#define             Rx_Empty_INT_TH         0               /* threshold will thrigger Rx empty INT */
#define             T_BUFFER_SIZE           128
#define             I2C_SPEED               400000
#define             I2C_Slave_ADDR          0x9             /* IIC Slve ADDR */

uint32_t            gu32BuffSize            = T_BUFFER_SIZE;
uint8_t             gau8TxBuf[T_BUFFER_SIZE];
uint8_t             gau8RxBuf[T_BUFFER_SIZE]; 
uint32_t            gu32_cnt_i2c_stop_isr;
ErrorStatus         estatus;
 
void Master_Bulk_TxRX_data(void)
{
  int i;
  uint32_t u32IsrCnt = 0;                                   /* Interrupt Check variable */

  /* Generate random datum to transmit */
  for(i=0; i < gu32BuffSize; i++)
    gau8TxBuf[i] = rand() & 0xFF;

  printf("Master Tx data...\n");
  I2C_MasterBulkWrite(I2C, I2C_ADDR_7BIT, I2C_Slave_ADDR, gau8TxBuf, gu32BuffSize);

  /*
   * In the interface of 'I2C_MasterBulkWriteData()', master will wait for the Tx FIFO empty
   * after this bulk, in other words, the master will sent a 'STOP' CMD to the IIC, and
   * then sent a 'RESTART' at the next bulk. we can count the bulk we has sent to get 
   * the INT count had entered.  
   */
  u32IsrCnt += 1;

  printf("Master Rx data...\n");
  /*Read the data had sent to the slave back and put them in 'gau8RxBuf'*/
  I2C_MasterBulkRead(I2C, I2C_ADDR_7BIT, I2C_Slave_ADDR, gau8RxBuf, gu32BuffSize);
  u32IsrCnt += 1;

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

  /*The aim of fllowing code is to check if the slave Tx/Rx is ok*/
  printf("Master Rx data...\n");
  I2C_MasterBulkRead(I2C, I2C_ADDR_7BIT, I2C_Slave_ADDR, gau8RxBuf, gu32BuffSize);
  u32IsrCnt += 1;

  printf("Master Tx data...\n");
  /*Sent the data had recieved back to the slave*/
  I2C_MasterBulkWrite(I2C, I2C_ADDR_7BIT, I2C_Slave_ADDR, gau8RxBuf, gu32BuffSize);
  u32IsrCnt += 1;
  
  /* Wait for I2C INT done */
  Delay_Us(300);

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


 /*************************************************************************************************************************
 *
 * @brief      In this case, the IIC controller is used as master and enbale the 'STOP' INT, and sent datum to slave with a
 *             'STOP' CMD after every bulk, so the number of INT equal the number of bulk had sent. 
 * 
 *             This demo code is couple with the slave demo code named "I2C_Slave_Bulk_Polling_TxRx".
 *
 *************************************************************************************************************************/


int main()
{
  FLASH_WALLOW();
  FLASH_SetTiming(200000000);
  /* Disable flash write access after flash operation had done */
  FLASH_WDIS();

  CLOCK_InitWithRCO(CLOCK_HCLK_200MHZ);

  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 GPIO38~39 as I2C function */
  GPIO_SetPinChannel(GPIO_38, GPIO38_I2C_SDA);
  GPIO_SetPinChannel(GPIO_39, GPIO39_I2C_SCL);

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

  /*
   * Tx/Rx FIFO threshold set as 0 means letting CPU process data once
   * FIFO has one entry data.
   */
  I2C_SetTxFIFOThreshold(I2C, Tx_Full_INT_TH);
  I2C_SetRxFIFOThreshold(I2C, Rx_Empty_INT_TH);

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

  /* Enable the INT of detecting the STOP of I2C */
  I2C_EnableStopDetectInt(I2C);

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

  /* Init I2C as Master */
  estatus = I2C_MasterInit(I2C, I2C_SPEED);
  if(estatus == ERROR)
  {
    printf("[IIC master init FAIL] I2C clock is not fast enough to support the speed\n");
    return 0;
  }

  /* Enable CM4 INT Request */
  NVIC_EnableIRQ(I2C_IRQn);

  /* Master start to transmit and recieve data */
  Master_Bulk_TxRX_data();

  while(1)
  {

  }
}

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