// Automatically generated C++ file on Thu May 2 15:09:53 2024 // // To build with Digital Mars C++ Compiler: // // dmc -mn -WD digital_pwm_gen.cpp kernel32.lib #include union uData { bool b; char c; unsigned char uc; short s; unsigned short us; int i; unsigned int ui; float f; double d; long long int i64; unsigned long long int ui64; char *str; unsigned char *bytes; }; // int DllMain() must exist and return 1 for a process to load the .DLL // See https://docs.microsoft.com/en-us/windows/win32/dlls/dllmain for more information. int __stdcall DllMain(void *module, unsigned int reason, void *reserved) { return 1; } void bzero(void *ptr, unsigned int count) { unsigned char *first = (unsigned char *) ptr; unsigned char *last = first + count; while(first < last) *first++ = '\0'; } // #undef pin names lest they collide with names in any header file(s) you might include. #undef Tick #undef PWM #undef nPWM #undef Reset #undef PWM_Test #undef Max_Duty struct sDIGITAL_PWM_GEN { // declare the structure here int Prev_Tick_State; //Holds previouse tick state int Time_Base_Counter; //This will hold the duty cycle generating counter int Dead_Time_Ticks; //Put here the amount ticks to form the required dead time. int Dead_Time_Counter; //This counter will count the dead time ticks int Dead_Time2_Counter; int Full_Cycle_TimeBase_Count; //This represents a full switching periode of 100 ticks (0-99) double Reset_Threshold; //This acts as the current sense (Reset pin) threshold level (Usually 1V). int Min_Duty; //1% is the minimum duty cycle allowed int Required_Max_Duty; //This will hold a limit set externally on the Max allowed duty cycle pin. bool State1_Completed; //Marks if all output transitions associated with (Time_Base_Counter = Required_Duty_Cycle)state were completed. bool State2_Completed; //Marks if all output transitions associated with (Time_Base_Counter =0) state were completed. bool Reset_State_Completed; //Marks that all output transitions associated with Reset were completed. bool Reset_Event; //This will act as a comparator marking "1" when the (Reset >= Reset_Threshold) bool Prev_Reset_Event; int init_detect; //initialization }; extern "C" __declspec(dllexport) void digital_pwm_gen(struct sDIGITAL_PWM_GEN **opaque, double t, union uData *data) { bool Tick = data[0].b; // input double Reset = data[1].d; // input int Max_Duty = data[2].i; // input bool &PWM = data[3].b; // output bool &nPWM = data[4].b; // output double &PWM_Test = data[5].d; // output if(!*opaque) { *opaque = (struct sDIGITAL_PWM_GEN *) malloc(sizeof(struct sDIGITAL_PWM_GEN)); bzero(*opaque, sizeof(struct sDIGITAL_PWM_GEN)); } struct sDIGITAL_PWM_GEN *inst = *opaque; // initialization if(inst->init_detect==0) { inst->init_detect=1; inst->Prev_Tick_State=0; inst->Time_Base_Counter =0; inst->Dead_Time_Ticks =2; inst->Dead_Time_Counter =1; inst->Dead_Time2_Counter=0; inst->Full_Cycle_TimeBase_Count =99; inst->Reset_Threshold =1; inst->Min_Duty =1; inst->Required_Max_Duty=0; inst->State1_Completed =true; inst->State2_Completed =true; inst->Reset_State_Completed =true; inst->Reset_Event=false; inst->Prev_Reset_Event=0; } // Implement module evaluation code here: if (inst->Prev_Tick_State==0 && Tick==1) //Actions on rising Edge of Tick { inst->Required_Max_Duty = int(Max_Duty); //Sample the required Max duty cycle limit pin if (inst->Required_Max_Duty > 99) inst->Required_Max_Duty=99; //Make sure we limit the maximum required duty cycle to a valid value. if (inst->Required_Max_Duty <= inst->Min_Duty ) inst->Required_Max_Duty = inst->Min_Duty; //Make sure we limit the minimum duty cycle too. // ---Sample Reset Pin------------ if ((Reset >= inst->Reset_Threshold)) //Sample the reset pin voltage once per switching cycle and act according to its value compared to a threshold { inst->Reset_Event=1; } else if ((Reset < inst->Reset_Threshold)) { inst->Reset_Event=0; } PWM_Test = inst->Time_Base_Counter; //----------------------------- if ((inst->Time_Base_Counter == 0)&&(inst->Reset_State_Completed)||(!inst->State2_Completed)) { nPWM=0; //Start new switching cycle by first holding the complimentary PWM output low. inst->State2_Completed=0; //Mark that the whole transition associated with this state as yet to be done if (inst->Dead_Time_Counter == inst->Dead_Time_Ticks) { PWM=1; //Output high on PWM output as Dead time elapse inst->Dead_Time_Counter=0; inst->State2_Completed=1; //Mark that we concluded this state associated outputs transitions } else { inst->Dead_Time_Counter++; } } //--------------------------- if (((inst->Time_Base_Counter == inst->Required_Max_Duty)&&(inst->Reset_State_Completed)||(!inst->State1_Completed))) { PWM=0; //Set PWM output low. inst->State1_Completed=0; //Mark that the whole transition associated with this state as yet to be done if (inst->Dead_Time_Counter == inst->Dead_Time_Ticks) { nPWM=1; //Output high on PWM output as Dead time elapse inst->Dead_Time_Counter=0; inst->State1_Completed=1; //Mark that we concluded this state associated outputs transitions } else { inst->Dead_Time_Counter++; //Increment the dead time counter } } //-------------------------- if ((inst->Time_Base_Counter < inst->Full_Cycle_TimeBase_Count))//We counted a full switching cycle { inst->Time_Base_Counter++; } else if ((inst->Time_Base_Counter == inst->Full_Cycle_TimeBase_Count)) { inst->Time_Base_Counter=0; } //------------------------- if ((inst->Reset_Event)&&((!inst->Reset_State_Completed)||(inst->Time_Base_Counter <= inst->Full_Cycle_TimeBase_Count))) //We got a Reset but didn't complete associated actions { PWM=0; //Hold PWM output at low. if (inst->Dead_Time_Counter == inst->Dead_Time_Ticks) //We concluded the dead time period { nPWM=1; //Set nPWM output inst->Dead_Time_Counter=0; //Mark that Dead time action was concluded if ((inst->Time_Base_Counter <= inst->Full_Cycle_TimeBase_Count)&& (inst->Dead_Time_Counter=0)) //We finished the output transitions but need to wait for full switching cycle completion { inst->Reset_State_Completed=0; //Mark that we didn't complete the reset state action inst->Time_Base_Counter++; //Keep increasing the time base counter } else { inst->Time_Base_Counter=0; //Restart a new counting cycle inst->Reset_State_Completed=1; } } else if (inst->Dead_Time_CounterDead_Time_Ticks) //We didn't conclude the dead time { inst->Dead_Time_Counter++; } } } //End of actions on rising Edge of Tick inst->Prev_Tick_State = Tick; //Store the current state of Tick } extern "C" __declspec(dllexport) void Destroy(struct sDIGITAL_PWM_GEN *inst) { free(inst); }