#include "driverlib.h"
#include "device.h"
#include "GATEDRIVER.h"
#include "CANSetup.h"
#include "Analog.h"
#include "Temperature.h"
#include "Current.h"
#include "Voltage.h"
#include <math.h>
#include <stdint.h>

#define EPWM_CMP_UP           1U
#define EPWM_CMP_DOWN         0U
#define EPWM6_TIMER_TBPRD  2000U
#define EPWM6_MAX_CMPA     1950U
#define EPWM6_MIN_CMPA       50U
#define PI 3.141592654f

typedef struct
{
    uint32_t epwmModule;
    uint16_t epwmPeriod;
    float epwmPwmPhase;
    uint16_t epwmDeadTime;
    float epwmRadian;
} epwmInformation;

typedef struct
{
    uint32_t epwmModule;
    uint16_t epwmCompADirection;
    uint16_t epwmTimerIntCount;
    uint16_t epwmMaxCompA;
    uint16_t epwmMinCompA;
} LEDepwmInformation;

epwmInformation epwm1Info;
epwmInformation epwm2Info;
epwmInformation epwm3Info;
LEDepwmInformation epwmLEDInfo;

void initGPIO(void);

void TestLEDS(void);
void enableNeg15V(void);
void enablePos15V(void);
void disableNeg15V(void);
void disablePos15V(void);
void TestLEDPulse(void);

void initEPWM1(void);
void initEPWM2(void);
void initEPWM3(void);
void initCaseLEDPWM(void);

__interrupt void epwm1ISR(void);
__interrupt void epwm6ISR(void);
__interrupt void epwm1TZISR(void);
__interrupt void epwm2TZISR(void);
__interrupt void epwm3TZISR(void);

void updatePWM(epwmInformation *epwmInfo);
void updateLED(LEDepwmInformation *epwmInfo);

void CANPacketEncode(uint16_t *PacketData);
void CANPacketDecode(uint16_t *PacketData);

__interrupt void ecap1ISR(void);
__interrupt void ecap2ISR(void);
__interrupt void ecap3ISR(void);

#define capCountsize 10

volatile uint16_t cap1Count[capCountsize] = {0};
volatile uint16_t cap1index = 0;
volatile uint16_t cap2Count[capCountsize] = {0};
volatile uint16_t cap2index = 0;
volatile uint16_t cap3Count[capCountsize] = {0};
volatile uint16_t cap3index = 0;

uint16_t FS = 0;
uint16_t FF = 0;
uint16_t ID = 0;
uint16_t TD = 0;
uint16_t PSEN1 = 0;
uint16_t PSEN2 = 0;
uint16_t PSEN3 = 0;
uint16_t LEN1 = 0;
uint16_t LEN2 = 0;
uint16_t LEN3 = 0;
uint16_t FAULT1 = 0;
uint16_t FAULT2 = 0;
uint16_t FAULT3 = 0;
uint16_t RESET = 0;
uint16_t FUND_FREQ = 0;
uint16_t EPwm_TBPRD = 0;
float MF = 0.0f;
uint16_t SWITCHING_FREQ = 0;
uint16_t DEAD_TIME = 0;

float Sine = 0.0f;
float Ts = 0.0f;
float radian = 0.0f;

// DEBUG
volatile uint32_t dbgMainLoopCount = 0;
volatile uint32_t dbgCanRxCount = 0;
volatile uint32_t dbgEpwm1IsrCount = 0;
volatile uint32_t dbgEcap1IsrCount = 0;
volatile uint32_t dbgEcap2IsrCount = 0;
volatile uint32_t dbgEcap3IsrCount = 0;

volatile uint16_t dbgRx0 = 0;
volatile uint16_t dbgRx1 = 0;
volatile uint16_t dbgRx2 = 0;
volatile uint16_t dbgRx3 = 0;
volatile uint16_t dbgRx4 = 0;
volatile uint16_t dbgRx5 = 0;
volatile uint16_t dbgRx6 = 0;
volatile uint16_t dbgRx7 = 0;

volatile uint16_t dbgTx0 = 0;
volatile uint16_t dbgTx1 = 0;
volatile uint16_t dbgTx2 = 0;
volatile uint16_t dbgTx3 = 0;
volatile uint16_t dbgTx4 = 0;
volatile uint16_t dbgTx5 = 0;
volatile uint16_t dbgTx6 = 0;
volatile uint16_t dbgTx7 = 0;

