4
\$\begingroup\$

I am having troubles understanding why a DSP low pass filter was that working on the M4 is no longer working on an M7.

I recently switched over to a STM32H753ZI from a STM32L432KC.

In addition to switching from the L4 to H7 I am using the P2MODI2S2 with the H7 and not the internal ADC like I was when using the L4.

The only thing that came to mind would be the difference of sampling rates. I was using a 44.410kHz sampling rate on the L4 and now I am using a 96kHz sampling rate on the H7 using the PMODI2S2. So I re-did the discrete function and put in the new IIR coefficients and no cigar.

Using the H7 with the PMODI2S2 as a passthrough:

enter image description here

CODE:

#define ARM_MATH_CM7

#include "main.h"

#include "arm_math.h"


void init_Clock(void);
void init_I2S(void);
void init_Debugging(void);
void init_Interrupt(void);
void init_SpeedTest(void);

uint32_t RxBuff[4];
uint32_t TxBuff[4];
uint8_t TC_Callback = 0;
uint8_t HC_Callback = 0;

char uartBuff[8];

float iir_coeffs[5] = {0.00102, 0.002041, 0.00102, 1.908, -0.9116}; //B0, B1, B2, A1, A2
float iir_mono_state[4];

float Rx_Buff_f[8];
float Rx_Buff_f_out[8];


arm_biquad_casd_df1_inst_f32 monoChannel;


void DMA1_Stream0_IRQHandler(void) {

    if (((DMA1 -> LISR) & (DMA_LISR_TCIF0)) != 0){
        DMA1 -> LIFCR |= DMA_LIFCR_CTCIF0;
        TC_Callback = 1;
    }

    else if (((DMA1 -> LISR) & (DMA_LISR_HTIF0)) != 0){
         DMA1 -> LIFCR |= DMA_LIFCR_CHTIF0;
         HC_Callback = 1;

    }
}

int main(void) {

    init_Clock();
    init_I2S();
    //init_Debugging();
    init_Interrupt();
    //init_SpeedTest();
    arm_biquad_cascade_df1_init_f32(&monoChannel, 1, iir_coeffs, iir_mono_state);

  while (1)
  {

      if (HC_Callback == 1){

         // GPIOA->BSRR |= GPIO_BSRR_BS3_HIGH;

         

          for (int i = 0; i < 2; i++){
                TxBuff[i] = RxBuff[i];
            }

          HC_Callback = 0;

      } else  if (TC_Callback == 1){


        //  GPIOA->BSRR |= GPIO_BSRR_BR3_LOW;



                  for (int i = 2; i < 4; i++){
                        TxBuff[i] =  RxBuff[i];
                    }



          TC_Callback = 0;

      }



  }

}

H7 with PMODI2S2 with IIR coefficients using 96kHz sampling rate:

enter image description here

Code:

#define ARM_MATH_CM7

#include "main.h"

#include "arm_math.h"


void init_Clock(void);
void init_I2S(void);
void init_Debugging(void);
void init_Interrupt(void);
void init_SpeedTest(void);

uint32_t RxBuff[4];
uint32_t TxBuff[4];
uint8_t TC_Callback = 0;
uint8_t HC_Callback = 0;

char uartBuff[8];

float iir_coeffs[5] = {0.00102, 0.002041, 0.00102, 1.908, -0.9116}; //B0, B1, B2, A1, A2
float iir_mono_state[4];

float Rx_Buff_f[8];
float Rx_Buff_f_out[8];


arm_biquad_casd_df1_inst_f32 monoChannel;


void DMA1_Stream0_IRQHandler(void) {

    if (((DMA1 -> LISR) & (DMA_LISR_TCIF0)) != 0){
        DMA1 -> LIFCR |= DMA_LIFCR_CTCIF0;
        TC_Callback = 1;
    }

    else if (((DMA1 -> LISR) & (DMA_LISR_HTIF0)) != 0){
         DMA1 -> LIFCR |= DMA_LIFCR_CHTIF0;
         HC_Callback = 1;

    }
}

