2021-10-07 05:55 AM
Hi! I need to use FMAC peripheral without any HAL or LL. So, according to RM0440, and AN5305 i`ve got code that works just fine for FIR and IIR filters, but only with coefficients that less than 1. For example, i divided both A and B coeffs by 4 and set Gain (parameter R) to 2 (binary log (4)) to keep digits in acceptable fixed point format. RDATA output transfer only min and max values 8000 to 7FFF, so there is only square form signal on output. Coeffs and gain are next:
IIR_struct fourth_order = {
.shift = 2,
.m = 4,
.n = 5,
.a = {(uint16_t)(-19411), (uint16_t)(18956), (uint16_t)(-8640), (uint16_t)(1535)},
.b = {(uint16_t)(40), (uint16_t)(158), (uint16_t)(237), (uint16_t)(158), (uint16_t)(40)},
};
What i missed?
void fmac_iir_config(IIR_struct* iir)
{
int buffsize = 1;
FMAC->X2BUFCFG |= 0 << FMAC_X2BUFCFG_X2_BASE_Pos;
FMAC->X2BUFCFG |= (iir->n + iir->m) << FMAC_X2BUFCFG_X2_BUF_SIZE_Pos;
FMAC->X1BUFCFG |= (iir->n + iir->m) << FMAC_X1BUFCFG_X1_BASE_Pos;
FMAC->X1BUFCFG |= (iir->n + buffsize) << FMAC_X1BUFCFG_X1_BUF_SIZE_Pos; //n + buffsize
FMAC->X1BUFCFG |= 0 << FMAC_X1BUFCFG_FULL_WM_Pos;
FMAC->YBUFCFG |= (2 * iir->n + iir->m + buffsize) << FMAC_YBUFCFG_Y_BASE_Pos; //2 * n + m + buffsize
FMAC->YBUFCFG |= (iir->m + buffsize) << FMAC_YBUFCFG_Y_BUF_SIZE_Pos; //m + buffsize
FMAC->YBUFCFG |= 0 << FMAC_YBUFCFG_EMPTY_WM_Pos;
FMAC->PARAM &= ~FMAC_PARAM_FUNC;
FMAC->PARAM |= FMAC_PARAM_FUNC_1; //Load X2
FMAC->PARAM &= ~FMAC_PARAM_P;
FMAC->PARAM |= iir->n << FMAC_PARAM_P_Pos;
FMAC->PARAM &= ~FMAC_PARAM_Q;
FMAC->PARAM |= iir->m << FMAC_PARAM_Q_Pos;
FMAC->PARAM &= ~FMAC_PARAM_R;
FMAC->PARAM |= FMAC_PARAM_START;
for(int i = 0; i < (iir->n); i++)
{
FMAC->WDATA = iir->b[i];
}
for(int i = 0; i < (iir->m); i++)
{
FMAC->WDATA = iir->a[i];
}
FMAC->PARAM &= ~FMAC_PARAM_FUNC;
FMAC->PARAM |= FMAC_PARAM_FUNC_3 + FMAC_PARAM_FUNC_0; //FUNC = 9 (IIR filter)
FMAC->PARAM &= ~FMAC_PARAM_P;
FMAC->PARAM |= iir->n << FMAC_PARAM_P_Pos; //P = N (feed-forward coeffs.)
FMAC->PARAM &= ~FMAC_PARAM_Q;
FMAC->PARAM |= iir->m << FMAC_PARAM_Q_Pos; //Q = M (feed-back coeffs.)
FMAC->PARAM &= ~FMAC_PARAM_R;
FMAC->PARAM |= iir->shift << FMAC_PARAM_R_Pos; //R = shift
FMAC->CR |= FMAC_CR_DMAREN + FMAC_CR_CLIPEN;
FMAC->PARAM |= FMAC_PARAM_START;
}