#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
#include "DSP2833x_PID.h"
#include "PID.h"


#define PWM1_INT_ENABLE  1
#define PWM2_INT_ENABLE  1
#define TIMER_TBPRD 3750
#define MIN 3600
#define MAX 3000
#define IREF 1283


// Prototype statements for functions found within this file.
extern void InitAdc(void);
extern void InitSysCtrl(void);
extern void InitPieCtrl(void);
extern void InitPieVectTable(void);
extern void InitEPwm1Gpio(void);
extern void InitEPwm2Gpio(void);
extern void InitFlash(void);

// Continue PID function for the voltage control
extern void pid_init_vdc(PID_VDC *vdc, double min, double max);
extern void pid_setconstants_vdc(PID_VDC *vdc,float kp, float ki,float kd);
extern float pid_update_f_vdc(float sp, float pv,PID_VDC *vdc);

// Continue PID function for the current control
extern void pid_init_idc(PID_IDC *idc, double min, double max);
extern void pid_setconstants_idc(PID_IDC *idc,float kp, float ki,float kd);
extern float pid_update_f_idc(float sp, float pv,PID_IDC *idc);

// Discrete PID controller function for current control
extern void pid_init(PID_NEW *lol, double min, double max);
extern void pid_setconstants(PID_NEW *lol,float kp, float ki,float kd);
extern float pid_pwm_compute(float sp, float pv,PID_NEW *lol);

//Discrete PID controller function
extern void pid_dis_init(PID_DIS *mdr,float min,float max,int N);
extern void pid_dis_setconstants(PID_DIS *mdr,float kp, float ki,float kd,float Ts);
extern float pid_dis_update(float sp, float pv,PID_DIS *mtr);


// System and initialisation function
void config_ADC(void);
void config_ePWM1(void);
void config_ePWM2(void);
void relay_active(void);
void set_duty(double PWM,float val);
float get_real_current_value(Uint16 val);
float get_real_voltage_value(Uint16 val);
float get_real_potent_value(Uint16);

interrupt void adc_isr(void);
interrupt void epwm1_timer_isr(void);
interrupt void epwm2_timer_isr(void);

// Global variable
Uint16 voltage_Vdc;      // Voltage acquisition
Uint16 current_Idc;      // Current acquisition
Uint16 potent_CC;        // Potentionmetre acquisition
Uint32  EPwm1TimerIntCount;
Uint32  EPwm2TimerIntCount;

volatile const float Vcc=3;
volatile float real_potent_CC;
volatile float real_voltage_CC;
volatile float real_current_CC;
volatile float step_update;
volatile float voltage_pid;
volatile float current_pid;
volatile float i,i1;


PID_VDC vdc;
PID_IDC idc;
//PID_NEW lol;
PID_DIS mdr;

main()
{

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks

   InitSysCtrl();

   EALLOW;
   #if (CPU_FRQ_150MHZ)     // Default - 150 MHz SYSCLKOUT
     #define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
   #endif
   #if (CPU_FRQ_100MHZ)
     #define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
   #endif
   EDIS;

   // Define ADCCLK clock frequency ( less than or equal to 25 MHz )
   // Assuming InitSysCtrl() has set SYSCLKOUT to 150 MHz
   EALLOW;
   SysCtrlRegs.HISPCP.all = ADC_MODCLK;
   EDIS;

// Step 2. Initialize GPIO:

   InitEPwm1Gpio();
   InitEPwm2Gpio();
   relay_active();

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize the PIE control registers to their default state.

   InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).

   InitPieVectTable();

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.

   EALLOW;  // This is needed to write to EALLOW protected register
   PieVectTable.ADCINT = &adc_isr;
   PieVectTable.EPWM1_INT = &epwm1_timer_isr;
   PieVectTable.EPWM2_INT = &epwm2_timer_isr;
   EDIS;    // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize all the Device Peripherals:

   InitAdc();  // For this example, init the ADC

   config_ADC();

   config_ePWM1();
   config_ePWM2();

 
// Step 5. User specific code, enable interrupts:
   EPwm1TimerIntCount = 0;
   EPwm2TimerIntCount = 0;
  
 //  pid_init(&lol,MIN,MAX);
  // pid_setconstants(&lol,0.01,0.05,0,0);

   pid_init_idc(&idc,MIN,MAX);
   pid_setconstants_idc(&idc,20,10,0);

  //pid_dis_init(&mdr,MIN,MAX,100);
  //pid_dis_setconstants(&mdr,0.01,0.01,0.01,0.00005);

// Enable ADCINT in PIE
   PieCtrlRegs.PIEIER1.bit.INTx6 = 1;

