/*******************************************************************************
 * the includes
 ******************************************************************************/
#include "hwctrl.h"
#include "canuser.h"

/*******************************************************************************
 * the defines
 ******************************************************************************/
 
 
 /*******************************************************************************
 * the typedefs
 ******************************************************************************/
 
 
 /*******************************************************************************
 * the globals
 ******************************************************************************/
 extern McuType mcu;
 uint32_t                     gCpuClockFrequency       = 0;
 uint32_t              adcResult[8];
 uint8_t PowerMode = 0;
 /*******************************************************************************
 * the const
 ******************************************************************************/
 /*! \brief The trgmux in out mappings table for trgmux configure
 */
const TrgMuxDrv_InOutMappingType c_trgmuxInOutMappings[] = {
    {TRGMUXDRV_TRIGSOURCE_SIM_SW_TRIG, TRGMUXDRV_TARGETMODULE_PDB0_TRG_IN, false}, /* Use SIM_SW_TRIG trigger PDB0 */
};
const uint16_t c_numOfTrgmuxInOutMappings = sizeof(c_trgmuxInOutMappings) / sizeof(TrgMuxDrv_InOutMappingType);
 
 
 /*******************************************************************************
 * the functions
 ******************************************************************************/
static void hw_clock_init(void);
static void GPIO_init(void);
static void AD_Init(void);

static void Watchdog_Init(void);


void hw_init(void)
{
    /* Initialize all MCU drivers: flash drv included */
    Mcu_Init(&mcu);

    WdgDrv_Disable(&mcu.wdgDrv);

    //初始化时钟
    hw_clock_init();


    /* get CAN controller default configuration */
    FlexCanBoot_Init();

    AD_Init();

    GPIO_init();

    WdgDrv_Refresh(&mcu.wdgDrv);
    Watchdog_Init();
}

static void hw_clock_init(void)
{
    /* Setup the clock */
    ClockDrv_ModuleClkConfigType clockConfig;

    /* Setup the Pll div2 clock */
    clockConfig.gating = true;
    clockConfig.source = CLOCKDRV_PLL;
    clockConfig.div    = 1;
    ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PLL_DIV, &clockConfig);

    /* Enable the clock for all port peripheral */
    clockConfig.gating = true;
    clockConfig.div    = 1;
    ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTA, &clockConfig);
    ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTB, &clockConfig);
    ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTC, &clockConfig);
    ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTD, &clockConfig);
    ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PORTE, &clockConfig);

    /* Enable the clock for ADC */
    clockConfig.gating = true;
    clockConfig.source = CLOCKDRV_PLL;
    clockConfig.div    = 4;
    ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_ADC, &clockConfig);

    /* Enable the clock for PDB0 */
    clockConfig.gating = true;
    ClockDrv_ConfigureClock(&mcu.clockDrv, CLOCKDRV_PDB, &clockConfig);


    /* Set system tick clock, 1ms event */
    ClockDrv_GetFreq(&mcu.clockDrv, CLOCKDRV_SYS, &gCpuClockFrequency);
    SysTick_Config(gCpuClockFrequency / 1000u);

    IrqDrv_EnableIrq(SysTick_IRQn);

    
}

