#include "F28x_Project.h"
extern volatile struct EPWM_REGS* ePWM[10];
#define AUTOCONVERT 1
//..........................................EPWM........................................................//
#ifdef CPU1
/*
 * EPWMs GPIO configuration
 */
void InitEPWMsGpio(unsigned int EpwmCh)
{
    EALLOW;
    switch (EpwmCh)
    {
        case 1:
                GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;    // Disable pull-up on EPWM1A
                GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;    // Disable pull-up on EPWM1B

                GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;   // Configure GPIO8 as EPWM1A
                GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;   // Configure GPIO9 as EPWM1B
                break;

        case 2:
                GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1;    // Disable pull-up on EPWM2A
                GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1;    // Disable pull-up on EPWM2B

                GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1;   // Configure GPIO8 as EPWM2A
                GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1;   // Configure GPIO9 as EPWM2B
                break;
        case 3:
                GpioCtrlRegs.GPAPUD.bit.GPIO4 = 1;    // Disable pull-up on EPWM3A
                GpioCtrlRegs.GPAPUD.bit.GPIO5 = 1;    // Disable pull-up on EPWM3B

                GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1;   // Configure GPIO8 as EPWM3A
                GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1;   // Configure GPIO9 as EPWM3B
                break;
        case 4:
                GpioCtrlRegs.GPAPUD.bit.GPIO6 = 1;    // Disable pull-up on EPWM4A
                GpioCtrlRegs.GPAPUD.bit.GPIO7 = 1;    // Disable pull-up on EPWM4B

                GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 1;   // Configure GPIO8 as EPWM4A
                GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 1;   // Configure GPIO9 as EPWM4B
                break;
        case 5:
                GpioCtrlRegs.GPAPUD.bit.GPIO8 = 1;    // Disable pull-up on EPWM5A
                GpioCtrlRegs.GPAPUD.bit.GPIO9 = 1;    // Disable pull-up on EPWM5B

                GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 1;   // Configure GPIO8 as EPWM5A
                GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 1;   // Configure GPIO9 as EPWM5B
                break;
        case 6:
                GpioCtrlRegs.GPAPUD.bit.GPIO10 = 1;    // Disable pull-up on EPWM6A
                GpioCtrlRegs.GPAPUD.bit.GPIO11 = 1;    // Disable pull-up on EPWM6B

                GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1;   // Configure GPIO8 as EPWM6A
                GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 1;   // Configure GPIO9 as EPWM6B
                break;
        default:;

    }



    EDIS;
}
#endif


/*
 * Normal EPWM duty cycle update
 */
void EPWM_dutyupdate(unsigned int EpwmCh,float Duty)
{
    // This function updates the duty cycle of normal epwm duty cycle (non-highres)
    // EpwmCh - the pwm channel you want to update
    // Duty   - duty cycle

    (*ePWM[EpwmCh]).CMPA.bit.CMPA = Duty * (*ePWM[EpwmCh]).TBPRD;
}

/*
 * Normal EPWM period update
 */
void EPWM_peridupdate(unsigned int EpwmCh, int Period)
{
    // This function updates the period of the normal epwm period (non-highres)
    // EpwmCh - the pwm channel you want to update
    // Period - Period counter value

    (*ePWM[EpwmCh]).TBPRD = Period;
}

/*
 * Normal EPWM phase shift update
 */
void EPWM_phaseshiftupdate(unsigned int EpwmCh, float phaseshift)
{
    // This function updates the phase shift of normal epwm (non-highres)
    // EpwmCh   - the pwm channel you want to update
    // phase shift - the phase shift

    (*ePWM[EpwmCh]).TBPHS.bit.TBPHS = phaseshift;
}

/*
 * Start EPWMs
 */