volatile float dbgMF = 0.0f;
volatile uint16_t dbgID = 0;
volatile uint16_t dbgFF = 0;
volatile uint16_t dbgFS = 0;
volatile uint16_t dbgTD = 0;
volatile float dbgSine = 0.0f;
volatile float dbgRadian = 0.0f;

volatile uint16_t dbgCap1 = 0;
volatile uint16_t dbgCap2 = 0;
volatile uint16_t dbgCap3 = 0;

volatile uint16_t dbgCanStarted = 0;
volatile uint16_t dbgFirstTxReleased = 0;

// NEU: Trip-Zone / Fault Debug
volatile uint16_t dbgTZ1 = 0;
volatile uint16_t dbgTZ2 = 0;
volatile uint16_t dbgTZ3 = 0;
volatile uint16_t dbgGlobalFault = 0;

void main(void)
{
    uint16_t i;
    uint16_t txMsgData[8];
    uint16_t rxMsgData[8];
    uint16_t TemperatureMsgData[8];
    uint16_t CurrentMsgData[8];
    uint16_t VoltageMsgData[8];
    uint16_t firstTxDelayDone = 0U;

    Device_init();
    Device_initGPIO();

    Interrupt_initModule();
    Interrupt_initVectorTable();

    Interrupt_register(INT_EPWM1, &epwm1ISR);
    Interrupt_register(INT_EPWM6, &epwm6ISR);
    Interrupt_register(INT_EPWM1_TZ, &epwm1TZISR);
    Interrupt_register(INT_EPWM2_TZ, &epwm2TZISR);
    Interrupt_register(INT_EPWM3_TZ, &epwm3TZISR);

    Interrupt_register(INT_ECAP1, &ecap1ISR);
    Interrupt_register(INT_ECAP2, &ecap2ISR);
    Interrupt_register(INT_ECAP3, &ecap3ISR);

    initGateDriverGPIO();
    GD_ALL_PSDisable();
    XM3_initCANGPIO();
    initGPIO();

    disableNeg15V();
    disablePos15V();

    SWITCHING_FREQ = 10000U;
    DEAD_TIME = 100U;
    FUND_FREQ = 200U;
    MF = 0.20f;
    radian = 0.0f;
    Ts = 2.0f * PI / ((float)SWITCHING_FREQ / (float)FUND_FREQ);

    LEN1 = 1U;
    LEN2 = 1U;
    LEN3 = 1U;
    PSEN1 = 1U;
    PSEN2 = 1U;
    PSEN3 = 1U;
    FAULT1 = 0U;
    FAULT2 = 0U;
    FAULT3 = 0U;
    RESET = 0U;

    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    initEPWM1();
    initEPWM2();
    initEPWM3();
    initCaseLEDPWM();

    initECAP1();
    initECAP2();
    initECAP3();

    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    Interrupt_enable(INT_EPWM1);
    Interrupt_enable(INT_EPWM6);
    Interrupt_enable(INT_ECAP1);
    Interrupt_enable(INT_ECAP2);
    Interrupt_enable(INT_ECAP3);

    EINT;
    ERTM;

    GD_ALL_PSEnable();
    DEVICE_DELAY_US(200);
    GD_ALL_Reset();

    initADCs();
    initADCSOCs();

    enableNeg15V();
    enablePos15V();

    DEVICE_DELAY_US(50000);

    XM3_initCAN();
    dbgCanStarted = 1U;

    DEVICE_DELAY_US(100000);

    for(i = 0; i < 8U; i++)
    {
        txMsgData[i] = 0U;
        rxMsgData[i] = 0U;
        TemperatureMsgData[i] = 0U;
        CurrentMsgData[i] = 0U;
        VoltageMsgData[i] = 0U;
    }

    while(1)
    {
        dbgMainLoopCount++;

        NOP;
        DEVICE_DELAY_US(100000);

        if(firstTxDelayDone == 0U)
        {
            DEVICE_DELAY_US(100000);
            firstTxDelayDone = 1U;
            dbgFirstTxReleased = 1U;
        }

        dbgGlobalFault = GD_Global_getFault();

        if(CAN_readMessage(CANA_BASE, 2, rxMsgData))
        {
            dbgCanRxCount++;

            dbgRx0 = rxMsgData[0];
            dbgRx1 = rxMsgData[1];
            dbgRx2 = rxMsgData[2];
            dbgRx3 = rxMsgData[3];
            dbgRx4 = rxMsgData[4];
            dbgRx5 = rxMsgData[5];
            dbgRx6 = rxMsgData[6];
            dbgRx7 = rxMsgData[7];

            GPIO_togglePin(52);

            CANPacketDecode(rxMsgData);

            dbgMF = MF;
            dbgID = ID;
            dbgFF = FF;
            dbgFS = FS;
            dbgTD = TD;

            CANPacketEncode(txMsgData);

            dbgTx0 = txMsgData[0];
            dbgTx1 = txMsgData[1];
            dbgTx2 = txMsgData[2];
            dbgTx3 = txMsgData[3];
            dbgTx4 = txMsgData[4];
            dbgTx5 = txMsgData[5];
            dbgTx6 = txMsgData[6];
            dbgTx7 = txMsgData[7];

            CAN_sendMessage(CANA_BASE, 1, 8U, txMsgData);
        }

        if(GD_Global_getFault())
        {
            GD_ALL_LogicDisable();
            LEN1 = 0U;
            LEN2 = 0U;
            LEN3 = 0U;

            FAULT1 = GD_A_getFault();
            FAULT2 = GD_B_getFault();
            FAULT3 = GD_C_getFault();
        }

        CANPacketEncode(txMsgData);
        CAN_sendMessage(CANA_BASE, 1, 8U, txMsgData);

        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER0);
        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER1);
        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER2);
        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER3);
        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER4);
        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER5);
        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER6);

        ADC_forceSOC(ADCB_BASE, ADC_SOC_NUMBER0);
        ADC_forceSOC(ADCB_BASE, ADC_SOC_NUMBER1);

        ADC_forceSOC(ADCC_BASE, ADC_SOC_NUMBER0);
        ADC_forceSOC(ADCC_BASE, ADC_SOC_NUMBER1);
        ADC_forceSOC(ADCC_BASE, ADC_SOC_NUMBER2);

        while(ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1) == false) {}
        ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);

        while(ADC_getInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1) == false) {}
        ADC_clearInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1);

        while(ADC_getInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1) == false) {}
        ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1);

        TemperatureMsgData[0] = (uint16_t)getECAPTempA() >> 8;
        TemperatureMsgData[1] = (uint16_t)getECAPTempA();

        TemperatureMsgData[2] = (uint16_t)getECAPTempB() >> 8;
        TemperatureMsgData[3] = (uint16_t)getECAPTempB();

        TemperatureMsgData[4] = (uint16_t)getECAPTempC() >> 8;
        TemperatureMsgData[5] = (uint16_t)getECAPTempC();

        TemperatureMsgData[6] = (uint16_t)getCaseTemp() >> 8;
        TemperatureMsgData[7] = (uint16_t)getCaseTemp();

        CurrentMsgData[0] = (int16_t)getCurrentA() >> 8;
        CurrentMsgData[1] = (int16_t)getCurrentA();

        CurrentMsgData[2] = (int16_t)getCurrentB() >> 8;
        CurrentMsgData[3] = (int16_t)getCurrentB();

        CurrentMsgData[4] = (int16_t)getCurrentC() >> 8;
        CurrentMsgData[5] = (int16_t)getCurrentC();

        CurrentMsgData[6] = (int16_t)getCurrentEXT() >> 8;
        CurrentMsgData[7] = (int16_t)getCurrentEXT();

        VoltageMsgData[0] = (int16_t)getVoltageA() >> 8;
        VoltageMsgData[1] = (int16_t)getVoltageA();

        VoltageMsgData[2] = (int16_t)getVoltageB() >> 8;
        VoltageMsgData[3] = (int16_t)getVoltageB();

        VoltageMsgData[4] = (int16_t)getVoltageC() >> 8;
        VoltageMsgData[5] = (int16_t)getVoltageC();

        VoltageMsgData[6] = (int16_t)getVoltageDC() >> 8;
        VoltageMsgData[7] = (int16_t)getVoltageDC();

        CAN_sendMessage(CANA_BASE, 3, 8U, TemperatureMsgData);
        CAN_sendMessage(CANA_BASE, 4, 8U, CurrentMsgData);
        CAN_sendMessage(CANA_BASE, 5, 8U, VoltageMsgData);
    }
}

