| 1 | /* |
| 2 | * PWM_sf.c |
| 3 | * |
| 4 | * Code generation for model "PWM_sf". |
| 5 | * |
| 6 | * Model version : 1.825 |
| 7 | * Simulink Coder version : 9.4 (R2020b) 29-Jul-2020 |
| 8 | * C source code generated on : Fri Apr 14 12:53:29 2023 |
| 9 | * |
| 10 | * Target selection: rtwsfcn.tlc |
| 11 | * Note: GRT includes extra infrastructure and instrumentation for prototyping |
| 12 | * Embedded hardware selection: ARM Compatible->ARM Cortex-M |
| 13 | * Emulation hardware selection: |
| 14 | * Differs from embedded hardware (MATLAB Host) |
| 15 | * Code generation objectives: |
| 16 | * 1. Execution efficiency |
| 17 | * 2. RAM efficiency |
| 18 | * Validation result: Not run |
| 19 | */ |
| 20 | |
| 21 | #include <math.h> |
| 22 | #include "PWM_sf.h" |
| 23 | #include "PWM_sf_private.h" |
| 24 | #include "simstruc.h" |
| 25 | #include "fixedpoint.h" |
| 26 | #if defined(RT_MALLOC) || defined(MATLAB_MEX_FILE) |
| 27 | |
| 28 | extern void *PWM_malloc(SimStruct *S); |
| 29 | |
| 30 | #endif |
| 31 | |
| 32 | #ifndef __RTW_UTFREE__ |
| 33 | #if defined (MATLAB_MEX_FILE) |
| 34 | |
| 35 | extern void * utMalloc(size_t); |
| 36 | extern void utFree(void *); |
| 37 | |
| 38 | #endif |
| 39 | #endif /* #ifndef __RTW_UTFREE__ */ |
| 40 | |
| 41 | /* Forward declaration for local functions */ |
| 42 | static real_T PWM_rt_remd_snf(real_T u0, real_T u1); |
| 43 | |
| 44 | #if defined(MATLAB_MEX_FILE) |
| 45 | #include "rt_nonfinite.c" |
| 46 | #endif |
| 47 | |
| 48 | static const char_T *RT_MEMORY_ALLOCATION_ERROR = |
| 49 | "memory allocation error in generated S-Function"; |
| 50 | |
| 51 | /* |
| 52 | * Time delay interpolation routine |
| 53 | * |
| 54 | * The linear interpolation is performed using the formula: |
| 55 | * |
| 56 | * (t2 - tMinusDelay) (tMinusDelay - t1) |
| 57 | * u(t) = ----------------- * u1 + ------------------- * u2 |
| 58 | * (t2 - t1) (t2 - t1) |
| 59 | */ |
| 60 | real_T PWM_sf_rt_TDelayInterpolate( |
| 61 | real_T tMinusDelay, /* tMinusDelay = currentSimTime - delay */ |
| 62 | real_T tStart, |
| 63 | real_T *tBuf, |
| 64 | real_T *uBuf, |
| 65 | int_T bufSz, |
| 66 | int_T *lastIdx, |
| 67 | int_T oldestIdx, |
| 68 | int_T newIdx, |
| 69 | real_T initOutput, |
| 70 | boolean_T discrete, |
| 71 | boolean_T minorStepAndTAtLastMajorOutput) |
| 72 | { |
| 73 | int_T i; |
| 74 | real_T yout, t1, t2, u1, u2; |
| 75 | |
| 76 | /* |
| 77 | * If there is only one data point in the buffer, this data point must be |
| 78 | * the t= 0 and tMinusDelay > t0, it ask for something unknown. The best |
| 79 | * guess if initial output as well |
| 80 | */ |
| 81 | if ((newIdx == 0) && (oldestIdx ==0 ) && (tMinusDelay > tStart)) |
| 82 | return initOutput; |
| 83 | |
| 84 | /* |
| 85 | * If tMinusDelay is less than zero, should output initial value |
| 86 | */ |
| 87 | if (tMinusDelay <= tStart) |
| 88 | return initOutput; |
| 89 | |
| 90 | /* For fixed buffer extrapolation: |
| 91 | * if tMinusDelay is small than the time at oldestIdx, if discrete, output |
| 92 | * tailptr value, else use tailptr and tailptr+1 value to extrapolate |
| 93 | * It is also for fixed buffer. Note: The same condition can happen for transport delay block where |
| 94 | * use tStart and and t[tail] other than using t[tail] and t[tail+1]. |
| 95 | * See below |
| 96 | */ |
| 97 | if ((tMinusDelay <= tBuf[oldestIdx] ) ) { |
| 98 | if (discrete) { |
| 99 | return(uBuf[oldestIdx]); |
| 100 | } else { |
| 101 | int_T tempIdx= oldestIdx + 1; |
| 102 | if (oldestIdx == bufSz-1) |
| 103 | tempIdx = 0; |
| 104 | t1= tBuf[oldestIdx]; |
| 105 | t2= tBuf[tempIdx]; |
| 106 | u1= uBuf[oldestIdx]; |
| 107 | u2= uBuf[tempIdx]; |
| 108 | if (t2 == t1) { |
| 109 | if (tMinusDelay >= t2) { |
| 110 | yout = u2; |
| 111 | } else { |
| 112 | yout = u1; |
| 113 | } |
| 114 | } else { |
| 115 | real_T f1 = (t2-tMinusDelay) / (t2-t1); |
| 116 | real_T f2 = 1.0 - f1; |
| 117 | |
| 118 | /* |
| 119 | * Use Lagrange's interpolation formula. Exact outputs at t1, t2. |
| 120 | */ |
| 121 | yout = f1*u1 + f2*u2; |
| 122 | } |
| 123 | |
| 124 | return yout; |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | /* |
| 129 | * When block does not have direct feedthrough, we use the table of |
| 130 | * values to extrapolate off the end of the table for delays that are less |
| 131 | * than 0 (less then step size). This is not completely accurate. The |
| 132 | * chain of events is as follows for a given time t. Major output - look |
| 133 | * in table. Update - add entry to table. Now, if we call the output at |
| 134 | * time t again, there is a new entry in the table. For very small delays, |
| 135 | * this means that we will have a different answer from the previous call |
| 136 | * to the output fcn at the same time t. The following code prevents this |
| 137 | * from happening. |
| 138 | */ |
| 139 | if (minorStepAndTAtLastMajorOutput) { |
| 140 | /* pretend that the new entry has not been added to table */ |
| 141 | if (newIdx != 0) { |
| 142 | if (*lastIdx == newIdx) { |
| 143 | (*lastIdx)--; |
| 144 | } |
| 145 | |
| 146 | newIdx--; |
| 147 | } else { |
| 148 | if (*lastIdx == newIdx) { |
| 149 | *lastIdx = bufSz-1; |
| 150 | } |
| 151 | |
| 152 | newIdx = bufSz - 1; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | i = *lastIdx; |
| 157 | if (tBuf[i] < tMinusDelay) { |
| 158 | /* Look forward starting at last index */ |
| 159 | while (tBuf[i] < tMinusDelay) { |
| 160 | /* May occur if the delay is less than step-size - extrapolate */ |
| 161 | if (i == newIdx) |
| 162 | break; |
| 163 | i = ( i < (bufSz-1) ) ? (i+1) : 0;/* move through buffer */ |
| 164 | } |
| 165 | } else { |
| 166 | /* |
| 167 | * Look backwards starting at last index which can happen when the |
| 168 | * delay time increases. |
| 169 | */ |
| 170 | while (tBuf[i] >= tMinusDelay) { |
| 171 | /* |
| 172 | * Due to the entry condition at top of function, we |
| 173 | * should never hit the end. |
| 174 | */ |
| 175 | i = (i > 0) ? i-1 : (bufSz-1); /* move through buffer */ |
| 176 | } |
| 177 | |
| 178 | i = ( i < (bufSz-1) ) ? (i+1) : 0; |
| 179 | } |
| 180 | |
| 181 | *lastIdx = i; |
| 182 | if (discrete) { |
| 183 | /* |
| 184 | * tempEps = 128 * eps; |
| 185 | * localEps = max(tempEps, tempEps*fabs(tBuf[i]))/2; |
| 186 | */ |
| 187 | double tempEps = (DBL_EPSILON) * 128.0; |
| 188 | double localEps = tempEps * fabs(tBuf[i]); |
| 189 | if (tempEps > localEps) { |
| 190 | localEps = tempEps; |
| 191 | } |
| 192 | |
| 193 | localEps = localEps / 2.0; |
| 194 | if (tMinusDelay >= (tBuf[i] - localEps)) { |
| 195 | yout = uBuf[i]; |
| 196 | } else { |
| 197 | if (i == 0) { |
| 198 | yout = uBuf[bufSz-1]; |
| 199 | } else { |
| 200 | yout = uBuf[i-1]; |
| 201 | } |
| 202 | } |
| 203 | } else { |
| 204 | if (i == 0) { |
| 205 | t1 = tBuf[bufSz-1]; |
| 206 | u1 = uBuf[bufSz-1]; |
| 207 | } else { |
| 208 | t1 = tBuf[i-1]; |
| 209 | u1 = uBuf[i-1]; |
| 210 | } |
| 211 | |
| 212 | t2 = tBuf[i]; |
| 213 | u2 = uBuf[i]; |
| 214 | if (t2 == t1) { |
| 215 | if (tMinusDelay >= t2) { |
| 216 | yout = u2; |
| 217 | } else { |
| 218 | yout = u1; |
| 219 | } |
| 220 | } else { |
| 221 | real_T f1 = (t2-tMinusDelay) / (t2-t1); |
| 222 | real_T f2 = 1.0 - f1; |
| 223 | |
| 224 | /* |
| 225 | * Use Lagrange's interpolation formula. Exact outputs at t1, t2. |
| 226 | */ |
| 227 | yout = f1*u1 + f2*u2; |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | return(yout); |
| 232 | } |
| 233 | |
| 234 | real_T PWM_look1_binlx(real_T u0, const real_T bp0[], const real_T table[], |
| 235 | uint32_T maxIndex) |
| 236 | { |
| 237 | real_T frac; |
| 238 | real_T yL_0d0; |
| 239 | uint32_T bpIdx; |
| 240 | uint32_T iLeft; |
| 241 | uint32_T iRght; |
| 242 | |
| 243 | /* Column-major Lookup 1-D |
| 244 | Search method: 'binary' |
| 245 | Use previous index: 'off' |
| 246 | Interpolation method: 'Linear point-slope' |
| 247 | Extrapolation method: 'Linear' |
| 248 | Use last breakpoint for index at or above upper limit: 'off' |
| 249 | Remove protection against out-of-range input in generated code: 'off' |
| 250 | */ |
| 251 | /* Prelookup - Index and Fraction |
| 252 | Index Search method: 'binary' |
| 253 | Extrapolation method: 'Linear' |
| 254 | Use previous index: 'off' |
| 255 | Use last breakpoint for index at or above upper limit: 'off' |
| 256 | Remove protection against out-of-range input in generated code: 'off' |
| 257 | */ |
| 258 | if (u0 <= bp0[0U]) { |
| 259 | iLeft = 0U; |
| 260 | frac = (u0 - bp0[0U]) / (bp0[1U] - bp0[0U]); |
| 261 | } else if (u0 < bp0[maxIndex]) { |
| 262 | /* Binary Search */ |
| 263 | bpIdx = maxIndex >> 1U; |
| 264 | iLeft = 0U; |
| 265 | iRght = maxIndex; |
| 266 | while (iRght - iLeft > 1U) { |
| 267 | if (u0 < bp0[bpIdx]) { |
| 268 | iRght = bpIdx; |
| 269 | } else { |
| 270 | iLeft = bpIdx; |
| 271 | } |
| 272 | |
| 273 | bpIdx = (iRght + iLeft) >> 1U; |
| 274 | } |
| 275 | |
| 276 | frac = (u0 - bp0[iLeft]) / (bp0[iLeft + 1U] - bp0[iLeft]); |
| 277 | } else { |
| 278 | iLeft = maxIndex - 1U; |
| 279 | frac = (u0 - bp0[maxIndex - 1U]) / (bp0[maxIndex] - bp0[maxIndex - 1U]); |
| 280 | } |
| 281 | |
| 282 | /* Column-major Interpolation 1-D |
| 283 | Interpolation method: 'Linear point-slope' |
| 284 | Use last breakpoint for index at or above upper limit: 'off' |
| 285 | Overflow mode: 'wrapping' |
| 286 | */ |
| 287 | yL_0d0 = table[iLeft]; |
| 288 | return (table[iLeft + 1U] - yL_0d0) * frac + yL_0d0; |
| 289 | } |
| 290 | |
| 291 | static real_T PWM_rt_remd_snf(real_T u0, real_T u1) |
| 292 | { |
| 293 | real_T q; |
| 294 | real_T y; |
| 295 | if (rtIsNaN(u0) || rtIsNaN(u1) || rtIsInf(u0)) { |
| 296 | y = (rtNaN); |
| 297 | } else if (rtIsInf(u1)) { |
| 298 | y = u0; |
| 299 | } else if ((u1 != 0.0) && (u1 != trunc(u1))) { |
| 300 | q = fabs(u0 / u1); |
| 301 | if (!(fabs(q - floor(q + 0.5)) > DBL_EPSILON * q)) { |
| 302 | y = 0.0 * u0; |
| 303 | } else { |
| 304 | y = fmod(u0, u1); |
| 305 | } |
| 306 | } else { |
| 307 | y = fmod(u0, u1); |
| 308 | } |
| 309 | |
| 310 | return y; |
| 311 | } |
| 312 | |
| 313 | /* Start for root system: '<Root>' */ |
| 314 | #define MDL_START |
| 315 | |
| 316 | static void mdlStart(SimStruct *S) |
| 317 | { |
| 318 | /* instance underlying S-Function data */ |
| 319 | #if defined(RT_MALLOC) || defined(MATLAB_MEX_FILE) |
| 320 | #if defined(MATLAB_MEX_FILE) |
| 321 | |
| 322 | /* non-finites */ |
| 323 | rt_InitInfAndNaN(sizeof(real_T)); |
| 324 | |
| 325 | /* Check for invalid switching between solver types */ |
| 326 | if (ssIsVariableStepSolver(S)) { |
| 327 | ssSetErrorStatus(S, "This Simulink Coder generated " |
| 328 | "S-Function cannot be used in a simulation with " |
| 329 | "a solver type of variable-step " |
| 330 | "because this S-Function was created from a model with " |
| 331 | "solver type of fixed-step and it has continuous time blocks. " |
| 332 | "See the Solver page of the simulation parameters dialog."); |
| 333 | return; |
| 334 | } |
| 335 | |
| 336 | if (fabs(ssGetFixedStepSize(S) - 5.0E-7) > mxGetEps()*100*5.0E-7) { |
| 337 | ssSetErrorStatus(S, "This Simulink Coder generated " |
| 338 | "S-Function cannot be used in a simulation with " |
| 339 | "the current fixed step size " |
| 340 | "because this S-Function was created from a model with " |
| 341 | "a fixed step size of 5.0E-7 and had both " |
| 342 | "continuous blocks and discrete blocks running at this rate. " |
| 343 | "See the Solver page of the simulation parameters dialog."); |
| 344 | return; |
| 345 | } |
| 346 | |
| 347 | #endif |
| 348 | |
| 349 | PWM_malloc(S); |
| 350 | if (ssGetErrorStatus(S) != (NULL) ) { |
| 351 | return; |
| 352 | } |
| 353 | |
| 354 | #endif |
| 355 | |
| 356 | { |
| 357 | B_PWM_T *_rtB; |
| 358 | _rtB = ((B_PWM_T *) ssGetLocalBlockIO(S)); |
| 359 | |
| 360 | /* Start for TransportDelay: '<S2>/Transport Delay' */ |
| 361 | { |
| 362 | real_T *pBuffer = &((real_T*) ssGetDWork(S, 0))[1]; |
| 363 | ((int_T*) ssGetDWork(S, 6))[0] = 0; |
| 364 | ((int_T*) ssGetDWork(S, 6))[1] = 0; |
| 365 | ((int_T*) ssGetDWork(S, 6))[2] = 0; |
| 366 | ((int_T*) ssGetDWork(S, 6))[3] = 1024; |
| 367 | pBuffer[0] = 0.0; |
| 368 | pBuffer[1024] = ssGetT(S); |
| 369 | ((void**) ssGetDWork(S, 3))[0] = (void *) &pBuffer[0]; |
| 370 | ((void**) ssGetDWork(S, 3))[1] = (void *) &pBuffer[1024]; |
| 371 | } |
| 372 | |
| 373 | /* Start for TransportDelay: '<S2>/Transport Delay1' */ |
| 374 | { |
| 375 | real_T *pBuffer = &((real_T*) ssGetDWork(S, 1))[1]; |
| 376 | ((int_T*) ssGetDWork(S, 7))[0] = 0; |
| 377 | ((int_T*) ssGetDWork(S, 7))[1] = 0; |
| 378 | ((int_T*) ssGetDWork(S, 7))[2] = 0; |
| 379 | ((int_T*) ssGetDWork(S, 7))[3] = 1024; |
| 380 | pBuffer[0] = 0.0; |
| 381 | pBuffer[1024] = ssGetT(S); |
| 382 | ((void**) ssGetDWork(S, 4))[0] = (void *) &pBuffer[0]; |
| 383 | ((void**) ssGetDWork(S, 4))[1] = (void *) &pBuffer[1024]; |
| 384 | } |
| 385 | |
| 386 | /* Start for TransportDelay: '<S2>/Transport Delay2' */ |
| 387 | { |
| 388 | real_T *pBuffer = &((real_T*) ssGetDWork(S, 2))[1]; |
| 389 | ((int_T*) ssGetDWork(S, 8))[0] = 0; |
| 390 | ((int_T*) ssGetDWork(S, 8))[1] = 0; |
| 391 | ((int_T*) ssGetDWork(S, 8))[2] = 0; |
| 392 | ((int_T*) ssGetDWork(S, 8))[3] = 1024; |
| 393 | pBuffer[0] = 0.0; |
| 394 | pBuffer[1024] = ssGetT(S); |
| 395 | ((void**) ssGetDWork(S, 5))[0] = (void *) &pBuffer[0]; |
| 396 | ((void**) ssGetDWork(S, 5))[1] = (void *) &pBuffer[1024]; |
| 397 | } |
| 398 | } |
| 399 | } |
| 400 | |
| 401 | /* Outputs for root system: '<Root>' */ |
| 402 | static void mdlOutputs(SimStruct *S, int_T tid) |
| 403 | { |
| 404 | /* local block i/o variables */ |
| 405 | real_T rtb_TransportDelay1; |
| 406 | real_T rtb_TransportDelay2; |
| 407 | real_T rtb_TransportDelay; |
| 408 | B_PWM_T *_rtB; |
| 409 | real_T expr_2_0_0; |
| 410 | real_T rtb_Abs; |
| 411 | real_T rtb_Abs2; |
| 412 | boolean_T rtb_RelationalOperator; |
| 413 | boolean_T rtb_RelationalOperator1; |
| 414 | boolean_T rtb_RelationalOperator2; |
| 415 | _rtB = ((B_PWM_T *) ssGetLocalBlockIO(S)); |
| 416 | if (ssIsContinuousTask(S, tid)) { |
| 417 | /* S-Function (sfun_tstart): '<S3>/startTime' */ |
| 418 | /* S-Function Block (sfun_tstart): <S3>/startTime */ |
| 419 | expr_2_0_0 = ssGetTStart(S); |
| 420 | |
| 421 | /* Lookup_n-D: '<S3>/Look-Up Table1' incorporates: |
| 422 | * Clock: '<S3>/Clock' |
| 423 | * Constant: '<S3>/Constant' |
| 424 | * Math: '<S3>/Math Function' |
| 425 | * Sum: '<S3>/Sum' |
| 426 | */ |
| 427 | expr_2_0_0 = PWM_look1_binlx(PWM_rt_remd_snf(ssGetT(S) - expr_2_0_0, 0.0001), |
| 428 | PWM_ConstP.LookUpTable1_bp01Data, PWM_ConstP.LookUpTable1_tableData, 2U); |
| 429 | |
| 430 | /* RelationalOperator: '<S2>/Relational Operator' */ |
| 431 | rtb_RelationalOperator = (expr_2_0_0 > *((const real_T **) |
| 432 | ssGetInputPortSignalPtrs(S, 0))[0]); |
| 433 | |
| 434 | /* TransportDelay: '<S2>/Transport Delay' */ |
| 435 | { |
| 436 | real_T **uBuffer = (real_T**)&((void**) ssGetDWork(S, 3))[0]; |
| 437 | real_T **tBuffer = (real_T**)&((void**) ssGetDWork(S, 3))[1]; |
| 438 | real_T simTime = ssGetT(S); |
| 439 | real_T tMinusDelay = simTime - 2.0E-6; |
| 440 | rtb_TransportDelay = PWM_sf_rt_TDelayInterpolate( |
| 441 | tMinusDelay, |
| 442 | 0.0, |
| 443 | *tBuffer, |
| 444 | *uBuffer, |
| 445 | ((int_T*) ssGetDWork(S, 6))[3], |
| 446 | &((int_T*) ssGetDWork(S, 6))[2], |
| 447 | ((int_T*) ssGetDWork(S, 6))[0], |
| 448 | ((int_T*) ssGetDWork(S, 6))[1], |
| 449 | 0.0, |
| 450 | 0, |
| 451 | (boolean_T) (ssIsMinorTimeStep(S) && (ssGetTimeOfLastOutput(S) == ssGetT |
| 452 | (S)))); |
| 453 | } |
| 454 | |
| 455 | /* DataTypeConversion: '<S2>/Data Type Conversion3' incorporates: |
| 456 | * Logic: '<S2>/Logical Operator' |
| 457 | */ |
| 458 | rtb_Abs2 = !rtb_RelationalOperator; |
| 459 | |
| 460 | /* Abs: '<S2>/Abs' incorporates: |
| 461 | * DataTypeConversion: '<S2>/Data Type Conversion3' |
| 462 | * Sum: '<S2>/Subtract' |
| 463 | */ |
| 464 | rtb_Abs = fabs(rtb_Abs2 - rtb_TransportDelay); |
| 465 | |
| 466 | /* Product: '<S2>/Product' */ |
| 467 | _rtB->Product = rtb_Abs2 * rtb_Abs; |
| 468 | |
| 469 | /* Product: '<S2>/Product1' */ |
| 470 | _rtB->Product1 = rtb_Abs * rtb_TransportDelay; |
| 471 | |
| 472 | /* RelationalOperator: '<S2>/Relational Operator1' */ |
| 473 | rtb_RelationalOperator1 = (expr_2_0_0 > *((const real_T **) |
| 474 | ssGetInputPortSignalPtrs(S, 0))[1]); |
| 475 | |
| 476 | /* TransportDelay: '<S2>/Transport Delay1' */ |
| 477 | { |
| 478 | real_T **uBuffer = (real_T**)&((void**) ssGetDWork(S, 4))[0]; |
| 479 | real_T **tBuffer = (real_T**)&((void**) ssGetDWork(S, 4))[1]; |
| 480 | real_T simTime = ssGetT(S); |
| 481 | real_T tMinusDelay = simTime - 2.0E-6; |
| 482 | rtb_TransportDelay1 = PWM_sf_rt_TDelayInterpolate( |
| 483 | tMinusDelay, |
| 484 | 0.0, |
| 485 | *tBuffer, |
| 486 | *uBuffer, |
| 487 | ((int_T*) ssGetDWork(S, 7))[3], |
| 488 | &((int_T*) ssGetDWork(S, 7))[2], |
| 489 | ((int_T*) ssGetDWork(S, 7))[0], |
| 490 | ((int_T*) ssGetDWork(S, 7))[1], |
| 491 | 0.0, |
| 492 | 0, |
| 493 | (boolean_T) (ssIsMinorTimeStep(S) && (ssGetTimeOfLastOutput(S) == ssGetT |
| 494 | (S)))); |
| 495 | } |
| 496 | |
| 497 | /* RelationalOperator: '<S2>/Relational Operator2' */ |
| 498 | rtb_RelationalOperator2 = (expr_2_0_0 > *((const real_T **) |
| 499 | ssGetInputPortSignalPtrs(S, 0))[2]); |
| 500 | |
| 501 | /* TransportDelay: '<S2>/Transport Delay2' */ |
| 502 | { |
| 503 | real_T **uBuffer = (real_T**)&((void**) ssGetDWork(S, 5))[0]; |
| 504 | real_T **tBuffer = (real_T**)&((void**) ssGetDWork(S, 5))[1]; |
| 505 | real_T simTime = ssGetT(S); |
| 506 | real_T tMinusDelay = simTime - 2.0E-6; |
| 507 | rtb_TransportDelay2 = PWM_sf_rt_TDelayInterpolate( |
| 508 | tMinusDelay, |
| 509 | 0.0, |
| 510 | *tBuffer, |
| 511 | *uBuffer, |
| 512 | ((int_T*) ssGetDWork(S, 8))[3], |
| 513 | &((int_T*) ssGetDWork(S, 8))[2], |
| 514 | ((int_T*) ssGetDWork(S, 8))[0], |
| 515 | ((int_T*) ssGetDWork(S, 8))[1], |
| 516 | 0.0, |
| 517 | 0, |
| 518 | (boolean_T) (ssIsMinorTimeStep(S) && (ssGetTimeOfLastOutput(S) == ssGetT |
| 519 | (S)))); |
| 520 | } |
| 521 | |
| 522 | /* DataTypeConversion: '<S2>/Data Type Conversion1' incorporates: |
| 523 | * Logic: '<S2>/Logical Operator1' |
| 524 | * ManualSwitch: '<S1>/Manual Switch' |
| 525 | */ |
| 526 | rtb_Abs2 = !rtb_RelationalOperator1; |
| 527 | |
| 528 | /* Abs: '<S2>/Abs1' incorporates: |
| 529 | * DataTypeConversion: '<S2>/Data Type Conversion1' |
| 530 | * ManualSwitch: '<S1>/Manual Switch' |
| 531 | * Sum: '<S2>/Subtract1' |
| 532 | */ |
| 533 | expr_2_0_0 = fabs(rtb_Abs2 - rtb_TransportDelay1); |
| 534 | |
| 535 | /* Outport: '<Root>/PWMb' incorporates: |
| 536 | * ManualSwitch: '<S1>/Manual Switch' |
| 537 | * Product: '<S2>/Product2' |
| 538 | * Product: '<S2>/Product3' |
| 539 | */ |
| 540 | ((real_T *)ssGetOutputPortSignal(S, 0))[2] = rtb_Abs2 * expr_2_0_0; |
| 541 | ((real_T *)ssGetOutputPortSignal(S, 0))[3] = expr_2_0_0 * |
| 542 | rtb_TransportDelay1; |
| 543 | |
| 544 | /* DataTypeConversion: '<S2>/Data Type Conversion5' incorporates: |
| 545 | * Logic: '<S2>/Logical Operator2' |
| 546 | * ManualSwitch: '<S1>/Manual Switch' |
| 547 | */ |
| 548 | expr_2_0_0 = !rtb_RelationalOperator2; |
| 549 | |
| 550 | /* Abs: '<S2>/Abs2' incorporates: |
| 551 | * ManualSwitch: '<S1>/Manual Switch' |
| 552 | * Sum: '<S2>/Subtract2' |
| 553 | */ |
| 554 | rtb_Abs2 = fabs(expr_2_0_0 - rtb_TransportDelay2); |
| 555 | |
| 556 | /* Outport: '<Root>/PWMb' incorporates: |
| 557 | * ManualSwitch: '<S1>/Manual Switch' |
| 558 | * Product: '<S2>/Product4' |
| 559 | * Product: '<S2>/Product5' |
| 560 | */ |
| 561 | ((real_T *)ssGetOutputPortSignal(S, 0))[0] = _rtB->Product; |
| 562 | ((real_T *)ssGetOutputPortSignal(S, 0))[1] = _rtB->Product1; |
| 563 | ((real_T *)ssGetOutputPortSignal(S, 0))[4] = expr_2_0_0 * rtb_Abs2; |
| 564 | ((real_T *)ssGetOutputPortSignal(S, 0))[5] = rtb_Abs2 * rtb_TransportDelay2; |
| 565 | |
| 566 | /* DataTypeConversion: '<S2>/Data Type Conversion6' */ |
| 567 | _rtB->DataTypeConversion6 = rtb_RelationalOperator2; |
| 568 | |
| 569 | /* DataTypeConversion: '<S2>/Data Type Conversion2' */ |
| 570 | _rtB->DataTypeConversion2 = rtb_RelationalOperator1; |
| 571 | } |
| 572 | |
| 573 | if (ssIsSampleHit(S, 1, tid)) { |
| 574 | } |
| 575 | |
| 576 | if (ssIsContinuousTask(S, tid)) { |
| 577 | /* DataTypeConversion: '<S2>/Data Type Conversion4' */ |
| 578 | _rtB->DataTypeConversion4 = rtb_RelationalOperator; |
| 579 | } |
| 580 | |
| 581 | UNUSED_PARAMETER(tid); |
| 582 | } |
| 583 | |
| 584 | /* Update for root system: '<Root>' */ |
| 585 | #define MDL_UPDATE |
| 586 | |
| 587 | static void mdlUpdate(SimStruct *S, int_T tid) |
| 588 | { |
| 589 | B_PWM_T *_rtB; |
| 590 | _rtB = ((B_PWM_T *) ssGetLocalBlockIO(S)); |
| 591 | if (ssIsContinuousTask(S, tid)) { |
| 592 | /* Update for TransportDelay: '<S2>/Transport Delay' */ |
| 593 | { |
| 594 | real_T **uBuffer = (real_T**)&((void**) ssGetDWork(S, 3))[0]; |
| 595 | real_T **tBuffer = (real_T**)&((void**) ssGetDWork(S, 3))[1]; |
| 596 | real_T simTime = ssGetT(S); |
| 597 | ((int_T*) ssGetDWork(S, 6))[1] = ((((int_T*) ssGetDWork(S, 6))[1] < |
| 598 | (((int_T*) ssGetDWork(S, 6))[3]-1)) ? (((int_T*) ssGetDWork(S, 6))[1]+1) |
| 599 | : 0); |
| 600 | if (((int_T*) ssGetDWork(S, 6))[1] == ((int_T*) ssGetDWork(S, 6))[0]) { |
| 601 | ((int_T*) ssGetDWork(S, 6))[0] = ((((int_T*) ssGetDWork(S, 6))[0] < |
| 602 | (((int_T*) ssGetDWork(S, 6))[3]-1)) ? (((int_T*) ssGetDWork(S, 6))[0]+ |
| 603 | 1) : 0); |
| 604 | } |
| 605 | |
| 606 | (*tBuffer)[((int_T*) ssGetDWork(S, 6))[1]] = simTime; |
| 607 | (*uBuffer)[((int_T*) ssGetDWork(S, 6))[1]] = _rtB->DataTypeConversion4; |
| 608 | } |
| 609 | |
| 610 | /* Update for TransportDelay: '<S2>/Transport Delay1' */ |
| 611 | { |
| 612 | real_T **uBuffer = (real_T**)&((void**) ssGetDWork(S, 4))[0]; |
| 613 | real_T **tBuffer = (real_T**)&((void**) ssGetDWork(S, 4))[1]; |
| 614 | real_T simTime = ssGetT(S); |
| 615 | ((int_T*) ssGetDWork(S, 7))[1] = ((((int_T*) ssGetDWork(S, 7))[1] < |
| 616 | (((int_T*) ssGetDWork(S, 7))[3]-1)) ? (((int_T*) ssGetDWork(S, 7))[1]+1) |
| 617 | : 0); |
| 618 | if (((int_T*) ssGetDWork(S, 7))[1] == ((int_T*) ssGetDWork(S, 7))[0]) { |
| 619 | ((int_T*) ssGetDWork(S, 7))[0] = ((((int_T*) ssGetDWork(S, 7))[0] < |
| 620 | (((int_T*) ssGetDWork(S, 7))[3]-1)) ? (((int_T*) ssGetDWork(S, 7))[0]+ |
| 621 | 1) : 0); |
| 622 | } |
| 623 | |
| 624 | (*tBuffer)[((int_T*) ssGetDWork(S, 7))[1]] = simTime; |
| 625 | (*uBuffer)[((int_T*) ssGetDWork(S, 7))[1]] = _rtB->DataTypeConversion2; |
| 626 | } |
| 627 | |
| 628 | /* Update for TransportDelay: '<S2>/Transport Delay2' */ |
| 629 | { |
| 630 | real_T **uBuffer = (real_T**)&((void**) ssGetDWork(S, 5))[0]; |
| 631 | real_T **tBuffer = (real_T**)&((void**) ssGetDWork(S, 5))[1]; |
| 632 | real_T simTime = ssGetT(S); |
| 633 | ((int_T*) ssGetDWork(S, 8))[1] = ((((int_T*) ssGetDWork(S, 8))[1] < |
| 634 | (((int_T*) ssGetDWork(S, 8))[3]-1)) ? (((int_T*) ssGetDWork(S, 8))[1]+1) |
| 635 | : 0); |
| 636 | if (((int_T*) ssGetDWork(S, 8))[1] == ((int_T*) ssGetDWork(S, 8))[0]) { |
| 637 | ((int_T*) ssGetDWork(S, 8))[0] = ((((int_T*) ssGetDWork(S, 8))[0] < |
| 638 | (((int_T*) ssGetDWork(S, 8))[3]-1)) ? (((int_T*) ssGetDWork(S, 8))[0]+ |
| 639 | 1) : 0); |
| 640 | } |
| 641 | |
| 642 | (*tBuffer)[((int_T*) ssGetDWork(S, 8))[1]] = simTime; |
| 643 | (*uBuffer)[((int_T*) ssGetDWork(S, 8))[1]] = _rtB->DataTypeConversion6; |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | UNUSED_PARAMETER(tid); |
| 648 | } |
| 649 | |
| 650 | /* Termination for root system: '<Root>' */ |
| 651 | static void mdlTerminate(SimStruct *S) |
| 652 | { |
| 653 | B_PWM_T *_rtB; |
| 654 | _rtB = ((B_PWM_T *) ssGetLocalBlockIO(S)); |
| 655 | |
| 656 | #if defined(RT_MALLOC) || defined(MATLAB_MEX_FILE) |
| 657 | |
| 658 | if (ssGetUserData(S) != (NULL) ) { |
| 659 | rt_FREE(ssGetLocalBlockIO(S)); |
| 660 | } |
| 661 | |
| 662 | rt_FREE(ssGetUserData(S)); |
| 663 | |
| 664 | #endif |
| 665 | |
| 666 | } |
| 667 | |
| 668 | #if defined(RT_MALLOC) || defined(MATLAB_MEX_FILE) |
| 669 | #include "PWM_mid.h" |
| 670 | #endif |
| 671 | |
| 672 | /* Function to initialize sizes. */ |
| 673 | static void mdlInitializeSizes(SimStruct *S) |
| 674 | { |
| 675 | ssSetNumSampleTimes(S, 2); /* Number of sample times */ |
| 676 | ssSetNumContStates(S, 0); /* Number of continuous states */ |
| 677 | ssSetNumNonsampledZCs(S, 0); /* Number of nonsampled ZCs */ |
| 678 | |
| 679 | /* Number of output ports */ |
| 680 | if (!ssSetNumOutputPorts(S, 1)) |
| 681 | return; |
| 682 | |
| 683 | /* outport number: 0 */ |
| 684 | if (!ssSetOutputPortVectorDimension(S, 0, 6)) |
| 685 | return; |
| 686 | if (ssGetSimMode(S) != SS_SIMMODE_SIZES_CALL_ONLY) { |
| 687 | ssSetOutputPortDataType(S, 0, SS_DOUBLE); |
| 688 | } |
| 689 | |
| 690 | ssSetOutputPortSampleTime(S, 0, 0.0); |
| 691 | ssSetOutputPortOffsetTime(S, 0, 0.0); |
| 692 | ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL); |
| 693 | |
| 694 | /* Number of input ports */ |
| 695 | if (!ssSetNumInputPorts(S, 1)) |
| 696 | return; |
| 697 | |
| 698 | /* inport number: 0 */ |
| 699 | { |
| 700 | if (!ssSetInputPortVectorDimension(S, 0, 3)) |
| 701 | return; |
| 702 | if (ssGetSimMode(S) != SS_SIMMODE_SIZES_CALL_ONLY) { |
| 703 | ssSetInputPortDataType(S, 0, SS_DOUBLE); |
| 704 | } |
| 705 | |
| 706 | ssSetInputPortDirectFeedThrough(S, 0, 1); |
| 707 | ssSetInputPortSampleTime(S, 0, 5.0E-7); |
| 708 | ssSetInputPortOffsetTime(S, 0, 0.0); |
| 709 | ssSetInputPortOverWritable(S, 0, 0); |
| 710 | ssSetInputPortOptimOpts(S, 0, SS_NOT_REUSABLE_AND_GLOBAL); |
| 711 | } |
| 712 | |
| 713 | ssSetRTWGeneratedSFcn(S, 1); /* Generated S-function */ |
| 714 | |
| 715 | /* DWork */ |
| 716 | if (!ssSetNumDWork(S, 9)) { |
| 717 | return; |
| 718 | } |
| 719 | |
| 720 | /* '<S2>/Transport Delay': RWORK */ |
| 721 | ssSetDWorkName(S, 0, "DWORK0"); |
| 722 | ssSetDWorkWidth(S, 0, 2049); |
| 723 | |
| 724 | /* '<S2>/Transport Delay1': RWORK */ |
| 725 | ssSetDWorkName(S, 1, "DWORK1"); |
| 726 | ssSetDWorkWidth(S, 1, 2049); |
| 727 | |
| 728 | /* '<S2>/Transport Delay2': RWORK */ |
| 729 | ssSetDWorkName(S, 2, "DWORK2"); |
| 730 | ssSetDWorkWidth(S, 2, 2049); |
| 731 | |
| 732 | /* '<S2>/Transport Delay': PWORK */ |
| 733 | ssSetDWorkName(S, 3, "DWORK3"); |
| 734 | ssSetDWorkWidth(S, 3, 2); |
| 735 | ssSetDWorkDataType(S, 3, SS_POINTER); |
| 736 | |
| 737 | /* '<S2>/Transport Delay1': PWORK */ |
| 738 | ssSetDWorkName(S, 4, "DWORK4"); |
| 739 | ssSetDWorkWidth(S, 4, 2); |
| 740 | ssSetDWorkDataType(S, 4, SS_POINTER); |
| 741 | |
| 742 | /* '<S2>/Transport Delay2': PWORK */ |
| 743 | ssSetDWorkName(S, 5, "DWORK5"); |
| 744 | ssSetDWorkWidth(S, 5, 2); |
| 745 | ssSetDWorkDataType(S, 5, SS_POINTER); |
| 746 | |
| 747 | /* '<S2>/Transport Delay': IWORK */ |
| 748 | ssSetDWorkName(S, 6, "DWORK6"); |
| 749 | ssSetDWorkWidth(S, 6, 4); |
| 750 | ssSetDWorkDataType(S, 6, SS_INTEGER); |
| 751 | |
| 752 | /* '<S2>/Transport Delay1': IWORK */ |
| 753 | ssSetDWorkName(S, 7, "DWORK7"); |
| 754 | ssSetDWorkWidth(S, 7, 4); |
| 755 | ssSetDWorkDataType(S, 7, SS_INTEGER); |
| 756 | |
| 757 | /* '<S2>/Transport Delay2': IWORK */ |
| 758 | ssSetDWorkName(S, 8, "DWORK8"); |
| 759 | ssSetDWorkWidth(S, 8, 4); |
| 760 | ssSetDWorkDataType(S, 8, SS_INTEGER); |
| 761 | |
| 762 | /* Tunable Parameters */ |
| 763 | ssSetNumSFcnParams(S, 0); |
| 764 | |
| 765 | /* Number of expected parameters */ |
| 766 | #if defined(MATLAB_MEX_FILE) |
| 767 | |
| 768 | if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) { |
| 769 | |
| 770 | #if defined(MDL_CHECK_PARAMETERS) |
| 771 | |
| 772 | mdlCheckParameters(S); |
| 773 | |
| 774 | #endif /* MDL_CHECK_PARAMETERS */ |
| 775 | |
| 776 | if (ssGetErrorStatus(S) != (NULL) ) { |
| 777 | return; |
| 778 | } |
| 779 | } else { |
| 780 | return; /* Parameter mismatch will be reported by Simulink */ |
| 781 | } |
| 782 | |
| 783 | #endif /* MATLAB_MEX_FILE */ |
| 784 | |
| 785 | /* Options */ |
| 786 | ssSetOptions(S, (SS_OPTION_RUNTIME_EXCEPTION_FREE_CODE | |
| 787 | SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED )); |
| 788 | |
| 789 | #if SS_SFCN_FOR_SIM |
| 790 | |
| 791 | { |
| 792 | ssSupportsMultipleExecInstances(S, false); |
| 793 | ssRegisterMsgForNotSupportingMultiExecInst(S, |
| 794 | "<diag_root><diag id=\"Simulink:blocks:BlockDoesNotSupportMultiExecInstances\" pr=\"d\"><arguments><arg type=\"encoded\">UABXAE0ALwBQAFcATQAvAG0AbwBkAHUAbABhAHQAZQBkACAAdwBhAHYAZQAvAHMAdABhAHIAdABUAGkAbQBlAAAA</arg><arg type=\"encoded\">PABfAF8AaQBpAFMAUwBfAF8APgA8AC8AXwBfAGkAaQBTAFMAXwBfAD4AAAA=</arg><arg type=\"encoded\">PABfAF8AaQB0AGUAcgBCAGwAawBfAF8APgA8AC8AXwBfAGkAdABlAHIAQgBsAGsAXwBfAD4AAAA=</arg></arguments><hs><h>AAAACIDlzUD+</h></hs></diag></diag_root>"); |
| 795 | ssHasStateInsideForEachSS(S, false); |
| 796 | } |
| 797 | |
| 798 | #endif |
| 799 | |
| 800 | } |
| 801 | |
| 802 | /* Function to initialize sample times. */ |
| 803 | static void mdlInitializeSampleTimes(SimStruct *S) |
| 804 | { |
| 805 | /* task periods */ |
| 806 | ssSetSampleTime(S, 0, 0.0); |
| 807 | ssSetSampleTime(S, 1, 5.0E-7); |
| 808 | |
| 809 | /* task offsets */ |
| 810 | ssSetOffsetTime(S, 0, 0.0); |
| 811 | ssSetOffsetTime(S, 1, 0.0); |
| 812 | } |
| 813 | |
| 814 | #if defined(MATLAB_MEX_FILE) |
| 815 | #include "fixedpoint.c" |
| 816 | #include "simulink.c" |
| 817 | #else |
| 818 | #undef S_FUNCTION_NAME |
| 819 | #define S_FUNCTION_NAME PWM_sf |
| 820 | #include "cg_sfun.h" |
| 821 | #endif /* defined(MATLAB_MEX_FILE) */ |
| 822 | |