// Automatically generated C++ file on Thu Aug 14 20:00:41 2025 // // To build with Digital Mars C++ Compiler: // // dmc -mn -WD pulse_block3.cpp kernel32.lib #include #include #include #include extern "C" __declspec(dllexport) int (*Display)( const char *format, ...) = 0; // works like printf() extern "C" __declspec(dllexport) const double *DegreesC = 0; // pointer to current circuit temperature extern "C" __declspec(dllexport) const int *StepNumber = 0; // pointer to current step number extern "C" __declspec(dllexport) const int *NumberSteps = 0; // pointer to estimated number of steps extern "C" __declspec(dllexport) const char *const *InstanceName = 0; // pointer to address of instance name extern "C" __declspec(dllexport) const char *QUX = 0; // path to QUX.exe extern "C" __declspec(dllexport) const bool *ForKeeps = 0; // pointer to whether being evaluated non-hypothetically extern "C" __declspec(dllexport) const bool *HoldICs = 0; // pointer to whether instance initial conditions are being held extern "C" __declspec(dllexport) int (*DFFT)(struct sComplex *u, bool inv, unsigned int N, double scale) = 0; // discrete Fast Fourier function extern "C" __declspec(dllexport) void (*bzero)(void *ptr, unsigned int count) = 0; extern "C" __declspec(dllexport) double (*EngAtof)(const char **string) = 0; // New (as of Aug 20, 2025) that expands a string token that has metric // multiplers (eg. u, m, n, p ...) 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; } // #undef pin names lest they collide with names in any header file(s) you might // include. #undef out #undef args struct sPULSE_BLOCK { // declare the structure here double timestep_nxt; // next timestep needed for Trunc(). double V1; // input parameter double V2; // input parameter double Td; // input parameter double Trise; // input parameter double Tfall; // input parameter double Ton; // input parameter double Tper; // input parameter int NCYCLES; // input parameter }; #define NUM_ARGS 8 /***********************************************************/ extern "C" __declspec(dllexport) void pulse_block3_v2( struct sPULSE_BLOCK **opaque, double t, union uData *data) { const char *args = data[0].str; // input parameter double &out = data[1].d; // output if (!*opaque) { *opaque = (struct sPULSE_BLOCK *)malloc(sizeof(struct sPULSE_BLOCK)); bzero(*opaque, sizeof(struct sPULSE_BLOCK)); // Decode the args struct sPULSE_BLOCK *inst = *opaque; const char *spp[NUM_ARGS]; // The argument string is parsed into up to 8 substrings. // #define WHITESPACE_FOUND 1 // bool notspace_prev = !WHITESPACE_FOUND; // char idx = 0; // int slen = strlen(args); // for (int i = 0; i < slen; i++) { // if (!isspace(args[i])) { // Found non whitespace char // if (notspace_prev == // !WHITESPACE_FOUND) { // prev char was a whitespace // spp[idx] = // &(args[i]); // log the pointer to the beginning of this // string. // idx++; // incr idx // if (idx >= NUM_ARGS) // break; // idx should not exceed number of args allowed. If // // exceed, break out of for(). // } // notspace_prev = WHITESPACE_FOUND; // set the prev to a non // whitespace. // } else // notspace_prev = !WHITESPACE_FOUND; // clear the prev to // whitespace. // } // Now convert each substring into a double var expanding any metric // multiplers. const char *pArgs = args; inst->V1 = EngAtof(&pArgs); inst->V2 = EngAtof(&pArgs); inst->Td = EngAtof(&pArgs); inst->Trise = EngAtof(&pArgs); inst->Tfall = EngAtof(&pArgs); inst->Ton = EngAtof(&pArgs); inst->Tper = EngAtof(&pArgs); inst->NCYCLES = (int)EngAtof(&pArgs); // Display("\nV1=%f V2=%f Td=%f Trise=%0.9f Tfall=%0.9f Ton=%f Tper=%f // NCYCLES=%d",inst->V1,inst->V2,inst->Td,inst->Trise,inst->Tfall,inst->Ton,inst->Tper,inst->NCYCLES); } struct sPULSE_BLOCK *inst = *opaque; // Implement module evaluation code here: double t_tmp = t - inst->Td; // remove the delay from the cycle int t_cycle = t_tmp / inst->Tper; // determine the # of the current cycle t_tmp -= t_cycle * inst->Tper; // determine the time portion of the current cycle if (t_cycle >= inst->NCYCLES) { // the next line is an error??? // inst->timestep_nxt == 1e308; inst->timestep_nxt = 1e308; return; } // completed number of cycles if (t_tmp < 0) { // t before first delay. inst->timestep_nxt = -t_tmp; // compute the next timestep needed for Trunc() out = inst->V1; // set the out state to V1 } else if (t_tmp < inst->Ton) { // out is in Ton state if (out == inst->V1) { // Change of out state to V2 required. inst->timestep_nxt = inst->Trise; // compute the next timestep needed // for Trunc() (slew=>Trise) out = inst->V2; // set the out state to V2 } else // keep out state to V2. inst->timestep_nxt = inst->Ton - t_tmp; // Determine next timestep until next change of // out state to V1. } else if (t_tmp < inst->Tper) // out in off state { // out is in Toff state (Tper-Ton) if (out == inst->V2) { // Change of out state to V1 required. inst->timestep_nxt = inst->Tfall; // compute the next timestep needed // for Trunc() (slew=>Tfall) out = inst->V1; // set the out state to V1 } // First change of out state. Set timestep at slew_rate else // keep out state to V1. inst->timestep_nxt = inst->Tper - t_tmp; // Determine next timestep until next change of // out state to V1. } // Display("\nout=%f t=%0.12f timestep_nxt=%0.12f", out, t, // inst->timestep_nxt); } /*********************************************************************** In this Trunc() function, I only needed to pre-compute, in the app loop, this component's next timestep to provide the timing accuracy required. *************************************************************************/ extern "C" __declspec(dllexport) void Trunc(struct sPULSE_BLOCK *inst, double t, union uData *data, double *timestep) { // limit the timestep to the minimum needed if the // circuit causes a change in struct sPULSE_BLOCK if (*timestep > inst->timestep_nxt) // Determine which is smaller, the current timestep // or the timestep needed for this component. { *timestep = inst->timestep_nxt; // set the next timestep to the smaller // value needed for this component. } } /************************************************************************/ extern "C" __declspec(dllexport) void Destroy(struct sPULSE_BLOCK *inst) { free(inst); } /* isspace example #include #include int main () { char c; int i=0; char str[]="Example sentence to test isspace\n"; while (str[i]) { c=str[i]; if (isspace(c)) c='\n'; putchar (c); i++; } return 0; } */