Skip to main content
Visitor II
May 15, 2024
Solved

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

  • May 15, 2024
  • 1 reply
  • 2240 views

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

    This topic has been closed for replies.
    Best answer by tjaekel

    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 

    1 reply

    tjaekelAuthor
    Visitor II
    May 15, 2024

    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?

    tjaekelAuthorAnswer
    Visitor II
    May 16, 2024

    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