This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PDM code implementation and testing

static void bsp_event_handler(bsp_event_t event)
{
    ret_code_t err_code;

    switch (event)
    {
        case BSP_EVENT_SLEEP:
            sleep_mode_enter();
            break; // BSP_EVENT_SLEEP

        case BSP_EVENT_DISCONNECT:
            err_code = sd_ble_gap_disconnect(m_conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
            break; // BSP_EVENT_DISCONNECT

        case BSP_EVENT_WHITELIST_OFF:
            if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
            {
                err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
            }
            break; // BSP_EVENT_KEY_0
          case BSP_EVENT_KEY_1:
            NRF_LOG_INFO("\n Press Button key 1\n");
            NRF_LOG_INFO("\n Erase the flash content !!\n");
//            err_code = pcm_pstorage_eraseall();
//            APP_ERROR_CHECK(err_code);
            break;

         case BSP_EVENT_KEY_2:
            NRF_LOG_INFO("\n Start:PDM --> PCM\n");
            err_code =  nrf_drv_pdm_start(); 
            APP_ERROR_CHECK(err_code);
            break;

         case BSP_EVENT_KEY_3:
            NRF_LOG_INFO("\n Stop:PDM --> PCM\n");
            // stop audio sample
            nrf_drv_pdm_stop();
            break;

        default:
            break;
    }
}









static void drv_audio_pdm_event_handler(uint32_t *p_buffer, uint16_t length)
{
	m_buffer_handler((int16_t *)p_buffer, length);
        int i;
//        for(i=0;i<= length;i++)
//        {
//          NRF_LOG_INFO("%s ",&p_buffer[i]);
//        }
//        NRF_LOG_INFO("\n ");
          NRF_LOG_INFO("pdm event handler \n");

}


uint32_t drv_audio_init(drv_audio_buffer_handler_t buffer_handler)
{
//    nrf_drv_pdm_config_t pdm_cfg = NRF_DRV_PDM_DEFAULT_CONFIG(CONFIG_IO_PDM_CLK,
//                                                              CONFIG_IO_PDM_DATA,
//                                                              m_pdm_buff[0],
//                                                              m_pdm_buff[1],
//                                                              CONFIG_PDM_BUFFER_SIZE_SAMPLES);
    nrf_drv_pdm_config_t pdm_cfg = NRF_DRV_PDM_DEFAULT_CONFIG(CONFIG_IO_PDM_CLK,CONFIG_IO_PDM_DATA);
    
    if (buffer_handler == NULL)
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    
    m_buffer_handler    = buffer_handler;
    pdm_cfg.gain_l      = CONFIG_PDM_GAIN;
    pdm_cfg.gain_r      = CONFIG_PDM_GAIN;
    

    return nrf_drv_pdm_init(&pdm_cfg, drv_audio_pdm_event_handler);
}










int main(void)
{
    bool erase_bonds;

    // Initialize.
    log_init();
    timers_init();
    buttons_leds_init(&erase_bonds);
    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    advertising_init();
    services_init();
    conn_params_init();
    peer_manager_init();

    // Start execution.
    NRF_LOG_INFO("Template example started.");
    application_timers_start();

//    advertising_start(erase_bonds);
    uint32_t err_code;
    err_code = drv_audio_init(drv_audio_pdm_event_handler);
    APP_ERROR_CHECK(err_code);
    
    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
    }
}

I have to connect a MIC  working on PDM to nrf52 DK Board.For that, I have written the above code.  But when I am testing I am not able to get the clock pulses at the defined pin. Also do not know at which Freq it is working?

