How to set PDM gain

Hello, I am trying to understand how to set the gain registers (GAINL and GAINR) of the PDM peripheral via the proper high-level Zephyr interface. I am expecting one of the following:

  • KConfig options
  • Devicetree settings
  • Something through the dmic API (zephyr/audio/dmic.h)

As far as I can tell, there is nothing. I am using Zephyr/SDK v2.5.0 installed through the Toolchain Manager and using build configuration nrf5340dk_nrf5340_cpuapp.

I am building using a copy of the samples/drivers/audio/dmic application. I am using the Adafruit 3492 ST MEMS PDM microphone connected using the default pin configuration from the demo.

I have looked all throughout the code. There is nothing that passes through to nrf_pdm_gain_set().

PDM_NRFX_DEVICE() uses NRFX_PDM_DEFAULT_CONFIG(), which sets the gain values to NRF_PDM_GAIN_DEFAULT.

I have looked through the existing DevZone posts and have not seen this question answered adequately.

Again, I am looking for something in the KConfig or in the Zephyr driver APIs that allows me to alter this and am not finding it.

Am I missing something?

  • Hi 

    You are not overlooking anything, no. The dmic example is quite generic and doesn't expose any functionality unique to the Nordic PDM peripheral. 

    In order to get full control over the PDM peripheral the best option is probably to use the nrfx_pdm driver directly, or to spin your own PDM driver based on the dmic_nfrx_pdm implementation. 

    The nrfx configuration is set in the code here, and you could always add some lines to set the gain_l and gain_r fields of the nrfx_cfg struct before the nrfx_pdm driver is initialized. 

    Best regards
    Torbjørn

  • I just ran into this same problem.  Would there be anything wrong with simply setting the gain registers after driver initialization?

  • Jeffrey Haynes said:
    I just ran into this same problem.  Would there be anything wrong with simply setting the gain registers after driver initialization?

    If it doesn't result in an error it's probably fine, but..

    In general you should either use nrfx driver or zephyr driver. It's best not to mix the usage of both at the same time in the application code, as zephyr is using the nrfx driver and mixing both might add some redundant code or an error, for example if a function should only be called once per initialization etc.

    PDM gain is set in the nrfx driver here,

    regards

    Jared 

  • Hi Jeffrey,

    The way we solved this was to call the the nrf_pdm_gain_set() between the calls to dmic_configure() and dmic_trigger().

            ret = dmic_configure(m_dmic_dev, &m_dmic_cfg);
            if (ret < 0) {
                LOG_ERR("Failed to configure the driver: %d", ret);
                return ret;
            }
    #ifdef NRF_PDM0_S
            // nRF5340
            nrf_pdm_gain_set(NRF_PDM0_S, NRF_PDM_GAIN_MAXIMUM, NRF_PDM_GAIN_MAXIMUM);
    #else
            // nRF52840
            nrf_pdm_gain_set(NRF_PDM, NRF_PDM_GAIN_MAXIMUM, NRF_PDM_GAIN_MAXIMUM);
    #endif
            ret = dmic_trigger(m_dmic_dev, DMIC_TRIGGER_START);
            if (ret < 0) {
                LOG_ERR("START trigger failed: %d", ret);
                return ret;
            }
Related