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

nrfx PDM mic driver for nRF52 with Zephyr

Hi, 

I am trying to use the nrfx_pdm driver with a microphone connected to the NRF52840DK. Currently, it is working but I cannot quite understand how handlers are functioning. 
Can you please elaborate on this? 
Here is the code example I did:

ISR_DIRECT_DECLARE(pdm_isr_handler)
{
    nrfx_pdm_irq_handler();
    ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency
              */
    //printk("pdm_isr_handler\n");

    return 1; /* We should check if scheduling decision should be made */
}

static void data_handler(nrfx_pdm_evt_t const * p_evt)
{
        nrfx_err_t err = 0;
        printk("data_handler error: %d, %d  ", p_evt->error, p_evt->buffer_requested);
        

        if(true == p_evt->buffer_requested){
            err = nrfx_pdm_buffer_set(pdm_buffer, PDM_DATA_BLOCK_WORDS);
            if(err != NRFX_SUCCESS)
            {
                printk("PDM buffer init error: %d\n", err);
            }
            else
            {
                printk("PDM buffer init OK\n");
            }
        }
        if(p_evt->buffer_released != 0){
            printk("buffer_released\n");
            data_ready_flag = true;
        }
}

void print_sound_data(void)
{
    /* print PCM stream */
    while(!data_ready_flag){
        k_sleep(K_MSEC(1));
    }
    nrfx_pdm_stop();

    memcpy(pdm_buffer, pdm_buffer_temp, sizeof(pdm_buffer));
    data_ready_flag = false;

    printk("PINRT DATA\n");
}

void main(void)
{
    nrfx_pdm_config_t config_pdm = NRFX_PDM_DEFAULT_CONFIG(PDM_CLK_PIN, PDM_DIN_PIN);

    //set buffer to zero
    memset(pdm_buffer_temp, 0x0000, PDM_DATA_BLOCK_WORDS);

    IRQ_DIRECT_CONNECT(PDM_IRQn, 0,
                       pdm_isr_handler, 0);

    nrfx_err_t err = nrfx_pdm_init(&config_pdm, data_handler);
    if(err != NRFX_SUCCESS){
        printk("PDM init error: %d\n", err);
    }
    else{
        printk("PDM init OK\n");
    }

    err = nrfx_pdm_start();
    if(err != NRFX_SUCCESS){
        printk("PDM start error: %d\n", err);
    }
    else{
        printk("PDM start OK\n");
    }

    while (1)
    {
        //k_sleep(K_SECONDS(2));
        printk("Hello World! %s\n", CONFIG_BOARD);
        print_sound_data();
    }
}

It is not clear how data is collected and using the handler.

cc

Best regards,
Vojislav

Parents
No Data
Reply
  • Hello 

    I took reference from your mentioned driver's and created simple example as mentioned in my main.c code. I am interfacing nRF52840 with MP34DT05 but have issues receiving PDM data from sensor.

    Sensor takes minimum 10ms after startup to give output at PDM frequency as per datasheet but I am just receiving 16Khz frequency output from PDM senro data pin.

    I have elaborated the same below.

    Firstly i am running PDM in default configuration as you see in my code. The clock frequency is set around 1MHz with Ratio of 64x which gives around 16K samples/sec.

    /*
     * Copyright (c) 2020 BayLibre, SAS
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <stdio.h>
    #include <nrfx_pdm.h>
    
    #include <string.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    #define PDM_BUF_SIZE 1024  //length of buffer in 16 bit words
    #define PDM_CLK_PIN                     36// 32+4 = p1.04
    #define PDM_DIN_PIN                     37// 32+5 = p1.05
    
    uint16_t pdm_buf[PDM_BUF_SIZE];
    
    static bool data_ready_flag = false;
    int8_t counter=0;
    bool write_data = false;
    
    
    
    void nrfx_pdm_event_handler(nrfx_pdm_evt_t const * const p_evt)
    {
        if(p_evt->buffer_requested)
        {
           nrfx_pdm_buffer_set(pdm_buf, PDM_BUF_SIZE);
        }
        if(p_evt->buffer_released != 0)
        {
          write_data = true;
           //printf("Out: %.2x %.2x\r\n", (uint16_t)pdm_buf[0], (uint16_t)pdm_buf[1]);
        }
    }
    
    /*ISR workaround given by Nordic*/
    ISR_DIRECT_DECLARE(pdm_isr_handler)
    {
      nrfx_pdm_irq_handler();
      ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency
                        */
      return 1; /* We should check if scheduling decision should be made */
    }
    
    
    void main(void)
    {
        nrfx_err_t ret = NRFX_SUCCESS;
    
        IRQ_DIRECT_CONNECT(PDM_IRQn, 0, pdm_isr_handler, 0);  //workaround line 
    
        nrfx_pdm_config_t pdm_config = NRFX_PDM_DEFAULT_CONFIG(PDM_CLK_PIN, PDM_DIN_PIN); /*configures CLK to pin 10 and Din to pin 11*/
    /*
        pdm_config.clock_freq = NRF_PDM_FREQ_1280K;
        pdm_config.ratio = NRF_PDM_RATIO_80X;
        pdm_config.edge = NRF_PDM_EDGE_LEFTRISING;
        pdm_config.gain_l = NRF_PDM_GAIN_MAXIMUM;
        pdm_config.gain_r = NRF_PDM_GAIN_MAXIMUM;
    */
    
        ret = nrfx_pdm_init(&pdm_config, nrfx_pdm_event_handler);
        if(ret != NRFX_SUCCESS){
          printk("PDM Init succesfull.\r\n");
        }
    
        ret = nrfx_pdm_start();
        if(ret != NRFX_SUCCESS)
        {
          printk("PDM recording started succesfully\r\n");
        }
    
      
      while(1)
      {
        while(!write_data){
          k_sleep(K_MSEC(100));
        }
    
        ret = nrfx_pdm_stop();
        if(ret != NRFX_SUCCESS){
          printk("Error Init\r\n");
        }
    
    
        printk("%4x is current value at %x\n", pdm_buf[0], &pdm_buf);
      }
    
    
    
    }
    

    I have a doubt here, shouldn't the output from sensor be 1MHz, which is than sampled by nRF52840 PDM peripheral by 64x ? 

    Because when i connect my logic analyzer on CLK pin and DIN pin nRF52840 board, CLK  is 1MHz freq., but the output seen on DIN pin is just around 7KHz frquency. 

    Below is the image for the refference:

    Now when i use the configurations that's commented in the above code,

        pdm_config.clock_freq = NRF_PDM_FREQ_1280K;
        pdm_config.ratio = NRF_PDM_RATIO_80X;
        pdm_config.edge = NRF_PDM_EDGE_LEFTRISING;
        pdm_config.gain_l = NRF_PDM_GAIN_MAXIMUM;
        pdm_config.gain_r = NRF_PDM_GAIN_MAXIMUM;
    

    I get CLK freq= 1.2 MHz and DIN frequency around 14-16KHz. Now again my question is shouldn't my DIN frquency from the sensor PDM output  be 1MHz instead of jutst 16KHz ? which than get sampled by PDM interface at nRF52840 side. 

    Have you faced any such issues while interfacing? Or do you have any idea what could be the problem here. Is it my sensor issue ?

Children
No Data
Related