cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5xx: ADF as PDM MIC input - mono and DC offset?

tjaekel
Lead

Using STM32U5A5 MCU and adding the ADF example (taken from en.stm32cubeu5-v1-4-0\STM32Cube_FW_U5_V1.4.0\Projects\STM32U575I-EV\Examples\MDF\ADF_AudioRecorder) seems to work.

I have changed to use the PLL3 and setup 3,072MHz as PDM MIC CLK (for 48KHz sample rate, with decimation 64). Also this works (I see the correct PDM CLK on pin and also the data in buffer ADF filtering done looks reasonable).

I have two major questions:

  1. Is my understanding right, as:
    There is just one ADF (not two). And using it for PDM MICs via MDF_SITF_NORMAL_SPI_MODE allows me just to connect/use one MIC?
    It means: I can select the clock edge, e.g. via MDF_BITSTREAM0_RISING (for left or right PDM MIC), but
    due to the fact that just ONE ADF is available - PDM MIC can work only in Mono mode (what I see in buffer as filter results, a MONO signal stream of PCM values)
    So, is ADF for PDM MIC always and just MONO? (just one ADF available)
    (just possible to select if the Left or the Right one should be processed)
  2. I have debugged the code and I have dropped the buffer content displayed in debugger into Excel/LibreOffice (to get a graph):
    I was playing a 1KHz sine wave from smartphone speaker and I can see it - cool, the PDM MIC works and gets the audio signal.
    But:
    a) There is a DC offset (around value 1600). I see this DC offset also with a quiet signal (just ambient noise):
        all values are around 1600 (plus/minus noise).
    b) Where is this DC offset coming from?
    c) How to set the output data size, e.g. 16bit signed PCM?
       The buffer is defined as: int16_t RecBuff[REC_BUFF_SIZE * 2U];
       Is there a config to force 16bit signed? (and why I never get the full swing?, or this DC offset?
       My gain setting is 0.)
    d) Let's assume I want to merge the result later as stereo, e.g. streaming via USB or SPDIF:
       Is there a way to "tell" the filter to place the results for a MONO channel on every second word in buffer?
       (so that I could copy over the entire buffer to the final stereo output, instead to add a "vector DMA"
        to do so)

Is using ADF for PDM MICs always Mono? (stereo MIC not possible)
Is there a DC Offset expected?

STM32U5A5_ADF_PDM.png

1 ACCEPTED SOLUTION

Accepted Solutions

I've found a way to get rid of the DC offset: enable the High Pass Filter on ADF:

  AdfFilterConfig0.HighPassFilter.Activation = ENABLE; 	//DISABLE; this seems to remove the DC offset

Now it works fine, except:
STM source code says, that the gain can be in 3dB steps up to value 24:

  int32_t                   Gain;            /*!< Filter gain in step of around 3db (from -48db to 72dB).
                                                  This parameter must be a number between Min_Data = -16
                                                  and Max_Data = 24 */

But it works for me just up to value 8, with 9 and larger - nothing works anymore.

It was tricky to setup the correct timing (PLL) to get ADF (for PDM MIC input) with SAI2 (as SPDIF output) to stay in sync all the time (a different story, maybe I share in a separate thread).

So, PDM MIC via ADF on a STM32U5A5 works fine now.
And: it is much better as any software based PDM2PCM approach (e.g. using this SW filter on a Portenta H7).
I do not see the harmonics (artefacts), it sounds much better, just the volume level is lower (but I can correct in the SW, in the "digital domain", e.g. scaling before forwarding the PCM sample values).

Here, how it looks like with ADF as PDM MIC input and a 1KHz sine wave from smartphone (pretty good):

STM32U5xx_ADF_PDM.png

My project is here:

https://github.com/tjaekel/NUCLEO-U5A5JZ-Q_QSPI 

View solution in original post

2 REPLIES 2
tjaekel
Lead

BTW: I have played with the gain for the ADF filter.
The comments in code say this:

/*!< Filter gain in step of around 3db (from -48db to 72dB). This parameter must be a number between Min_Data = -16 and Max_Data = 24 */

What happens is:

  • setting gain to 10 (approx. 30dB, which works on a SW PDM2PCM filter, e.g. on Portenta H7) - the signal is completely saturated!
    (just 32767 as all values)
  • if I use 1 (as +3dB = doubled amplitude): the DC Offset is now doubled!

I "must" get rid of this DC Offset, otherwise the gain setting does not make any sense!
It would move the DC Offset into saturation and the signal is clipped/lost (and not really amplified).

How to avoid this DC Offset?

I've found a way to get rid of the DC offset: enable the High Pass Filter on ADF:

  AdfFilterConfig0.HighPassFilter.Activation = ENABLE; 	//DISABLE; this seems to remove the DC offset

Now it works fine, except:
STM source code says, that the gain can be in 3dB steps up to value 24:

  int32_t                   Gain;            /*!< Filter gain in step of around 3db (from -48db to 72dB).
                                                  This parameter must be a number between Min_Data = -16
                                                  and Max_Data = 24 */

But it works for me just up to value 8, with 9 and larger - nothing works anymore.

It was tricky to setup the correct timing (PLL) to get ADF (for PDM MIC input) with SAI2 (as SPDIF output) to stay in sync all the time (a different story, maybe I share in a separate thread).

So, PDM MIC via ADF on a STM32U5A5 works fine now.
And: it is much better as any software based PDM2PCM approach (e.g. using this SW filter on a Portenta H7).
I do not see the harmonics (artefacts), it sounds much better, just the volume level is lower (but I can correct in the SW, in the "digital domain", e.g. scaling before forwarding the PCM sample values).

Here, how it looks like with ADF as PDM MIC input and a 1KHz sine wave from smartphone (pretty good):

STM32U5xx_ADF_PDM.png

My project is here:

https://github.com/tjaekel/NUCLEO-U5A5JZ-Q_QSPI