These are the 2 main functions in my code.
I do not know if there will be any problem in using 2 cascaded FIR filters ...
All times are OK. I change a pin state in the various places and the ADC is read every 1/20KHz, the filter runs every 1/5KHz and the duration of the calculations does not exceed the time available. So everything seems to be right ...
#define LPF_ORDER 20
#define LPF_HALF_ORDER (LPF_ORDER/2)
#define FILTER_COEFF_MULT 13 //2^13
#define BPF_ORDER 50
#define BPF_ORDER_1 (BPF_ORDER - 1)
#define BPF_HALF_ORDER (BPF_ORDER/2)
//buffer com as últimas leituras da ADC
int16_t ADC_readings_array[LPF_ORDER];
//Index para executar buffer circular da ADC
uint8_t adc_buf_head;
//buffer com as últimas leituras da ADC
int16_t LPF_results_array[BPF_ORDER];
//ultimo resultado do calculo do FIR
int32_t fir_result;
//LOW-PASS FILTER
const int16_t LPF_2000Hz[LPF_HALF_ORDER] =
{ -14, -23, -12, 41, 155, 335, 565, 807, 1010, 1127 };
//BAND-PASS FILTER
const int16_t BPF_100Hz[BPF_HALF_ORDER] =
{ 3, -3, -18, -9, 35, 49, -25, -106, -41, 133, 161, -73, -273, -97, 285, 318, -133, -469, -156, 433, 456, -181, -604,
-190, 503 };
//Interrupt routine to read the ADC value
void Routine_20KHz(void)
{
//save the ADC reading to circular buffer
ADC_readings_array[adc_buf_head] = ADC_DMA[SIGNAL_ADC] - ADC_in_avg;
//update buffer head index
adc_buf_head++;
if (adc_buf_head >= LPF_ORDER)
adc_buf_head = 0;
}
//Function called every 1/5KHz
void FIR_cascade_filter(void)
{
int8_t i;
uint8_t circular_head;
int16_t ADC_order_buffer[LPF_ORDER];
int32_t fir_result;
//Update the ouput "DAC" with the last filter calculation to maintain syncronism
update_output(fir_result);
//*************************************** INIT LOW PASS FILTER****************************
//Order the ADC readings
circular_head = adc_buf_head;
for (i = 0; i < LPF_ORDER; i++)
{
ADC_order_buffer[i] = ADC_readings_array[circular_head];
circular_head++;
if (circular_head >= LPF_ORDER)
circular_head = 0;
}
//Reset fir_result variable
fir_result = 0;
//first part of coeffs
for (i = 0; i < LPF_HALF_ORDER; i++)
{
//multiplication and sum of filter
fir_result += ADC_order_buffer[i] * LPF_2000Hz[i];
}
//second part of coeffs
circular_head = LPF_HALF_ORDER;
for (i = (LPF_HALF_ORDER - 1); i >= 0; i--)
{
//multiplication and sum of filter
fir_result += ADC_order_buffer[circular_head] * LPF_2000Hz[i];
circular_head++;
}
//Divide filter result by 2^13
fir_result = fir_result >> FILTER_COEFF_MULT;
//*************************************** END LOW PASS FILTER****************************
//*************************************** INIT BAND PASS FILTER**************************
//order the LPF results
for (i = 0; i < (BPF_ORDER - 1); i++)
{
LPF_results_array[i + 1] = LPF_results_array[i];
}
//add the last calculation
LPF_results_array[0] = (int16_t) fir_result;
fir_result = 0;
//first part of coeffs
for (i = 0; i < BPF_HALF_ORDER; i++)
{
//multiplication and sum of filter
fir_result += LPF_results_array[i] * BPF_100Hz[i];
}
//second part of coeffs
circular_head = BPF_HALF_ORDER;
for (i = (BPF_HALF_ORDER - 1); i >= 0; i--)
{
//multiplication and sum of filter
fir_result += LPF_results_array[circular_head] * BPF_100Hz[i];
circular_head++;
}
//Divide filter result by 2^13
fir_result = fir_result >> FILTER_COEFF_MULT;
//*************************************** END BAND PASS FILTER**************************
}