我正在尝试使用MATLAB C Coder工具箱将我的二阶IIR滤波器从MATLAB转换为定点C代码。 IIR滤波器如下图所示: lead_lag_controller_tustin =
10.83 + 0.003411 z ^ -1 - 10.83 z ^ -2
1 - 1.728 z ^ -1 + 0.7279 z ^ -2
只是为了笑容,我将上面的过滤器手动转换为定点C,使用Visual Studio Express(带有测试输入和所有)进行编译,并确保它有效。
现在开始使用Matlab C Coder应用程序。这个应用程序生成的定点C代码远非易于理解。我给出了下面的代码,并在代码部分之后发布了我的qns:
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) */
我无法跟随MATLAB C Coder做出的缩放选择。
1 *)这到底发生了什么?
/* %% 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是一个64位有符号长long类型。系数b0定义为32位有符号整数,其中23位为小数值。输入x是带符号的16位短路,小数部分为14位。我们将b0的缩放版本与输入x相乘,并将结果存储在i0中。然后我们正在测试i0的某事。我们测试i0是为了某种饱和度还是溢出?
2 *如下所示,需要定义和调用这两个子程序来乘以两个定点数?
/* %% 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]);
我们是否在这些子程序中再次检查饱和度和/或溢出?
我已经给出了Matlab C Coder提出的两个子程序:
static void sMultiWordMul(const unsigned long long u1[], int n1, const unsigned
long long u2[], int n2, unsigned long long y[], int n)
{
boolean_T isNegative1;
boolean_T isNegative2;
unsigned long long cb1;
int k;
int i;
unsigned long long cb;
unsigned long long u1i;
unsigned long long a1;
unsigned long long a0;
unsigned long long cb2;
int nj;
int j;
unsigned long long yk;
unsigned long long b1;
unsigned long long w10;
unsigned long long w01;
unsigned long long b_yk;
unsigned long long c_yk;
unsigned long long d_yk;
isNegative1 = ((u1[n1 - 1] & 9223372036854775808ULL) != 0ULL);
isNegative2 = ((u2[n2 - 1] & 9223372036854775808ULL) != 0ULL);
cb1 = 1ULL;
/* Initialize output to zero */
for (k = 0; k < n; k++) {
y[k] = 0ULL;
}
for (i = 0; i < n1; i++) {
cb = 0ULL;
u1i = u1[i];
if (isNegative1) {
u1i = ~u1i + cb1;
if (u1i < cb1) {
cb1 = 1ULL;
} else {
cb1 = 0ULL;
}
}
a1 = u1i >> 32U;
a0 = u1i & 4294967295ULL;
cb2 = 1ULL;
k = n - i;
if (n2 <= k) {
nj = n2;
} else {
nj = k;
}
k = i;
for (j = 0; j < nj; j++) {
yk = y[k];
u1i = u2[j];
if (isNegative2) {
u1i = ~u1i + cb2;
if (u1i < cb2) {
cb2 = 1ULL;
} else {
cb2 = 0ULL;
}
}
b1 = u1i >> 32U;
u1i &= 4294967295ULL;
w10 = a1 * u1i;
w01 = a0 * b1;
yk += cb;
if (yk < cb) {
cb = 1ULL;
} else {
cb = 0ULL;
}
u1i *= a0;
yk += u1i;
if (yk < u1i) {
b_yk = 1ULL;
} else {
b_yk = 0ULL;
}
cb += b_yk;
u1i = w10 << 32U;
yk += u1i;
if (yk < u1i) {
c_yk = 1ULL;
} else {
c_yk = 0ULL;
}
cb += c_yk;
u1i = w01 << 32U;
yk += u1i;
if (yk < u1i) {
d_yk = 1ULL;
} else {
d_yk = 0ULL;
}
cb += d_yk;
y[k] = yk;
cb += w10 >> 32U;
cb += w01 >> 32U;
cb += a1 * b1;
k++;
}
if (k < n) {
y[k] = cb;
}
}
/* Apply sign */
if (isNegative1 != isNegative2) {
cb = 1ULL;
for (k = 0; k < n; k++) {
yk = ~y[k] + cb;
y[k] = yk;
if (yk < cb) {
cb = 1ULL;
} else {
cb = 0ULL;
}
}
}
}
static void sMultiWordShr(const unsigned long long u1[], int n1, unsigned int n2,
unsigned long long y[], int n)
{
int nb;
int i;
unsigned long long ys;
int nc;
unsigned int nr;
unsigned int nl;
unsigned long long u1i;
int i1;
unsigned long long yi;
nb = (int)n2 / 64;
i = 0;
if ((u1[n1 - 1] & 9223372036854775808ULL) != 0ULL) {
ys = MAX_uint64_T;
} else {
ys = 0ULL;
}
if (nb < n1) {
nc = n + nb;
if (nc > n1) {
nc = n1;
}
nr = n2 - nb * 64U;
if (nr > 0U) {
nl = 64U - nr;
u1i = u1[nb];
for (i1 = nb + 1; i1 < nc; i1++) {
yi = u1i >> nr;
u1i = u1[i1];
y[i] = yi | u1i << nl;
i++;
}
yi = u1i >> nr;
if (nc < n1) {
u1i = u1[nc];
} else {
u1i = ys;
}
y[i] = yi | u1i << nl;
i++;
} else {
for (i1 = nb; i1 < nc; i1++) {
y[i] = u1[i1];
i++;
}
}
}
while (i < n) {
y[i] = ys;
i++;
}
}