int main(void) {

    init_Clock();
    init_I2S();
    //init_Debugging();
    init_Interrupt();
    //init_SpeedTest();
    arm_biquad_cascade_df1_init_f32(&monoChannel, 1, iir_coeffs, iir_mono_state);

  while (1)
  {

      if (HC_Callback == 1){

         // GPIOA->BSRR |= GPIO_BSRR_BS3_HIGH;

          for (int i = 0; i < 2; i++){
              Rx_Buff_f[i] = (float)RxBuff[i];
          }

          arm_biquad_cascade_df1_f32(&monoChannel, Rx_Buff_f, Rx_Buff_f_out, 2);

          for (int i = 0; i < 2; i++){
                TxBuff[i] = (uint32_t)Rx_Buff_f_out[i];
            }

          HC_Callback = 0;

      } else  if (TC_Callback == 1){


        //  GPIOA->BSRR |= GPIO_BSRR_BR3_LOW;


          for (int i = 2; i < 4; i++){
               Rx_Buff_f[i] = (float)RxBuff[i];
            }

                  arm_biquad_cascade_df1_f32(&monoChannel, &Rx_Buff_f[2], &Rx_Buff_f_out[2], 2);

                  for (int i = 2; i < 4; i++){
                        TxBuff[i] =  (uint32_t)Rx_Buff_f_out[i];
                    }



          TC_Callback = 0;

      }



  }

}

So I thought to myself, since I am using a I2S protocol and since its stereo I tried using a sampling rate of 192kHz just to see what happens:

enter image description here

CODE:

#define ARM_MATH_CM7

#include "main.h"

#include "arm_math.h"


void init_Clock(void);
void init_I2S(void);
void init_Debugging(void);
void init_Interrupt(void);
void init_SpeedTest(void);

uint32_t RxBuff[4];
uint32_t TxBuff[4];
uint8_t TC_Callback = 0;
uint8_t HC_Callback = 0;

char uartBuff[8];

float iir_coeffs[5] = {0.0002507, 0.0005013, 0.0002507, 1.955, -0.9557}; //B0, B1, B2, A1, A2
float iir_mono_state[4];

float Rx_Buff_f[8];
float Rx_Buff_f_out[8];


arm_biquad_casd_df1_inst_f32 monoChannel;


void DMA1_Stream0_IRQHandler(void) {

    if (((DMA1 -> LISR) & (DMA_LISR_TCIF0)) != 0){
        DMA1 -> LIFCR |= DMA_LIFCR_CTCIF0;
        TC_Callback = 1;
    }

    else if (((DMA1 -> LISR) & (DMA_LISR_HTIF0)) != 0){
         DMA1 -> LIFCR |= DMA_LIFCR_CHTIF0;
         HC_Callback = 1;

    }
}

int main(void) {

    init_Clock();
    init_I2S();
    //init_Debugging();
    init_Interrupt();
    //init_SpeedTest();
    arm_biquad_cascade_df1_init_f32(&monoChannel, 1, iir_coeffs, iir_mono_state);

  while (1)
  {

      if (HC_Callback == 1){

         // GPIOA->BSRR |= GPIO_BSRR_BS3_HIGH;

          for (int i = 0; i < 2; i++){
              Rx_Buff_f[i] = (float)RxBuff[i];
          }

          arm_biquad_cascade_df1_f32(&monoChannel, Rx_Buff_f, Rx_Buff_f_out, 2);

          for (int i = 0; i < 2; i++){
                TxBuff[i] = (uint32_t)Rx_Buff_f_out[i];
            }

          HC_Callback = 0;

      } else  if (TC_Callback == 1){


        //  GPIOA->BSRR |= GPIO_BSRR_BR3_LOW;


          for (int i = 2; i < 4; i++){
               Rx_Buff_f[i] = (float)RxBuff[i];
            }

                  arm_biquad_cascade_df1_f32(&monoChannel, &Rx_Buff_f[2], &Rx_Buff_f_out[2], 2);

                  for (int i = 2; i < 4; i++){
                        TxBuff[i] =  (uint32_t)Rx_Buff_f_out[i];
                    }



          TC_Callback = 0;

      }



  }

}

Any ideas? I am not sure if its the M7 or the peripheral in question. This was working on an L4, no problem.

UPDATE 1: I recorded the variables in debugger mode to see what is happening. I took three pictures. The first iteration is index 0-2 and the second iteration from 2-4 and the third picture is many iterations afterwards.

enter image description here

enter image description here

enter image description here

What I noticed is that RxBuffer and RxBuffer_f are out of sync. I also noticed that many iterations later the RxBuffer_f_out just becomes an int like data type and no longer contain any sort of decimals.

UPDATE 2:

I also notice that I am using a I2S device that shoots out stereo audio, am I maybe not adding the coefficients properly to the buffers. What I mean by this do I need to adjust the buffers when they come in, like bit shift them or anything along those lines? The only thing I know about that PMODI2S2 is that I believe it shoots out 24 bits in a 32 data frame, so I am assuming its padded with zeroes and why not.

UPDATE 3:

Was playing around with just multiplying the RxBuffer before putting in the TxBuffer and what it did was increase the PK - PK of the signal, however increasing it more caused this:

Multiplying the RxBuffer by 2^0 (Passthrough)

enter image description here

Multiplying the RxBuffer by 2^1

enter image description here

Multiplying the RxBuffer by 2^2

enter image description here

The last picture looks like the problem I am having, is this maybe an overflow issue?

UPDATE 4:

Talking to a concerned citizen he mentioned the I2S protocol is a 2's complement data encoded. I know what 2's complement is, however I am not sure if the TxBuff or the Rxbuff needs to be complemented. Anyhow I changed both data type of the TxBuff and the Rxbuff to int32_t datatypes and the problem still insist.

UPDATE 5: Tried using the 2's complement or simply just casting it as an int32_t. No luck.

CODE:

#define ARM_MATH_CM7

#include "main.h"

#include "arm_math.h"


void init_Clock(void);
void init_I2S(void);
void init_Debugging(void);
void init_Interrupt(void);
void init_SpeedTest(void);

uint32_t RxBuff[4];
uint32_t TxBuff[4];
uint8_t TC_Callback = 0;
uint8_t HC_Callback = 0;

char uartBuff[8];

float iir_coeffs[5] = {0.00102, 0.002041, 0.00102, 1.908, -0.9116}; //B0, B1, B2, A1, A2
float iir_mono_state[4];

float Rx_Buff_f[4];
float Rx_Buff_f_out[4];


arm_biquad_casd_df1_inst_f32 monoChannel;


void DMA1_Stream0_IRQHandler(void) {

    if (((DMA1 -> LISR) & (DMA_LISR_TCIF0)) != 0){
        DMA1 -> LIFCR |= DMA_LIFCR_CTCIF0;
        TC_Callback = 1;
    }

    else if (((DMA1 -> LISR) & (DMA_LISR_HTIF0)) != 0){
         DMA1 -> LIFCR |= DMA_LIFCR_CHTIF0;
         HC_Callback = 1;

    }
}

int main(void) {

    init_Clock();
    init_I2S();
    //init_Debugging();
    init_Interrupt();
    //init_SpeedTest();
    arm_biquad_cascade_df1_init_f32(&monoChannel, 1, iir_coeffs, iir_mono_state);

  while (1)
  {

      if (HC_Callback == 1){

         // GPIOA->BSRR |= GPIO_BSRR_BS3_HIGH;

          for (int i = 0; i < 2; i++){
              Rx_Buff_f[i] = (float)((int32_t)RxBuff[i]);
          }

          arm_biquad_cascade_df1_f32(&monoChannel, Rx_Buff_f, Rx_Buff_f_out, 2);

          for (int i = 0; i < 2; i++){
                TxBuff[i] = (int32_t)Rx_Buff_f_out;
            }

          HC_Callback = 0;

      } else  if (TC_Callback == 1){


        //  GPIOA->BSRR |= GPIO_BSRR_BR3_LOW;


          for (int i = 2; i < 4; i++){
               Rx_Buff_f[i] = (float)((int32_t)RxBuff[i]);
            }

                  arm_biquad_cascade_df1_f32(&monoChannel, &Rx_Buff_f[2], &Rx_Buff_f_out[2], 2);

                  for (int i = 2; i < 4; i++){
                        TxBuff[i] =  (int32_t)Rx_Buff_f_out;
                    }



          TC_Callback = 0;

      }



  }

}

UPDATE 6:

Changed code according to a concerned citizen comments

CODE:

#define ARM_MATH_CM7

#include "main.h"

#include "arm_math.h"


void init_Clock(void);
void init_I2S(void);
void init_Debugging(void);
void init_Interrupt(void);
void init_SpeedTest(void);

int32_t RxBuff[4];
int32_t TxBuff[4];
uint8_t TC_Callback = 0;
uint8_t HC_Callback = 0;

char uartBuff[8];
 float32_t iir_coeffs[5] = {0.00102, 0.002041, 0.00102, 1.908, -0.9116}; //B0, B1, B2, A1, A2
float32_t iir_mono_state[4];

float32_t Rx_Buff_f[4];
float32_t Rx_Buff_f_out[4];


arm_biquad_casd_df1_inst_f32 monoChannel;


void DMA1_Stream0_IRQHandler(void) {

    if (((DMA1 -> LISR) & (DMA_LISR_TCIF0)) != 0){
        DMA1 -> LIFCR |= DMA_LIFCR_CTCIF0;
        TC_Callback = 1;
    }

    else if (((DMA1 -> LISR) & (DMA_LISR_HTIF0)) != 0){
         DMA1 -> LIFCR |= DMA_LIFCR_CHTIF0;
         HC_Callback = 1;

    }
}