__interrupt void epwm1ISR(void)
{
    dbgEpwm1IsrCount++;

    updatePWM(&epwm1Info);
    updatePWM(&epwm2Info);
    updatePWM(&epwm3Info);

    dbgSine = Sine;
    dbgRadian = epwm1Info.epwmRadian;

    // NEU: Trip-Zone Status lesen
    dbgTZ1 = EPWM_getTripZoneFlagStatus(EPWM1_BASE);
    dbgTZ2 = EPWM_getTripZoneFlagStatus(EPWM2_BASE);
    dbgTZ3 = EPWM_getTripZoneFlagStatus(EPWM3_BASE);
    dbgGlobalFault = GD_Global_getFault();

    EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}

__interrupt void epwm1TZISR(void)
{
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2);
}

__interrupt void epwm2TZISR(void)
{
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2);
}

__interrupt void epwm3TZISR(void)
{
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2);
}

void initEPWM1(void)
{
    EPwm_TBPRD = (uint16_t)(100e6 / (float)SWITCHING_FREQ / 2.0f);

    EPWM_setEmulationMode(EPWM1_BASE, EPWM_EMULATION_FREE_RUN);
    EPWM_setTimeBasePeriod(EPWM1_BASE, EPwm_TBPRD);
    EPWM_setPhaseShift(EPWM1_BASE, 0U);
    EPWM_setTimeBaseCounter(EPWM1_BASE, 0U);
    EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);

    EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPwm_TBPRD / 2U);
    EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_disablePhaseShiftLoad(EPWM1_BASE);
    EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

    EPWM_setDeadBandControlShadowLoadMode(EPWM1_BASE, EPWM_DB_LOAD_ON_CNTR_ZERO);
    EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_FED, true);
    EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_RED, true);
    EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
    EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    EPWM_setRisingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA);
    EPWM_setFallingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA);
    EPWM_setRisingEdgeDelayCount(EPWM1_BASE, DEAD_TIME);
    EPWM_setFallingEdgeDelayCount(EPWM1_BASE, DEAD_TIME);
    EPWM_setDeadBandCounterClock(EPWM1_BASE, EPWM_DB_COUNTER_CLOCK_FULL_CYCLE);

    EPWM_enableTripZoneSignals(EPWM1_BASE, EPWM_TZ_SIGNAL_OSHT1);
    EPWM_setTripZoneAction(EPWM1_BASE, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);
    EPWM_setTripZoneAction(EPWM1_BASE, EPWM_TZ_ACTION_EVENT_TZB, EPWM_TZ_ACTION_LOW);
    EPWM_enableTripZoneInterrupt(EPWM1_BASE, EPWM_TZ_INTERRUPT_OST);

    EPWM_setInterruptSource(EPWM1_BASE, EPWM_INT_TBCTR_ZERO);
    EPWM_enableInterrupt(EPWM1_BASE);
    EPWM_setInterruptEventCount(EPWM1_BASE, 1U);

    epwm1Info.epwmModule = EPWM1_BASE;
    epwm1Info.epwmPeriod = EPwm_TBPRD;
    epwm1Info.epwmPwmPhase = 0.0f;
    epwm1Info.epwmDeadTime = DEAD_TIME;
    epwm1Info.epwmRadian = 0.0f;
}

