| /* |
| * Copyright (c) 2019 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr.h> |
| #include <audio/dmic.h> |
| |
| #define LOG_LEVEL LOG_LEVEL_INF |
| #include <logging/log.h> |
| LOG_MODULE_REGISTER(dmic_sample); |
| |
| #define AUDIO_SAMPLE_FREQ 48000 |
| #define AUDIO_SAMPLE_WIDTH 32 |
| #define SAMPLES_PER_FRAME (64) |
| |
| #define NUM_MIC_CHANNELS 8 |
| #define MIC_FRAME_SAMPLES (SAMPLES_PER_FRAME * NUM_MIC_CHANNELS) |
| #define MIC_FRAME_BYTES (MIC_FRAME_SAMPLES * AUDIO_SAMPLE_WIDTH / 8) |
| |
| #define LP_SRAM_BASE 0xBE800000 |
| #define LP_SRAM_BASE_UNCACHED 0x9E800000 |
| #define LP_SRAM_SIZE (16 << 10) |
| |
| #define DMIC_DEV_NAME "PDM" |
| #define MIC_IN_BUF_COUNT 2 |
| |
| #define FRAMES_PER_ITERATION 100 |
| #define NUM_ITERATIONS 4 |
| #define DELAY_BTW_ITERATIONS K_MSEC(20) |
| |
| static struct k_mem_slab dmic_mem_slab; |
| static char audio_buffers[MIC_FRAME_BYTES * MIC_IN_BUF_COUNT]; |
| static struct device *dmic_device; |
| |
| static void dmic_init(void) |
| { |
| int ret; |
| struct pcm_stream_cfg stream = { |
| .pcm_rate = AUDIO_SAMPLE_FREQ, |
| .pcm_width = AUDIO_SAMPLE_WIDTH, |
| .block_size = MIC_FRAME_BYTES, |
| .mem_slab = &dmic_mem_slab, |
| }; |
| struct dmic_cfg cfg = { |
| .io = { |
| .min_pdm_clk_freq = 1024000, |
| .max_pdm_clk_freq = 4800000, |
| .min_pdm_clk_dc = 48, |
| .max_pdm_clk_dc = 52, |
| .pdm_clk_pol = 0, |
| .pdm_data_pol = 0, |
| }, |
| .streams = &stream, |
| .channel = { |
| .req_chan_map_lo = |
| dmic_build_channel_map(0, 0, PDM_CHAN_RIGHT) | |
| dmic_build_channel_map(1, 0, PDM_CHAN_LEFT) | |
| dmic_build_channel_map(2, 2, PDM_CHAN_RIGHT) | |
| dmic_build_channel_map(3, 2, PDM_CHAN_LEFT) | |
| dmic_build_channel_map(4, 1, PDM_CHAN_RIGHT) | |
| dmic_build_channel_map(5, 1, PDM_CHAN_LEFT) | |
| dmic_build_channel_map(6, 3, PDM_CHAN_RIGHT) | |
| dmic_build_channel_map(7, 3, PDM_CHAN_LEFT), |
| .req_num_chan = NUM_MIC_CHANNELS, |
| .req_num_streams = 1, |
| }, |
| }; |
| |
| k_mem_slab_init(&dmic_mem_slab, audio_buffers, MIC_FRAME_BYTES, |
| MIC_IN_BUF_COUNT); |
| dmic_device = device_get_binding(DMIC_DEV_NAME); |
| if (!dmic_device) { |
| LOG_ERR("unable to find device %s", DMIC_DEV_NAME); |
| return; |
| } |
| |
| ret = dmic_configure(dmic_device, &cfg); |
| if (ret != 0) { |
| LOG_ERR("dmic_configure failed with %d error", ret); |
| } |
| } |
| |
| static void dmic_start(void) |
| { |
| int ret; |
| |
| LOG_DBG("starting dmic"); |
| ret = dmic_trigger(dmic_device, DMIC_TRIGGER_START); |
| if (ret) { |
| LOG_ERR("dmic_trigger failed with code %d", ret); |
| } |
| } |
| |
| static void dmic_receive(void) |
| { |
| int frame_counter = 0; |
| s32_t *mic_in_buf; |
| size_t size; |
| int ret; |
| |
| while (frame_counter++ < FRAMES_PER_ITERATION) { |
| ret = dmic_read(dmic_device, 0, (void **)&mic_in_buf, &size, |
| K_FOREVER); |
| if (ret) { |
| LOG_ERR("dmic_read failed %d", ret); |
| } else { |
| LOG_DBG("dmic_read buffer %p size %u frame %d", |
| mic_in_buf, size, frame_counter); |
| k_mem_slab_free(&dmic_mem_slab, (void **)&mic_in_buf); |
| } |
| } |
| } |
| |
| static void dmic_stop(void) |
| { |
| int ret; |
| |
| ret = dmic_trigger(dmic_device, DMIC_TRIGGER_STOP); |
| if (ret) { |
| LOG_ERR("dmic_trigger failed with code %d", ret); |
| } else { |
| LOG_DBG("dmic stopped"); |
| } |
| } |
| |
| static void dmic_sample_app(void *p1, void *p2, void *p3) |
| { |
| int loop_count = 0; |
| |
| dmic_init(); |
| |
| LOG_INF("Starting DMIC sample app ..."); |
| while (loop_count++ < NUM_ITERATIONS) { |
| dmic_start(); |
| dmic_receive(); |
| dmic_stop(); |
| k_sleep(DELAY_BTW_ITERATIONS); |
| LOG_INF("Iteration %d/%d complete, %d audio frames received.", |
| loop_count, NUM_ITERATIONS, |
| FRAMES_PER_ITERATION); |
| } |
| LOG_INF("Exiting DMIC sample app ..."); |
| } |
| |
| K_THREAD_DEFINE(dmic_sample, 1024, dmic_sample_app, NULL, NULL, NULL, 10, 0, |
| K_NO_WAIT); |