Skip to content

Commit da5fa34

Browse files
committed
tests: drivers: audio: Add test that collects audio from microphone
Verify operation of PDM driver with physical microphone and sound analysis. Signed-off-by: Sebastian Głąb <sebastian.glab@nordicsemi.no>
1 parent 92fcf93 commit da5fa34

File tree

7 files changed

+239
-0
lines changed

7 files changed

+239
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(dmic)
7+
8+
target_sources(app PRIVATE src/main.c)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2021 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&pinctrl {
8+
pdm0_default_alt: pdm0_default_alt {
9+
group1 {
10+
psels = <NRF_PSEL(PDM_CLK, 0, 30)>,
11+
<NRF_PSEL(PDM_DIN, 0, 31)>;
12+
};
13+
};
14+
};
15+
16+
dmic_dev: &pdm0 {
17+
status = "okay";
18+
pinctrl-0 = <&pdm0_default_alt>;
19+
pinctrl-names = "default";
20+
clock-source = "PCLK32M_HFXO";
21+
};
22+
23+
&uart0 {
24+
current-speed = < 921600 >;
25+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2021 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&clock {
8+
hfclkaudio-frequency = <12288000>;
9+
};
10+
11+
&pinctrl {
12+
pdm0_default_alt: pdm0_default_alt {
13+
group1 {
14+
psels = <NRF_PSEL(PDM_CLK, 0, 25)>,
15+
<NRF_PSEL(PDM_DIN, 0, 26)>;
16+
};
17+
};
18+
};
19+
20+
dmic_dev: &pdm0 {
21+
status = "okay";
22+
pinctrl-0 = <&pdm0_default_alt>;
23+
pinctrl-names = "default";
24+
clock-source = "ACLK";
25+
};
26+
27+
&uart0 {
28+
current-speed = < 921600 >;
29+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&pinctrl {
8+
pdm20_default_alt: pdm20_default_alt {
9+
group1 {
10+
psels = <NRF_PSEL(PDM_CLK, 1, 12)>,
11+
<NRF_PSEL(PDM_DIN, 1, 13)>;
12+
};
13+
};
14+
};
15+
16+
dmic_dev: &pdm20 {
17+
status = "okay";
18+
pinctrl-0 = <&pdm20_default_alt>;
19+
pinctrl-names = "default";
20+
clock-source = "PCLK32M";
21+
};
22+
23+
&uart20 {
24+
current-speed = < 921600 >;
25+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CONFIG_BOOT_BANNER=n
2+
CONFIG_NCS_BOOT_BANNER=n
3+
4+
CONFIG_AUDIO=y
5+
CONFIG_AUDIO_DMIC=y
6+
7+
CONFIG_LOG=n
8+
CONFIG_LOG_MODE_IMMEDIATE=n
9+
CONFIG_PRINTK=y
10+
11+
CONFIG_MAIN_STACK_SIZE=16384
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
sample:
2+
name: DMIC sample
3+
tests:
4+
sample.drivers.audio.dmic_dump_buffer:
5+
tags: dmic
6+
filter: dt_nodelabel_enabled("dmic_dev")
7+
integration_platforms:
8+
- nrf52840dk/nrf52840
9+
- nrf5340dk/nrf5340/cpuapp
10+
- nrf54l15dk/nrf54l15/cpuapp
11+
harness: console
12+
harness_config:
13+
type: multi_line
14+
ordered: true
15+
regex:
16+
- "DMIC sample"
17+
- "Exiting"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <string.h>
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/audio/dmic.h>
10+
11+
#include <zephyr/logging/log.h>
12+
LOG_MODULE_REGISTER(dmic_sample);
13+
14+
#define SAMPLE_RATE 16000
15+
#define SAMPLE_BIT_WIDTH 16
16+
#define BYTES_PER_SAMPLE (SAMPLE_BIT_WIDTH / 8)
17+
#define NO_OF_CHANNELS 1
18+
19+
/* Milliseconds to wait for a block to be captured by PCM peripheral. */
20+
#define READ_TIMEOUT 1200
21+
22+
/* Driver will allocate blocks from this slab to receive audio data into them.
23+
* Application, after getting a given block from the driver and processing its
24+
* data, needs to free that block.
25+
*/
26+
#define AUDIO_BLOCK_SIZE (BYTES_PER_SAMPLE * SAMPLE_RATE * NO_OF_CHANNELS / 10)
27+
/* Why driver fails when BLOCK_COUNT is decreased to 2? */
28+
#define BLOCK_COUNT 4
29+
K_MEM_SLAB_DEFINE_STATIC(mem_slab, AUDIO_BLOCK_SIZE, BLOCK_COUNT, 4);
30+
31+
int main(void)
32+
{
33+
const struct device *const dmic_dev = DEVICE_DT_GET(DT_NODELABEL(dmic_dev));
34+
int ret;
35+
int loop_counter = 1;
36+
void *buffer;
37+
uint32_t size;
38+
39+
if (!device_is_ready(dmic_dev)) {
40+
LOG_ERR("%s is not ready", dmic_dev->name);
41+
return 0;
42+
}
43+
44+
struct pcm_stream_cfg stream = {
45+
.pcm_rate = SAMPLE_RATE,
46+
.pcm_width = SAMPLE_BIT_WIDTH,
47+
.block_size = AUDIO_BLOCK_SIZE,
48+
.mem_slab = &mem_slab,
49+
};
50+
51+
struct dmic_cfg cfg = {
52+
.io = {
53+
/* These fields can be used to limit the PDM clock
54+
* configurations that the driver is allowed to use
55+
* to those supported by the microphone.
56+
*/
57+
.min_pdm_clk_freq = 1000000,
58+
.max_pdm_clk_freq = 3250000,
59+
.min_pdm_clk_dc = 40,
60+
.max_pdm_clk_dc = 60,
61+
},
62+
.streams = &stream,
63+
.channel = {
64+
.req_num_chan = 1,
65+
.req_num_streams = 1,
66+
.req_chan_map_lo = dmic_build_channel_map(0, 0, PDM_CHAN_LEFT),
67+
},
68+
};
69+
70+
ret = dmic_configure(dmic_dev, &cfg);
71+
if (ret < 0) {
72+
LOG_ERR("Failed to configure the driver: %d", ret);
73+
return ret;
74+
}
75+
76+
ret = dmic_trigger(dmic_dev, DMIC_TRIGGER_START);
77+
if (ret < 0) {
78+
LOG_ERR("START trigger failed: %d", ret);
79+
return ret;
80+
}
81+
82+
while (1) {
83+
ret = dmic_read(dmic_dev, 0, &buffer, &size, READ_TIMEOUT);
84+
if (ret < 0) {
85+
LOG_ERR("%d - read failed: %d", loop_counter, ret);
86+
return ret;
87+
}
88+
89+
/* Print buffer on serial in binary mode */
90+
unsigned char pcm_l, pcm_h;
91+
int j;
92+
93+
uint16_t *pcm_out = buffer;
94+
// uint8_t *pcm_out = buffer;
95+
96+
for (j = 2; j < size/2; j++) {
97+
pcm_l = (char)(pcm_out[j] & 0xFF);
98+
pcm_h = (char)((pcm_out[j] >> 8) & 0xFF);
99+
100+
z_impl_k_str_out(&pcm_l, 1);
101+
z_impl_k_str_out(&pcm_h, 1);
102+
}
103+
104+
// for (j = 0; j < size; j+=2) {
105+
// pcm_l = (char)pcm_out[j];
106+
// pcm_h = (char)pcm_out[j+1];
107+
108+
// z_impl_k_str_out(&pcm_l, 1);
109+
// z_impl_k_str_out(&pcm_h, 1);
110+
// }
111+
112+
k_mem_slab_free(&mem_slab, buffer);
113+
114+
loop_counter++;
115+
}
116+
117+
ret = dmic_trigger(dmic_dev, DMIC_TRIGGER_STOP);
118+
if (ret < 0) {
119+
LOG_ERR("STOP trigger failed: %d", ret);
120+
return ret;
121+
}
122+
123+
return 0;
124+
}

0 commit comments

Comments
 (0)