void StartEPWM(unsigned int EpwmCh,unsigned int updown)
{
    EALLOW;
        (*ePWM[EpwmCh]).TBCTR = 0;                                        //Force PWM counter to 0
        (*ePWM[EpwmCh]).TZCLR.bit.OST = 1;                                //Clear TZ flag--PWM module can work now
//        if (updown == 1)
//            (*ePWM[EpwmCh]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;              //Enable up-down PWM counter mode
//        else
//            (*ePWM[EpwmCh]).TBCTL.bit.CTRMODE = TB_COUNT_UP;              //Enable up-down PWM counter mode
    EDIS;
}

/*
 * Stop EPWMs
 */

void StopEPWM(unsigned int EpwmCh)
{
    EALLOW;
       (*ePWM[EpwmCh]).TZFRC.bit.OST = 1;                                //Force ePWM7 TZ
//       (*ePWM[EpwmCh]).TBCTL.bit.CTRMODE = 3;                            //Disable PWM counter
       (*ePWM[EpwmCh]).TBCTR = 1;                                        //Force PWM counter to 1 instead of 0 or PRD
    EDIS;
}

/*
 *  General EPWM initialization (up-down counter)
 */
void InitUPDOWNEPWM(unsigned int Epwm_Ch,int Period,int DBRED, int DBFED, float theta_fwd,float ini_duty,unsigned int ADC_trigger)
{
    // General EPWM channel initialization based on inputs, note that the PWM is configured with up-down count
    // Epwm_Ch          -   the PWM channel that you want to initialize
    // Period           -   the counter period, after conversion from [s] to counter number
    // DBRED            -   rising edge dead time [counter number]
    // DBFED            -   falling edge dead time [counter number]
    // theta_fwd        -   the initial correction on the duty cycle, (1-theta_fwd)*period*duty
    // ini_duty         -   the initial duty cycle implemented in the initialization process, can be changed later with control
    // ADC_trigger      -   Set start of conversion based on this channel if 1


    // Setup TBCLK
    (*ePWM[Epwm_Ch]).TBCTL.bit.CTRMODE = 3;                            // Freeze the counter
    (*ePWM[Epwm_Ch]).TBPRD = Period;                                   // Set timer period (6000+1) TBCLK counts
    (*ePWM[Epwm_Ch]).TBPHS.bit.TBPHS = 0x0000;                         // Phase is 0
    (*ePWM[Epwm_Ch]).TBCTR = 0x0000;                                   // Clear counter


    (*ePWM[Epwm_Ch]).TBCTL.bit.PHSEN = TB_DISABLE;                     // Disable phase loading
    (*ePWM[Epwm_Ch]).TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;                 // Disbale sync down-stream module (obselete on 28388D)
//    (*ePWM[Epwm_Ch]).EPWMSYNCINSEL.all = SYNC_IN_SRC_DISABLE_ALL;       // Disbale sync down-stream module
    (*ePWM[Epwm_Ch]).TBCTL.bit.PRDLD = TB_SHADOW;                      // Shadow mode to enable synchronous para update
    (*ePWM[Epwm_Ch]).TBCTL.bit.HSPCLKDIV = TB_DIV1;                    // Clock ratio to SYSCLKOUT
    (*ePWM[Epwm_Ch]).TBCTL.bit.CLKDIV = TB_DIV1;

    (*ePWM[Epwm_Ch]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;                 // Load registers every ZERO
    (*ePWM[Epwm_Ch]).CMPCTL.bit.SHDWBMODE = CC_SHADOW;
//    (*ePWM[Epwm_Ch]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
//    (*ePWM[Epwm_Ch]).CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
    (*ePWM[Epwm_Ch]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;
    (*ePWM[Epwm_Ch]).CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD;
    (*ePWM[Epwm_Ch]).TBCTL.bit.FREE_SOFT = 00;                         // disable the free running

    //
    // Setup compare -- Duty cycle
    //
    (*ePWM[Epwm_Ch]).CMPA.bit.CMPA = (1-theta_fwd) * Period * ini_duty;                      // 50% fixed duty for EPWM1A
    (*ePWM[Epwm_Ch]).CMPB.bit.CMPB = (1-theta_fwd) * Period * (1-ini_duty);                      // 50% fixed duty for EPWM1A


//    (*ePWM[Epwm_Ch]).TBCTL.bit.CTRMODE = count_mode;                  // Start ePWM - Count up

    /* Count up-down */
    (*ePWM[Epwm_Ch]).AQCTLA.bit.CAU = AQ_CLEAR;                        // zero PWMA reaching CMPA when increasing (positive logic for duty cycle)
    (*ePWM[Epwm_Ch]).AQCTLA.bit.CAD = AQ_SET;                      // Set PWMB reaching CMPA when decreasing
        // Inverted output
    (*ePWM[Epwm_Ch]).AQCTLB.bit.CBU = AQ_SET;                        // set PWM7b reaching CMPB when increasing (off time)
    (*ePWM[Epwm_Ch]).AQCTLB.bit.CBD = AQ_CLEAR;                          // clear PWM7B reaching CMPB when decreasing

    /* count up
    (*ePWM[Epwm_Ch]).AQCTLA.bit.ZRO = AQ_SET;                          // Set PWM7A on Zero
    (*ePWM[Epwm_Ch]).AQCTLA.bit.CAU = AQ_CLEAR; */

    //
    // Active HIGH PWMs - Setup Deadband
    //
    (*ePWM[Epwm_Ch]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    (*ePWM[Epwm_Ch]).DBCTL.bit.POLSEL = DB_ACTV_HIC;
    (*ePWM[Epwm_Ch]).DBCTL.bit.IN_MODE = DBA_ALL;
    (*ePWM[Epwm_Ch]).DBRED.bit.DBRED = DBRED;                    // Variable deadband for rising/falling edge
    (*ePWM[Epwm_Ch]).DBFED.bit.DBFED = DBFED;

    if (ADC_trigger == 1)
    {
        /// Interrupt where we will measure ADC (comment when software trigger)
        (*ePWM[Epwm_Ch]).ETSEL.bit.SOCAEN      = 1;                                    // Enable SOC on ADC group A
        (*ePWM[Epwm_Ch]).ETSEL.bit.SOCBEN      = 1;                                    // Enable SOC on ADC group B
        (*ePWM[Epwm_Ch]).ETSEL.bit.SOCASEL     = ET_CTR_PRDZERO;                       // Select SOC on zero event (1), PRD (2), zero or PRD (3) refer to Table 13-68 for ADCA
        (*ePWM[Epwm_Ch]).ETSEL.bit.SOCBSEL     = ET_CTR_PRDZERO;
        (*ePWM[Epwm_Ch]).ETPS.bit.SOCAPRD      = ET_1ST;                               // Generate pulse on 1st event
        (*ePWM[Epwm_Ch]).ETPS.bit.SOCBPRD      = ET_1ST;                               // Generate pulse on 1st event

        /// Interrupt where we will enter the interrupt and update the CCCV control
        (*ePWM[Epwm_Ch]).ETSEL.bit.INTSEL      = ET_CTR_PRDZERO;                       // Select INT on Zero event  * when the control action is updated
        (*ePWM[Epwm_Ch]).ETSEL.bit.INTEN       = 1;                                    // Enable INT
        (*ePWM[Epwm_Ch]).ETPS.bit.INTPRD       = ET_1ST;                               // Generate INT on 1st event
    }

    /// Trip zone setting
    EALLOW;
        (*ePWM[Epwm_Ch]).TZCTL.bit.TZA = TZ_FORCE_LO;                          // Trip action set to force-low for output A
        (*ePWM[Epwm_Ch]).TZCTL.bit.TZB = TZ_FORCE_LO;                          // Trip action set to force-low for output B
        //***** DON'T USE OSHT123!!!!! THEY ARE MUXED TO EXTERNAL SIGNALS, THEY WON'T BE CLEARED SO ALWAYS TRIPPED******
        (*ePWM[Epwm_Ch]).TZSEL.bit.OSHT4 = 0x1;                        // TZ1 configured for OSHT trip of ePWM7
        (*ePWM[Epwm_Ch]).TZCLR.bit.OST = 0x1;                          // Clear OST flag just in case
    EDIS;
}
