Qns on converting IIR filter code from MATLAB to fixed point C using MATLAB C coder
Afficher commentaires plus anciens
I am trying to convert my second order IIR filter from MATLAB to fixed point C code using the MATLAB C Coder toolbox. The IIR filter is as shown: lead_lag_controller_tustin =
10.83 + 0.003411 z^-1 - 10.83 z^-2
1 - 1.728 z^-1 + 0.7279 z^-2
Just for grins, I hand-converted the above filter to fixed point C, compiled it using Visual Studio Express (with a test input and all) and made sure it worked.
Now on to the Matlab C Coder app. The fixed point C code generated by this app is far from easy to understand. I give the code below and post my qns after the code section:
void lead_lag_controller_fixpt(const short x[256], short y[256])
{
int m_x1;
int m_x2;
int m_y1;
int m_y2;
int fir_signal_0[256];
int fir_signal_1[256];
int fir_signal_2[256];
int iir_signal_1[256];
int iir_signal_2[256];
int jj;
unsigned short b_jj;
long long i0;
long long i1;
unsigned long long u0;
unsigned long long u1;
int128m_T r0;
int128m_T r1;
int128m_T r2;
long long i2;
long long i3;
long long i4;
long long i5;
long long i6;
long long i7;
long long i8;
long long i9;
long long i10;
long long i11;
/* % Initialising all the filter states to zero. */
m_x1 = 0;
m_x2 = 0;
m_y1 = 0;
m_y2 = 0;
/* % Starting the filter loop per se */
for (jj = 0; jj < 256; jj++) {
b_jj = (unsigned short)(jj + 1);
/* %%FIR signal , no delay */
i0 = 90848624LL * x[b_jj - 1];
if ((i0 & 140737488355328LL) != 0LL) {
i1 = i0 | -140737488355328LL;
} else {
i1 = i0 & 140737488355327LL;
}
fir_signal_0[b_jj - 1] = (int)(i1 >> 14);
/* %%FIR signal , after one delay */
fir_signal_1[b_jj - 1] = (int)(28613LL * m_x1 >> 23);
/* %%FIR signal , after two delays */
fir_signal_2[b_jj - 1] = (int)(-90848625LL * m_x2 >> 23);
/* %%IIR signal , single delay */
u0 = 14495515ULL;
u1 = (unsigned long long)m_y1;
sMultiWordMul(&u0, 1, &u1, 1, &r0.chunks[0U], 2);
sMultiWordShr(&r0.chunks[0U], 2, 23U, &r1.chunks[0U], 2);
iir_signal_1[b_jj - 1] = (int)MultiWord2sLong(&r1.chunks[0U]);
/* %%IIR signal , after two delays */
u0 = 18446744073703445549ULL;
u1 = (unsigned long long)m_y2;
sMultiWordMul(&u0, 1, &u1, 1, &r2.chunks[0U], 2);
sMultiWordShr(&r2.chunks[0U], 2, 23U, &r0.chunks[0U], 2);
iir_signal_2[b_jj - 1] = (int)MultiWord2sLong(&r0.chunks[0U]);
/* %%Filter output signal, summed up */
i0 = fir_signal_0[b_jj - 1];
i2 = fir_signal_1[b_jj - 1];
if ((i0 & 4294967296LL) != 0LL) {
i3 = i0 | -4294967296LL;
} else {
i3 = i0 & 4294967295LL;
}
if ((i2 & 4294967296LL) != 0LL) {
i4 = i2 | -4294967296LL;
} else {
i4 = i2 & 4294967295LL;
}
i0 = i3 + i4;
if ((i0 & 4294967296LL) != 0LL) {
i0 |= -4294967296LL;
} else {
i0 &= 4294967295LL;
}
i2 = fir_signal_2[b_jj - 1];
if ((i0 & 8589934592LL) != 0LL) {
i5 = i0 | -8589934592LL;
} else {
i5 = i0 & 8589934591LL;
}
if ((i2 & 8589934592LL) != 0LL) {
i6 = i2 | -8589934592LL;
} else {
i6 = i2 & 8589934591LL;
}
i0 = i5 + i6;
if ((i0 & 8589934592LL) != 0LL) {
i0 |= -8589934592LL;
} else {
i0 &= 8589934591LL;
}
i2 = iir_signal_1[b_jj - 1];
if ((i0 & 17179869184LL) != 0LL) {
i7 = i0 | -17179869184LL;
} else {
i7 = i0 & 17179869183LL;
}
if ((i2 & 17179869184LL) != 0LL) {
i8 = i2 | -17179869184LL;
} else {
i8 = i2 & 17179869183LL;
}
i0 = i7 + i8;
if ((i0 & 17179869184LL) != 0LL) {
i0 |= -17179869184LL;
} else {
i0 &= 17179869183LL;
}
i2 = iir_signal_2[b_jj - 1];
if ((i0 & 34359738368LL) != 0LL) {
i9 = i0 | -34359738368LL;
} else {
i9 = i0 & 34359738367LL;
}
if ((i2 & 34359738368LL) != 0LL) {
i10 = i2 | -34359738368LL;
} else {
i10 = i2 & 34359738367LL;
}
i0 = i9 + i10;
if ((i0 & 34359738368LL) != 0LL) {
i11 = i0 | -34359738368LL;
} else {
i11 = i0 & 34359738367LL;
}
y[b_jj - 1] = (short)(i11 >> 15);
/* %%update the delay lines */
m_x2 = m_x1;
m_y2 = m_y1;
m_x1 = x[b_jj - 1] << 9;
m_y1 = y[b_jj - 1] << 15;
}
}
/* End of code generation (lead_lag_controller_fixpt.c) */
I have trouble following the scaling choices being made by MATLAB C Coder.
1*) What exactly is happening here?
/* %%FIR signal , no delay */
i0 = 90848624LL * x[b_jj - 1];//b0 = 10.83 and b0 * 2^23 = 90848624. x[b_jj-1] is the input signal
//The above is equivalent to fir_signal_0(jj) = b0*x(jj) from the MATLAB code;
//Thus i0 is fir_signal_0(jj) before testing for the sign
if ((i0 & 140737488355328LL) != 0LL) {
i1 = i0 | -140737488355328LL;
} else {
i1 = i0 & 140737488355327LL;
}
fir_signal_0[b_jj - 1] = (int)(i1 >> 14);
i0 is a 64 bit signed long long type. The coefficient b0 is defined as a 32 bits signed int with 23 bits for the fractional value. The input x is a signed 16 bit short with 14 bits for the fractional part. We are multiplying the scaled version of b0 with the input x and store the result in i0. Then we are testing i0 for something. Are we testing i0 for some kind of saturation and or overflow?
2* What is the need for defining and calling these two subroutines for multiplying two fixed point numbers as shown below?
/* %%IIR signal , single delay */
u0 = 14495515ULL;
u1 = (unsigned long long)m_y1;
sMultiWordMul(&u0, 1, &u1, 1, &r0.chunks[0U], 2);
sMultiWordShr(&r0.chunks[0U], 2, 23U, &r1.chunks[0U], 2);
iir_signal_1[b_jj - 1] = (int)MultiWord2sLong(&r1.chunks[0U]);
Réponses (0)
Catégories
En savoir plus sur Filter Design dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!