void initEPWM2(void)
{
    EPwm_TBPRD = (uint16_t)(100e6 / (float)SWITCHING_FREQ / 2.0f);

    EPWM_setEmulationMode(EPWM2_BASE, EPWM_EMULATION_FREE_RUN);
    EPWM_setTimeBasePeriod(EPWM2_BASE, EPwm_TBPRD);
    EPWM_setPhaseShift(EPWM2_BASE, 0U);
    EPWM_setTimeBaseCounter(EPWM2_BASE, 0U);
    EPWM_setSyncOutPulseMode(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);

    EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, EPwm_TBPRD / 2U);
    EPWM_setTimeBaseCounterMode(EPWM2_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_enablePhaseShiftLoad(EPWM2_BASE);
    EPWM_setClockPrescaler(EPWM2_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setCounterCompareShadowLoadMode(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

    EPWM_setDeadBandControlShadowLoadMode(EPWM2_BASE, EPWM_DB_LOAD_ON_CNTR_ZERO);
    EPWM_setDeadBandDelayMode(EPWM2_BASE, EPWM_DB_FED, true);
    EPWM_setDeadBandDelayMode(EPWM2_BASE, EPWM_DB_RED, true);
    EPWM_setDeadBandDelayPolarity(EPWM2_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
    EPWM_setDeadBandDelayPolarity(EPWM2_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    EPWM_setRisingEdgeDeadBandDelayInput(EPWM2_BASE, EPWM_DB_INPUT_EPWMA);
    EPWM_setFallingEdgeDeadBandDelayInput(EPWM2_BASE, EPWM_DB_INPUT_EPWMA);
    EPWM_setRisingEdgeDelayCount(EPWM2_BASE, DEAD_TIME);
    EPWM_setFallingEdgeDelayCount(EPWM2_BASE, DEAD_TIME);
    EPWM_setDeadBandCounterClock(EPWM2_BASE, EPWM_DB_COUNTER_CLOCK_FULL_CYCLE);

    EPWM_enableTripZoneSignals(EPWM2_BASE, EPWM_TZ_SIGNAL_OSHT1);
    EPWM_setTripZoneAction(EPWM2_BASE, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);
    EPWM_setTripZoneAction(EPWM2_BASE, EPWM_TZ_ACTION_EVENT_TZB, EPWM_TZ_ACTION_LOW);
    EPWM_enableTripZoneInterrupt(EPWM2_BASE, EPWM_TZ_INTERRUPT_OST);

    epwm2Info.epwmModule = EPWM2_BASE;
    epwm2Info.epwmPeriod = EPwm_TBPRD;
    epwm2Info.epwmPwmPhase = 0.0f;
    epwm2Info.epwmDeadTime = DEAD_TIME;
    epwm2Info.epwmRadian = 2.0f * PI / 3.0f;
}

void initEPWM3(void)
{
    EPwm_TBPRD = (uint16_t)(100e6 / (float)SWITCHING_FREQ / 2.0f);

    EPWM_setEmulationMode(EPWM3_BASE, EPWM_EMULATION_FREE_RUN);
    EPWM_setTimeBasePeriod(EPWM3_BASE, EPwm_TBPRD);
    EPWM_setPhaseShift(EPWM3_BASE, 0U);
    EPWM_setTimeBaseCounter(EPWM3_BASE, 0U);
    EPWM_setSyncOutPulseMode(EPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);

    EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_A, EPwm_TBPRD / 2U);
    EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_enablePhaseShiftLoad(EPWM3_BASE);
    EPWM_setClockPrescaler(EPWM3_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setCounterCompareShadowLoadMode(EPWM3_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

    EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

    EPWM_setDeadBandControlShadowLoadMode(EPWM3_BASE, EPWM_DB_LOAD_ON_CNTR_ZERO);
    EPWM_setDeadBandDelayMode(EPWM3_BASE, EPWM_DB_FED, true);
    EPWM_setDeadBandDelayMode(EPWM3_BASE, EPWM_DB_RED, true);
    EPWM_setDeadBandDelayPolarity(EPWM3_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
    EPWM_setDeadBandDelayPolarity(EPWM3_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    EPWM_setRisingEdgeDeadBandDelayInput(EPWM3_BASE, EPWM_DB_INPUT_EPWMA);
    EPWM_setFallingEdgeDeadBandDelayInput(EPWM3_BASE, EPWM_DB_INPUT_EPWMA);
    EPWM_setRisingEdgeDelayCount(EPWM3_BASE, DEAD_TIME);
    EPWM_setFallingEdgeDelayCount(EPWM3_BASE, DEAD_TIME);
    EPWM_setDeadBandCounterClock(EPWM3_BASE, EPWM_DB_COUNTER_CLOCK_FULL_CYCLE);

    EPWM_enableTripZoneSignals(EPWM3_BASE, EPWM_TZ_SIGNAL_OSHT1);
    EPWM_setTripZoneAction(EPWM3_BASE, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);
    EPWM_setTripZoneAction(EPWM3_BASE, EPWM_TZ_ACTION_EVENT_TZB, EPWM_TZ_ACTION_LOW);
    EPWM_enableTripZoneInterrupt(EPWM3_BASE, EPWM_TZ_INTERRUPT_OST);

    epwm3Info.epwmModule = EPWM3_BASE;
    epwm3Info.epwmPeriod = EPwm_TBPRD;
    epwm3Info.epwmPwmPhase = 0.0f;
    epwm3Info.epwmDeadTime = DEAD_TIME;
    epwm3Info.epwmRadian = 4.0f * PI / 3.0f;
}

void updatePWM(epwmInformation *epwmInfo)
{
    if(FUND_FREQ == 0U)
    {
        return;
    }

    if(SWITCHING_FREQ == 0U)
    {
        SWITCHING_FREQ = 10000U;
    }

    Ts = 2.0f * PI / ((float)SWITCHING_FREQ / (float)FUND_FREQ);
    EPwm_TBPRD = (uint16_t)(100e6 / (float)SWITCHING_FREQ / 2.0f);

    EPWM_setTimeBasePeriod(epwmInfo->epwmModule, EPwm_TBPRD);
    EPWM_setPhaseShift(epwmInfo->epwmModule, (uint16_t)(EPwm_TBPRD * epwmInfo->epwmPwmPhase));

    epwmInfo->epwmDeadTime = DEAD_TIME;
    EPWM_setRisingEdgeDelayCount(epwmInfo->epwmModule, epwmInfo->epwmDeadTime);
    EPWM_setFallingEdgeDelayCount(epwmInfo->epwmModule, epwmInfo->epwmDeadTime);

    Sine = ((MF * sinf(epwmInfo->epwmRadian)) + 1.0f) / 2.0f;
    epwmInfo->epwmRadian += Ts;

    if(epwmInfo->epwmRadian > (2.0f * PI))
    {
        epwmInfo->epwmRadian -= (2.0f * PI);
    }

    EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, (uint16_t)(Sine * EPwm_TBPRD));
}

void updateLED(LEDepwmInformation *epwmInfo)
{
    uint16_t compAValue;

    compAValue = EPWM_getCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A);

    if(epwmInfo->epwmTimerIntCount == 10U)
    {
        epwmInfo->epwmTimerIntCount = 0U;

        if(epwmInfo->epwmCompADirection == EPWM_CMP_UP)
        {
            if(compAValue < epwmInfo->epwmMaxCompA)
            {
                EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, (uint16_t)(compAValue + 1U));
            }
            else
            {
                epwmInfo->epwmCompADirection = EPWM_CMP_DOWN;
                EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, (uint16_t)(compAValue - 1U));
            }
        }
        else
        {
            if(compAValue == epwmInfo->epwmMinCompA)
            {
                epwmInfo->epwmCompADirection = EPWM_CMP_UP;
                EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, (uint16_t)(compAValue + 1U));
            }
            else
            {
                EPWM_setCounterCompareValue(epwmInfo->epwmModule, EPWM_COUNTER_COMPARE_A, (uint16_t)(compAValue - 1U));
            }
        }
    }
    else
    {
        epwmInfo->epwmTimerIntCount++;
    }
}

void CANPacketEncode(uint16_t *PacketData)
{
    FS = (uint16_t)(SWITCHING_FREQ / 1000U);
    ID = (uint16_t)(MF * 1000.0f);
    TD = (uint16_t)(DEAD_TIME * 10U);
    FF = FUND_FREQ;

    PacketData[0] = (uint16_t)FS;
    PacketData[1] = (uint16_t)(ID >> 2);
    PacketData[2] = (uint16_t)((ID << 6) | (TD >> 6));
    PacketData[3] = (uint16_t)((TD << 2) | (FF >> 8));
    PacketData[4] = (uint16_t)(FF);
    PacketData[5] = (uint16_t)((PSEN1 << 6) | (PSEN2 << 5) | (PSEN3 << 4) | (LEN1 << 2) | (LEN2 << 1) | LEN3);
    PacketData[6] = (uint16_t)((RESET << 7) | (FAULT1 << 6) | (FAULT2 << 5) | (FAULT3 << 4));
    PacketData[7] = 0U;
}

void CANPacketDecode(uint16_t *PacketData)
{
    FS = (PacketData[0]) & 0x00FFU;
    ID = ((PacketData[1] << 2) | (PacketData[2] >> 6)) & 0x03FFU;
    TD = (((PacketData[2] & 0x3FU) << 6) | (PacketData[3] >> 2)) & 0x0FFFU;
    FF = (((PacketData[3] & 0x03U) << 8) | PacketData[4]) & 0x03FFU;

    PSEN1 = (PacketData[5] & 0x40U) >> 6;
    PSEN2 = (PacketData[5] & 0x20U) >> 5;
    PSEN3 = (PacketData[5] & 0x10U) >> 4;
    LEN1  = (PacketData[5] & 0x04U) >> 2;
    LEN2  = (PacketData[5] & 0x02U) >> 1;
    LEN3  = PacketData[5] & 0x01U;

    FAULT1 = (PacketData[6] & 0x40U) >> 6;
    FAULT2 = (PacketData[6] & 0x20U) >> 5;
    FAULT3 = (PacketData[6] & 0x10U) >> 4;
    RESET  = (PacketData[6] & 0x80U) >> 7;

    SWITCHING_FREQ = (uint16_t)(FS * 1000U);
    if(SWITCHING_FREQ == 0U)
    {
        SWITCHING_FREQ = 10000U;
    }

    MF = (float)ID / 1000.0f;
    DEAD_TIME = (uint16_t)(TD / 10U);
    FUND_FREQ = FF;

    if(FUND_FREQ == 0U)
    {
        FUND_FREQ = 200U;
    }

    if(FUND_FREQ > 500U)
    {
        FUND_FREQ = 500U;
    }

    if(PSEN1 == 1U) { GD_A_PSEnable(); } else { GD_A_PSDisable(); }
    if(PSEN2 == 1U) { GD_B_PSEnable(); } else { GD_B_PSDisable(); }
    if(PSEN3 == 1U) { GD_C_PSEnable(); } else { GD_C_PSDisable(); }

    if(LEN1 == 1U) { GD_A_LogicEnable(); } else { GD_A_LogicDisable(); }
    if(LEN2 == 1U) { GD_B_LogicEnable(); } else { GD_B_LogicDisable(); }
    if(LEN3 == 1U) { GD_C_LogicEnable(); } else { GD_C_LogicDisable(); }

    if(RESET == 1U)
    {
        GD_ALL_Reset();

        EPWM_clearTripZoneFlag(EPWM1_BASE, (EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_OST));
        EPWM_clearTripZoneFlag(EPWM2_BASE, (EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_OST));
        EPWM_clearTripZoneFlag(EPWM3_BASE, (EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_OST));

        FAULT1 = 0U;
        FAULT2 = 0U;
        FAULT3 = 0U;
        RESET = 0U;
    }
}

__interrupt void epwm6ISR(void)
{
    updateLED(&epwmLEDInfo);
    EPWM_clearEventTriggerInterruptFlag(EPWM6_BASE);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}

__interrupt void ecap1ISR(void)
{
    dbgEcap1IsrCount++;
    cap1Count[cap1index] = (uint16_t)ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_2);
    dbgCap1 = cap1Count[cap1index];

    ECAP_clearInterrupt(ECAP1_BASE, ECAP_ISR_SOURCE_CAPTURE_EVENT_4);
    ECAP_clearGlobalInterrupt(ECAP1_BASE);
    ECAP_reArm(ECAP1_BASE);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP4);

    cap1index++;
    if(cap1index >= capCountsize) cap1index = 0U;
}