static void GPIO_init(void)
{
    PinsDrv_SetMuxModeSel(&mcu.ptd, 0, PINSDRV_MUX_AS_GPIO);
    PinsDrv_SetPinDirection(&mcu.ptd, 0, 0);
    PinsDrv_SetMuxModeSel(&mcu.ptd, 1, PINSDRV_MUX_AS_GPIO);
    PinsDrv_SetPinDirection(&mcu.ptd, 1, 0);
    PinsDrv_SetMuxModeSel(&mcu.ptd, 2, PINSDRV_MUX_AS_GPIO);
    PinsDrv_SetPinDirection(&mcu.ptd, 2, 0);
    PinsDrv_SetMuxModeSel(&mcu.ptd, 3, PINSDRV_MUX_AS_GPIO);
    PinsDrv_SetPinDirection(&mcu.ptd, 3, 0);
    PinsDrv_SetMuxModeSel(&mcu.ptd, 5, PINSDRV_MUX_AS_GPIO);
    PinsDrv_SetPinDirection(&mcu.ptd, 5, 0);

    PinsDrv_SetMuxModeSel(&mcu.ptc, 1, PINSDRV_MUX_AS_GPIO);
    PinsDrv_SetPinDirection(&mcu.ptc, 1, 0);
    PinsDrv_SetMuxModeSel(&mcu.ptc, 16, PINSDRV_MUX_AS_GPIO);
    PinsDrv_SetPinDirection(&mcu.ptc, 16, 0);
    PinsDrv_SetMuxModeSel(&mcu.ptc, 15, PINSDRV_MUX_AS_GPIO);
    PinsDrv_SetPinDirection(&mcu.ptc, 15, 0);

    //PinsDrv_SetPortInputDisable(&mcu.ptd,0);
}


uint8_t getKeyIO(KEYID_t keyid)
{
    switch (keyid)
    {
    case KEY_KB_F:
        return PinsDrv_ReadPin(&mcu.ptd, 2) == 0 ? 1:0;
    case KEY_KB_R:
        return PinsDrv_ReadPin(&mcu.ptd, 3) == 0 ? 1:0;
    case KEY_HG_F:
        return PinsDrv_ReadPin(&mcu.ptd, 1) == 0 ? 1:0;
    case KEY_HG_R:
        return PinsDrv_ReadPin(&mcu.ptd, 0) == 0 ? 1:0;

    case KEY_TT_U:
        return PinsDrv_ReadPin(&mcu.ptd, 5) == 0 ? 1:0;
    case KEY_TT_D:
        return PinsDrv_ReadPin(&mcu.ptc, 1) == 0 ? 1:0;

    case KEY_ZERO_ON:
        return PinsDrv_ReadPin(&mcu.ptc, 15) == 0 ? 1:0;
    case KEY_ZERO_OFF:
        return PinsDrv_ReadPin(&mcu.ptc, 16) == 0 ? 1:0;
    default:
        return 0;
    }
}

static void AD_Init(void)
{
    /* TRGMUX */
    TrgMuxDrv_ConfigType trgmuxConfig;
    trgmuxConfig.numOfInOutMappings = c_numOfTrgmuxInOutMappings;
    trgmuxConfig.inOutMapping       = c_trgmuxInOutMappings;
    TrgMuxDrv_Configure(&mcu.trgMuxDrv, &trgmuxConfig);
    /* Configure ADC module */
    AdcDrv_ConfigType adcCfg;
    AdcDrv_GetDefaultConfig(&adcCfg);
    adcCfg.conversionMode   = ADCDRV_CONVERSION_12BIT; /* Selects the ADC resolution to 12-bit conversion */
    adcCfg.avgEnable        = true;                    /* Enable hardware average function */
    adcCfg.avgSamplesSel    = ADCDRV_AVERAGE_32;       /* Select 32 samples average */
    adcCfg.continuousMode   = ADCDRV_ONESHOT;          /* Select one-shot mode */
    adcCfg.chnCfg[0].chnSel = ADCDRV_INCHN_EXT10;
    adcCfg.chnCfg[1].chnSel = ADCDRV_INCHN_EXT11;

    AdcDrv_Configure(&mcu.adcDrv, &adcCfg);

    uint32_t pdbFreq;
    ClockDrv_GetFreq(&mcu.clockDrv, CLOCKDRV_PDB, &pdbFreq);

    PdbDrv_ConfigType pdbCfg;
    PdbDrv_GetDefaultConfig(&pdbCfg);
    pdbCfg.ldmode               = PDBDRV_LDMOD_LOAD_VAL_IMMEDIATELY; /* The internal registers are loaded with the values from their buffers, immediately after 1 is written to LDOK */
    pdbCfg.trgInSel             = PDBDRV_TRGSEL_TRGGER_IN_0;         /* Use hardware trigger source */
    pdbCfg.cMode                = PDBDRV_CONT_CONTINUOUS;            /* PDB operation in Continuous mode */
    pdbCfg.prescalerFactor      = PDBDRV_PRESCALER_128MULT;          /* Counting uses the peripheral clock divided by MULT (the multiplication factor) */
    pdbCfg.mult                 = PDBDRV_MULT_FACTOR_40;             /* Multiplication factor is 40 */
    pdbCfg.preTrgCfg.mode[0][0] = PDBDRV_PRETRG_DELAY_MODE;          /* The first channel start with delay operation */
    pdbCfg.preTrgCfg.mode[0][1] = PDBDRV_PRETRG_BB_MODE;             /* PDB channel[0][1-7] with Back-to-Back operation*/

    pdbCfg.dlyCfg.modCnt        = 1*pdbFreq / 128 / 40 / 200;              /* Periodic triggering PDB in 5ms*/
    pdbCfg.dlyCfg.dlyCnt[0][0]  = 0;                                 /* first channel don't need delay time*/
    PdbDrv_Configure(&mcu.pdbDrv, &pdbCfg);

    PdbDrv_EnablePdb(&mcu.pdbDrv); /* Enable PDB0 */

    TrgMuxDrv_GenSWTrigger(&mcu.trgMuxDrv, 100); /* Trigger PDB0 */
}

