I'm trying to implement a realtime lowpass FIR filter using the CMSIS library.
I'm essentially following this example:
The only difference is that instead of running the filter on a block of samples, I want to run the filter sample by sample. I want to feed one sample from the ADC into the fir function and output the resulting sample to the the DAC. So I decided to use a blocksize of 1.
Here's my relevant code. I have other code for the ADC and DAC which I know works. However, if you want the full code, I can post that as well.
#include "main.h" #include "stm32f4xx_hal.h" #include "arm_math.h" #define BLOCK_SIZE 1 #define NUM_TAPS 29 uint32_t ADC_Buffer[2]; uint32_t DAC_Buffer; float32_t signal_in = 0; float32_t signal_out = 0; float32_t totalval = 0; uint32_t blockSize = BLOCK_SIZE; arm_fir_instance_f32 S; static float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1]; static float32_t firCoeffs[NUM_TAPS] = { -0.0018225230f, -0.0015879294f, +0.0000000000f, +0.0036977508f, +0.0080754303f, +0.0085302217f, -0.0000000000f, -0.0173976984f, -0.0341458607f, -0.0333591565f, +0.0000000000f, +0.0676308395f, +0.1522061835f, +0.2229246956f, +0.2504960933f, +0.2229246956f, +0.1522061835f, +0.0676308395f, +0.0000000000f, -0.0333591565f, -0.0341458607f, -0.0173976984f, -0.0000000000f, +0.0085302217f, +0.0080754303f, +0.0036977508f, +0.0000000000f, -0.0015879294f, -0.0018225230f }; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_DMA_Init(); MX_TIM2_Init(); MX_ADC1_Init(); MX_ADC2_Init(); MX_DAC_Init(); if(HAL_ADC_Start(&hadc2) != HAL_OK) return 0; HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADC_Buffer, 2); HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, &DAC_Buffer, 1, DAC_ALIGN_12B_R); HAL_ADC_Start_IT(&hadc1); HAL_TIM_Base_Start(&htim2); arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs[0], (float32_t *)&firStateF32[0], blockSize); while (1) { } } void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if(hadc->Instance == ADC1) { ADC_Buffer[0] = ADC_Buffer[0] & 0x00000FFF; signal_in = (float32_t)ADC_Buffer[0]*3/4096; signal_in = signal_in - 0.5f; arm_fir_f32(&S, &signal_in, &signal_out, blockSize); signal_out = signal_out + 0.5f; totalval = signal_out*4096/3; DAC_Buffer = (uint32_t) totalval; //signal_out; } }
The problem is that I always get the same signal_out no matter how signal_in changes. After stepping through the arm_fir_f32() function, signal_out is always -1.9764*10^-22.
signal_out
signal_in
arm_fir_f32()
-1.9764*10^-22
Another strange thing is that all the firStateF32 values are 0. They never change.
firStateF32
0
The only thing I'm essentially doing differently from their example is using a blocksize of 1.
Any ideas where I'm going wrong?