/******************************************************************************
 * @file     main.c
 * @brief    Main program body
 * @version  V4.0.3
 * @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>
#include<math.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               PWM_BlankWIN_Size       100                                /* 100 TBCNT CLK */
#define               PWM_Blank_Offset        50                                 /* 50 TBCNT CLK */
#define               COMP_FilterWIN          300                                /* 300ns */
/* This macro is used to get the PWM period with a specified frequency */
#define               PWMPeriod(u32PWMFreqHz)             ((CLOCK_GetModuleClock(PWM_MODULE))/u32PWMFreqHz)/2;
#define               PWM_FREQ                            20000                  /* 20kHz PWM */

uint32_t            u32PWMPeriod;
uint32_t            u32Duty = 75;

void PWMX_Set_Digiter_Compare(PWM_REGS *PWMx)
{
    /* Set DCAH from COMP0H */
    PWM_EnableDCAHTripEvent(PWMx, DC_TRIP_COMP0H);

    PWM_SetRawDCAEVT1(PWMx, DCH_HIGH_DCL_X);

    /* Set the filtered event as the final DCAEVT1, and trigger TZ sb-model when DCH is high */
    PWM_SetDCAEVT1(PWMx, DCEVT_FILTERED);
    
    /*
     * 1.Configure DC event filter
     *
     * 2.Input is DCAEVT1, apply blank window with original polarity
     *
     * 3.Set the blank window position relative to TBCNT=0
     */
    PWM_SetDCFilter(PWMx, DCF_FROM_RAW_DCAEVT1, DCF_ALIGN_ON_ZERO);

    /* Set blank window size as 100 TBCLK and offset as 50 TBCLK */
    PWM_SetDCFilterBlankWindow(PWMx, PWM_BlankWIN_Size, PWM_Blank_Offset);
    
    /* Enable PWM DC filter blank function */
    PWM_EnableDCFilterBlank(PWMx);

    PWM_SetCBCTripEvent(PWMx, TRIP_EVENT_DCAEVT, TRIP_OUTPUT_LATCH);
}




