Qns on converting IIR filter code from MATLAB to fixed point C using MATLAB C coder
8 ビュー (過去 30 日間)
古いコメントを表示
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]);
0 件のコメント
回答 (0 件)
参考
カテゴリ
Help Center および File Exchange で Single-Rate Filters についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!