/* * rt_TDelayInterpolate.cpp * * Academic License - for use in teaching, academic research, and meeting * course requirements at degree granting institutions only. Not for * government, commercial, or other organizational use. * * Code generation for model "VFControl". * * Model version : 1.1 * Simulink Coder version : 24.1 (R2024a) 19-Nov-2023 * C++ source code generated on : Wed Oct 16 11:32:21 2024 * Created for block: /Transport Delay */ #include "rt_TDelayInterpolate.h" #include #include #include "rtwtypes.h" /* * Time delay interpolation routine * * The linear interpolation is performed using the formula: * * (t2 - tMinusDelay) (tMinusDelay - t1) * u(t) = ----------------- * u1 + ------------------- * u2 * (t2 - t1) (t2 - t1) */ real_T rt_TDelayInterpolate( real_T tMinusDelay, /* tMinusDelay = currentSimTime - delay */ real_T tStart, real_T *uBuf, int_T bufSz, int_T *lastIdx, int_T oldestIdx, int_T newIdx, real_T initOutput, boolean_T discrete, boolean_T minorStepAndTAtLastMajorOutput) { int_T i; real_T yout, t1, t2, u1, u2; real_T* tBuf = uBuf + bufSz; /* * If there is only one data point in the buffer, this data point must be * the t= 0 and tMinusDelay > t0, it ask for something unknown. The best * guess if initial output as well */ if ((newIdx == 0) && (oldestIdx ==0 ) && (tMinusDelay > tStart)) return initOutput; /* * If tMinusDelay is less than zero, should output initial value */ if (tMinusDelay <= tStart) return initOutput; /* For fixed buffer extrapolation: * if tMinusDelay is small than the time at oldestIdx, if discrete, output * tailptr value, else use tailptr and tailptr+1 value to extrapolate * It is also for fixed buffer. Note: The same condition can happen for transport delay block where * use tStart and and t[tail] other than using t[tail] and t[tail+1]. * See below */ if ((tMinusDelay <= tBuf[oldestIdx] ) ) { if (discrete) { return(uBuf[oldestIdx]); } else { int_T tempIdx= oldestIdx + 1; if (oldestIdx == bufSz-1) tempIdx = 0; t1= tBuf[oldestIdx]; t2= tBuf[tempIdx]; u1= uBuf[oldestIdx]; u2= uBuf[tempIdx]; if (t2 == t1) { if (tMinusDelay >= t2) { yout = u2; } else { yout = u1; } } else { real_T f1 = (t2-tMinusDelay) / (t2-t1); real_T f2 = 1.0 - f1; /* * Use Lagrange's interpolation formula. Exact outputs at t1, t2. */ yout = f1*u1 + f2*u2; } return yout; } } /* * When block does not have direct feedthrough, we use the table of * values to extrapolate off the end of the table for delays that are less * than 0 (less then step size). This is not completely accurate. The * chain of events is as follows for a given time t. Major output - look * in table. Update - add entry to table. Now, if we call the output at * time t again, there is a new entry in the table. For very small delays, * this means that we will have a different answer from the previous call * to the output fcn at the same time t. The following code prevents this * from happening. */ if (minorStepAndTAtLastMajorOutput) { /* pretend that the new entry has not been added to table */ if (newIdx != 0) { if (*lastIdx == newIdx) { (*lastIdx)--; } newIdx--; } else { if (*lastIdx == newIdx) { *lastIdx = bufSz-1; } newIdx = bufSz - 1; } } i = *lastIdx; if (tBuf[i] < tMinusDelay) { /* Look forward starting at last index */ while (tBuf[i] < tMinusDelay) { /* May occur if the delay is less than step-size - extrapolate */ if (i == newIdx) break; i = ( i < (bufSz-1) ) ? (i+1) : 0;/* move through buffer */ } } else { /* * Look backwards starting at last index which can happen when the * delay time increases. */ while (tBuf[i] >= tMinusDelay) { /* * Due to the entry condition at top of function, we * should never hit the end. */ i = (i > 0) ? i-1 : (bufSz-1); /* move through buffer */ } i = ( i < (bufSz-1) ) ? (i+1) : 0; } *lastIdx = i; if (discrete) { /* * tempEps = 128 * eps; * localEps = max(tempEps, tempEps*fabs(tBuf[i]))/2; */ double tempEps = (DBL_EPSILON) * 128.0; double localEps = tempEps * std::abs(tBuf[i]); if (tempEps > localEps) { localEps = tempEps; } localEps = localEps / 2.0; if (tMinusDelay >= (tBuf[i] - localEps)) { yout = uBuf[i]; } else { if (i == 0) { yout = uBuf[bufSz-1]; } else { yout = uBuf[i-1]; } } } else { if (i == 0) { t1 = tBuf[bufSz-1]; u1 = uBuf[bufSz-1]; } else { t1 = tBuf[i-1]; u1 = uBuf[i-1]; } t2 = tBuf[i]; u2 = uBuf[i]; if (t2 == t1) { if (tMinusDelay >= t2) { yout = u2; } else { yout = u1; } } else { real_T f1 = (t2-tMinusDelay) / (t2-t1); real_T f2 = 1.0 - f1; /* * Use Lagrange's interpolation formula. Exact outputs at t1, t2. */ yout = f1*u1 + f2*u2; } } return(yout); }