2025-01-17 10:19:40 +03:00
|
|
|
|
#include "pwm_sim.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;
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
PWMPhaseSimHandle PWMPhaseA1;
|
|
|
|
|
PWMPhaseSimHandle PWMPhaseB1;
|
|
|
|
|
PWMPhaseSimHandle PWMPhaseC1;
|
|
|
|
|
PWMPhaseSimHandle PWMPhaseA2;
|
|
|
|
|
PWMPhaseSimHandle PWMPhaseB2;
|
|
|
|
|
PWMPhaseSimHandle PWMPhaseC2;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
void Simulate_PWM(void)
|
2025-01-17 10:19:40 +03:00
|
|
|
|
{
|
2025-01-17 12:50:59 +03:00
|
|
|
|
Simulate_PWMPhase(&PWMPhaseA1, xpwm_time.Ta0_1, xpwm_time.Ta0_0);
|
|
|
|
|
Simulate_PWMPhase(&PWMPhaseB1, xpwm_time.Tb0_1, xpwm_time.Tb0_0);
|
|
|
|
|
Simulate_PWMPhase(&PWMPhaseC1, xpwm_time.Tc0_1, xpwm_time.Tc0_0);
|
|
|
|
|
Simulate_PWMPhase(&PWMPhaseA2, xpwm_time.Ta1_1, xpwm_time.Ta1_0);
|
|
|
|
|
Simulate_PWMPhase(&PWMPhaseB2, xpwm_time.Tb1_1, xpwm_time.Tb1_0);
|
|
|
|
|
Simulate_PWMPhase(&PWMPhaseC2, xpwm_time.Tc1_1, xpwm_time.Tc1_0);
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
void Init_PWM_Simulation(void)
|
2025-01-17 10:19:40 +03:00
|
|
|
|
{
|
2025-01-17 12:50:59 +03:00
|
|
|
|
Init_PWMPhase_Simulation(&PWMPhaseA1, &t1sim, &t2sim,
|
|
|
|
|
PWM_PERIOD, PWM_TICK_STEP);
|
2025-01-17 10:19:40 +03:00
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
Init_PWMPhase_Simulation(&PWMPhaseB1, &t3sim, &t4sim,
|
|
|
|
|
PWM_PERIOD, PWM_TICK_STEP);
|
2025-01-17 10:19:40 +03:00
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
Init_PWMPhase_Simulation(&PWMPhaseC1, &t5sim, &t6sim,
|
|
|
|
|
PWM_PERIOD, PWM_TICK_STEP);
|
|
|
|
|
|
|
|
|
|
Init_PWMPhase_Simulation(&PWMPhaseA2, &t7sim, &t8sim,
|
|
|
|
|
PWM_PERIOD, PWM_TICK_STEP);
|
|
|
|
|
|
|
|
|
|
Init_PWMPhase_Simulation(&PWMPhaseB2, &t9sim, &t10sim,
|
|
|
|
|
PWM_PERIOD, PWM_TICK_STEP);
|
|
|
|
|
|
|
|
|
|
Init_PWMPhase_Simulation(&PWMPhaseC2, &t11sim, &t12sim,
|
|
|
|
|
PWM_PERIOD, PWM_TICK_STEP);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
t1sim.simulatePwm = (void (*)())Simulate_MainTIM;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Simulate_PWMPhase(PWMPhaseSimHandle* tksim, int T1, int T0)
|
2025-01-17 10:19:40 +03:00
|
|
|
|
{
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tksim->tsim1->simulatePwm(tksim->tsim1, T1);
|
|
|
|
|
tksim->tsim2->simulatePwm(tksim->tsim2, T0);
|
|
|
|
|
|
|
|
|
|
#ifdef PWM_SIMULATION_MODE_TK_LINES
|
|
|
|
|
convertSVGenTimesToTkLines(tksim);
|
|
|
|
|
xilinxPwm3LevelSimulation(tksim);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef PWM_SIMULATION_MODE_REGULAR_PWM
|
|
|
|
|
simulateActionActionQualifierSubmodule(tksim->tsim1);
|
|
|
|
|
simulateDeadBendSubmodule(tksim->tsim1, &tksim->pwmOut.ci1A, &tksim->pwmOut.ci1B);
|
|
|
|
|
simulateTripZoneSubmodule(tksim->tsim1);
|
|
|
|
|
|
|
|
|
|
simulateActionActionQualifierSubmodule(tksim->tsim2);
|
|
|
|
|
simulateDeadBendSubmodule(tksim->tsim2, &tksim->pwmOut.ci2A, &tksim->pwmOut.ci2B);
|
|
|
|
|
simulateTripZoneSubmodule(tksim->tsim2);
|
|
|
|
|
#endif
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
void Simulate_MainTIM(TimerSimHandle* tsim, int compare)
|
2025-01-17 10:19:40 +03:00
|
|
|
|
{
|
2025-01-17 12:50:59 +03:00
|
|
|
|
#ifdef ENABLE_UNITED_COUNTER_FOR_ALL_PWM
|
2025-01-17 10:19:40 +03:00
|
|
|
|
tsim->tcntAuxPrev = tsim->tcntAux;
|
|
|
|
|
tsim->tcntAux += tsim->TxCntPlus;
|
|
|
|
|
#endif
|
|
|
|
|
if (simulateTimAndGetCompare(tsim, compare))
|
|
|
|
|
mcu_simulate_step();
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
void Simulate_SimpleTIM(TimerSimHandle* tsim, int compare)
|
2025-01-17 10:19:40 +03:00
|
|
|
|
{
|
2025-01-17 12:50:59 +03:00
|
|
|
|
simulateTimAndGetCompare(tsim, compare);
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int simulateTimAndGetCompare(TimerSimHandle* tsim, int compare)
|
|
|
|
|
{
|
|
|
|
|
int interruptflag = 0;
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
#ifdef ENABLE_UNITED_COUNTER_FOR_ALL_PWM
|
2025-01-17 10:19:40 +03:00
|
|
|
|
tsim->tcntAuxPrev = t1sim.tcntAuxPrev;
|
|
|
|
|
tsim->tcntAux = t1sim.tcntAux;
|
|
|
|
|
#else
|
|
|
|
|
tsim->tcntAuxPrev = tsim->tcntAux;
|
|
|
|
|
tsim->tcntAux += tsim->TxCntPlus;
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (tsim->tcntAux > tsim->TxPeriod) {
|
|
|
|
|
tsim->tcntAux -= tsim->TxPeriod * 2.;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
tsim->cmpA = compare;
|
|
|
|
|
interruptflag = 1;
|
|
|
|
|
}
|
|
|
|
|
if ((tsim->tcntAuxPrev < 0) && (tsim->tcntAux >= 0)) {
|
|
|
|
|
tsim->cmpA = compare;
|
|
|
|
|
interruptflag = 1;
|
|
|
|
|
}
|
|
|
|
|
tsim->tcnt = fabs(tsim->tcntAux);
|
|
|
|
|
return interruptflag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
void convertSVGenTimesToTkLines(PWMPhaseSimHandle *tksim) {
|
2025-01-17 10:19:40 +03:00
|
|
|
|
TimerSimHandle* tsim1 = tksim->tsim1;
|
|
|
|
|
TimerSimHandle* tsim2 = tksim->tsim2;
|
|
|
|
|
//Phase Uni
|
|
|
|
|
if ((tsim1->cmpA < tsim1->tcnt) && (tsim2->cmpA < tsim2->tcnt)) {
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tksim->tkLineA = 0;
|
|
|
|
|
tksim->tkLineB = 1;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
else if ((tsim1->cmpA > tsim1->tcnt) && (tsim2->cmpA > tsim2->tcnt)) {
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tksim->tkLineA = 1;
|
|
|
|
|
tksim->tkLineB = 0;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
else if ((tsim1->cmpA < tsim1->tcnt) && (tsim2->cmpA > tsim2->tcnt)) {
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tksim->tkLineA = 1;
|
|
|
|
|
tksim->tkLineB = 1;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
else {
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tksim->tkLineA = 0;
|
|
|
|
|
tksim->tkLineB = 0;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
void xilinxPwm3LevelSimulation(PWMPhaseSimHandle *tksim) {
|
|
|
|
|
TimerSimHandle* tsim1 = tksim->tsim1;
|
|
|
|
|
TimerSimHandle* tsim2 = tksim->tsim2;
|
|
|
|
|
DeadTimeSimHandle* deadtime = &tksim->deadtime;
|
|
|
|
|
PWMPhaseOutput* pwmOut = &tksim->pwmOut;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
|
|
|
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
//PhaseA Uni1
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (tksim->tkLineB == 0 && tksim->tkLineA == 1) {
|
|
|
|
|
if ((pwmOut->ci1A == 0 || pwmOut->ci2A == 0) && deadtime->stateDt == stateDtReady) {
|
|
|
|
|
pwmOut->ci1B = 0;
|
|
|
|
|
pwmOut->ci2B = 0;
|
|
|
|
|
deadtime->dtcnt = deadtime->DtPeriod;
|
|
|
|
|
deadtime->stateDt = stateDtWait;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (deadtime->stateDt == stateDtWait) {
|
|
|
|
|
if (deadtime->dtcnt > 0)
|
|
|
|
|
deadtime->dtcnt--;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
else
|
2025-01-17 12:50:59 +03:00
|
|
|
|
deadtime->stateDt = stateDtReady;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (deadtime->stateDt == stateDtReady) {
|
|
|
|
|
pwmOut->ci1A = 1;
|
|
|
|
|
pwmOut->ci2A = 1;
|
|
|
|
|
pwmOut->ci1B = 0;
|
|
|
|
|
pwmOut->ci2B = 0;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
else if (tksim->tkLineB == 1 && tksim->tkLineA == 0) {
|
|
|
|
|
if ((pwmOut->ci1B == 0 || pwmOut->ci2B == 0) && deadtime->stateDt == stateDtReady) {
|
|
|
|
|
pwmOut->ci1A = 0;
|
|
|
|
|
pwmOut->ci2B = 0;
|
|
|
|
|
deadtime->dtcnt = deadtime->DtPeriod;
|
|
|
|
|
deadtime->stateDt = stateDtWait;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (deadtime->stateDt == stateDtWait) {
|
|
|
|
|
if (deadtime->dtcnt > 0)
|
|
|
|
|
deadtime->dtcnt--;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
else
|
2025-01-17 12:50:59 +03:00
|
|
|
|
deadtime->stateDt = stateDtReady;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (deadtime->stateDt == stateDtReady) {
|
|
|
|
|
pwmOut->ci1A = 0;
|
|
|
|
|
pwmOut->ci2A = 0;
|
|
|
|
|
pwmOut->ci1B = 1;
|
|
|
|
|
pwmOut->ci2B = 1;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
else if (tksim->tkLineA == 0 && tksim->tkLineB == 0) {
|
|
|
|
|
if ((pwmOut->ci1B == 0 || pwmOut->ci2A == 0) && deadtime->stateDt == stateDtReady) {
|
|
|
|
|
pwmOut->ci1A = 0;
|
|
|
|
|
pwmOut->ci2B = 0;
|
|
|
|
|
deadtime->dtcnt = deadtime->DtPeriod;
|
|
|
|
|
deadtime->stateDt = stateDtWait;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (deadtime->stateDt == stateDtWait) {
|
|
|
|
|
if (deadtime->dtcnt > 0)
|
|
|
|
|
deadtime->dtcnt--;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
else
|
2025-01-17 12:50:59 +03:00
|
|
|
|
deadtime->stateDt = stateDtReady;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (deadtime->stateDt == stateDtReady) {
|
|
|
|
|
pwmOut->ci1A = 0;
|
|
|
|
|
pwmOut->ci2A = 1;
|
|
|
|
|
pwmOut->ci1B = 1;
|
|
|
|
|
pwmOut->ci2B = 0;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2025-01-17 12:50:59 +03:00
|
|
|
|
pwmOut->ci1A = 0;
|
|
|
|
|
pwmOut->ci2A = 0;
|
|
|
|
|
pwmOut->ci1B = 0;
|
|
|
|
|
pwmOut->ci2B = 0;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void simulateActionActionQualifierSubmodule(TimerSimHandle* tsim)
|
|
|
|
|
{
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Action-Qualifier Submodule
|
|
|
|
|
if (tsim->cmpA > tsim->tcnt) {
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tsim->deadtime.pre_ciA = 0;
|
|
|
|
|
tsim->deadtime.pre_ciB = 1;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
else if (tsim->cmpA < tsim->tcnt) {
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tsim->deadtime.pre_ciA = 1;
|
|
|
|
|
tsim->deadtime.pre_ciB = 0;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-17 12:50:59 +03:00
|
|
|
|
void simulateDeadBendSubmodule(TimerSimHandle* tsim, int* ciA, int* ciB)
|
2025-01-17 10:19:40 +03:00
|
|
|
|
{
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Dead-Band Submodule
|
2025-01-17 12:50:59 +03:00
|
|
|
|
if (tsim->deadtime.stateDt == 0) {
|
|
|
|
|
*ciA = tsim->deadtime.pre_ciA;
|
|
|
|
|
*ciB = 0;
|
|
|
|
|
if (tsim->deadtime.pre_ciA == 1)
|
|
|
|
|
tsim->deadtime.dtcnt = tsim->deadtime.DtPeriod;
|
|
|
|
|
if (tsim->deadtime.dtcnt > 0)
|
|
|
|
|
tsim->deadtime.dtcnt--;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
else
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tsim->deadtime.stateDt = 1;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
2025-01-17 12:50:59 +03:00
|
|
|
|
else if (tsim->deadtime.stateDt == 1) {
|
|
|
|
|
*ciA = 0;
|
|
|
|
|
*ciB = tsim->deadtime.pre_ciB;
|
|
|
|
|
if (tsim->deadtime.pre_ciB == 1)
|
|
|
|
|
tsim->deadtime.dtcnt = tsim->deadtime.DtPeriod;
|
|
|
|
|
if (tsim->deadtime.dtcnt > 0)
|
|
|
|
|
tsim->deadtime.dtcnt--;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
else
|
2025-01-17 12:50:59 +03:00
|
|
|
|
tsim->deadtime.stateDt = 0;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void simulateTripZoneSubmodule(TimerSimHandle* tsim)
|
|
|
|
|
{
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Trip-Zone Submodule
|
|
|
|
|
// ... clear flag for one-shot trip latch
|
|
|
|
|
// // ... 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;
|
2025-01-17 12:50:59 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Init_PWMPhase_Simulation(PWMPhaseSimHandle* tksim, TimerSimHandle* tsim1, TimerSimHandle* tsim2, int period, double step)
|
|
|
|
|
{
|
|
|
|
|
tksim->tsim1 = tsim1;
|
|
|
|
|
tksim->tsim2 = tsim2;
|
|
|
|
|
|
|
|
|
|
Init_TIM_Simulation(tksim->tsim1, period, step);
|
|
|
|
|
Init_TIM_Simulation(tksim->tsim2, period, step);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Init_TIM_Simulation(TimerSimHandle* tsim, int period, double step)
|
|
|
|
|
{
|
|
|
|
|
tsim->deadtime.stateDt = stateDtWait;
|
|
|
|
|
tsim->TxPeriod = period;
|
|
|
|
|
tsim->TxCntPlus = step * 2;
|
|
|
|
|
tsim->deadtime.DtPeriod = (int)(DT / hmcu.sSimSampleTime);
|
|
|
|
|
tsim->simulatePwm = (void (*)())Simulate_SimpleTIM;
|
2025-01-17 10:19:40 +03:00
|
|
|
|
}
|