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

#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

#define               REF3V3_CODE            242221056        /* Ideal code for 3.3V input related to +-3.657143V range. 7392(ideal_code)*2^15 */
#define               REF1V2_CODE            88080384         /* Ideal code for 1.2V input related to +-3.657143V range. 2688(ideal_code)*2^15 */

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] */
int32_t               adc_sha_result         = 0;
int32_t               adc_shb_result         = 0;
int32_t               adc_shc_result         = 0;


/*************************************************************************************************************************
*
* @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();

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

    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;     // positive 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 conversion 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;     // positive 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;     // positive 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;     // positive 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;     // positive 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;     // positive 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_result = ADC->ADCRESULT[0].all;
    adc_sha_gain = REF3V3_CODE / (ADC->ADCRESULT[1].all - adc_sha_result);

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

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

    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("\n************** ADC Calibration Test ERROR ******************\n");
        return ERROR;
    }
    else
    {
        printf("\n************** ADC Calibration Test PASS ******************\n");
        return SUCCESS;
    }
}
