#define MAIN 1

#include "system_defines.h"
#include "cyclone_device.h"
#include "pmbus_commands.h"
#include "pmbus.h"
#include "variables.h"
#include "function_definitions.h"
#include "software_interrupts.h"
#include "cyclone_defines.h"
#include "stdio.h"

#define PERIOD         (40000) // 4 Ghz high speed clock/100 KHz switching frequency = 40000.

//to jumper 64 pin open loop board for fake power supply feed back
//
//  J22 pins 2 to 3 - DPWM0A to FLTRDPWM0
// J11 pins 1 to 2 - FLTRDPWM0 to voltage loop feedback
// j7 pins 1 to 2 - voltage loop feedback to EAP0

int ram_eadcdac; 
// comment for hyperknob [min=0, max=16383, step=256]

void init_dpwm0(void) 
{

    Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 0;     //disable locally for init
	Dpwm0Regs.DPWMCTRL0.bit.CLA_EN = 1;		//default is 1 - use cla

	Dpwm0Regs.DPWMCTRL0.bit.PWM_MODE = 0; //normal mode
	Dpwm0Regs.DPWMPRD.all = PERIOD;         //use .all for all values, make sure scaling matches.
	Dpwm0Regs.DPWMEV1.all = 0;              //Put event 1 at start of period
	Dpwm0Regs.DPWMEV2.all = PERIOD/4;       //1/4 of period - divide is OK because it's all constants.
	Dpwm0Regs.DPWMEV3.all = PERIOD/2;       //1/2 of period   
	Dpwm0Regs.DPWMEV4.all = (PERIOD * 3)/4; //3/4 of period
	Dpwm0Regs.DPWMSAMPTRIG1.all = (PERIOD * 3)/4; //3/4 of period

	Dpwm0Regs.DPWMCTRL2.bit.SAMPLE_TRIG_1_EN = 1; //enable 1 sample trigger
	Dpwm0Regs.DPWMCTRL1.bit.EVENT_UP_SEL = 1; //update at end of period

    Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 1;     //enable locally

}

void init_filter0(void)
{

//PID setup taken from a random topology - lab is for closing loop, not tuning parameters.

	Filter0Regs.FILTERKPCOEF0.bit.KP_COEF_0 = 800;

	Filter0Regs.FILTERKICOEF0.bit.KI_COEF_0 = 50;

	Filter0Regs.FILTERKDCOEF0.bit.KD_COEF_0 = 1500;

	Filter0Regs.FILTERKDALPHA.bit.KD_ALPHA_0 = -1;

	Filter0Regs.FILTERKICLPHI.bit.KI_CLAMP_HIGH = 0x7FFFFF;
    Filter0Regs.FILTERKICLPLO.bit.KI_CLAMP_LOW = 0;

	Filter0Regs.FILTEROCLPHI.bit.OUTPUT_CLAMP_HIGH = 0x7FFFFF;
	Filter0Regs.FILTEROCLPLO.bit.OUTPUT_CLAMP_LOW = 0;

    Filter0Regs.FILTERCTRL.bit.FILTER_EN = 1;
     //enable OK here, because nothing will happen until DPWM and front end are globally enabled

	//Better option for handling shoot through - uses full dynamic range of filter

	LoopMuxRegs.FILTERKCOMPA.bit.KCOMP0 = (PERIOD/2) >> 4; //KCOMP is at 4 ns, period is at 250 ps
	Filter0Regs.FILTERCTRL.bit.OUTPUT_MULT_SEL = 0; //select half period kcomp for output multiplier

}

void init_loop_mux(void)
{
	LoopMuxRegs.DPWMMUX.bit.DPWM0_FILTER_SEL = 0; //use filter 0 for DPWM 0
	
	LoopMuxRegs.SAMPTRIGCTRL.bit.FE0_TRIG_DPWM0_EN = 1; //use DPWM0 for filter0 sample trigger	
}

void global_enable(void)
{
	union GLBEN_REG glben_store; //collect global enable bits for simultaneous use

	glben_store.all = 0;

	glben_store.bit.DPWM0_EN = 1;

	glben_store.bit.FE_CTRL0_EN = 1;

	LoopMuxRegs.GLBEN = glben_store;
}
void init_front_end0(void)
{
	FeCtrl0Regs.EADCDAC.bit.DAC_VALUE = 0;
	FeCtrl0Regs.EADCCTRL.bit.AFE_GAIN = 2;
}

void main()
{
	if(GioRegs.FAULTIN.bit.TMS_IN == 0) //emergency backdoor - TMS is normally pulled up by external resistor
	{
		clear_integrity_word();  //if it's pulled down, clear checksum (integrity word)
	}

	init_pmbus();
	init_dpwm0();
	init_filter0();
	init_loop_mux();
	init_front_end0();
	global_enable();
	ram_eadcdac = FeCtrl0Regs.EADCDAC.bit.DAC_VALUE; //initialize hyperknob
	for(;;)
	{
		pmbus_handler();
		FeCtrl0Regs.EADCDAC.bit.DAC_VALUE = ram_eadcdac; //put hyperknob value into register
	}
}

#pragma INTERRUPT(c_int00,RESET)

void c_int00(void)
{
	main();
}
