/* ==============================================================================
System Name:    Power Factor Correction for single phase AC input with two phase
                interleaved transition mode totem pole configuration

File Name:      pfc2philtrmttpl_Board.h

Target:         F28004x

Author:         Hrishi Nene

Description:	This file consits of common variables for a particular hardware
                board. Like variables and functions to read current and voltage 
                signals on the board functions to setup the basic peripherals 
                of the board.
				These common set is independent of the control method used and 
                hence helps in eliminating duplication of this code when 
                implementing different control schemes on the same design
				This file must be settings independent, an settings dependent 
                code should reside in the parent solution project.
==============================================================================*/
//#############################################################################
// $TI Release: TIDA_00961 v1.00.02.00 $
// $Release Date: Mon Jul 29 16:03:54 CDT 2019 $
// $Copyright:
// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
// 
//   Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the   
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################

#ifdef __cplusplus

extern "C" {
#endif


//*****************************************************************************
// the includes
//*****************************************************************************
// Include the IQmath Library First, define Global Q
#define MATH_TYPE 1
#include "IQmathLib.h"
// Include files for device support, F2806x in this case
#include "driverlib.h"
#include "device.h"

#include "pfc2philtrmttpl_settings.h"

//*****************************************************************************
//defines
//*****************************************************************************
// Analog pin mux select define for AIO245 (so that ADC input can be used as a
// digital Input)
#define GPHAMSEL_MASK                        0x00200000
#define GPHAMSEL_VALUE                       0x00000000

// Timer definitions based on System Clock
// 150 MHz devices
#define     mSec0_5     0.5*SYSTEM_FREQUENCY*1000       // 0.5 mS
#define     mSec1       1*SYSTEM_FREQUENCY*1000     // 1.0 mS
#define     mSec2       2.0*SYSTEM_FREQUENCY*1000       // 2.0 mS
#define     mSec5       5*SYSTEM_FREQUENCY*1000     // 5.0 mS
#define     mSec7_5     7.5*SYSTEM_FREQUENCY*1000       // 7.5 mS
#define     mSec10      10*SYSTEM_FREQUENCY*1000        // 10 mS
#define     mSec20      20*SYSTEM_FREQUENCY*1000        // 20 mS
#define     mSec50      50*SYSTEM_FREQUENCY*1000        // 50 mS
#define     mSec100     100*SYSTEM_FREQUENCY*1000       // 100 mS
#define     mSec500     500*SYSTEM_FREQUENCY*1000   // 500 mS
#define     mSec1000    1000*SYSTEM_FREQUENCY*1000  // 1000 mS

#ifndef TRUE
#define FALSE 0
#define TRUE  1
#endif

#define HVBUS_FB    ADC_readResult(HVBUS_ADCRESULTREGBASE,HVBUS_ADC_SOC_NO)
#define AC_CUR_ADC_REF_FB  ADC_readResult(AC_CUR_REF_ADCRESULTREGBASE,AC_CUR_REF_ADC_SOC_NO)
#define AC_CUR_SENSE_FB  ADC_readResult(AC_CUR_SENSE_ADCRESULTREGBASE,AC_CUR_SENSE_ADC_SOC_NO)
#define AC_CUR_SENSE_2_FB  ADC_readResult(AC_CUR_SENSE_2_ADCRESULTREGBASE,AC_CUR_SENSE_2_ADC_SOC_NO)
#define AC_CUR_SENSE_3_FB  ADC_readResult(AC_CUR_SENSE_3_ADCRESULTREGBASE,AC_CUR_SENSE_3_ADC_SOC_NO)
#define AC_CUR_SENSE_4_FB  ADC_readResult(AC_CUR_SENSE_4_ADCRESULTREGBASE,AC_CUR_SENSE_4_ADC_SOC_NO)

#define ACL_SENSE_FB ADC_readResult(ACL_SENSE_ADCRESULTREGBASE,ACL_SENSE_ADC_SOC_NO)
#define ACL_SENSE_2_FB  ADC_readResult(ACL_SENSE_2_ADCRESULTREGBASE,ACL_SENSE_2_ADC_SOC_NO)
#define ACL_SENSE_3_FB  ADC_readResult(ACL_SENSE_3_ADCRESULTREGBASE,ACL_SENSE_3_ADC_SOC_NO)
#define ACL_SENSE_4_FB  ADC_readResult(ACL_SENSE_4_ADCRESULTREGBASE,ACL_SENSE_4_ADC_SOC_NO)

#define ACN_SENSE_FB ADC_readResult(ACN_SENSE_ADCRESULTREGBASE,ACN_SENSE_ADC_SOC_NO)
#define ACN_SENSE_2_FB  ADC_readResult(ACN_SENSE_2_ADCRESULTREGBASE,ACN_SENSE_2_ADC_SOC_NO)
#define ACN_SENSE_3_FB  ADC_readResult(ACN_SENSE_3_ADCRESULTREGBASE,ACN_SENSE_3_ADC_SOC_NO)
#define ACN_SENSE_4_FB  ADC_readResult(ACN_SENSE_4_ADCRESULTREGBASE,ACN_SENSE_4_ADC_SOC_NO)

#define ZVS1_FB ADC_readResult(ZVS1_ADCRESULTREGBASE,ZVS1_ADC_SOC_NO)
#define ZVS2_FB ADC_readResult(ZVS2_ADCRESULTREGBASE,ZVS2_ADC_SOC_NO)

#define L100_CS_FB ADC_readResult(L100_CS_ADCRESULTREGBASE,L100_CS_ADC_SOC_NO)
#define L101_CS_FB ADC_readResult(L101_CS_ADCRESULTREGBASE,L101_CS_ADC_SOC_NO)
#define L102_CS_FB ADC_readResult(L102_CS_ADCRESULTREGBASE,L102_CS_ADC_SOC_NO)

#define PWM_TRIP_STATUS EPWM_getTripZoneFlagStatus

#define HistorySize 8
//#define DLOG_SIZE   200

//1.0/4096
#define ADC_PU_SCALE_FACTOR  (float)(0.000244140625)
#define HI_RES_SHIFT (float)(65536.0)
#define ADC_PU_PPB_SCALE_FACTOR 0.000488281250 //1/2^11
#define SD_PU_SCALE_FACTOR  0.000030517578125 // 1/2^15
///0.000003814697265625 // 1/2^18
#define SD32_PU_SCALE_FACTOR  (float) ( 1.0 / (100.0*100.0*100.0))

//definitions for selecting DACH reference
#define REFERENCE_VDDA     0

//definitions for COMPH input selection
#define NEGIN_DAC          0
#define NEGIN_PIN          1

//definitions for CTRIPH/CTRIPOUTH output selection
#define CTRIP_ASYNCH       0
#define CTRIP_SYNCH        1
#define CTRIP_FILTER       2
#define CTRIP_LATCH        3

// ADC Configuration
#define REFERENCE_INTERNAL 0 //internal reference (12-bit only)
#define REFERENCE_EXTERNAL 1 //external reference
//definitions for selecting ADC resolution
#define RESOLUTION_12BIT 0 //12-bit resolution
#define RESOLUTION_16BIT 1 //16-bit resolution (not supported for all variants)
//definitions for selecting ADC signal mode
#define SIGNAL_SINGLE 0 //single-ended channel conversions (12-bit mode only)
#define SIGNAL_DIFFERENTIAL 1 //differential pair channel conversions


#define REFERENCE_VDAC     0
#define REFERENCE_VREF     1

#define HWREG32(x) (*((volatile Uint32 *)(x)))
#define HWREG16(x) (*((volatile Uint16 *)(x)))

//*****************************************************************************
//globals
//*****************************************************************************


//*****************************************************************************
// the function prototypes
//*****************************************************************************

void setupDevice(void);
void setupGaNFetPWM(uint32_t base1,uint32_t base2, uint16_t pwm_period_ticks,
                    uint16_t pwm_dbred_ticks, uint16_t pwm_dbfed_ticks);
void setupSiFeTPWM(uint32_t base1, uint16_t pwm_period_ticks,
                   uint16_t pwm_db_ticks_ls, uint16_t pwm_db_ticks_hs);
void setupSinglePWM(uint32_t base1, uint16_t pwm_period_ticks);
void setupAdcOvrSamplPWM(uint32_t base1, uint16_t pwm_period_ticks);
void initCmpssAcCur(void);
void initCmpssZvs(void);
void setupADCSOCTrigger(uint32_t base);
void setupADCconversion(uint32_t adc_base, uint16_t adc_soc_number,
                        uint16_t adc_trig_source, uint16_t adc_pin,
                        uint16_t acqps);
void setupADC(void);
void setupADCaConversion(uint16_t trig_sel, uint16_t acqps, uint16_t I_pin,
                         uint16_t Vin_pin, uint16_t Vout_pin,
                         uint16_t Vref_pin);
void setupGpios(void);
void setupPwms(void);
void setupBoardProtection(uint32_t base1,uint32_t base2, uint32_t base3);
void setupCMPSS(uint32_t base1, float current_limit, float current_max_sense );
void initGlobalVariables(void);
void setupAcCurGainGPIO(void);
void setupRelayGPIO(void);
void setupFanGPIO(void);
void setupGaNFaultGPIOs(void);
void setupAcCurFaultGPIOs(void);
void setupLEDGPIO(void);
void setupSCIconnectionForSFRA(void);
inline void calibrateOffset(volatile float *ac_cur_sensedOffset,float k1,
                            float k2);
inline void disablePWMCLKCounting(void);
inline void enablePWMCLKCounting(void);
inline void toggleLED(void);
inline void closeRelay(void);
inline void openRelay(void);
inline void turnOnFan(void);
inline void turnOffFan(void);
inline void setProfilingGPIO(void);
inline void resetProfilingGPIO(void);
inline void enableAcCurSample(void);
inline void disableAcCurSample(void);
inline uint16_t usGetRecShutDownStatus(void);
inline uint16_t usGetGaNFault1Status(void);
inline uint16_t usGetGaNFault2Status(void);

void setupGainChangeGPIO(void);
void DeviceInit(void);
void MemCopy(void);
void InitFlash(void);

void setPinsAsPWM();

void setupCLA(void);


#ifndef __TMS320C28XX_CLA__
interrupt void controlISR(void);
interrupt void pwmISR(void);
#endif

interrupt void tenKHzISR(void);

// Inline functions

static inline void EPWM_setCounterCompareValueOptimized(uint32_t base,
                                 EPWM_CounterCompareModule compModule,
                                 uint16_t compCount)
{
    uint32_t registerOffset;

    // Get the register offset for the Counter compare
    registerOffset = EPWM_O_CMPA + (uint16_t)compModule;
    // Write to the counter compare registers.

    if((compModule == EPWM_COUNTER_COMPARE_A) ||
    (compModule == EPWM_COUNTER_COMPARE_B))
    {
        // write to CMPA or COMPB bits
        HWREGH(base + registerOffset + 1) = (uint16_t)compCount;
    }
    else
    { // write to COMPC or COMPD bits
        HWREGH(base + registerOffset) = compCount;
    }

}


inline void update_constONtime( uint32_t base2, uint32_t base3, uint32_t base4,  uint16_t ton_calc, uint16_t calc_period)
{
    // Set new period based on '1-D' (Toff) calculations
    EPWM_setTimeBasePeriod(base2, calc_period);
    EPWM_setTimeBasePeriod(base4, calc_period);
    EPWM_setTimeBasePeriod(base3, (calc_period-1));

    EPWM_setCounterCompareValue(base2,EPWM_COUNTER_COMPARE_A,ton_calc);
    EPWM_setCounterCompareValue(base4,EPWM_COUNTER_COMPARE_A,ton_calc);
    EPWM_setCounterCompareValue(base3,EPWM_COUNTER_COMPARE_A,ton_calc);

    EPWM_setCounterCompareValue(base2,EPWM_COUNTER_COMPARE_C,(calc_period-40));

}

inline void update_GaNFetPWMs( uint32_t base2, uint32_t base3, uint32_t base4,
                               float duty, uint16_t calc_period,
                               uint16_t max_period)
{
    uint32_t dutyPWMReg;

    // Set new period based on '1-D' (Toff) calculations
    EPWM_setTimeBasePeriod(base2, calc_period);
    EPWM_setTimeBasePeriod(base4, calc_period);
    EPWM_setTimeBasePeriod(base3, calc_period);

    // Duty maybe +ve or -ve and therefore the use of (IQ24abs() i.e. fabs()).
    // Calculate Ton value based on duty cycle value and max_period value
    dutyPWMReg= _IQ24mpy(max_period,_IQ24abs(duty));

    // If calculated ON time is > calc period, make it 50 counts less than period
    dutyPWMReg = (dutyPWMReg > calc_period)?(calc_period-50):dutyPWMReg;

    EPWM_setCounterCompareValueOptimized(base2,EPWM_COUNTER_COMPARE_A,
                                         dutyPWMReg);
    EPWM_setCounterCompareValueOptimized(base4,EPWM_COUNTER_COMPARE_A,
                                         dutyPWMReg);
    EPWM_setCounterCompareValueOptimized(base3,EPWM_COUNTER_COMPARE_A,
                                         dutyPWMReg);

// Need to use global load as the switching frequency could be much higher
// than the control ISR freq
    EPWM_setGlobalLoadOneShotLatch(base2);
}

inline void enableAcCurSample(void)
{
    GPIO_writePin(GAC_I_IO,1);
}//End function enableAcCurSample
inline void disableAcCurSample(void)
{
    GPIO_writePin(GAC_I_IO,0);
}//End function disableAcCurSample
inline uint16_t usGetRecShutDownStatus(void)
{
    return(GPIO_readPin(REC_SHUTDWON_IO));

}//End function usGetRecShutDownStatus
inline uint16_t usGetGaNFault1Status(void)
{
    return(GPIO_readPin(GaN_FAULT1_IO));
}//End function usGetGaNFault1Status
inline uint16_t usGetGaNFault2Status(void)
{
    return(GPIO_readPin(GaN_FAULT2_IO));

}//End function usGetGaNFault2Status

//TODO closeRelay
inline void closeRelay(void)
{
    GPIO_writePin(RELAY_IO,1);
}

//TODO openRelay
inline void openRelay(void)
{
    GPIO_writePin(RELAY_IO,0);
}

//TODO turnOnFan
inline void turnOnFan(void)
{
    GPIO_writePin(FAN_FB_IO,1);
}

//TODO turnOffFan
inline void turnOffFan(void)
{
    GPIO_writePin(FAN_FB_IO,0);
}

//TODO gainHighSetforLowCurrent
inline void gainHighSetforLowCurrent(void)
{
    GPIO_writePin(11,1);
}

//TODO gainLowSetforHighCurrent
inline void gainLowSetforHighCurrent(void)
{
    GPIO_writePin(11,0);
}

//TODO setProfilingGPIO
inline void setProfilingGPIO(void)
{
    GPIO_writePin(15,1);
}

//TODO resetProfilingGPIO
inline void resetProfilingGPIO(void)
{
    GPIO_writePin(15,0);
}

//TODO setProfilingGPIO
inline void setProfilingGPIO2(void)
{
    GPIO_writePin(15,1);
}

//TODO resetProfilingGPIO
inline void resetProfilingGPIO2(void)
{
    GPIO_writePin(15,0);
}

//TODO clearPWMTrip
inline void clearAllPWMTripFlags(uint32_t base)
{
    // clear all the configured trip sources for the PWM module
    EPWM_clearTripZoneFlag(base,EPWM_TZ_INTERRUPT_OST | EPWM_TZ_INTERRUPT_CBC |
                           EPWM_TZ_INTERRUPT_DCAEVT1);
}

inline void clearOSTPWMTripFlag(uint32_t base)
{
    // clear all the configured trip sources for the PWM module
    EPWM_clearTripZoneFlag(base,EPWM_TZ_INTERRUPT_OST);
}

inline void forceOSTPWMTrip(uint32_t base)
{
    EPWM_forceTripZoneEvent(base,EPWM_TZ_FORCE_EVENT_OST);
}

//TODO clearPWM Interrupt Flag
inline void clearPWMInterruptFlag(uint32_t base)
{
    EPWM_clearEventTriggerInterruptFlag(base);
}

//TODO enable PWM Interrupt generation
inline void enablePWMInterruptGeneration(uint32_t base)
{
    EPWM_setInterruptSource(base,EPWM_INT_TBCTR_U_CMPB); // INT on CTRBU event
    EPWM_setInterruptEventCount(base,CNTRL_ISR_FREQ_RATIO);
    EPWM_enableInterrupt(base);
    EPWM_clearEventTriggerInterruptFlag(base);
}

//TODO enable PWM Interrupt generation
inline void enablePWMInterruptGeneration_PWM(uint32_t base)
{
    EPWM_setInterruptSource(base,EPWM_INT_TBCTR_U_CMPC); // INT on CTRCU event
    EPWM_setInterruptEventCount(base,PWM_ISR_FREQ_RATIO);
    EPWM_enableInterrupt(base);
    EPWM_clearEventTriggerInterruptFlag(base);
}


//TODO calibrateOffset()
inline void calibrateOffset(volatile float *ac_cur_sensedOffset,float k1, float k2)
{
    int16_t offsetCalCounter=0;

    /* Select SOC from counter at ctr =CMPAU*/
    EPWM_setADCTriggerSource(LOW_FREQ_PWM_BASE,EPWM_SOC_A,EPWM_SOC_TBCTR_U_CMPC);
    EPWM_setCounterCompareValue(LOW_FREQ_PWM_BASE,EPWM_COUNTER_COMPARE_C,20);

    /* Generate pulse on 1st even*/
    EPWM_setADCTriggerEventPrescale(LOW_FREQ_PWM_BASE,EPWM_SOC_A,1);

    /* Enable SOC on A group*/
    EPWM_enableADCTrigger(LOW_FREQ_PWM_BASE,EPWM_SOC_A);


    //PWM1 INT is used to trigger the ISR

    // INT on Period event
    EPWM_setInterruptSource(LOW_FREQ_PWM_BASE,EPWM_INT_TBCTR_U_CMPB);
    // Enable INT
    EPWM_enableInterrupt(LOW_FREQ_PWM_BASE);
    // Generate INT on every event
    EPWM_setInterruptEventCount(LOW_FREQ_PWM_BASE,1);

    EPWM_clearEventTriggerInterruptFlag(LOW_FREQ_PWM_BASE);

    offsetCalCounter=0;
    while(offsetCalCounter<20000)
    {
        if(EPWM_getEventTriggerInterruptStatus(LOW_FREQ_PWM_BASE)==1)
        {
            if(offsetCalCounter>1000)
            {
                // offset of the inductor current sense
                *ac_cur_sensedOffset =  k1* (*ac_cur_sensedOffset) + k2 * (AC_CUR_SENSE_FB) * ADC_PU_SCALE_FACTOR;
            }
            EPWM_clearEventTriggerInterruptFlag(LOW_FREQ_PWM_BASE);
            offsetCalCounter++;
        }
    }

    ADC_setPPBCalibrationOffset(ADCA_BASE,ADC_PPB_NUMBER1,(0*4096.0));
    ADC_setPPBCalibrationOffset(ADCA_BASE,ADC_PPB_NUMBER2,(0*4096.0));
    ADC_setPPBCalibrationOffset(ADCA_BASE,ADC_PPB_NUMBER3,(0*4096.0));
}


//TODO disablePWMCLKCounting
inline void disablePWMCLKCounting(void)
{
    EALLOW;
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    EDIS;
}

//TODO enablePWMCLKCounting
inline void enablePWMCLKCounting(void)
{
    EALLOW;
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    EDIS;
}


//TODO toggleLED()
inline void toggleLED(void)
{
    static uint16_t ledCnt1=0;

    if(ledCnt1==0)
        {
        GPIO_togglePin(LED_CCARD2_IO);
        ledCnt1=10;
        }
    else
        ledCnt1--;
}


#ifndef __TMS320C28XX_CLA__
//TODO clearInterrupt
inline void clearInterrupt(uint16_t pie_group_no)
{
    Interrupt_clearACKGroup(pie_group_no);
}


inline void setupInterrupt(void)
{
    Interrupt_register(LOW_FREQ_PWM_INT, &controlISR);
    enablePWMInterruptGeneration(LOW_FREQ_PWM_BASE);
    // Note that PWM1 ISR will be generated at a rate as defined by
    // CNTRL_ISR_FREQ_RATIO in prj settings
    clearInterrupt(C28x_CONTROLISR_INTERRUPT_PIE_GROUP_NO);
    Interrupt_enable(LOW_FREQ_PWM_INT);

    Interrupt_register(HIGH_FREQ_PWM1_INT, &pwmISR);
    // Note that PWM2 ISR will be generated at a rate as defined by
    // PWM_ISR_FREQ_RATIO in prj settings
    enablePWMInterruptGeneration_PWM(HIGH_FREQ_PWM1_BASE);
    clearInterrupt(C28x_CONTROLISR_INTERRUPT_PIE_GROUP_NO);
    Interrupt_enable(HIGH_FREQ_PWM1_INT);

    CPUTimer_enableInterrupt(CPUTIMER2_BASE);
    CPUTimer_clearOverflowFlag(CPUTIMER2_BASE);
    Interrupt_register(INT_TIMER2, &tenKHzISR);
    Interrupt_enable(INT_TIMER2);

    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM
    EDIS;
}

#endif

#ifdef __cplusplus
}
#endif                                  /* extern "C" */

