使用MATLAB C编码器将IIR滤波器代码从MATLAB转换为定点C的问题

时间:2015-08-13 16:08:33

标签: c matlab

我正在尝试使用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++;
  }
}

0 个答案:

没有答案