1
\$\begingroup\$

I am trying to implement a digital High-Pass filter (IIR) with a cut off frequency around ~20Hz on a STM32H753ZI with the CMSIS DSP API. Every time I try to go test it, the output is no longer recognizable below the Fc but looks fine above it.

The way I'm creating the filter is by having MATLAB FDATOOL do most of the work then using the Direct II - Transposed form with a precision of a double.

Before anyone asked, yes the STM32H7 is equipped with a DP-FPU (Double Precision - FPU)

I was doing float precision before and could see why I couldn't go low that frequencies, but I would imagine with double precision I would have no problems.

Any suggestions?

Coefficients for HP Filter with Fc ~ 20Hz:

The order of the filters is : 11

The number of section of the filter is: 6

    0.99982445967420, -1.99964891934840, 0.99982445967420, 1.99964816177700, -0.99964967691960,
    0.99948849907220, -1.99897699814440, 0.99948849907220, 1.99897624082800, -0.99897775546090,
    0.99919412499170, -1.99838824998340, 0.99919412499170, 1.99838749289000, -0.99838900707690,
    0.99896509406540, -1.99793018813080, 0.99896509406540, 1.99792943121100, -0.99793094505080,
    0.99881986128070, -1.99763972256140, 0.99881986128070, 1.99763896575200, -0.99764047937130,
    0.99938486903600, -0.99938486903600, 0.00000000000000, 0.99876973807200, -0.00000000000000

Code:

/*
 * DSP_FACTORY.c
 *
 *  Created on: May 7, 2021
 *      Author: Christopher
 */

#define ARM_MATH_CM7
#include "main.h"
#include "arm_math.h"
#include "FILTER.h"
#include "CONSTANTS.h"
#include "OPCODE.h"
#include "I2S_FACTORY.h"

static double inputCompensator = 1.0;
static uint8_t volumeCurrent = 100;

static arm_biquad_cascade_df2T_instance_f64 audioStream_L;
static arm_biquad_cascade_df2T_instance_f64 audioStream_R;

void INIT_FILTER(uint8_t sourceMode) {

    switch(sourceMode) {

    case INPUT_INLINE:

        arm_biquad_cascade_df2T_init_f64(&audioStream_L, 6, initFilter_96kHz_inline, pState_L_96kHz_inline);
        arm_biquad_cascade_df2T_init_f64(&audioStream_R, 6, initFilter_96kHz_inline, pState_L_96kHz_inline);
        break;

    case INPUT_BLUETOOTH:

        arm_biquad_cascade_df2T_init_f64(&audioStream_L, 8, initFilter_96kHz_inline, pState_L_44_1kHz_bluetooth);
        arm_biquad_cascade_df2T_init_f64(&audioStream_R, 8, initFilter_96kHz_inline, pState_R_44_1kHz_bluetooth);
        break;
    }
}

void I2S_HALFCOMPLETE_CALLBACK() {

    int * I2S1_RxBUFF = getI2S1_RxBUFF();
    int * I2S1_TxBUFF = getI2S1_TxBUFF();

    double INSAMPLE_I2S_L[1024];
    double INSAMPLE_I2S_R[1024];

    double OUTSAMPLE_I2S_L[1024];
    double OUTSAMPLE_I2S_R[1024];

    for (int i = 0; i < 2048; i ++){

        if ( i % 2 == 0){ // R Samples

              INSAMPLE_I2S_L[i-(i >> 1)] = (double) (I2S1_RxBUFF[i] << ADC_COMPENSATOR) * (0.01 * (double) volumeCurrent) * inputCompensator;

        } else if ( i % 2 == 1){ // R Samples

              INSAMPLE_I2S_R[i-1-((i-1)>>1)] = (double) (I2S1_RxBUFF[i] << ADC_COMPENSATOR) * (0.01 * (double) volumeCurrent) * inputCompensator;

        }
}
                 arm_biquad_cascade_df2T_f64(&audioStream_L, INSAMPLE_I2S_L, OUTSAMPLE_I2S_L, 1024);
                 arm_biquad_cascade_df2T_f64(&audioStream_R, INSAMPLE_I2S_R, OUTSAMPLE_I2S_R, 1024);

                 for (int i = 0; i < 2048; i ++){

                                   if (i % 2 == 0) { // L Samples

                                       I2S1_TxBUFF[i] = (int)OUTSAMPLE_I2S_L[i-(i >> 1)];

                                 } else if ( i % 2 == 1) { // R Samples

                                       I2S1_TxBUFF[i] = (int)OUTSAMPLE_I2S_R[i-1-((i-1)>>1)];

                                 }
                            }






}

