/******************************************************************************
 * @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>

#define               REF3V3_CODE            242221056        /* Ideal code for 3.3V input related to +-3.657143V range. 7392(ideal_code)*32768 */
#define               REF1V2_CODE            88080384         /* Ideal code for 1.2V input related to +-3.657143V range. 2688(ideal_code)*32768 */
#define               LSB                    29257            /* Ideal ADC LSB Votage: 0.44643mV * 65536 */
#define               NREP                   32               /* Unit: time */
#define               TDLY                   1                /* Unit: us */

int32_t               voltage;
int16_t               adc_sha_offset         =0;              /* sampler A offset [-80,80] */
int16_t               adc_shb_offset         =0;              /* sampler B offset [-80,80] */
int16_t               adc_shc_offset         =0;              /* sampler C offset [-80,80] */
uint32_t              adc_sha_gain           =0;              /* sampler A Gain [31130,34406] */
uint32_t              adc_shb_gain           =0;              /* sampler A Gain [31130,34406] */
uint32_t              adc_shc_gain           =0;              /* sampler A Gain [31130,34406] */


 /*************************************************************************************************************************
 *
 * @brief      ADC Calibration Function to get ADC calibration parameter
 *             method for sampler ADC A : (1) the two channel of sampler A connect to AGND, and save the measure result as
 *                                            'adc_sha_offset'
 *                                        (2) connect the two channel of sampler A to VDD (3.3V), the measure result is 'VDD_CODE'
 *                                        (3) use 'adc_sha_offset' and 'VDD_CODE' to calculate 'adc_sha_gain'
 *                                        (4) from now on, we get the gain and offset calibration value : 'adc_sha_gain' and
 *                                            'adc_sha_offset'
 *             method for sampler B and C is the same as A.
 *
 * @param[in]  
 *
 * @return     The gain and offset for SHA is saved to adcgaintrim_shagain and adcoffsettrim_shaoffset. 
 *             The gain and offset for SHB is saved to adcgaintrim_shbgain and adcoffsettrim_shboffset. 
 *             These four parameter are save as the global variations.
 *
 *             ADC calibration function 
 *
 *************************************************************************************************************************/


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);

  printf("\n************** ADC Calibration Test Start ******************\n");	

  /************************** ADC configuration ******************/	
  /* Power up ADC */
  ADC_PowerUp();

  /* Div ADC clock */
  CLOCK->ADCCLKCTL.bit.DIV = 0x1F;       // ADC Clock divider control : 1 means the clock frequency = systemclk / 2

  ADC->ADCIE.all = 0x0000ffff;           // Enable ADC Interrupt Flag

  Delay_Us(100);

  ADC->ADCSOCCTL[0].bit.SAMPCNT = 127;   // 875ns sample time
  ADC->ADCSOCCTL[0].bit.CONVCNT = 8;     // 125ns conversion time
  ADC->ADCSOCCTL[0].bit.AVGCNT  = 4;     // averaging 16 times
  ADC->ADCSOCCTL[0].bit.TRIGSEL = 0;     // trigger source selection: 0 means software trigger
  ADC->ADCSOCCTL[0].bit.CHSELP  = 0;     // positve terminal select AGND
  ADC->ADCSOCCTL[0].bit.CHSELN  = 0;     // negative terminal select AGND
  ADC->ADCSOCCTL[0].bit.SHEN    = 1;     // sampler enable: 1 means sampler A enable
  ADC->ADCIC.bit.INT0 = 1;               // clear INT0
  ADC->ADCSOCFRC.bit.SOC0 = 1;           // Software trigger SOC0
  while(ADC->ADCIF.bit.INT0 != 1) {};    // wait for ADC convertion done

  ADC->ADCSOCCTL[1].bit.SAMPCNT = 127;   // 875ns sample time
  ADC->ADCSOCCTL[1].bit.CONVCNT = 8;     // 125ns conversion time
  ADC->ADCSOCCTL[1].bit.AVGCNT  = 4;     // averaging 16 times
  ADC->ADCSOCCTL[1].bit.TRIGSEL = 0;     // trigger source selection: 0 means software trigger
  ADC->ADCSOCCTL[1].bit.CHSELP  = 4;     // positve terminal select ADC0  (3.3V)
  ADC->ADCSOCCTL[1].bit.CHSELN  = 4;     // negative terminal select ADC1 (0V)
  ADC->ADCSOCCTL[1].bit.SHEN    = 1;     // sampler enable: 1 means sampler A enable
  ADC->ADCIC.bit.INT1 = 1;
  ADC->ADCSOCFRC.bit.SOC1 = 1;           // Software trigger SOC1
  while(ADC->ADCIF.bit.INT1 != 1) {};

  ADC->ADCSOCCTL[2].bit.SAMPCNT = 127;   // 875ns sample time
  ADC->ADCSOCCTL[2].bit.CONVCNT = 8;     // 125ns conversion time
  ADC->ADCSOCCTL[2].bit.AVGCNT  = 4;     // averaging 16 times
  ADC->ADCSOCCTL[2].bit.TRIGSEL = 0;     // trigger source selection: 0 means software trigger
  ADC->ADCSOCCTL[2].bit.CHSELP  = 0;     // positve terminal select AGND
  ADC->ADCSOCCTL[2].bit.CHSELN  = 0;     // negative terminal select AGND
  ADC->ADCSOCCTL[2].bit.SHEN    = 2;     // sampler enable: 2 means sampler B enable
  ADC->ADCIC.bit.INT2 = 1;
  ADC->ADCSOCFRC.bit.SOC2 = 1;           // Software trigger SOC2
  while(ADC->ADCIF.bit.INT2 != 1) {};

  ADC->ADCSOCCTL[3].bit.SAMPCNT = 127;   // 875ns sample time
  ADC->ADCSOCCTL[3].bit.CONVCNT = 8;     // 125ns conversion time
  ADC->ADCSOCCTL[3].bit.AVGCNT  = 4;     // averaging 16 times
  ADC->ADCSOCCTL[3].bit.TRIGSEL = 0;     // trigger source selection: 0 means software trigger
  ADC->ADCSOCCTL[3].bit.CHSELP  = 4;     // positve terminal select ADC0  (3.3V)
  ADC->ADCSOCCTL[3].bit.CHSELN  = 4;     // negative terminal select ADC1 (0V)
  ADC->ADCSOCCTL[3].bit.SHEN    = 2;     // sampler enable: 2 means sampler B enable
  ADC->ADCIC.bit.INT3 = 1;
  ADC->ADCSOCFRC.bit.SOC3 = 1;           // Software trigger SOC3
  while(ADC->ADCIF.bit.INT3 != 1) {};

  ADC->ADCSOCCTL[4].bit.SAMPCNT = 127;   // 875ns sample time
  ADC->ADCSOCCTL[4].bit.CONVCNT = 8;     // 125ns conversion time
  ADC->ADCSOCCTL[4].bit.AVGCNT  = 4;     // averaging 16 times
  ADC->ADCSOCCTL[4].bit.TRIGSEL = 0;     // trigger source selection: 0 means software trigger
  ADC->ADCSOCCTL[4].bit.CHSELP  = 0;     // positve terminal select AGND
  ADC->ADCSOCCTL[4].bit.CHSELN  = 0;     // negative terminal select AGND
  ADC->ADCSOCCTL[4].bit.SHEN    = 3;     // sampler enable: 3 means sampler C enable
  ADC->ADCIC.bit.INT4 = 1;
  ADC->ADCSOCFRC.bit.SOC4 = 1;           // Software trigger SOC4
  while(ADC->ADCIF.bit.INT4 != 1) {};

  ADC->ADCSOCCTL[5].bit.SAMPCNT = 127;   // 875ns sample time
  ADC->ADCSOCCTL[5].bit.CONVCNT = 8;     // 125ns conversion time
  ADC->ADCSOCCTL[5].bit.AVGCNT  = 4;     // averaging 16 times
  ADC->ADCSOCCTL[5].bit.TRIGSEL = 0;     // trigger source selection: 0 means software trigger
  ADC->ADCSOCCTL[5].bit.CHSELP  = 4;     // positve terminal select ADC0 (3.3V)
  ADC->ADCSOCCTL[5].bit.CHSELN  = 4;     // negative terminal select ADC1 (0V)
  ADC->ADCSOCCTL[5].bit.SHEN    = 3;     // sampler enable: 3 means sampler C enable
  ADC->ADCIC.bit.INT5 = 1;
  ADC->ADCSOCFRC.bit.SOC5 = 1;           // Software trigger SOC5
  while(ADC->ADCIF.bit.INT5 != 1) {};

  printf("SHA Measure AGND  Code is %d \n", ADC->ADCRESULT[0].all);
  printf("SHA Measure VDD33 Code is %d \n", ADC->ADCRESULT[1].all);
  printf("SHB Measure AGND  Code is %d \n", ADC->ADCRESULT[2].all);
  printf("SHB Measure VDD33 Code is %d \n", ADC->ADCRESULT[3].all);
  printf("SHC Measure AGND  Code is %d \n", ADC->ADCRESULT[4].all);
  printf("SHC Measure VDD33 Code is %d \n", ADC->ADCRESULT[5].all);

  adc_sha_offset = ADC->ADCRESULT[0].all;
  adc_sha_gain = REF3V3_CODE / ( ADC->ADCRESULT[1].all - ADC->ADCRESULT[0].all );

  adc_shb_offset = ADC->ADCRESULT[2].all;
  adc_shb_gain = REF3V3_CODE / ( ADC->ADCRESULT[3].all - ADC->ADCRESULT[2].all );

  adc_shc_offset = ADC->ADCRESULT[4].all;
  adc_shc_gain = REF3V3_CODE / ( ADC->ADCRESULT[5].all - ADC->ADCRESULT[4].all );

  ADC->ADCOFFSETA.all = adc_sha_offset;
  ADC->ADCOFFSETB.all = adc_shb_offset;
  ADC->ADCOFFSETC.all = adc_shc_offset;

  ADC->ADCGAINA.all = adc_sha_gain;
  ADC->ADCGAINB.all = adc_shb_gain;
  ADC->ADCGAINC.all = adc_shc_gain;

  printf("ADC SHA Offset: %d \n", adc_sha_offset);
  printf("ADC SHA Gain:   %d \n", adc_sha_gain);
  printf("ADC SHB Offset: %d \n", adc_shb_offset);
  printf("ADC SHB Gain:   %d \n", adc_shb_gain);
  printf("ADC SHC Offset: %d \n", adc_shc_offset);
  printf("ADC SHC Gain:   %d \n", adc_shc_gain);

  printf("\n************** ADC Calibration Test End ******************\n");	

  if(adc_sha_offset > 80 || adc_sha_offset < -80 || adc_sha_gain > 34406 || adc_sha_gain < 31130 ||
     adc_shb_offset > 80 || adc_shb_offset < -80 || adc_shb_gain > 34406 || adc_shb_gain < 31130 ||
     adc_shc_offset > 80 || adc_shc_offset < -80 || adc_shc_gain > 34406 || adc_shc_gain < 31130)
  {
    printf("************** ADC Calibration SUCCESS **************\n");
    return ERROR;
  }
  else
  {
    printf("************** ADC Calibration FAIL **************\n");
    return SUCCESS;
  }
}
