#include "pwm_sim.h"
#include "xp_write_xpwm_time.h"
#include "main_matlab.h"
#include "wrapper_inu.h"
#include "params_pwm24.h"
#include "def.h"

TimerSimHandle t1sim;
TimerSimHandle t2sim;
TimerSimHandle t3sim;
TimerSimHandle t4sim;
TimerSimHandle t5sim;
TimerSimHandle t6sim;
TimerSimHandle t7sim;
TimerSimHandle t8sim;
TimerSimHandle t9sim;
TimerSimHandle t10sim;
TimerSimHandle t11sim;
TimerSimHandle t12sim;

void Simulate_Timers(void)
{
	SimulateMainPWM(&t1sim, xpwm_time.Ta0_0);
	SimulatePWM(&t2sim, xpwm_time.Ta0_1);
	SimulatePWM(&t3sim, xpwm_time.Tb0_0);
	SimulatePWM(&t4sim, xpwm_time.Tb0_1);
	SimulatePWM(&t5sim, xpwm_time.Tc0_0);
	SimulatePWM(&t6sim, xpwm_time.Tc0_1);
	SimulatePWM(&t7sim, xpwm_time.Ta1_0);
	SimulatePWM(&t8sim, xpwm_time.Ta1_1);
	SimulatePWM(&t9sim, xpwm_time.Tb1_0);
	SimulatePWM(&t10sim, xpwm_time.Tb1_1);
	SimulatePWM(&t11sim, xpwm_time.Tc1_0);
	SimulatePWM(&t12sim, xpwm_time.Tc1_1);
}

void Init_Timers(void)
{
	initSimulateTim(&t1sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t2sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t3sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t4sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t5sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t6sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t7sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t8sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t9sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t10sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t11sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
	initSimulateTim(&t12sim, FREQ_INTERNAL_GENERATOR_XILINX_TMS / FREQ_PWM, FREQ_INTERNAL_GENERATOR_XILINX_TMS * dt);
}




void initSimulateTim(TimerSimHandle* tsim, int period, double step)
{
	tsim->dtsim.stateDt = 1;
	tsim->TPr = period/2;
	tsim->TxCntPlus = step;
	tsim->dtsim.DtCntPeriod = (int)(DT / dt);
}

void SimulateMainPWM(TimerSimHandle* tsim, int compare)
{
	if (simulateTimAndGetCompare(tsim, compare))
		mcu_simulate_step();
	simulateActionActionQualifierSubmodule(tsim);
	simulateDeadBendSubmodule(tsim);
	simulateTripZoneSubmodule(tsim);
}

void SimulatePWM(TimerSimHandle* tsim, int compare)
{
	simulateTimAndGetCompare(tsim, compare);
	simulateActionActionQualifierSubmodule(tsim);
	tsim->ciA = tsim->dtsim.ciA_DT;
	tsim->ciB = tsim->dtsim.ciB_DT;
	//simulateDeadBendSubmodule(tsim);
	//simulateTripZoneSubmodule(tsim);
}


int simulateTimAndGetCompare(TimerSimHandle *tsim, int compare)
{
	int interruptflag = 0;
	tsim->tcntAuxPrev = tsim->tcntAux;
	tsim->tcntAux += tsim->TxCntPlus;

	if (tsim->tcntAux > tsim->TPr) {
		tsim->tcntAux -= tsim->TPr * 2.;
		tsim->cmpA = compare;
		interruptflag = 1;
	}
	if ((tsim->tcntAuxPrev < 0) && (tsim->tcntAux >= 0)) {
		tsim->cmpA = compare;
		interruptflag = 1;
	}
	tsim->tcnt = fabs(tsim->tcntAux);
	return interruptflag;
}



void simulateActionActionQualifierSubmodule(TimerSimHandle* tsim)
{
	// Моделируем Action-Qualifier Submodule
	if (tsim->cmpA > tsim->tcnt) {
		tsim->dtsim.ciA_DT = 0;
		tsim->dtsim.ciB_DT = 1;
	}
	else if (tsim->cmpA < tsim->tcnt) {
		tsim->dtsim.ciA_DT = 1;
		tsim->dtsim.ciB_DT = 0;
	}
}

void simulateDeadBendSubmodule(TimerSimHandle* tsim)
{
	// Моделируем Dead-Band Submodule
	if (tsim->dtsim.stateDt == 1) {
		tsim->ciA = tsim->dtsim.ciA_DT;
		tsim->ciB = 0;
		if (tsim->dtsim.ciA_DT == 1)
			tsim->dtsim.dtcnt = tsim->dtsim.DtCntPeriod;
		if (tsim->dtsim.dtcnt > 0)
			tsim->dtsim.dtcnt--;
		else
			tsim->dtsim.stateDt = 2;
	}
	else if (tsim->dtsim.stateDt == 2) {
		tsim->ciA = 0;
		tsim->ciB = tsim->dtsim.ciB_DT;
		if (tsim->dtsim.ciB_DT == 1)
			tsim->dtsim.dtcnt = tsim->dtsim.DtCntPeriod;
		if (tsim->dtsim.dtcnt > 0)
			tsim->dtsim.dtcnt--;
		else
			tsim->dtsim.stateDt = 1;
	}
}

void simulateTripZoneSubmodule(TimerSimHandle* tsim)
{
	//// Моделируем Trip-Zone Submodule
	//	// ... clear flag for one-shot trip latch
	//if (EPwm1Regs.TZCLR.all == 0x0004) {
	//	EPwm1Regs.TZCLR.all = 0x0000;
	//	EPwm1Regs.TZFRC.all = 0x0000;
	//}	// ... forces a one-shot trip event
	//if (EPwm1Regs.TZFRC.all == 0x0004)
	//	ci1A_DT = ci1B_DT = 0;
}