/*************************************************************************************************************************
*
* @brief      In this case, we use two PWM to generate two waveform with 180 phase differ, and the two waveform are merged
*             to form one waveform which is used to charge a cap, when the voltage of the cap is over-flow then the target
*             voltage we set, then a trip-zone event will be triggered by the comparator, then PWM waveform will be trip-zone,
*             the voltage of the cap will became lower.
*
*
*             FIG 1:
*
*                                                        ----------------
*                                                       |   PWM0 module  |                    
*                                        |\             |   ----    ---  |                  
*                                ADC-----| \--------x---|--|    |  |   |-------PWM0A------------      
*                                        |  \       |   |  |DC  |  |TZ | |               |
*                                        |  /       |   |  |sub |--|sub| |               |
*                                DAC-----| /----x---|---|--|    |  |   | |               |
*                                        |/     |   |   |   ----    ---  |               |
*                                Comparator     |   |   |                |               |
*                                               |   |    ----------------                |
*                                               |   |                                    |
*                                               |   |                                    |
*                                               |   |                                    |
*                                               |   |                                    |
*                                               |   |                                    |
*                                               |   |                                    |
*                                               |   |    ----------------                |
*                                               |   |   |   PWM1 module  |               |
*                                               |   |   |   ----    ---  |               |
*                                               |   x---|--|    |  |   |-------PWM1A-----x     
*                                               |       |  |DC  |  |TZ | |
*                                               |       |  |sub |--|sub| |
*                                               x-------|--|    |  |   | |
*                                                       |   ----    ---  |
*                                                       |                |
*                                                        ----------------
*
*
*              The two waveform which phase is differ 180 with each other and output be merged to 
*              form the final waveform, just as showed in FIG 2.
*
*               FIG 2:
*                           __             __             __             __ 
*                          |  |           |  |           |  |           |  |
*                        __|  |___________|  |___________|  |___________|  |___________         PWM0A 
*                                  __             __             __             __
*                                 |  |           |  |           |  |           |  |
*                          _______|  |___________|  |___________|  |___________|  |___________  PWM1A 
*                        
*
*                           __     __      __     __      __     __      __      __
*                          |  |   |  |    |  |   |  |    |  |   |  |    |  |    |  |
*                        __|  |___|  |____|  |___|  |____|  |___|  |____|  |____|  |____       MERGE WAVEFORM
*
*              when the final waveform level is high, a cap is charged, and the voltage is became high, the higher voltage will
*              make comparator generate a signal to trigger PWM trip-zone, then we will trip-zone the PWM waveform to let the cap
*              discharge, and the voltage will become lower.
*
*************************************************************************************************************************/


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

    /* Select output of PWM0 respectively */
    GPIO_SetPinChannel(GPIO_18, GPIO18_PWM0A);

    /* Select output of PWM1 respectively */
    GPIO_SetPinChannel(GPIO_20, GPIO20_PWM1A);

    /* Init PWM on both channel A */
    PWM_SingleChannelInit(PWM0, PWM_CHA, PWM_FREQ);
    PWM_SingleChannelInit(PWM1, PWM_CHA, PWM_FREQ);

    /* Set PWMxA output duty waveform */
    u32PWMPeriod = PWMPeriod(PWM_FREQ);
    PWM_SetCMPA(PWM0, ((u32PWMPeriod * u32Duty) / 100));
    PWM_SetCMPA(PWM1, ((u32PWMPeriod * (100 - u32Duty)) / 100));

    PWM0->AQCTLA.all  =  AQCTLA_ALL_ZRO_SET_HIGH    /* set high when CNT=Zero */
                     | AQCTLA_ALL_CAU_SET_LOW;      /* set low when TBCNT=CMPA and TBCNT is counting up */

    PWM1->AQCTLA.all  =  AQCTLA_ALL_PRD_SET_HIGH    /* set high when TBCNT=TBPRD */
                         | AQCTLA_ALL_CAD_SET_LOW;  /* set low when TBCNT=CMPA and TBCNT is counting down */

    /* Use the SYNCO to Sync phase */
    PWM_SetSyncOutEvent(PWM0, TBCTL_BIT_SYNCOSEL_TBCNT_EQU_ZERO);
    PWM_SetSyncOutEvent(PWM1, TBCTL_BIT_SYNCOSEL_DISABLE);

    /* Enable PWM synchronization */
    PWM_EnableSync(PWM1);

    /* Set PWMx counting up after SYNC */
    PWM_SetCounterDirAfterSync(PWM1, COUNT_UP);

    /* Set the re-load value when SYNC signal happened */
    PWM_SetSyncReloadValue(PWM1, 0);

    /* Start counting */
    PWM_RunCounter(PWM0);
    PWM_RunCounter(PWM1);

    /*
     * As the title described, we suppose GPIO8(ADC8) can be used to sample the voltage
     * of current sampling resistor in the BLDC circuit. so, we need to set the GPIOs as ADCs.
     */
    GPIO_SetPinChannel(GPIO_8, GPIO8_ADC8);
    COMP_Init(COMP_0_HI, COMP0_FROM_ADC8, 3000, COMP_FilterWIN);

    /* Set the DC sub-module */
    PWMX_Set_Digiter_Compare(PWM0);
    PWMX_Set_Digiter_Compare(PWM1);

    /* Set output to tri-state upon TZ trip event */
    PWM_SetCHAOutputWhenTrip(PWM0, TZU_TRIP_AS_LOW |
                             TZD_TRIP_DO_NOTHING |
                             DCEVT0U_TRIP_DO_NOTHING |
                             DCEVT0D_TRIP_DO_NOTHING |
                             DCEVT1U_TRIP_DO_NOTHING |
                             DCEVT1D_TRIP_DO_NOTHING);

    PWM_SetCHAOutputWhenTrip(PWM1, TZU_TRIP_DO_NOTHING |
                             TZD_TRIP_AS_LOW |
                             DCEVT0U_TRIP_DO_NOTHING |
                             DCEVT0D_TRIP_DO_NOTHING |
                             DCEVT1U_TRIP_DO_NOTHING |
                             DCEVT1D_TRIP_DO_NOTHING);

    NVIC_EnableIRQ(PWM0TZ_IRQn);
    NVIC_EnableIRQ(PWM1TZ_IRQn);
    
    PWM_EnableDCAEVT1TripInt(PWM0);
    PWM_EnableDCAEVT1TripInt(PWM1);

    while (1)
    {

    }
}

void PWM0TZ_IRQHandler(void)
{
    uint32_t u32TZStatus = PWM0->TZSTS.all;

    if (u32TZStatus & TZSTS_ALL_DCAEVT1_OCCUR)
    {
        printf("PWM0 DCAEVT1_OCCUR occurred\n");

        PWM0->TZSTSCLR.bit.DCAEVT1 = 1;
    }

    PWM_ClearTripGlobalInt(PWM0);
}

void PWM1TZ_IRQHandler(void)
{
    uint32_t u32TZStatus = PWM1->TZSTS.all;

    if (u32TZStatus & TZSTS_ALL_DCAEVT1_OCCUR)
    {
        printf("PWM1 DCAEVT1_OCCUR occurred\n");

        PWM1->TZSTSCLR.bit.DCAEVT1 = 1;
    }

    PWM_ClearTripGlobalInt(PWM1);
}



