Hi,
I am working on pdm mic integration in zephyr RTOS. I used INMP441 mic sensor. I got SPL in dB by using nrfx. I want to create a driver for this mic. Please help me how to create driver.
I attached the working code of nrfx pdm mic.
Thank you.
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <zephyr.h>
#include <nrfx_power.h>
#include <nrfx_pdm.h>
#include <hal/nrf_pdm.h>
#include <nrfx_log.h>
#define RMS_BUFFER_SIZE 4096
#define MAX_SOUND_PRESSURE_LEVEL 120 /*<-- change for specific mic*/
#define PDM_BUF_ADDRESS 0x20000000 // buffer address in RAM
#define PDM_BUF_SIZE 512
#define CLK_PIN 30 /*<-- change for specific pin*/
#define DIN_PIN 31 /*<-- change for specific pin*/
int16_t pdm_buf[PDM_BUF_SIZE];
int16_t rms_buffer[RMS_BUFFER_SIZE];
double rms_normalized = 0.0;
double rms_db_spl = 0.0;
uint16_t rms_buffer_cursor = 0;
double calculate_rms(int16_t *buffer, uint16_t num_samples) {
uint64_t sum = 0;
for (uint16_t j = 0; j < num_samples; j++) {
rms_buffer[rms_buffer_cursor] = buffer[j];
rms_buffer_cursor = (rms_buffer_cursor + 1) % RMS_BUFFER_SIZE;
}
for (uint16_t j = 0; j < RMS_BUFFER_SIZE; j++) {
sum += rms_buffer[j] * rms_buffer[j];
}
double tosquirt = sum / RMS_BUFFER_SIZE;
return sqrt(tosquirt);
}
double calculate_dbfs_from_normalized(double rms_normalized) {
double fabsRmsNormalised = fabs(rms_normalized);
return log10(fabsRmsNormalised) * 20;
}
double get_db_spl(double normalized_rms) {
const uint8_t db_spl_offset = MAX_SOUND_PRESSURE_LEVEL;
double out = calculate_dbfs_from_normalized(normalized_rms) + db_spl_offset;
// printk("RMS out: %f\n", out);
return out;
}
void audio_callback(int16_t *buffer, uint16_t size) {
// Calculate RMS of last 250 ms
double rms = calculate_rms(buffer, size);
// printk("RMS value: %f\n", rms);
// Convert int16_t to double
rms_normalized = rms / (double) 32768.0;
// Convert rms to dB value
rms_db_spl = get_db_spl(rms_normalized);
printk("dB value %f\n", rms_db_spl);
}
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) {
audio_callback(pdm_buf, PDM_BUF_SIZE);
//k_sleep(K_MSEC(1000));
}
}
static void pdm_init(void)
{
nrfx_pdm_config_t pdm_config = NRFX_PDM_DEFAULT_CONFIG(CLK_PIN, DIN_PIN);
nrfx_pdm_init(&pdm_config, nrfx_pdm_event_handler);
}
void main(void)
{
nrfx_err_t ret;
printk("Starting PDM program!\n");
printk("PDM Buffer size: %d\n", (PDM_BUF_SIZE * 4));
printk("PDM Starting Address: %x\n", PDM_BUF_ADDRESS);
pdm_init();
ret = nrfx_pdm_start();
if (ret == NRFX_SUCCESS)
{
printk("Pdm start was successfull\n");
}
else {
printk("Pdm start was NOT successfull\n");
}
}