nRF5280 PDM sample at 48Khz fails

Hi,

I'd like to sample PDM at 48kHz, I'm using nRF52840 DK and nRF5 SDK.

I read a post (devzone.nordicsemi.com/.../single-pdm-microphone-at-higher-pcm-sampling-rate) long ago, and I set the PDM clock frequency as shown in the code to 3.2M, and this should indicate a sample rate at 3.2M / 64 = 50kHz.

My code works fine with lower sample rate, I can read adequat samples at 16kHz or around 20kHz. However, when I set it to 3.2M, I can only read at about 29kHz on my Mac, and also the audio sounds terrible.

Can anyone help me with it? I'm not sure if there is anything wrong with the UART.

Thank you so much!

//UART achieve code
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "nordic_common.h"
#include "boards.h"
#include "nrf_uart.h"

#include <hal/nrf_pdm.h>
#include "nrf_drv_pdm.h"
#include "nrfx_pdm.h"

#include "nrf_delay.h"

// config of PDM
// PDM buffer
#define CLK_PIN 28
#define DIN_PIN 29
#define PDM_BUFF_SIZE 256

static int16_t pdm_buffer[PDM_BUFF_SIZE];
static bool pdm_buffer_ready;
static uint16_t pdm_size;

void myPrint(char *message){
  uint8_t i = 0;
  while(message[i] != NULL){ 
   app_uart_put(message[i++]);
  }
  char *new_line = "\r\n";
  app_uart_put(new_line[0]);
  app_uart_put(new_line[1]);
}

void audio_callback(int16_t  *buffer, uint16_t size){
    // Convert the buffer data to a string and send over UART
    //for (uint16_t i = 0; i < 1; i++) {
    //    char str[16]; // Buffer to hold the string representation of the data
    //    snprintf(str, sizeof(str), "%d", buffer[i]); // Convert the sample to string
    //    myPrint("1");
    //}
    pdm_buffer_ready = true;
    pdm_size = size;
}

void nrfx_pdm_event_handler(nrfx_pdm_evt_t const *const p_evt)
{
  if (p_evt->buffer_requested) {
    nrfx_pdm_buffer_set(pdm_buffer, PDM_BUFF_SIZE);						
  }
  if (p_evt->buffer_released != 0) {	
    audio_callback(pdm_buffer, PDM_BUFF_SIZE);
  }
}

static void pdm_init(void)
{
  nrfx_pdm_config_t pdm_config = NRFX_PDM_DEFAULT_CONFIG(CLK_PIN, DIN_PIN);
  pdm_config.clock_freq = PDM_PDMCLKCTRL_FREQ_3200K; // Set to 3.2 MHz
  // #define PDM_PDMCLKCTRL_FREQ_3200K (0x19000000UL) /*!< PDM_CLK = 32 MHz / 10 = 3.2 MHz */
  nrfx_pdm_init(&pdm_config, nrfx_pdm_event_handler);
  NRF_PDM->RATIO = 0;
}

// configs of UART
#define UART_TX_BUFF_SIZE 1024
#define UART_RX_BUFF_SIZE 1024

#define UART_HWFC APP_UART_FLOW_CONTROL_DISABLED

void uart_err_handle(app_uart_evt_t * p_event){
    if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR) {
        APP_ERROR_HANDLER(p_event->data.error_communication);
    }
    else if (p_event->evt_type == APP_UART_FIFO_ERROR) {
        APP_ERROR_HANDLER(p_event->data.error_code);
    }
}

uint32_t uart_init(){
  uint32_t err_code;

  const app_uart_comm_params_t com_params = {
    RX_PIN_NUMBER,
    TX_PIN_NUMBER,
    RTS_PIN_NUMBER,
    CTS_PIN_NUMBER,
    UART_HWFC,
    false,
    //NRF_UART_BAUDRATE_115200
    NRF_UART_BAUDRATE_1000000
  };
  APP_UART_FIFO_INIT(&com_params, UART_RX_BUFF_SIZE, UART_TX_BUFF_SIZE, uart_err_handle, APP_IRQ_PRIORITY_LOWEST, err_code);
  return err_code;

}


int main(void)
{
    nrfx_err_t err_code;

    err_code = uart_init();
    APP_ERROR_CHECK(err_code);

    pdm_init();
    pdm_buffer_ready = false;
    err_code = nrfx_pdm_start();

    APP_ERROR_CHECK(err_code);
    if (err_code == NRFX_SUCCESS){
    }
    char str[16];
    uint8_t cr;

    while (true)
    {
        while (app_uart_get(&cr) != NRF_SUCCESS) {

        }
        if (cr == 't'){
          while (1){
            if (pdm_buffer_ready){
              for (uint16_t i = 0; i < pdm_size; i++) {
                  char high;
                  char low;
                  high = (pdm_buffer[i] >> 8) & 0xFF;
                  low = pdm_buffer[i] & 0xFF;
                  app_uart_put(high);
                  app_uart_put(low);
              }
              pdm_buffer_ready = false;

            }
            if (app_uart_get(&cr) == NRF_SUCCESS){
              if (cr == 'k'){
                break;
              }
            }
          }

        }
    }
}

Related