/**************************************************************************//**
 * @file     main.c
 * @brief    Main program body
 * @version  V4.0.1
 * @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 "spd1188.h"
#include <stdio.h>

/* As descripted below, ADC result convert to voltage can calculate as the follow */
#define                     ValueToVoltage(x)         ((x * 3657) / 8192) /1000

int16_t                     i16VSP;
uint32_t                    u32PWMPeriod;
uint8_t                     u8PREDRIID                                    = 0;                 /* PRE-DRIVER mode ID */
uint8_t                     u8PREDRIDATA;                                                       /* Data read from PRE-DRIVER */
ErrorStatus                 eErrorState;
uint32_t                    u32SSPBaundrate                               = 1000000;           /* The baundrate of SSP communicating with PRE-DRIVER mode */
uint32_t                    u32Timeout                                    = 500;               /* The number of times try to get PRE-DRIVER mode ID */
uint8_t                     u8Count;
ErrorStatus                 eStatus                                       = ERROR;

 /*************************************************************************************************************************
 *
 * @brief      In GAUSS silicon, ADC2~7 is connected to the motor U/V/W PGA respectively. In this demo code, we sense the
 *             sensing resistor's voltage which was gained by motor PGA.
 *
 *             Key point:
 *                 PRE-DRIVER init include two step��
 *                     <1> Init the communication circuits(SSP circyits) with MCU, we call this step 'Init PRE-DRIVER module'.
 *                     <2> Init PRE-DRIVER socket itself, we call this step 'Power up PRE-DRIVER mode'.
 *
 *************************************************************************************************************************/


int main(void)
{
    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);
    
    /* Init PRE-DRIVER module(this step means 'Init PRE-DRIVER module') and get the ID */
    eErrorState = HV_Init(u32SSPBaundrate, &u8PREDRIID, u32Timeout);
    if(eErrorState == ERROR)
    {
        printf("Init PRE-DRIVER mode FAIL\n");
        return 0;
    }
    else
    {
        printf("Init PRE-DRIVER mode SUCCESS[ID:%d]\n",u8PREDRIID);
    }
    
    /* Read the value PGACTL had haven */
    eErrorState = HV_ReadReg(HV_REG_PGACTL, &u8PREDRIDATA);
    if(eErrorState == ERROR)
    {
        printf("Read PGACTL FAIL\n");
        return 0;
    }
    
    /* Enable U/V/W phase PGA and set GAIN value as 2X */
    eErrorState = HV_WriteReg(HV_REG_PGACTL, (u8PREDRIDATA & (~0xf7)) | PGACTL_ALL_UEN_ENABLE
                                                                      | PGACTL_ALL_VEN_ENABLE
                                                                      | PGACTL_ALL_WEN_ENABLE
                                                                      | PGACTL_ALL_GAIN_2X);
    if(eErrorState == ERROR)
    {
        printf("Enbale motor PGA and set GAIN value FAIL\n");
        return ERROR;
    }

    /* PDRVCTL register can only be writable when CTLKEY=0x99 */
    eErrorState = HV_WriteReg(HV_REG_CTLKEY, CTLKEY_ALL_KEY_BUCKEN);
    if(eErrorState == ERROR)
    {
        printf("Write CTLKEY register FAIL\n");
        return 0;
    }

    /* Power up PRE-DRIVER mode(this step means 'Power up PRE-DRIVER mode') */
    eErrorState = HV_WriteReg(HV_REG_PDRVCTL, PDRVCTL_ALL_EN_ENABLE);
    if(eErrorState == ERROR)
    {
        printf("Power up PRE-DRIVER FAIL\n");
        return 0;
    }
    
    /* Delay 100us to wait for the VDDG LDO ready */
    Delay_Us(100);
    
    /* Wait for PRE-DRIVER mode become enable */
    u8Count = 0;
    do{
          eErrorState = HV_ReadReg(HV_REG_GLBSTS0, &u8PREDRIDATA);
          if(eErrorState == ERROR)
          {
              printf("PRE-DRIVER enable FAIL[%02x]\n",u8PREDRIDATA);
              return 0;
          }
          
          u8Count++;
          
          if(u8Count >= 10)
          {
              printf("PRE-DRIVER enable timeout\n");
              return 0;
          }
    }while(((u8PREDRIDATA & GLBSTS0_ALL_CPRDY_READY) == 0) && (u8Count < 10));
    
    /* additional delay after VDDG ready, for final power settling */
    Delay_Us(100);
    
    /* Enable G-INT for SOC0/1/2 */
    NVIC_EnableIRQ(ADC0_IRQn);
    NVIC_EnableIRQ(ADC1_IRQn);
    NVIC_EnableIRQ(ADC2_IRQn);
    
    /* ADC Init */
    eStatus = ADC_EasyInit2(ADC_SOC_0,ADC2_GPIO2,ADC3_GPIO3,ADCTRIG_Software);
    if (ERROR != eStatus)
    {
        printf("ADC_Init ERROR\n");
        return 1;
    }
    
    eStatus = ADC_EasyInit2(ADC_SOC_1,ADC4_GPIO4,ADC5_GPIO5,ADCTRIG_Software);
    if (ERROR != eStatus)
    {
        printf("ADC_Init ERROR\n");
        return 1;
    }
    
    eStatus = ADC_EasyInit2(ADC_SOC_2,ADC6_GPIO6,ADC7_GPIO7,ADCTRIG_Software);
    if (ERROR != eStatus)
    {
        printf("ADC_Init ERROR\n");
        return 1;
    }
    
    
    /* Enbale SOC1/2 can be triggered by signal come from ADC EOC(end of convert) INT */
    ADC_EnableIntTriggerSOC(ADC_SOC_1);
    ADC_EnableIntTriggerSOC(ADC_SOC_2);
    
    /* Set the trigger source of SOC1/2 as the EOC of SOC0 */
    ADC_SelectIntTriggerSOC(ADC_SOC_1, ADC_INT_0);
    ADC_SelectIntTriggerSOC(ADC_SOC_2, ADC_INT_0);

    while(1)
    { 
        /* Use software to trigger SOC0 to work */
        ADC_SoftwareTrigger(ADC_SOC_0);
        
        Delay_Ms(2000);
    }
}