And when I read the pdm documentation it says I need to change the PSEL.CLK register value? Then how should I do it and with what value? same for PSEL.DIN register. I am confused a lot. Please suggest me the solution to all my doubts.I have checked the clk pin on Oscilloscope, the clock is not being generated.In order to generate clk at pin number 22 of nrf52 DK board should I define pin clk  as #define CONFIG_IO_PDM_CLK 0x22 or 0x16 (hex value of 22 )instead o rtf 0x22?

  • The I suggest you single step through the init function to where the HAL actually writes to one of these registers, and see what happens with the registers when you single-step through the functions.

  • I was checking the wrong register group. So when I checked the PDM register group the values in the register were being updated. I have attached the images of register values. But still,

    PDM                                       
        TASKS_START                           
        TASKS_STOP                            
        EVENTS_STARTED          0x00000000    
        EVENTS_STOPPED          0x00000000    
        EVENTS_END              0x00000000    
        INTEN                   0x00000003    
            STARTED             1             
            STOPPED             1             
            END                 0             
        INTENSET                0x00000003    
            STARTED             1             
            STOPPED             1             
            END                 0             
        INTENCLR                0x00000003    
            STARTED             1             
            STOPPED             1             
            END                 0             
        ENABLE                  0x00000001    
            ENABLE              1             
        PDMCLKCTRL              0x08000000    
            FREQ                134217728     
        MODE                    0x00000003    
            OPERATION           1             
            EDGE                1             
        GAINL                   0x00000028    
            GAINL               40            
        GAINR                   0x00000028    
            GAINR               40            
        PSEL.CLK                0x00000016    
            PIN                 0x16          
            CONNECT             0             
        PSEL.DIN                0x00000005    
            PIN                 0x05          
            CONNECT             0             
        SAMPLE.PTR              0x00000000    
            SAMPLEPTR           0x00000000    
        SAMPLE.MAXCNT           0x00000000    
            BUFFSIZE            0x0000        
    the clk is not being generated when I am checking on CRO. What could be the reason?

  • Maybe you need to set up the sample buffer first, nrfx_pdm_buffer_set

    Are you using the nRF52DK (PCA10040)?

  • Yes I am using nRF52DK (PCA10040) and SDK 15.3.0. And is there any limitations on the pin for clk ? I mean whether it should be an analog pin or general-purpose I/O? Now will check after using buffer set

  • which buffer should I use to in nrfx_pdm_buffer_set? because when I debug it takes me to the hardfault error. I have attached my code snippet for your reference.

    #define DEVICE_NAME                     "Nordic_Template"                       /**< Name of device. Will be included in the advertising data. */
    #define MANUFACTURER_NAME               "NordicSemiconductor"                   /**< Manufacturer. Will be passed to Device Information Service. */
      
    #define CONFIG_PDM_BUFFER_SIZE_SAMPLES 320
    
    // <o> PDM Decimation Filter Gain <0x00-0x50>
    // <i> For details on the PDM decimation filter, see the 'Decimation filter' section in the nRF52 Product Specification document.
    #define CONFIG_PDM_GAIN 0x28
    
    
    // <o> PDM CLK Pin
    #define CONFIG_IO_PDM_CLK  29
    
    // <o> PDM DATA Pin
    #define CONFIG_IO_PDM_DATA 5//0x05
    
    // <o> PDM Microphone Power Control Pin
    #define CONFIG_IO_PDM_MIC_PWR_CTRL 0x1A
    
    
    /**@brief Audio buffer handler. */
    typedef void (*drv_audio_buffer_handler_t)(int16_t *p_buffer, uint16_t samples);
    
    
    
    static int16_t                      m_pdm_buff[2][CONFIG_PDM_BUFFER_SIZE_SAMPLES];
    
    static drv_audio_buffer_handler_t   m_buffer_handler;
    
    
    
    
    static void drv_audio_pdm_event_handler(uint32_t *p_buffer, uint16_t length)
    {
    	m_buffer_handler((int16_t *)p_buffer, length);
    
              NRF_LOG_INFO("pdm event handler \n");
           
    
    }
    
    
    
    uint32_t drv_audio_init(drv_audio_buffer_handler_t buffer_handler)
    {
    //    nrf_drv_pdm_config_t pdm_cfg = NRF_DRV_PDM_DEFAULT_CONFIG(CONFIG_IO_PDM_CLK,
    //                                                              CONFIG_IO_PDM_DATA,
    //                                                              m_pdm_buff[0],
    //                                                              m_pdm_buff[1],
    //                                                              CONFIG_PDM_BUFFER_SIZE_SAMPLES);
        nrf_drv_pdm_config_t pdm_cfg = NRF_DRV_PDM_DEFAULT_CONFIG(CONFIG_IO_PDM_CLK,CONFIG_IO_PDM_DATA);
        
        if (buffer_handler == NULL)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
        
        m_buffer_handler    = buffer_handler;
        pdm_cfg.gain_l      = CONFIG_PDM_GAIN;
        pdm_cfg.gain_r      = CONFIG_PDM_GAIN;
    
        return nrf_drv_pdm_init(&pdm_cfg, drv_audio_pdm_event_handler);
         
    }
    
    
    void pdm_init(void)
    {
      uint32_t err_code;
      err_code = drv_audio_init(drv_audio_pdm_event_handler);
    //    nrf_pdm_enable();
    }
    
    
    
    
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
       // Start execution.
        pdm_init();
        nrfx_pdm_buffer_set(m_pdm_buff,CONFIG_PDM_BUFFER_SIZE_SAMPLES);
        nrfx_pdm_start();
      // Enter main loop.
      
    }
    
    
    /**
     * @}
     */
    

Related