/* ==================================================================================
File name:       F281XPWM.C
                    
Originator:	Digital Control Systems Group
			Texas Instruments

Description:   This file contains source for the Full Compare PWM  drivers for the F281x

Target: TMS320F281x family

=====================================================================================
History:
-------------------------------------------------------------------------------------
 04-15-2005	Version 3.20: Using DSP281x v. 1.00 or higher
----------------------------------------------------------------------------------*/

#include "DSP281x_Examples.h"   // DSP281x Examples Include File
#include "DSP281x_Device.h"     // DSP281x Headerfile Include File
#include "IQmathLib.h"

#include <f281xpwm.h>

#include "DSP281x_Ev.h"
//#include "params.h"


void F281X_EV1_PWM_Init(PWMGEN *p)
{
        EvaRegs.T1PR = p->PeriodMax;              // Init Timer 1 period Register
        EvaRegs.T1CON.all = PWM_INIT_STATE;       // Symmetrical Operation
        EvaRegs.DBTCONA.all = DBTCON_INIT_STATE;  // Init DBTCONA Register
        EvaRegs.ACTRA.all = ACTR_INIT_STATE;      // Init ACTRA Register

        EvaRegs.COMCONA.all = 0xA600;             // Init COMCONA Register

        EvaRegs.CMPR1 = p->PeriodMax;             // Init CMPR1 Register
        EvaRegs.CMPR2 = p->PeriodMax;             // Init CMPR2 Register
        EvaRegs.CMPR3 = p->PeriodMax;             // Init CMPR3 Register
        EALLOW;                       // Enable EALLOW
        GpioMuxRegs.GPAMUX.all |= 0x003F;   // Setting PWM1-6 as primary output pins
        EDIS;                         // Disable EALLOW
}


void F281X_EV1_PWM_Update(PWMGEN *p) 
{       
		int16 MPeriod;
        int32 Tmp;

// Compute the timer period (Q0) from the period modulation input (Q15)
        Tmp = (int32)p->PeriodMax*(int32)p->MfuncPeriod;           // Q15 = Q0*Q15
        MPeriod = (int16)(Tmp>>16) + (int16)(p->PeriodMax>>1);     // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvaRegs.T1PR = MPeriod;

// Compute the compare 1 (Q0) from the PWM 1&2 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC1;                    // Q15 = Q0*Q15
        EvaRegs.CMPR1 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);    // Q0 = (Q15->Q0)/2 + (Q0/2)

// Compute the compare 2 (Q0) from the PWM 3&4 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC2;                   // Q15 = Q0*Q15
        EvaRegs.CMPR2 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)

// Compute the compare 3 (Q0) from the PWM 5&6 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC3;                   // Q15 = Q0*Q15
        EvaRegs.CMPR3 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)
}


void F281X_EV2_PWM_Init(PWMGEN *p)
{
        EvbRegs.T3PR = p->PeriodMax;              // Init Timer 1 period Register
        EvbRegs.T3CON.all = PWM_INIT_STATE;       // Symmetrical Operation
        EvbRegs.DBTCONB.all = DBTCON_INIT_STATE;  // Init DBTCONA Register
        EvbRegs.ACTRB.all = ACTR_INIT_STATE;      // Init ACTRA Register

        EvbRegs.COMCONB.all = 0xA600;             // Init COMCONA Register

        EvbRegs.CMPR4 = p->PeriodMax;             // Init CMPR1 Register
        EvbRegs.CMPR5 = p->PeriodMax;             // Init CMPR2 Register
        EvbRegs.CMPR6 = p->PeriodMax;             // Init CMPR3 Register
        EALLOW;                       // Enable EALLOW
        GpioMuxRegs.GPBMUX.all |= 0x003F;   // Setting PWM1-6 as primary output pins
        EDIS;                         // Disable EALLOW
}