void ADC0_IRQHandler(void)
{
    /* Result gotten from 'ADC_GetResult()' can be a negtive value or a positive value */ 
    i16VSP = ADC_GetResult(ADC_SOC_0);

    printf("ADC SOC0 Voltage = %2fV(data is %d)\n", (double)ValueToVoltage(i16VSP),i16VSP);

    /* Result gotten from 'ADC_GetTrimResult1()' is a positive value */
    i16VSP = ADC_GetTrimResult1(ADC_SOC_0);

    printf("ADC SOC0 Voltage = %2fV(Trim data is %d)\n", (double)ValueToVoltage(i16VSP),i16VSP);

    /* Clear SOC INT */
    ADC_ClearInt0();

    /* Clear SOC INT flag */
    ADC_ClearInt(ADC_SOC_0);

    i16VSP = -1;
}

void ADC1_IRQHandler(void)
{
    /* Result gotten from 'ADC_GetResult()' can be a negtive value or a positive value */
    i16VSP = ADC_GetResult(ADC_SOC_1);

    printf("ADC SOC1 Voltage = %2fV(data is %d)\n", (double)ValueToVoltage(i16VSP),i16VSP);

    /* Result gotten from 'ADC_GetTrimResult1()' is a positive value */
    i16VSP = ADC_GetTrimResult1(ADC_SOC_1);

    printf("ADC SOC1 Voltage = %2fV(Trim data is %d)\n", (double)ValueToVoltage(i16VSP),i16VSP);

    /* Clear SOC INT */
    ADC_ClearInt1();

    /* Clear SOC INT flag */
    ADC_ClearInt(ADC_SOC_1);

    i16VSP = -1;
}

void ADC2_IRQHandler(void)
{
    /* Result gotten from 'ADC_GetResult()' can be a negtive value or a positive value */
    i16VSP = ADC_GetResult(ADC_SOC_2);

    printf("ADC SOC2 Voltage = %2fV(data is %d)\n", (double)ValueToVoltage(i16VSP),i16VSP);

    /* Result gotten from 'ADC_GetTrimResult1()' is a positive value */
    i16VSP = ADC_GetTrimResult1(ADC_SOC_2);

    printf("ADC SOC2 Voltage = %2fV(trim data is %d)\n", (double)ValueToVoltage(i16VSP),i16VSP);

    /* Clear SOC INT */
    ADC_ClearInt2();

    /* Clear SOC INT flag */
    ADC_ClearInt(ADC_SOC_2);

    i16VSP = -1;
}
