Created
March 16, 2023 02:24
-
-
Save hlord2000/52949ffc1650bb91f2170a4ac160ebae to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2021 Nordic Semiconductor ASA | |
* | |
* SPDX-License-Identifier: Apache-2.0 | |
*/ | |
#include <zephyr/kernel.h> | |
#include <zephyr/audio/dmic.h> | |
#include <zephyr/drivers/pwm.h> | |
#include <zephyr/logging/log.h> | |
#include <math.h> | |
LOG_MODULE_REGISTER(dmic_sample); | |
static const struct pwm_dt_spec pwm_led_0 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led0)); | |
#define MAX_SAMPLE_RATE 16000 | |
#define SAMPLE_BIT_WIDTH 16 | |
#define BYTES_PER_SAMPLE sizeof(int16_t) | |
/* Milliseconds to wait for a block to be read. */ | |
#define READ_TIMEOUT SYS_FOREVER_MS | |
/* Size of a block for 100 ms of audio data. */ | |
#define BLOCK_SIZE(_sample_rate, _number_of_channels) \ | |
(BYTES_PER_SAMPLE * (_sample_rate / 10) * _number_of_channels) | |
/* Driver will allocate blocks from this slab to receive audio data into them. | |
* Application, after getting a given block from the driver and processing its | |
* data, needs to free that block. | |
*/ | |
#define MAX_BLOCK_SIZE BLOCK_SIZE(MAX_SAMPLE_RATE, 2) | |
#define BLOCK_COUNT 4 | |
K_MEM_SLAB_DEFINE_STATIC(mem_slab, MAX_BLOCK_SIZE, BLOCK_COUNT, 4); | |
static int do_pdm_transfer(const struct device *dmic_dev, | |
struct dmic_cfg *cfg, | |
size_t block_count) | |
{ | |
int ret; | |
LOG_INF("PCM output rate: %u, channels: %u", | |
cfg->streams[0].pcm_rate, cfg->channel.req_num_chan); | |
ret = dmic_configure(dmic_dev, cfg); | |
if (ret < 0) { | |
LOG_ERR("Failed to configure the driver: %d", ret); | |
return ret; | |
} | |
ret = dmic_trigger(dmic_dev, DMIC_TRIGGER_START); | |
if (ret < 0) { | |
LOG_ERR("START trigger failed: %d", ret); | |
return ret; | |
} | |
while (true){ | |
for (int i = 0; i < block_count; ++i) { | |
void *buffer; | |
uint32_t size; | |
int ret; | |
ret = dmic_read(dmic_dev, 0, &buffer, &size, READ_TIMEOUT); | |
if (ret < 0) { | |
LOG_ERR("%d - read failed: %d", i, ret); | |
return ret; | |
} | |
//LOG_INF("%d - got buffer %p of %u bytes", i, buffer, size); | |
double sum = 0; | |
for (int j = 0; j < size; j += 2) { | |
int16_t sample = ((int16_t *)buffer)[j / 2]; | |
float sample_f = (float)sample / 32768.0; | |
// Now calculate the root mean square fo the buffer | |
sum += sample_f * sample_f; | |
} | |
sum = sum / (size / 2); | |
double rms = sqrt(sum); | |
LOG_INF("RMS: %f", rms); | |
pwm_set_pulse_dt(&pwm_led_0, (int)(rms * 10000000)); | |
k_mem_slab_free(&mem_slab, &buffer); | |
} | |
} | |
return ret; | |
} | |
void main(void) | |
{ | |
const struct device *const dmic_dev = DEVICE_DT_GET(DT_NODELABEL(dmic_dev)); | |
int ret; | |
LOG_INF("DMIC sample"); | |
if (!device_is_ready(dmic_dev)) { | |
LOG_ERR("%s is not ready", dmic_dev->name); | |
return; | |
} | |
struct pcm_stream_cfg stream = { | |
.pcm_width = SAMPLE_BIT_WIDTH, | |
.mem_slab = &mem_slab, | |
}; | |
struct dmic_cfg cfg = { | |
.io = { | |
/* These fields can be used to limit the PDM clock | |
* configurations that the driver is allowed to use | |
* to those supported by the microphone. | |
*/ | |
.min_pdm_clk_freq = 1000000, | |
.max_pdm_clk_freq = 3500000, | |
.min_pdm_clk_dc = 40, | |
.max_pdm_clk_dc = 60, | |
}, | |
.streams = &stream, | |
.channel = { | |
.req_num_streams = 1, | |
}, | |
}; | |
cfg.channel.req_num_chan = 1; | |
cfg.channel.req_chan_map_lo = | |
dmic_build_channel_map(0, 0, PDM_CHAN_LEFT); | |
cfg.channel.req_chan_map_hi = | |
dmic_build_channel_map(1, 0, PDM_CHAN_LEFT); | |
cfg.streams[0].pcm_rate = MAX_SAMPLE_RATE; | |
cfg.streams[0].block_size = | |
BLOCK_SIZE(cfg.streams[0].pcm_rate, cfg.channel.req_num_chan); | |
while (true) { | |
ret = do_pdm_transfer(dmic_dev, &cfg, 2 * BLOCK_COUNT); | |
if (ret < 0) { | |
return; | |
} | |
} | |
LOG_INF("Exiting"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment