The module features an onboard MSM261S4030H0R digital microphone and a MAX98357AEWL+T digital amplifier. Both use a single I2S BCLK and WS signal, requiring only four wires to add speaker and microphone functionality to the project.
Test code
IDF5.2
ESP32-S3 N16R8
Note that psram is enabled in menuconfig
#include
#include
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_std.h"
#include "driver/gpio.h"
#include "esp_check.h"
#define EXAMPLE_STD_BCLK_IO1 GPIO_NUM_17 // I2S bit clock io number I2S_BCLK
#define EXAMPLE_STD_WS_IO1 GPIO_NUM_15 // I2S word select io number I2S_LRC WS
#define EXAMPLE_STD_DOUT_IO1 GPIO_NUM_18 // I2S data out io number I2S_DOUT SPK
#define EXAMPLE_STD_DIN_IO1 GPIO_NUM_16 // I2S data in io number I2S_DIN MIC
#define SAMPLE_RATE 48000
i2s_chan_handle_t tx_handle;
i2s_chan_handle_t rx_handle;
EXT_RAM_BSS_ATTR uint8_t buffer[1024 * 200 * 3];
static void i2s_example_task(void *args) {
size_t n;
while (1) {
for (int i = 0; i < 200; ++i) {
if (i2s_channel_read(rx_handle, buffer + i * 1024 * 3, 1024 * 3, &n, 1000) == ESP_OK) {
printf("Read Task: %d
", n);
}
}
for (int i = 0; i < 200; ++i) {
if (i2s_channel_write(tx_handle, buffer + i * 1024* 3, 1024 * 3, &n, 1000) == ESP_OK) {
printf("Write Task: %d
", n);
}
}
}
ESP_ERROR_CHECK(i2s_channel_disable(tx_handle));
ESP_ERROR_CHECK(i2s_channel_disable(rx_handle));
vTaskDelete(NULL);
}
static void i2s_example_init_std_simplex(void) {
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
.slot_cfg = {
.data_bit_width = I2S_DATA_BIT_WIDTH_24BIT,
.slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT,
.slot_mode = I2S_SLOT_MODE_MONO,
.slot_mask = I2S_STD_SLOT_LEFT,
.ws_width = I2S_DATA_BIT_WIDTH_32BIT,
.ws_pol = false,
.bit_shift = true,
.left_align = true,
.big_endian = false,
.bit_order_lsb = false
},
.gpio_cfg = {
.mclk = I2S_GPIO_UNUSED, // some codecs may require mclk signal, this example doesn't need it
.bclk = EXAMPLE_STD_BCLK_IO1,
.ws = EXAMPLE_STD_WS_IO1,
.dout = EXAMPLE_STD_DOUT_IO1,
.din = EXAMPLE_STD_DIN_IO1,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
};
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
}
void app_main(void) {
i2s_example_init_std_simplex();
ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));
ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));
xTaskCreate(i2s_example_task, "i2s_example_task", 4096, NULL, 5, NULL);
}