esp-idf/examples/peripherals/i2s/i2s_basic/i2s_pdm/main/i2s_pdm_rx.c

100 wiersze
3.9 KiB
C

/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdint.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_pdm.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "sdkconfig.h"
#include "i2s_pdm_example.h"
#define EXAMPLE_PDM_RX_CLK_IO GPIO_NUM_0 // I2S PDM RX clock io number
#define EXAMPLE_PDM_RX_DIN_IO GPIO_NUM_4 // I2S PDM RX data in io number
#if CONFIG_IDF_TARGET_ESP32S3
#define EXAMPLE_PDM_RX_DIN1_IO GPIO_NUM_5 // I2S PDM RX data line1 in io number
#define EXAMPLE_PDM_RX_DIN2_IO GPIO_NUM_6 // I2S PDM RX data line2 in io number
#define EXAMPLE_PDM_RX_DIN3_IO GPIO_NUM_7 // I2S PDM RX data line3 in io number
#endif
#define EXAMPLE_PDM_RX_FREQ_HZ 16000 // I2S PDM RX frequency
static i2s_chan_handle_t i2s_example_init_pdm_rx(void)
{
i2s_chan_handle_t rx_chan; // I2S rx channel handler
/* Setp 1: Determine the I2S channel configuration and allocate RX channel only
* The default configuration can be generated by the helper macro,
* but note that PDM channel can only be registered on I2S_NUM_0 */
i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&rx_chan_cfg, NULL, &rx_chan));
/* Step 2: Setting the configurations of PDM RX mode and initialize the RX channel
* The slot configuration and clock configuration can be generated by the macros
* These two helper macros is defined in 'i2s_pdm.h' which can only be used in PDM RX mode.
* They can help to specify the slot and clock configurations for initialization or re-configuring */
i2s_pdm_rx_config_t pdm_rx_cfg = {
.clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(EXAMPLE_PDM_RX_FREQ_HZ),
/* The data bit-width of PDM mode is fixed to 16 */
.slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
.gpio_cfg = {
.clk = EXAMPLE_PDM_RX_CLK_IO,
#if CONFIG_IDF_TARGET_ESP32S3
// Only ESP32-S3 can support 4-line PDM RX
.dins = {
EXAMPLE_PDM_RX_DIN_IO,
EXAMPLE_PDM_RX_DIN1_IO,
EXAMPLE_PDM_RX_DIN2_IO,
EXAMPLE_PDM_RX_DIN3_IO,
},
#else
.din = EXAMPLE_PDM_RX_DIN_IO,
#endif
.invert_flags = {
.clk_inv = false,
},
},
};
#if CONFIG_IDF_TARGET_ESP32S3
// Enable all slots for example
pdm_rx_cfg.slot_cfg.slot_mode = I2S_SLOT_MODE_STEREO;
pdm_rx_cfg.slot_cfg.slot_mask = I2S_PDM_LINE_SLOT_ALL;
#endif
ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_chan, &pdm_rx_cfg));
/* Step 3: Enable the rx channels before reading data */
ESP_ERROR_CHECK(i2s_channel_enable(rx_chan));
return rx_chan;
}
void i2s_example_pdm_rx_task(void *args)
{
int16_t *r_buf = (int16_t *)calloc(1, EXAMPLE_BUFF_SIZE);
assert(r_buf);
i2s_chan_handle_t rx_chan = i2s_example_init_pdm_rx();
size_t r_bytes = 0;
/* ATTENTION: The print and delay in the read task only for monitoring the data by human,
* Normally there shouldn't be any delays to ensure a short polling time,
* Otherwise the dma buffer will overflow and lead to the data lost */
while (1) {
/* Read i2s data */
if (i2s_channel_read(rx_chan, r_buf, EXAMPLE_BUFF_SIZE, &r_bytes, 1000) == ESP_OK) {
printf("Read Task: i2s read %d bytes\n-----------------------------------\n", r_bytes);
printf("[0] %d [1] %d [2] %d [3] %d\n[4] %d [5] %d [6] %d [7] %d\n\n",
r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]);
} else {
printf("Read Task: i2s read failed\n");
}
vTaskDelay(pdMS_TO_TICKS(200));
}
free(r_buf);
vTaskDelete(NULL);
}