void AD_Task(void)//5ms
{
    static uint16_t  power_cnt;
    adcResult[0] = AdcDrv_GetRn(&mcu.adcDrv, 0);
    adcResult[1] = AdcDrv_GetRn(&mcu.adcDrv, 1);
    uint16_t batvol = getBatVoltage();
    switch (PowerMode)
    {
    case 0:
        if (batvol > 16500)
        {
            power_cnt++;
            if(power_cnt > 800)
            {
                power_cnt = 0;
                PowerMode = 1;
            }
        }
        else if (batvol < 8500)
        {
            power_cnt++;
            if(power_cnt > 800)
            {
                power_cnt = 0;
                PowerMode = 2;
            }
        }
        else
        {
            power_cnt = 0;
        }
        break;
    case 1:
        if (batvol < 16000)
        {
            power_cnt++;
            if(power_cnt > 800)
            {
                power_cnt = 0;
                PowerMode = 0;
            }
        }
        else
        {
            power_cnt = 0;
        }
        break;
    case 2:
        if (batvol > 9000)
        {
            power_cnt++;
            if(power_cnt > 800)
            {
                power_cnt = 0;
                PowerMode = 0;
            }
        }
        else
        {
            power_cnt = 0;
        }
        break;
    default:
        break;
    }
}

uint16_t getBatVoltage(void)
{
    uint32_t temp;
    temp = adcResult[0];
    temp *= 55000;
    temp >>= 12;
    temp += 700;
    return temp;
}

uint16_t getACCVoltage(void)
{
    uint32_t temp;
    temp = adcResult[1];
    temp *= 55000;
    temp >>= 12;
    temp += 700;
    return temp;
}

uint8_t getPowerMode(void)
{
    return PowerMode;
}

static void Watchdog_Init(void)
{
    /* Initialize WDG drivers */
    WdgDrv_ConfigureType wdgConfigParams;
    WdgDrv_GetDefaultConfig(&wdgConfigParams);
    wdgConfigParams.clkSource       = WDGDRV_CLK_SRC_LPO128K;
    wdgConfigParams.winEnable       = false;
    wdgConfigParams.prescalerEnable = false;
    wdgConfigParams.enable          = true;
    wdgConfigParams.intEnable       = false;
    wdgConfigParams.updateEnable    = true;
    wdgConfigParams.stopModeEnable  = false;
    wdgConfigParams.timeoutValue    = 12800;//100ms
    wdgConfigParams.windowValue     = 1000;
    WdgDrv_Configure(&mcu.wdgDrv, &wdgConfigParams);
}