// Enable EPWM1_INT in PIE
   PieCtrlRegs.PIEIER3.bit.INTx1 = PWM1_INT_ENABLE;
   PieCtrlRegs.PIEIER3.bit.INTx2 = PWM2_INT_ENABLE;
   
   IER |= M_INT1; // Enable CPU Interrupt 1
   IER |= M_INT3;

   EINT;          // Enable Global interrupt INTM
   ERTM;          // Enable Global realtime interrupt DBGM

  

// Wait for ADC interrupt
   while(1)
   {

    /*real_potent_CC = get_potent_val(potent_CC);
	real_voltage_CC = get_real_voltage_value(voltage_Vdc);
	curr_volt= get_real_curr_volt_val(current_Idc);
	real_current_CC = get_real_current_value(current_Idc);*/
//	i=pid_update_f_idc(IREF,current_Idc,&idc);
	
  
	 if(GpioDataRegs.GPADAT.bit.GPIO23 == 0)
	 {
	   
	   GpioDataRegs.GPASET.bit.GPIO7 = 1;

	 }
	 else
	 {

	  GpioDataRegs.GPACLEAR.bit.GPIO7 = 1;
	  

	 }

   }
}

void config_ADC(void)
{
  AdcRegs.ADCTRL1.all = 0;            // Whole initialisation

  AdcRegs.ADCTRL1.all = 0x0050;            // Whole setting
  /*
     bit 15        0:       Reserved
     bit 14        0:       Reset, 0 = No effect
	 bit 13-12     00:      SUSMOD, 00 = Mode 0. Emulation suspend is ignored
	 bit 11-8      0000:    ACQ_PS[3:0], 000 = Acquisition window size
	 bit 7       
	 3
	 .  0:       CPS, 0 => ADCCLK = Fclk/1
	 bit 6         1:       CONT_RUN, 1 = Continuous conversion mode
	 bit 5         0:       SEQ_OVRD, 0 = Disabled
	 bit 4         1:       SEQ_CASC, 1 = Cascaded mode. SEQ1 and SEQ2 operate as a single 16-state sequencer (SEQ).
	 bit 3-0       000:     Reserved
	*/

  AdcRegs.ADCTRL2.all = 0;

   AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;// Enable SOCA from ePWM to start SEQ1
   AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS) 
   AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0;	// 0= interrupt after every end of sequence 
   //AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;

  AdcRegs.ADCTRL3.bit.ADCCLKPS = 0;

  AdcRegs.ADCMAXCONV.all = 0x0002;       // Setup 2 conv's on SEQ2               
  AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x8; // Setup ADCINB0 as 1st SEQ2 conv.      
  AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x9; // Setup ADCINB1 as 2nd SEQ2 conv.
  AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0xA; // Setup ADCINB2 as 2nd SEQ2 conv.

  // Assumes ePWM1 clock is already enabled in InitSysCtrl();
   EPwm3Regs.ETSEL.bit.SOCAEN = 1;        // Enable SOC on A group
   EPwm3Regs.ETSEL.bit.SOCASEL = 4;       // Select SOC from from CPMA on upcount
   EPwm3Regs.ETPS.bit.SOCAPRD = 1;        // Generate pulse on 1st event
   EPwm3Regs.CMPA.half.CMPA = 0x0080;//0x0080;	  // Set compare A value
   EPwm3Regs.TBPRD = 0xFFFF;              // Set period for ePWM3 - same period as the adc converter-- previous value 0xFFFF
   EPwm3Regs.TBCTL.bit.CTRMODE = 0;		  // count up and start
}