int main(void) {

    init_Clock();
    init_I2S();
    //init_Debugging();
    init_Interrupt();
    //init_SpeedTest();
    arm_biquad_cascade_df1_init_f32(&monoChannel, 1, iir_coeffs, iir_mono_state);

  while (1)
  {

      if (HC_Callback == 1){

         // GPIOA->BSRR |= GPIO_BSRR_BS3_HIGH;

          for (int i = 0; i < 2; i++){
              Rx_Buff_f[i] = (float32_t)RxBuff[i];
          }

          arm_biquad_cascade_df1_f32(&monoChannel, Rx_Buff_f, Rx_Buff_f_out, 2);

          for (int i = 0; i < 2; i++){
                TxBuff[i] = Rx_Buff_f_out[i];
            }

          HC_Callback = 0;

      } else  if (TC_Callback == 1){


        //  GPIOA->BSRR |= GPIO_BSRR_BR3_LOW;


          for (int i = 2; i < 4; i++){
               Rx_Buff_f[i] = (float32_t)RxBuff[i];
            }

                  arm_biquad_cascade_df1_f32(&monoChannel, &Rx_Buff_f[2], &Rx_Buff_f_out[2], 2);

                  for (int i = 2; i < 4; i++){
                        TxBuff[i] =  Rx_Buff_f_out[i];
                    }



          TC_Callback = 0;

      }



  }

}
\$\endgroup\$
16
  • 1
    \$\begingroup\$ That looks like an offset, signedness or I2S bit position error. Try first with what should be a straight passthrough with no processing. \$\endgroup\$ Oct 14, 2020 at 3:56
  • \$\begingroup\$ Isnt that what my first picture is? Its just a pass through no processing \$\endgroup\$
    – Leoc
    Oct 14, 2020 at 4:07
  • \$\begingroup\$ Then try different patterns and see if you can figure out where it goes bad. Particularly, try to separate the algorithm from the output. You might build a quick and dirty 8-sample sine synthesizer with a multiplicate volume control and feed that through the output verifying you have the numeric range you think you do. \$\endgroup\$ Oct 14, 2020 at 4:13
  • \$\begingroup\$ is there a chance it could be caused not taking in the data properly if its stereo and being sent as a 24bit anything along those lines, do I need to bit shift anythign \$\endgroup\$
    – Leoc
    Oct 14, 2020 at 4:21
  • 1
    \$\begingroup\$ @Leoc That looks like it. You're working with uint32_t, so the high amplification causes the values to wrap. Add this as an answer, it's useful for the future, when people will search for similar problems, when they will see this question with an answer. If you think that solves your problems, accept your own answer. \$\endgroup\$ Oct 14, 2020 at 6:04

1 Answer 1

4
\$\begingroup\$

Solution:

So, I got it working I am not sure if it was due to poorly documentation of I2S or me not understanding the left/ right aligness of a bit, but after reading this on a forum from one the of users, it stated this

"The one you show is Left-justified or as TI calls it "Standard format""

I saw the standard format from here the ADC C5343 datasheet on Pg. 14 in the Serial Audio Interface timing diagram.

Then I tried in the SPI_I2SCFGR register and changed the DATFMT bit to 0x01 for Left aligned and boom everything worked. The filter is working and the wave looks perfect.

The only question left is why it left the voltage on my output sine wave so small ~340mV Pk-PK

\$\endgroup\$
7
  • \$\begingroup\$ So it was the darn signed-ness, after all. This was long battle, I'm glad it's over. +1 from me, because you earned it. You can also accept your own answer. Future searches for this kind of problem will reveal a question with an accepted answer. \$\endgroup\$ Oct 15, 2020 at 7:35
  • 1
    \$\begingroup\$ @aconcernedcitizen We did it mate! Holy feel like celebrating hahaha. I dont get it how the heck would I know its Left aligned if I didnt get lucky with a google search \$\endgroup\$
    – Leoc
    Oct 15, 2020 at 7:37
  • \$\begingroup\$ What frequency is the signal? Maybe it falls in the stopband? \$\endgroup\$ Oct 15, 2020 at 7:38
  • \$\begingroup\$ @aconcernedcitizen The signal input is currently at 620Hz, the stopband is around 2kHz. Could it be the lose of data from going from float -> int32_t? Because with the passthrough it was around 600mV so I lost 6dB worth of gain somewhere \$\endgroup\$
    – Leoc
    Oct 15, 2020 at 7:38
  • \$\begingroup\$ Be sure to use the correct sampling, what sampling frequency did you calculate your coefficients for? \$\endgroup\$ Oct 15, 2020 at 7:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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