Modify the signature of the k_mem_slab_free() function with a new one, replacing the old void **mem with void *mem as a parameter. The following function: void k_mem_slab_free(struct k_mem_slab *slab, void **mem); has the wrong signature. mem is only used as a regular pointer, so there is no need to use a double-pointer. The correct signature should be: void k_mem_slab_free(struct k_mem_slab *slab, void *mem); The issue with the current signature, although functional, is that it is extremely confusing. I myself, a veteran Zephyr developer, was confused by this parameter when looking at it recently. All in-tree uses of the function have been adapted. Fixes #61888. Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
137 lines
3.3 KiB
C
137 lines
3.3 KiB
C
/*
|
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/audio/dmic.h>
|
|
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(dmic_sample);
|
|
|
|
#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 1000
|
|
|
|
/* 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;
|
|
}
|
|
|
|
for (int i = 0; i < block_count; ++i) {
|
|
void *buffer;
|
|
uint32_t size;
|
|
|
|
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);
|
|
|
|
k_mem_slab_free(&mem_slab, buffer);
|
|
}
|
|
|
|
ret = dmic_trigger(dmic_dev, DMIC_TRIGGER_STOP);
|
|
if (ret < 0) {
|
|
LOG_ERR("STOP trigger failed: %d", ret);
|
|
return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int 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 0;
|
|
}
|
|
|
|
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.streams[0].pcm_rate = MAX_SAMPLE_RATE;
|
|
cfg.streams[0].block_size =
|
|
BLOCK_SIZE(cfg.streams[0].pcm_rate, cfg.channel.req_num_chan);
|
|
|
|
ret = do_pdm_transfer(dmic_dev, &cfg, 2 * BLOCK_COUNT);
|
|
if (ret < 0) {
|
|
return 0;
|
|
}
|
|
|
|
cfg.channel.req_num_chan = 2;
|
|
cfg.channel.req_chan_map_lo =
|
|
dmic_build_channel_map(0, 0, PDM_CHAN_LEFT) |
|
|
dmic_build_channel_map(1, 0, PDM_CHAN_RIGHT);
|
|
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);
|
|
|
|
ret = do_pdm_transfer(dmic_dev, &cfg, 2 * BLOCK_COUNT);
|
|
if (ret < 0) {
|
|
return 0;
|
|
}
|
|
|
|
LOG_INF("Exiting");
|
|
return 0;
|
|
}
|