void config_ePWM1(void)
{
  EPwm1Regs.TBCTL.all=0;            // Whole initialisation
  EPwm1Regs.TBPRD = TIMER_TBPRD;    // TBPRD = (SYSCLKOUT/2*Fpwm) = (150Mhz/2*20kHz)
  EPwm1Regs.TBPHS.all = 0;          // Set Phase register to zero
  EPwm1Regs.TBCTR = 0;              // clear TB counter or Set the TB counter to start at 0

  EPwm1Regs.TBCTL.all=0xC012;            // Timer control register configuration
    /*
     bit 15-14      11:     FREE/SOFT, 11 = ignore emulation suspend
     bit 13        0:       PHSDIR, 0 = count down after sync event
	 bit 12-10     000:     CLKDIV, 000 => TBCLK = HSPCLK/1
	 bit 9-7       000:     HSPCLKDIV, 000 => HSPCLK = SYSCLKOUT/1
	 bit 6         0:       SWFSYNC, 0 = no software sync produced
	 bit 5-4       01:      SYNCOSEL, 01 = Time-base counter equal to zero (TBCTR = 0x0000)
	 bit 3         0:       PRDLD, 0 = reload PRD on counter=0
	 bit 2         0:       PHSEN, 0 = phase control disabled
	 bit 1-0       10:      CTRMODE, 10 = Up-down-count mode
	*/

  EPwm1Regs.CMPCTL.all =0;            // Compare control register configuration

  EPwm1Regs.AQCTLA.all =0x0060;          // Action-Qualifier control register A configuration
  /*
     bit 15-12     Reserved
	 bit 11-10     000:    CBD, 00 = Do nothing (action disabled)
	 bit 9-8       00:     CBU, 00 = Do nothing (action disabled)
	 bit 7-6       10:     CAD, 10 = Clear: force EPWMxA output low
	 bit 5-4       10:     CAU, 10 = Set: force EPWMxA output high
	 bit 3-2       00:     PRD, 00 = Do nothing (action disabled)
	 bit 1-0       00:     ZR0, 00 = Do nothing (action disabled)
	*/

  EPwm1Regs.ETSEL.bit.INTEN = 1;        // Enable EPWMx_INT generation
  EPwm1Regs.ETSEL.bit.INTSEL = 0;       // Enable event time-base counter equal to period (TBCTR = TBPRD)*/

  EPwm1Regs.ETPS.bit.INTPRD =1;           // Generate interrupt on the first event*/

  EPwm1Regs.CMPA.half.CMPA = 3000;  //Initialisation of CMPA at 2% of TBPRD
}

void config_ePWM2(void)
{
  EPwm2Regs.TBCTL.all=0;            // Whole initialisation
  EPwm2Regs.TBPRD = TIMER_TBPRD;    // TBPRD = (SYSCLKOUT/2*Fpwm) = (150Mhz/2*20kHz)
  //EPwm2Regs.TBPHS.all = 0;          // Set Phase register to zero
  EPwm2Regs.TBCTR = 0;              // clear TB counter or Set the TB counter to start at 0

  EPwm2Regs.TBCTL.all=0xC006;            // Timer control register configuration
    /*
     bit 15-14      11:     FREE/SOFT, 11 = ignore emulation suspend
     bit 13        0:       PHSDIR, 0 = count down after sync event
	 bit 12-10     000:     CLKDIV, 000 => TBCLK = HSPCLK/1
	 bit 9-7       000:     HSPCLKDIV, 000 => HSPCLK = SYSCLKOUT/1
	 bit 6         0:       SWFSYNC, 0 = no software sync produced
	 bit 5-4       00:      SYNCOSEL, 00 = sync-out=syn-in
	 bit 3         0:       PRDLD, 0 = reload PRD on counter=0
	 bit 2         1:       PHSEN, 1 = phase control enable
	 bit 1-0       10:      CTRMODE, 10 = Up-down-count mode
	*/

  EPwm2Regs.TBPHS.half.TBPHS = 3750;	// full phase shift

  EPwm2Regs.CMPCTL.all =0;            // Compare control register configuration

  EPwm2Regs.AQCTLA.all =0x0060;          // Action-Qualifier control register A configuration
  /*
     bit 15-12     Reserved
	 bit 11-10     000:    CBD, 00 = Do nothing (action disabled)
	 bit 9-8       00:     CBU, 00 = Do nothing (action disabled)
	 bit 7-6       10:     CAD, 10 = Clear: force EPWMxA output low
	 bit 5-4       10:     CAU, 10 = Set: force EPWMxA output high
	 bit 3-2       00:     PRD, 00 = Do nothing (action disabled)
	 bit 1-0       00:     ZR0, 00 = Do nothing (action disabled)
	*/

  EPwm2Regs.ETSEL.bit.INTEN = 1;        // Enable EPWMx_INT generation
  EPwm2Regs.ETSEL.bit.INTSEL = 0;       // Enable event time-base counter equal to period (TBCTR = TBPRD)*/

  EPwm2Regs.ETPS.bit.INTPRD =1;           // Generate interrupt on the first event*/

  EPwm2Regs.CMPA.half.CMPA = 3000;  //Initialisation of CMPA at 2% of TBPRD
}