void F281X_EV2_PWM_Update(PWMGEN *p)
{
		int16 MPeriod;
        int32 Tmp;

// Compute the timer period (Q0) from the period modulation input (Q15)
        Tmp = (int32)p->PeriodMax*(int32)p->MfuncPeriod;           // Q15 = Q0*Q15
        MPeriod = (int16)(Tmp>>16) + (int16)(p->PeriodMax>>1);     // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvbRegs.T3PR = MPeriod;

// Compute the compare 1 (Q0) from the PWM 1&2 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC1;                    // Q15 = Q0*Q15
        EvbRegs.CMPR4 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);    // Q0 = (Q15->Q0)/2 + (Q0/2)

// Compute the compare 2 (Q0) from the PWM 3&4 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC2;                   // Q15 = Q0*Q15
        EvbRegs.CMPR5 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)

// Compute the compare 3 (Q0) from the PWM 5&6 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC3;                   // Q15 = Q0*Q15
        EvbRegs.CMPR6 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)

}



void F281X_EVD_PWM_Init(PWMGEND *p)
{
//unsigned int pna=0,pnb=0;

        EvaRegs.T1PR = p->PeriodMax;              // Init Timer 1 period Register

#ifdef DOUBLE_UPDATE_PWM
        EvaRegs.T1CON.all = PWM_INIT_STATE_DOUBLE_UPADTE;       // Symmetrical Operation + DOUBLE UPDATE
#else
        EvaRegs.T1CON.all = PWM_INIT_STATE;       // Symmetrical Operation
#endif		
        
        EvaRegs.DBTCONA.all = DBTCON_INIT_STATE;  // Init DBTCONA Register
        EvaRegs.ACTRA.all = ACTR_INIT_STATE;      // Init ACTRA Register

        EvaRegs.COMCONA.all = 0xa600;//0xA600;             // Init COMCONA Register

        EvaRegs.CMPR1 = p->PeriodMax;             // Init CMPR1 Register
        EvaRegs.CMPR2 = p->PeriodMax;             // Init CMPR2 Register
        EvaRegs.CMPR3 = p->PeriodMax;             // Init CMPR3 Register
        EALLOW;                       // Enable EALLOW
        GpioMuxRegs.GPAMUX.all |= 0x003F;   // Setting PWM1-6 as primary output pins
        EDIS;                         // Disable EALLOW


        EvbRegs.T3PR = p->PeriodMax;              // Init Timer 1 period Register

#ifdef DOUBLE_UPDATE_PWM
        EvbRegs.T3CON.all = PWM_INIT_STATE_DOUBLE_UPADTE;       // Symmetrical Operation + DOUBLE UPDATE
#else
        EvbRegs.T3CON.all = PWM_INIT_STATE;       // Symmetrical Operation
#endif		

        EvbRegs.DBTCONB.all = DBTCON_INIT_STATE;  // Init DBTCONA Register
        EvbRegs.ACTRB.all = ACTR_INIT_STATE;      // Init ACTRA Register

        EvbRegs.COMCONB.all = 0xa600;//0xA600;             // Init COMCONA Register

        EvbRegs.CMPR4 = p->PeriodMax;             // Init CMPR1 Register
        EvbRegs.CMPR5 = p->PeriodMax;             // Init CMPR2 Register
        EvbRegs.CMPR6 = p->PeriodMax;             // Init CMPR3 Register
        EALLOW;                       // Enable EALLOW
        GpioMuxRegs.GPBMUX.all |= 0x003F;   // Setting PWM1-6 as primary output pins
        EDIS;                         // Disable EALLOW
//        pna = p->ShiftPhaseA;//(p->PeriodMax);
//		pnb = p->ShiftPhaseB;


        EvaRegs.T1CNT = 0x0000;
		EvbRegs.T3CNT = 0x0000;

}

#pragma CODE_SECTION(set_predel_dshim,".fast_run");
int16 set_predel_dshim(int16 dshim,int16 dmin,int16 dpwm)
{
    if (dshim < dmin)
   	{
   	  dshim = dmin;
   	}

   	if (dshim > (dpwm - dmin) )
   	{
   	  dshim = (dpwm - dmin);
   	}
    return dshim;
}