void I2S_TRANSFERCOMPLETE_CALLBACK() {

    int * I2S1_RxBUFF = getI2S1_RxBUFF();
    int * I2S1_TxBUFF = getI2S1_TxBUFF();

    double INSAMPLE_I2S_L[1024];
    double INSAMPLE_I2S_R[1024];

    double OUTSAMPLE_I2S_L[1024];
    double OUTSAMPLE_I2S_R[1024];

    for (int i = 2048; i < 4096; i ++){

                      if (i % 2 == 0){ // L Samples

                          INSAMPLE_I2S_L[i-(i >> 1)-1024] = (double) (I2S1_RxBUFF[i] << ADC_COMPENSATOR) * (0.01 * (double) volumeCurrent) * inputCompensator;

                    } else if ( i % 2 == 1){ // R Samples

                         INSAMPLE_I2S_R[i-1-((i-1)>>1)-1024] = (double) (I2S1_RxBUFF[i] << ADC_COMPENSATOR) * (0.01 * (double) volumeCurrent) * inputCompensator;

                    }
                }

                     arm_biquad_cascade_df2T_f64(&audioStream_L, INSAMPLE_I2S_L, OUTSAMPLE_I2S_L, 1024);
                     arm_biquad_cascade_df2T_f64(&audioStream_R, INSAMPLE_I2S_R, OUTSAMPLE_I2S_R, 1024);


                     for (int i = 2048; i < 4096; i ++){

                                           if (i % 2 == 0) { // L Samples

                                               I2S1_TxBUFF[i] = (int)OUTSAMPLE_I2S_L[i-(i >> 1)-1024];

                                         } else if ( i % 2 == 1) { // R Samples

                                               I2S1_TxBUFF[i] = (int)OUTSAMPLE_I2S_R[i-1-((i-1)>>1)-1024];

                                         }
                                    }




}

void MUTE(uint8_t INPUT_AUDIO_SELECTOR) {


    if((INPUT_AUDIO_SELECTOR == INPUT_INLINE) | (INPUT_AUDIO_SELECTOR == INPUT_BLUETOOTH))

             SPI1->CR1 |= SPI_CR1_CSUSP;
             while (!((SPI1->CR1) & (SPI_CR1_CSTART)));
             DMA1_Stream0->CR &= ~DMA_SxCR_EN;
             DMA1_Stream1->CR &= ~DMA_SxCR_EN;
             SPI1->CR1 &= ~SPI_CR1_SPE;
}

void UNMUTE(uint8_t INPUT_AUDIO_SELECTOR) {


    if((INPUT_AUDIO_SELECTOR == INPUT_INLINE) | (INPUT_AUDIO_SELECTOR == INPUT_BLUETOOTH))

             DMA1_Stream0->CR |= DMA_SxCR_EN;
             DMA1_Stream1->CR |= DMA_SxCR_EN;
             SPI1->CR1 |= SPI_CR1_SPE;
             SPI1->CR1 |= SPI_CR1_CSTART;
}

UPDATE 1:

Fc = 15Hz enter image description here

Fc = 40Hz enter image description here

Fc = 400Hz enter image description here

Frequency Response enter image description here

\$\endgroup\$
9
  • \$\begingroup\$ "Every time I try to go test it, the output is no longer recognizable below the Fc but looks fine above it". Can you post sample input and output waveforms for sinusoidal waves at, say, 10Hz, 20Hz and 30Hz? Perhaps, being a high pass filter, this is expected? \$\endgroup\$ – AJN Jun 8 at 6:24
  • \$\begingroup\$ @AJN I see what you mean, ill post a picture to describe what I am saying with more clarity. \$\endgroup\$ – Leoc Jun 8 at 6:25
  • \$\begingroup\$ Seeing so many coefficients, wha is the order of the filter? Please post a frequency response from the Matlab tool used to create the coefficients. \$\endgroup\$ – AJN Jun 8 at 6:26
  • 1
    \$\begingroup\$ What sampling rates are you using? If the ratio is too great (looks like it), then you'll run into numerical problems. See this on dsp.ee for some tricks. \$\endgroup\$ – a concerned citizen Jun 8 at 6:30
  • 1
    \$\begingroup\$ Is there a typo at the line ... init_f64(&audioStream_R, ..., pState_L_ ... \$\endgroup\$ – AJN Jun 8 at 11:33
2
\$\begingroup\$

I don't understand the code;

I guessed that the problem is with improper state transfer between batches being processed. The sudden dips usually indicate that. The reason why it is not seen for higher frequency input may be because you are viewing at magnified time scale for those inputs. The scope is not showing you the boundaries of the 1024 samples (by chance).

These lines supports my suspicion. Is there a typo ? Should an L be an R ?

arm_biquad_cascade_df2T_init_f64(&audioStream_L, 6, initFilter_96kHz_inline,
pState_
L
_96kHz_inline);
        
arm_biquad_cascade_df2T_init_f64(&audioStream_R, 6, initFilter_96kHz_inline,
pState_
L
_96kHz_inline);
\$\endgroup\$
3
  • \$\begingroup\$ If this guess is correct INPUT_BLUETOOTH should work correctly. Also, I wasn't able to recreate the frequency response plots from the coefficients you posted. Verify it using a software like Matlab / Octave to be doubly sure. \$\endgroup\$ – AJN Jun 8 at 11:37
  • \$\begingroup\$ Hi! I am not sure you mean typo? the INPUT_BLUETOOTH doesnt work for its own reasons as Ill fix it after (it has to be with the 16 bits and the DMA 32 bits) \$\endgroup\$ – Leoc Jun 8 at 15:15
  • \$\begingroup\$ HOLY! it works yeah my god I am sorry it was really late last night I probably oversaw it when I was fixing up the Pstates. The typo fix did it !!! \$\endgroup\$ – Leoc Jun 8 at 15:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.