__interrupt void ecap2ISR(void)
{
    dbgEcap2IsrCount++;
    cap2Count[cap2index] = (uint16_t)ECAP_getEventTimeStamp(ECAP2_BASE, ECAP_EVENT_2);
    dbgCap2 = cap2Count[cap2index];

    ECAP_clearInterrupt(ECAP2_BASE, ECAP_ISR_SOURCE_CAPTURE_EVENT_4);
    ECAP_clearGlobalInterrupt(ECAP2_BASE);
    ECAP_reArm(ECAP2_BASE);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP4);

    cap2index++;
    if(cap2index >= capCountsize) cap2index = 0U;
}

__interrupt void ecap3ISR(void)
{
    dbgEcap3IsrCount++;
    cap3Count[cap3index] = (uint16_t)ECAP_getEventTimeStamp(ECAP3_BASE, ECAP_EVENT_2);
    dbgCap3 = cap3Count[cap3index];

    ECAP_clearInterrupt(ECAP3_BASE, ECAP_ISR_SOURCE_CAPTURE_EVENT_4);
    ECAP_clearGlobalInterrupt(ECAP3_BASE);
    ECAP_reArm(ECAP3_BASE);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP4);

    cap3index++;
    if(cap3index >= capCountsize) cap3index = 0U;
}

