// Automatically generated C++ file on Mon Feb 19 11:51:53 2024 // // To build with Digital Mars C++ Compiler: // // dmc -mn -WD delaycompare.cpp kernel32.lib #include #include #include #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 display(const char *fmt, ...) { // for diagnostic print statements msleep(30); fflush(stdout); va_list args = { 0 }; va_start(args, fmt); vprintf(fmt, args); va_end(args); fflush(stdout); msleep(30); } 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 V1 #undef V2 #undef OUT #undef DelayOut struct sDELAYCOMPARE { // declare the structure here double lastOUT; double lastDelayOut; double lastT; }; extern "C" __declspec(dllexport) void delaycompare(struct sDELAYCOMPARE **opaque, double t, union uData *data) { double V1 = data[0].d; // input double V2 = data[1].d; // input double delay = data[2].d; // input parameter bool &OUT = data[3].b; // output bool &DelayOut = data[4].b; // output if(!*opaque) { *opaque = (struct sDELAYCOMPARE *) malloc(sizeof(struct sDELAYCOMPARE)); bzero(*opaque, sizeof(struct sDELAYCOMPARE)); } struct sDELAYCOMPARE *inst = *opaque; // Implement module evaluation code here: // inst->lastT is time triggered compare event if (inst->lastT==0) inst->lastT=1e308; // set triggered time to infinite at startup // compare event if (V1 > V2 & OUT==0){ // trigger by V1 > V2 and active OUT equal 0 OUT=1; // set OUT to 1 inst->lastOUT = OUT; // store OUT into inst->lastOUT for Trunc() inst->lastT = t; // store triggering time into inst->lastT } else if (V2 > V1 & OUT==1){ // trigger by V2 > V1 and active OUT equal 1 OUT=0; // set OUT to 0 inst->lastOUT = OUT; inst->lastT=t; } // delay event if (t - inst->lastT>delay & DelayOut==0){ // trigger by time (t) - triggered time (inst->lastT) > delay and active DelayOut equal 0 DelayOut=1; // set DelayOut to 1 inst->lastDelayOut=DelayOut; // store DelayOut into inst->lastDelayOut for Trunc() inst->lastT=1e308; // reset triggered time to infinite } else if (t - inst->lastT>delay & DelayOut==1){ // trigger by time (t) - triggered time (inst->lastT) > delay and active DelayOut equal 1 DelayOut=0; // set DelayOut to 0 inst->lastDelayOut=DelayOut; inst->lastT=1e308; } } extern "C" __declspec(dllexport) double MaxExtStepSize(struct sDELAYCOMPARE *inst) { return 1e308; // implement a good choice of max timestep size that depends on struct sDELAYCOMPARE } extern "C" __declspec(dllexport) void Trunc(struct sDELAYCOMPARE *inst, double t, union uData *data, double *timestep) { // limit the timestep to a tolerance if the circuit causes a change in struct sDELAYCOMPARE const double ttol = 1e-9; if(*timestep > ttol) { bool &OUT = data[3].b; // output bool &DelayOut = data[4].b; // output // Save output vector const bool _OUT = OUT ; const bool _DelayOut = DelayOut; struct sDELAYCOMPARE tmp = *inst; delaycompare(&(&tmp), t, data); // if(tmp != *inst) // implement a meaningful way to detect if the state has changed // *timestep = ttol; // Trunc() to reduce timestep to TTOL if OUT changes its status if (tmp.lastOUT != inst->lastOUT) *timestep = ttol; // Trunc() to reduce timestep to TTOL if DelayOut changes its status if (tmp.lastDelayOut != inst->lastDelayOut) *timestep = ttol; // Restore output vector OUT = _OUT ; DelayOut = _DelayOut; } } extern "C" __declspec(dllexport) void Destroy(struct sDELAYCOMPARE *inst) { free(inst); }