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?

Parents Reply
  • TWIS0 registers are not changing their default values I mean they remain in their  same state. I am attaching the register values below

    TWIS0                                          
        TASKS_STOP                                 
        TASKS_SUSPEND                              
        TASKS_RESUME                               
        TASKS_PREPARERX                            
        TASKS_PREPARETX                            
        EVENTS_STOPPED               0x00000000    
        EVENTS_ERROR                 0x00000000    
        EVENTS_RXSTARTED             0x00000000    
        EVENTS_TXSTARTED             0x00000000    
        EVENTS_WRITE                 0x00000000    
        EVENTS_READ                  0x00000000    
        SHORTS                       0x00000000    
            WRITE_SUSPEND            0             
            READ_SUSPEND             0             
        INTEN                        0x00000000    
            STOPPED                  0             
            ERROR                    0             
            RXSTARTED                0             
            TXSTARTED                0             
            WRITE                    0             
            READ                     0             
        INTENSET                     0x00000000    
            STOPPED                  0             
            ERROR                    0             
            RXSTARTED                0             
            TXSTARTED                0             
            WRITE                    0             
            READ                     0             
        INTENCLR                     0x00000000    
            STOPPED                  0             
            ERROR                    0             
            RXSTARTED                0             
            TXSTARTED                0             
            WRITE                    0             
            READ                     0             
        ERRORSRC                     0x00000000    
            OVERFLOW                 0             
            DNACK                    0             
            OVERREAD                 0             
        MATCH                        0x00000000    
            MATCH                    0             
        ENABLE                       0x00000000    
            ENABLE                   0             
        ADDRESS[0]                   0x00000000    
            ADDRESS                  0x00          
        ADDRESS[1]                   0x00000000    
            ADDRESS                  0x00          
        CONFIG                       0x00000001    
            ADDRESS0                 1             
            ADDRESS1                 0             
        ORC                          0x00000000    
            ORC                      0x00          
        PSEL.SCL                     0xffffffff    
            PIN                      0x1f          
            CONNECT                  1             
        PSEL.SDA                     0xffffffff    
            PIN                      0x1f          
            CONNECT                  1             
        RXD.PTR                      0x00000000    
            PTR                      0x00000000    
        RXD.MAXCNT                   0x00000000    
            MAXCNT                   0x00          
        RXD.AMOUNT                   0x00000000    
            AMOUNT                   0x00          
        TXD.PTR                      0x00000000    
            PTR                      0x00000000    
        TXD.MAXCNT                   0x00000000    
            MAXCNT                   0x00          
        TXD.AMOUNT                   0x00000000    
            AMOUNT                   0x00          
    
    .Now to set the values what should I do?

Children
  • 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