void TestLEDPulse()
{
    Interrupt_register(INT_EPWM6, &epwm6ISR);
    initCaseLEDPWM();
    Interrupt_enable(INT_EPWM6);
}

void initCaseLEDPWM()
{
    GPIO_setPadConfig(10, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_10_EPWM6A);

    EPWM_setEmulationMode(EPWM6_BASE, EPWM_EMULATION_FREE_RUN);
    EPWM_setTimeBasePeriod(EPWM6_BASE, EPWM6_TIMER_TBPRD);
    EPWM_setPhaseShift(EPWM6_BASE, 0U);
    EPWM_setTimeBaseCounter(EPWM6_BASE, 0U);

    EPWM_setCounterCompareValue(EPWM6_BASE, EPWM_COUNTER_COMPARE_A, 1000U);
    EPWM_setTimeBaseCounterMode(EPWM6_BASE, EPWM_COUNTER_MODE_UP);
    EPWM_disablePhaseShiftLoad(EPWM6_BASE);
    EPWM_setClockPrescaler(EPWM6_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setCounterCompareShadowLoadMode(EPWM6_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

    EPWM_setActionQualifierAction(EPWM6_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(EPWM6_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);

    EPWM_setInterruptSource(EPWM6_BASE, EPWM_INT_TBCTR_ZERO);
    EPWM_enableInterrupt(EPWM6_BASE);
    EPWM_setInterruptEventCount(EPWM6_BASE, 6U);

    epwmLEDInfo.epwmCompADirection = EPWM_CMP_UP;
    epwmLEDInfo.epwmTimerIntCount = 0U;
    epwmLEDInfo.epwmModule = EPWM6_BASE;
    epwmLEDInfo.epwmMaxCompA = EPWM6_MAX_CMPA;
    epwmLEDInfo.epwmMinCompA = EPWM6_MIN_CMPA;
}

void TestLEDS()
{
    GPIO_togglePin(10);
    GPIO_togglePin(31);
    GPIO_togglePin(34);
    GPIO_togglePin(41);
    GPIO_togglePin(52);
    GPIO_togglePin(65);
    DEVICE_DELAY_US(200000);
}

void enableNeg15V(void)
{
    GPIO_writePin(125, 0);
}

void enablePos15V(void)
{
    GPIO_writePin(124, 0);
}

void disableNeg15V(void)
{
    GPIO_writePin(125, 1);
}

void disablePos15V(void)
{
    GPIO_writePin(124, 1);
}

void initGPIO(void)
{
    GPIO_setPadConfig(10, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_10_EPWM6A);

    GPIO_setPadConfig(31, GPIO_PIN_TYPE_STD);
    GPIO_writePin(31, 0);
    GPIO_setPinConfig(GPIO_31_GPIO31);
    GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);

    GPIO_setPadConfig(34, GPIO_PIN_TYPE_STD);
    GPIO_writePin(34, 0);
    GPIO_setPinConfig(GPIO_34_GPIO34);
    GPIO_setDirectionMode(34, GPIO_DIR_MODE_OUT);

    GPIO_setPadConfig(41, GPIO_PIN_TYPE_STD);
    GPIO_writePin(41, 0);
    GPIO_setPinConfig(GPIO_41_GPIO41);
    GPIO_setDirectionMode(41, GPIO_DIR_MODE_OUT);

    GPIO_setPadConfig(52, GPIO_PIN_TYPE_STD);
    GPIO_writePin(52, 0);
    GPIO_setPinConfig(GPIO_52_GPIO52);
    GPIO_setDirectionMode(52, GPIO_DIR_MODE_OUT);

    GPIO_setPadConfig(65, GPIO_PIN_TYPE_STD);
    GPIO_writePin(65, 0);
    GPIO_setPinConfig(GPIO_65_GPIO65);
    GPIO_setDirectionMode(65, GPIO_DIR_MODE_OUT);

    GPIO_setPadConfig(124, GPIO_PIN_TYPE_STD);
    GPIO_writePin(124, 0);
    GPIO_setPinConfig(GPIO_124_GPIO124);
    GPIO_setDirectionMode(124, GPIO_DIR_MODE_OUT);

    GPIO_setPadConfig(125, GPIO_PIN_TYPE_STD);
    GPIO_writePin(125, 0);
    GPIO_setPinConfig(GPIO_125_GPIO125);
    GPIO_setDirectionMode(125, GPIO_DIR_MODE_OUT);

    GPIO_setPadConfig(20, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(21, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(99, GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode(20, GPIO_QUAL_SYNC);
    GPIO_setQualificationMode(21, GPIO_QUAL_SYNC);
    GPIO_setQualificationMode(99, GPIO_QUAL_SYNC);
    GPIO_setPinConfig(GPIO_20_EQEP1A);
    GPIO_setPinConfig(GPIO_21_EQEP1B);
    GPIO_setPinConfig(GPIO_99_EQEP1I);

    GPIO_setPadConfig(54, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(55, GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig(57, GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode(54, GPIO_QUAL_SYNC);
    GPIO_setQualificationMode(55, GPIO_QUAL_SYNC);
    GPIO_setQualificationMode(57, GPIO_QUAL_SYNC);
    GPIO_setPinConfig(GPIO_54_EQEP2A);
    GPIO_setPinConfig(GPIO_55_EQEP2B);
    GPIO_setPinConfig(GPIO_57_EQEP2I);
}