void relay_active(void)
{
  EALLOW;

  GpioCtrlRegs.GPBPUD.bit.GPIO59 = 0;     // Pull-up enable
  GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 0;    // Set GPIO 59 as I/O peripheral
  GpioCtrlRegs.GPBDIR.bit.GPIO59 = 1;     // Set GPIO 59 as output 
  GpioDataRegs.GPBCLEAR.bit.GPIO59 = 1;   // Relays is toggle to off

  GpioCtrlRegs.GPBPUD.bit.GPIO61 = 0;     // Pull-up enable
  GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 0;    // Set GPIO 61 as I/O peripheral
  GpioCtrlRegs.GPBDIR.bit.GPIO61 = 1;     // Set GPIO 61 as output
  GpioDataRegs.GPBCLEAR.bit.GPIO61 = 1;   // Relays is toggle to off

  GpioCtrlRegs.GPBPUD.bit.GPIO63 = 0;     // Pull-up enable
  GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 0;    // Set GPIO 63 as I/O peripheral
  GpioCtrlRegs.GPBDIR.bit.GPIO63 = 1;     // Set GPIO 63 as output 
  GpioDataRegs.GPBCLEAR.bit.GPIO63 = 1;   // Relays is toggle to off

  GpioCtrlRegs.GPAPUD.bit.GPIO7 = 0;     // Pull-up enable
  GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 0;    // Set GPIO 07 as I/O peripheral
  GpioCtrlRegs.GPADIR.bit.GPIO7 = 1;     // Set GPIO 07 as output 
  GpioDataRegs.GPACLEAR.bit.GPIO7 = 1;   // Active the IGBT gate

  /*GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0;     
  GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 0;    
  GpioCtrlRegs.GPADIR.bit.GPIO21 = 1;    
  GpioDataRegs.GPACLEAR.bit.GPIO31 = 1;  
  
  GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0;     
  GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 0;    
  GpioCtrlRegs.GPADIR.bit.GPIO19 = 1;    
  GpioDataRegs.GPACLEAR.bit.GPIO19 = 1; */   

  EDIS;

}

float get_real_potent_value(Uint16 val)
{
  volatile float p_pin;
  volatile float real_potent_CC;
  p_pin = Vcc*val/4095;
  real_potent_CC = p_pin*1.36;

  return real_potent_CC;
}

float get_real_voltage_value(Uint16 val)
{
  volatile float v_pin;
  volatile float real_voltage_Vdc;  // True value of voltage acquisition
  v_pin = Vcc*val/4095;
  real_voltage_Vdc = v_pin*3.3;

  return real_voltage_Vdc;
}

 

float get_real_current_value(Uint16 val)
{
  volatile float real_current_Idc;  // True value of current acquisition
  volatile float a_pin;
  volatile float current_volt;
  a_pin=Vcc*val/4095;
  current_volt= a_pin*0.071;          // Value of the current in voltage
  real_current_Idc = current_volt*10;

  return real_current_Idc;
}

void set_duty(double PWM,float val)
{
 if(val>0)
 {
  if((PWM+val)<MAX)
   {
    PWM+=val;
   }
   else
   {
    PWM=MAX;
   }
  }

  if(val<0)
 {
  if((PWM+val)>MIN)
   {
    PWM+=val;
   }
   else
   {
    PWM=MIN;
   }
  }
}
 
interrupt void adc_isr(void)
{

  voltage_Vdc = AdcRegs.ADCRESULT0 >>4;	// store results global
  current_Idc = AdcRegs.ADCRESULT1 >>4;	// store results global
  potent_CC = AdcRegs.ADCRESULT2 >>4;	// store results global

  real_current_CC = get_real_current_value(current_Idc);

  // i=pid_update_f_idc(IREF,current_Idc,&idc);
   i=pid_update_f_idc(0.68,real_current_CC,&idc);
  //i=pid_pwm_compute(IREF,current_Idc,&lol);
  i1=i*10;

  if(i1>0)
  {
   if((EPwm1Regs.CMPA.half.CMPA + i1)<MAX)
   {
    EPwm1Regs.CMPA.half.CMPA+=i1;
	EPwm2Regs.CMPA.half.CMPA=EPwm1Regs.CMPA.half.CMPA;
   }
   else
   {
    EPwm1Regs.CMPA.half.CMPA=MAX;
	EPwm2Regs.CMPA.half.CMPA=MAX;
	}
  }
  if(i1<0)
  {
  if((EPwm1Regs.CMPA.half.CMPA + i1)>MIN)
   {
    EPwm1Regs.CMPA.half.CMPA+=i1;
	EPwm2Regs.CMPA.half.CMPA=EPwm1Regs.CMPA.half.CMPA;
   }
   else
   {
    EPwm1Regs.CMPA.half.CMPA=MIN;
	EPwm2Regs.CMPA.half.CMPA=MIN;
   }

  // Reinitialize for next ADC sequence
  AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ2
  AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ2 bit
  PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE

  }

}


interrupt void epwm1_timer_isr(void)
{
   EPwm1TimerIntCount++;

  // Clear INT flag for this timer
   EPwm1Regs.ETCLR.bit.INT = 1;

    
  // Acknowledge this interrupt to receive more interrupts from group 3
  PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}


interrupt void epwm2_timer_isr(void)
{
   EPwm2TimerIntCount++;
   
  // Clear INT flag for this timer
   EPwm2Regs.ETCLR.bit.INT = 1;

  // Acknowledge this interrupt to receive more interrupts from group 3
  PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}

 