#pragma CODE_SECTION(set_predel_dshim_max,".fast_run");
int16 set_predel_dshim_max(int16 dshim,int16 dmin,int16 dpwm)
{
  int d2;
  
/*
    if (dshim < dmin)
   	{   	  
	  return 0;
   	}
	else
	{
   	 if (dshim > (dpwm - dmin) )
   	 {
//   	  dshim = (dpwm + 1);
      return (dpwm + 10);
   	 }
	 else
	  return dshim;
	 
	}
*/	

    
	d2 = dmin/2;

    if (dshim < d2)
   	{
   	  dshim = 0;
	  return dshim;
   	}

    if (dshim < dmin)
   	{
   	  dshim = dmin;
	  return dshim;
   	}


   	if (dshim > (dpwm - d2) )
   	{
   	  dshim = dpwm+dmin;
	  return dshim;
   	}


   	if (dshim > (dpwm - dmin) )
   	{
   	  dshim = (dpwm - dmin);
      return dshim;
   	}

    return dshim;


}


//#pragma CODE_SECTION(F281X_EVD_PWM_Update,".fast_run");
void F281X_EVD_PWM_Update(PWMGEND *p)
{
		int16 MPeriod, Dshim;
        int32 Tmp;


// Compute the timer period (Q0) from the period modulation input (Q15)
        Tmp = (int32)p->PeriodMax*(int32)p->MfuncPeriod;           // Q15 = Q0*Q15
        MPeriod = (int16)(Tmp>>16) + (int16)(p->PeriodMax>>1);     // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvaRegs.T1PR = MPeriod;

// Compute the compare 1 (Q0) from the PWM 1&2 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC1;                    // Q15 = Q0*Q15
		Dshim = (int16)(Tmp>>16) + (int16)(MPeriod>>1);  // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvaRegs.CMPR1 = set_predel_dshim(Dshim,(int16)p->PeriodMin,(int16)MPeriod);

// Compute the compare 2 (Q0) from the PWM 3&4 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC2;                   // Q15 = Q0*Q15
		Dshim = (int16)(Tmp>>16) + (int16)(MPeriod>>1);  // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvaRegs.CMPR2 = set_predel_dshim(Dshim,(int16)p->PeriodMin,(int16)MPeriod);

// Compute the compare 3 (Q0) from the PWM 5&6 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC3;                   // Q15 = Q0*Q15
		Dshim = (int16)(Tmp>>16) + (int16)(MPeriod>>1);  // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvaRegs.CMPR3 = set_predel_dshim(Dshim,(int16)p->PeriodMin,(int16)MPeriod);


// Compute the timer period (Q0) from the period modulation input (Q15)
//        Tmp = (int32)p->PeriodMax*(int32)p->MfuncPeriod;           // Q15 = Q0*Q15
//        MPeriod = (int16)(Tmp>>16) + (int16)(p->PeriodMax>>1);     // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvbRegs.T3PR = MPeriod;

// Compute the compare 1 (Q0) from the PWM 1&2 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC4;                    // Q15 = Q0*Q15
		Dshim = (int16)(Tmp>>16) + (int16)(MPeriod>>1);  // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvbRegs.CMPR4 = set_predel_dshim(Dshim,(int16)p->PeriodMin,(int16)MPeriod);

// Compute the compare 2 (Q0) from the PWM 3&4 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC5;                   // Q15 = Q0*Q15
		Dshim = (int16)(Tmp>>16) + (int16)(MPeriod>>1);  // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvbRegs.CMPR5 = set_predel_dshim(Dshim,(int16)p->PeriodMin,(int16)MPeriod);

// Compute the compare 3 (Q0) from the PWM 5&6 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC6;                   // Q15 = Q0*Q15
		Dshim = (int16)(Tmp>>16) + (int16)(MPeriod>>1);  // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvbRegs.CMPR6 = set_predel_dshim(Dshim,(int16)p->PeriodMin,(int16)MPeriod);

}

