From 0b145fdc2d4857a77f9f0a3662646d52da61d5b2 Mon Sep 17 00:00:00 2001 From: MikeTeachman Date: Tue, 20 Feb 2024 21:37:30 -0800 Subject: [PATCH] esp32/machine_i2s: Integrate new I2S IDF driver. The legacy I2S "shim" is removed and replaced by the new I2S driver. The new driver fixes a bug where mono audio plays only in one channel. Application code size is reduced by 2672 bytes with this change. Tested on ESP32, ESP32+spiram, ESP32-S3 using example code from https://github.com/miketeachman/micropython-i2s-examples Signed-off-by: Mike Teachman --- extmod/machine_i2s.c | 25 +-- ports/esp32/boards/sdkconfig.base | 1 - ports/esp32/machine_i2s.c | 282 +++++++++++++++--------------- ports/esp32/mpconfigport.h | 6 +- 4 files changed, 151 insertions(+), 163 deletions(-) diff --git a/extmod/machine_i2s.c b/extmod/machine_i2s.c index 7e069c5d76..9c92eb4c92 100644 --- a/extmod/machine_i2s.c +++ b/extmod/machine_i2s.c @@ -608,6 +608,7 @@ static mp_uint_t machine_i2s_stream_write(mp_obj_t self_in, const void *buf_in, #else uint32_t num_bytes_written = copy_appbuf_to_dma(self, &appbuf); #endif + return num_bytes_written; } } @@ -632,16 +633,8 @@ static mp_uint_t machine_i2s_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ ret |= MP_STREAM_POLL_RD; } #else - // check event queue to determine if a DMA buffer has been filled - // (which is an indication that at least one DMA buffer is available to be read) - // note: timeout = 0 so the call is non-blocking - i2s_event_t i2s_event; - if (xQueueReceive(self->i2s_event_queue, &i2s_event, 0)) { - if (i2s_event.type == I2S_EVENT_RX_DONE) { - // getting here means that at least one DMA buffer is now full - // indicating that audio samples can be read from the I2S object - ret |= MP_STREAM_POLL_RD; - } + if (self->dma_buffer_status == DMA_MEMORY_NOT_EMPTY) { + ret |= MP_STREAM_POLL_RD; } #endif } @@ -657,16 +650,8 @@ static mp_uint_t machine_i2s_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ ret |= MP_STREAM_POLL_WR; } #else - // check event queue to determine if a DMA buffer has been emptied - // (which is an indication that at least one DMA buffer is available to be written) - // note: timeout = 0 so the call is non-blocking - i2s_event_t i2s_event; - if (xQueueReceive(self->i2s_event_queue, &i2s_event, 0)) { - if (i2s_event.type == I2S_EVENT_TX_DONE) { - // getting here means that at least one DMA buffer is now empty - // indicating that audio samples can be written to the I2S object - ret |= MP_STREAM_POLL_WR; - } + if (self->dma_buffer_status == DMA_MEMORY_NOT_FULL) { + ret |= MP_STREAM_POLL_WR; } #endif } diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index 05624f0d74..fef25fe308 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -112,7 +112,6 @@ CONFIG_UART_ISR_IN_IRAM=y # IDF 5 deprecated CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=y CONFIG_RMT_SUPPRESS_DEPRECATE_WARN=y -CONFIG_I2S_SUPPRESS_DEPRECATE_WARN=y CONFIG_ETH_USE_SPI_ETHERNET=y CONFIG_ETH_SPI_ETHERNET_W5500=y diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c index 574125ad6a..6ba2f54c35 100644 --- a/ports/esp32/machine_i2s.c +++ b/ports/esp32/machine_i2s.c @@ -28,9 +28,7 @@ // extmod/machine_i2s.c via MICROPY_PY_MACHINE_I2S_INCLUDEFILE. #include "py/mphal.h" - -#include "driver/i2s.h" -#include "soc/i2s_reg.h" +#include "driver/i2s_std.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" @@ -62,23 +60,32 @@ typedef struct _non_blocking_descriptor_t { direction_t direction; } non_blocking_descriptor_t; +typedef enum { + DMA_MEMORY_FULL, + DMA_MEMORY_NOT_FULL, + DMA_MEMORY_EMPTY, + DMA_MEMORY_NOT_EMPTY, +} dma_buffer_status_t; + typedef struct _machine_i2s_obj_t { mp_obj_base_t base; i2s_port_t i2s_id; + i2s_chan_handle_t i2s_chan_handle; mp_hal_pin_obj_t sck; mp_hal_pin_obj_t ws; mp_hal_pin_obj_t sd; - int8_t mode; - i2s_bits_per_sample_t bits; + i2s_dir_t mode; + i2s_data_bit_width_t bits; format_t format; int32_t rate; int32_t ibuf; mp_obj_t callback_for_non_blocking; io_mode_t io_mode; + bool is_deinit; uint8_t transform_buffer[SIZEOF_TRANSFORM_BUFFER_IN_BYTES]; - QueueHandle_t i2s_event_queue; QueueHandle_t non_blocking_mode_queue; TaskHandle_t non_blocking_mode_task; + dma_buffer_status_t dma_buffer_status; } machine_i2s_obj_t; static mp_obj_t machine_i2s_deinit(mp_obj_t self_in); @@ -87,10 +94,10 @@ static mp_obj_t machine_i2s_deinit(mp_obj_t self_in); // from DMA memory (32-bit stereo, with the L and R channels reversed) to the format specified // in the I2S constructor. e.g. 16-bit mono static const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYTES] = { - { 6, 7, -1, -1, -1, -1, -1, -1 }, // Mono, 16-bits - { 4, 5, 6, 7, -1, -1, -1, -1 }, // Mono, 32-bits - { 6, 7, 2, 3, -1, -1, -1, -1 }, // Stereo, 16-bits - { 4, 5, 6, 7, 0, 1, 2, 3 }, // Stereo, 32-bits + { 2, 3, -1, -1, -1, -1, -1, -1 }, // Mono, 16-bits + { 0, 1, 2, 3, -1, -1, -1, -1 }, // Mono, 32-bits + { 2, 3, 6, 7, -1, -1, -1, -1 }, // Stereo, 16-bits + { 0, 1, 2, 3, 4, 5, 6, 7 }, // Stereo, 32-bits }; void machine_i2s_init0() { @@ -99,49 +106,15 @@ void machine_i2s_init0() { } } -// The following function takes a sample buffer and swaps L/R channels -// -// Background: For 32-bit stereo, the ESP-IDF API has a L/R channel orientation that breaks -// convention with other ESP32 channel formats -// -// appbuf[] = [L_0-7, L_8-15, L_16-23, L_24-31, R_0-7, R_8-15, R_16-23, R_24-31] = [Left channel, Right channel] -// dma[] = [R_0-7, R_8-15, R_16-23, R_24-31, L_0-7, L_8-15, L_16-23, L_24-31] = [Right channel, Left channel] -// -// where: -// L_0-7 is the least significant byte of the 32 bit sample in the Left channel -// L_24-31 is the most significant byte of the 32 bit sample in the Left channel -// -// Example: -// -// appbuf[] = [0x99, 0xBB, 0x11, 0x22, 0x44, 0x55, 0xAB, 0x77] = [Left channel, Right channel] -// dma[] = [0x44, 0x55, 0xAB, 0x77, 0x99, 0xBB, 0x11, 0x22] = [Right channel, Left channel] -// where: -// LEFT Channel = 0x99, 0xBB, 0x11, 0x22 -// RIGHT Channel = 0x44, 0x55, 0xAB, 0x77 -// -// samples in appbuf are in little endian format: -// 0x77 is the most significant byte of the 32-bit sample -// 0x44 is the least significant byte of the 32-bit sample -static void swap_32_bit_stereo_channels(mp_buffer_info_t *bufinfo) { - int32_t swap_sample; - int32_t *sample = bufinfo->buf; - uint32_t num_samples = bufinfo->len / 4; - for (uint32_t i = 0; i < num_samples; i += 2) { - swap_sample = sample[i + 1]; - sample[i + 1] = sample[i]; - sample[i] = swap_sample; - } -} - -static int8_t get_frame_mapping_index(i2s_bits_per_sample_t bits, format_t format) { +static int8_t get_frame_mapping_index(i2s_data_bit_width_t bits, format_t format) { if (format == MONO) { - if (bits == I2S_BITS_PER_SAMPLE_16BIT) { + if (bits == I2S_DATA_BIT_WIDTH_16BIT) { return 0; } else { // 32 bits return 1; } } else { // STEREO - if (bits == I2S_BITS_PER_SAMPLE_16BIT) { + if (bits == I2S_DATA_BIT_WIDTH_16BIT) { return 2; } else { // 32 bits return 3; @@ -149,32 +122,32 @@ static int8_t get_frame_mapping_index(i2s_bits_per_sample_t bits, format_t forma } } -static i2s_bits_per_sample_t get_dma_bits(uint8_t mode, i2s_bits_per_sample_t bits) { - if (mode == (I2S_MODE_MASTER | I2S_MODE_TX)) { +static i2s_data_bit_width_t get_dma_bits(uint8_t mode, i2s_data_bit_width_t bits) { + if (mode == MICROPY_PY_MACHINE_I2S_CONSTANT_TX) { return bits; } else { // Master Rx // read 32 bit samples for I2S hardware. e.g. MEMS microphones - return I2S_BITS_PER_SAMPLE_32BIT; + return I2S_DATA_BIT_WIDTH_32BIT; } } -static i2s_channel_fmt_t get_dma_format(uint8_t mode, format_t format) { - if (mode == (I2S_MODE_MASTER | I2S_MODE_TX)) { +static i2s_slot_mode_t get_dma_format(uint8_t mode, format_t format) { + if (mode == MICROPY_PY_MACHINE_I2S_CONSTANT_TX) { if (format == MONO) { - return I2S_CHANNEL_FMT_ONLY_LEFT; + return I2S_SLOT_MODE_MONO; } else { // STEREO - return I2S_CHANNEL_FMT_RIGHT_LEFT; + return I2S_SLOT_MODE_STEREO; } } else { // Master Rx // read stereo frames for all I2S hardware - return I2S_CHANNEL_FMT_RIGHT_LEFT; + return I2S_SLOT_MODE_STEREO; } } -static uint32_t get_dma_buf_count(uint8_t mode, i2s_bits_per_sample_t bits, format_t format, int32_t ibuf) { +static uint32_t get_dma_buf_count(uint8_t mode, i2s_data_bit_width_t bits, format_t format, int32_t ibuf) { // calculate how many DMA buffers need to be allocated uint32_t dma_frame_size_in_bytes = - (get_dma_bits(mode, bits) / 8) * (get_dma_format(mode, format) == I2S_CHANNEL_FMT_RIGHT_LEFT ? 2: 1); + (get_dma_bits(mode, bits) / 8) * (get_dma_format(mode, format) == I2S_SLOT_MODE_STEREO ? 2: 1); uint32_t dma_buf_count = ibuf / (DMA_BUF_LEN_IN_I2S_FRAMES * dma_frame_size_in_bytes); @@ -204,18 +177,23 @@ static uint32_t fill_appbuf_from_dma(machine_i2s_obj_t *self, mp_buffer_info_t * TickType_t delay; if (self->io_mode == ASYNCIO) { - delay = 0; // stop i2s_read() operation if DMA memory becomes empty + delay = 0; // stop i2s_channel_read() operation if DMA memory becomes empty } else { delay = portMAX_DELAY; // block until supplied buffer is filled } - esp_err_t ret = i2s_read( - self->i2s_id, + esp_err_t ret = i2s_channel_read( + self->i2s_chan_handle, self->transform_buffer, num_bytes_requested_from_dma, &num_bytes_received_from_dma, delay); - check_esp_err(ret); + + // i2s_channel_read returns ESP_ERR_TIMEOUT when buffer cannot be filled by the timeout delay. + if ((self->io_mode != ASYNCIO) || + ((self->io_mode == ASYNCIO) && (ret != ESP_ERR_TIMEOUT))) { + check_esp_err(ret); + } // process the transform buffer one frame at a time. // copy selected bytes from the transform buffer into the user supplied appbuf. @@ -246,9 +224,7 @@ static uint32_t fill_appbuf_from_dma(machine_i2s_obj_t *self, mp_buffer_info_t * if ((self->io_mode == ASYNCIO) && (num_bytes_received_from_dma < num_bytes_requested_from_dma)) { // Unable to fill the entire app buffer from DMA memory. This indicates all DMA RX buffers are empty. - // Clear the I2S event queue so ioctl() indicates that the I2S object cannot currently - // supply more audio samples - xQueueReset(self->i2s_event_queue); + self->dma_buffer_status = DMA_MEMORY_EMPTY; break; } } @@ -257,34 +233,28 @@ static uint32_t fill_appbuf_from_dma(machine_i2s_obj_t *self, mp_buffer_info_t * } static size_t copy_appbuf_to_dma(machine_i2s_obj_t *self, mp_buffer_info_t *appbuf) { - if ((self->bits == I2S_BITS_PER_SAMPLE_32BIT) && (self->format == STEREO)) { - swap_32_bit_stereo_channels(appbuf); - } - size_t num_bytes_written = 0; TickType_t delay; if (self->io_mode == ASYNCIO) { - delay = 0; // stop i2s_write() operation if DMA memory becomes full + delay = 0; // stop i2s_channel_write() operation if DMA memory becomes full } else { delay = portMAX_DELAY; // block until supplied buffer is emptied } - esp_err_t ret = i2s_write(self->i2s_id, appbuf->buf, appbuf->len, &num_bytes_written, delay); - check_esp_err(ret); + esp_err_t ret = i2s_channel_write(self->i2s_chan_handle, appbuf->buf, appbuf->len, &num_bytes_written, delay); + + // i2s_channel_write returns ESP_ERR_TIMEOUT when buffer cannot be emptied by the timeout delay. + if ((self->io_mode != ASYNCIO) || + ((self->io_mode == ASYNCIO) && (ret != ESP_ERR_TIMEOUT))) { + check_esp_err(ret); + } if ((self->io_mode == ASYNCIO) && (num_bytes_written < appbuf->len)) { // Unable to empty the entire app buffer into DMA memory. This indicates all DMA TX buffers are full. - // Clear the I2S event queue so ioctl() indicates that the I2S object cannot currently - // accept more audio samples - xQueueReset(self->i2s_event_queue); - - // Undo the swap transformation as the buffer has not been completely emptied. - // The asyncio stream writer will use the same buffer in a future write call. - if ((self->bits == I2S_BITS_PER_SAMPLE_32BIT) && (self->format == STEREO)) { - swap_32_bit_stereo_channels(appbuf); - } + self->dma_buffer_status = DMA_MEMORY_FULL; } + return num_bytes_written; } @@ -306,6 +276,34 @@ static void task_for_non_blocking_mode(void *self_in) { } } +// callback indicating that a DMA buffer was just filled with samples received from an I2S port +static IRAM_ATTR bool i2s_rx_recv_callback(i2s_chan_handle_t handle, i2s_event_data_t *event, void *self_in) { + machine_i2s_obj_t *self = (machine_i2s_obj_t *)self_in; + self->dma_buffer_status = DMA_MEMORY_NOT_EMPTY; + return false; +} + +// callback indicating that samples in a DMA buffer were just transmitted to an I2S port +static IRAM_ATTR bool i2s_tx_sent_callback(i2s_chan_handle_t handle, i2s_event_data_t *event, void *self_in) { + machine_i2s_obj_t *self = (machine_i2s_obj_t *)self_in; + self->dma_buffer_status = DMA_MEMORY_NOT_FULL; + return false; +} + +i2s_event_callbacks_t i2s_callbacks = { + .on_recv = i2s_rx_recv_callback, + .on_recv_q_ovf = NULL, + .on_sent = i2s_tx_sent_callback, + .on_send_q_ovf = NULL, +}; + +i2s_event_callbacks_t i2s_callbacks_null = { + .on_recv = NULL, + .on_recv_q_ovf = NULL, + .on_sent = NULL, + .on_send_q_ovf = NULL, +}; + static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *args) { // are Pins valid? int8_t sck = args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj); @@ -313,16 +311,16 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar int8_t sd = args[ARG_sd].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sd].u_obj); // is Mode valid? - i2s_mode_t mode = args[ARG_mode].u_int; - if ((mode != (I2S_MODE_MASTER | I2S_MODE_RX)) && - (mode != (I2S_MODE_MASTER | I2S_MODE_TX))) { + int8_t mode = args[ARG_mode].u_int; + if ((mode != (MICROPY_PY_MACHINE_I2S_CONSTANT_RX)) && + (mode != (MICROPY_PY_MACHINE_I2S_CONSTANT_TX))) { mp_raise_ValueError(MP_ERROR_TEXT("invalid mode")); } // is Bits valid? - i2s_bits_per_sample_t bits = args[ARG_bits].u_int; - if ((bits != I2S_BITS_PER_SAMPLE_16BIT) && - (bits != I2S_BITS_PER_SAMPLE_32BIT)) { + i2s_data_bit_width_t bits = args[ARG_bits].u_int; + if ((bits != I2S_DATA_BIT_WIDTH_16BIT) && + (bits != I2S_DATA_BIT_WIDTH_32BIT)) { mp_raise_ValueError(MP_ERROR_TEXT("invalid bits")); } @@ -348,54 +346,57 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar self->rate = args[ARG_rate].u_int; self->ibuf = args[ARG_ibuf].u_int; self->callback_for_non_blocking = MP_OBJ_NULL; - self->i2s_event_queue = NULL; self->non_blocking_mode_queue = NULL; self->non_blocking_mode_task = NULL; self->io_mode = BLOCKING; + self->is_deinit = false; - i2s_config_t i2s_config; - i2s_config.communication_format = I2S_COMM_FORMAT_STAND_I2S; - i2s_config.mode = mode; - i2s_config.bits_per_sample = get_dma_bits(mode, bits); - i2s_config.channel_format = get_dma_format(mode, format); - i2s_config.sample_rate = self->rate; - i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LOWMED; - i2s_config.dma_desc_num = get_dma_buf_count(mode, bits, format, self->ibuf); - i2s_config.dma_frame_num = DMA_BUF_LEN_IN_I2S_FRAMES; - i2s_config.use_apll = false; - i2s_config.tx_desc_auto_clear = true; - i2s_config.fixed_mclk = 0; - i2s_config.mclk_multiple = I2S_MCLK_MULTIPLE_256; - i2s_config.bits_per_chan = 0; - - // I2S queue size equals the number of DMA buffers - check_esp_err(i2s_driver_install(self->i2s_id, &i2s_config, i2s_config.dma_desc_num, &self->i2s_event_queue)); - - // apply low-level workaround for bug in some ESP-IDF versions that swap - // the left and right channels - // https://github.com/espressif/esp-idf/issues/6625 - #if CONFIG_IDF_TARGET_ESP32S3 - REG_SET_BIT(I2S_TX_CONF_REG(self->i2s_id), I2S_TX_MSB_SHIFT); - REG_SET_BIT(I2S_TX_CONF_REG(self->i2s_id), I2S_RX_MSB_SHIFT); - #else - REG_SET_BIT(I2S_CONF_REG(self->i2s_id), I2S_TX_MSB_RIGHT); - REG_SET_BIT(I2S_CONF_REG(self->i2s_id), I2S_RX_MSB_RIGHT); - #endif - - i2s_pin_config_t pin_config; - pin_config.mck_io_num = I2S_PIN_NO_CHANGE; - pin_config.bck_io_num = self->sck; - pin_config.ws_io_num = self->ws; - - if (mode == (I2S_MODE_MASTER | I2S_MODE_RX)) { - pin_config.data_in_num = self->sd; - pin_config.data_out_num = I2S_PIN_NO_CHANGE; - } else { // TX - pin_config.data_in_num = I2S_PIN_NO_CHANGE; - pin_config.data_out_num = self->sd; + if (mode == MICROPY_PY_MACHINE_I2S_CONSTANT_TX) { + self->dma_buffer_status = DMA_MEMORY_NOT_FULL; + } else { // rx + self->dma_buffer_status = DMA_MEMORY_NOT_EMPTY; } - check_esp_err(i2s_set_pin(self->i2s_id, &pin_config)); + i2s_chan_config_t chan_config = I2S_CHANNEL_DEFAULT_CONFIG(self->i2s_id, I2S_ROLE_MASTER); + chan_config.dma_desc_num = get_dma_buf_count(mode, bits, format, self->ibuf); + chan_config.dma_frame_num = DMA_BUF_LEN_IN_I2S_FRAMES; + chan_config.auto_clear = true; + + if (mode == MICROPY_PY_MACHINE_I2S_CONSTANT_TX) { + ESP_ERROR_CHECK(i2s_new_channel(&chan_config, &self->i2s_chan_handle, NULL)); + } else { // rx + ESP_ERROR_CHECK(i2s_new_channel(&chan_config, NULL, &self->i2s_chan_handle)); + } + + i2s_std_slot_config_t slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(get_dma_bits(mode, bits), get_dma_format(mode, format)); + slot_cfg.slot_mask = I2S_STD_SLOT_BOTH; + + i2s_std_config_t std_cfg = { + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(self->rate), + .slot_cfg = slot_cfg, + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = self->sck, + .ws = self->ws, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + + if (mode == MICROPY_PY_MACHINE_I2S_CONSTANT_TX) { + std_cfg.gpio_cfg.dout = self->sd; + std_cfg.gpio_cfg.din = I2S_GPIO_UNUSED; + } else { // rx + std_cfg.gpio_cfg.dout = I2S_GPIO_UNUSED; + std_cfg.gpio_cfg.din = self->sd; + } + + ESP_ERROR_CHECK(i2s_channel_init_std_mode(self->i2s_chan_handle, &std_cfg)); + ESP_ERROR_CHECK(i2s_channel_register_event_callback(self->i2s_chan_handle, &i2s_callbacks, self)); + ESP_ERROR_CHECK(i2s_channel_enable(self->i2s_chan_handle)); } static machine_i2s_obj_t *mp_machine_i2s_make_new_instance(mp_int_t i2s_id) { @@ -417,19 +418,22 @@ static machine_i2s_obj_t *mp_machine_i2s_make_new_instance(mp_int_t i2s_id) { } static void mp_machine_i2s_deinit(machine_i2s_obj_t *self) { - i2s_driver_uninstall(self->i2s_id); + if (!self->is_deinit) { + ESP_ERROR_CHECK(i2s_channel_disable(self->i2s_chan_handle)); + ESP_ERROR_CHECK(i2s_channel_register_event_callback(self->i2s_chan_handle, &i2s_callbacks_null, self)); + ESP_ERROR_CHECK(i2s_del_channel(self->i2s_chan_handle)); - if (self->non_blocking_mode_task != NULL) { - vTaskDelete(self->non_blocking_mode_task); - self->non_blocking_mode_task = NULL; + if (self->non_blocking_mode_task != NULL) { + vTaskDelete(self->non_blocking_mode_task); + self->non_blocking_mode_task = NULL; + } + + if (self->non_blocking_mode_queue != NULL) { + vQueueDelete(self->non_blocking_mode_queue); + self->non_blocking_mode_queue = NULL; + } + self->is_deinit = true; } - - if (self->non_blocking_mode_queue != NULL) { - vQueueDelete(self->non_blocking_mode_queue); - self->non_blocking_mode_queue = NULL; - } - - self->i2s_event_queue = NULL; } static void mp_machine_i2s_irq_update(machine_i2s_obj_t *self) { diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index acf065384b..be02d45883 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -9,7 +9,7 @@ #include "esp_random.h" #include "esp_system.h" #include "freertos/FreeRTOS.h" -#include "driver/i2s.h" +#include "driver/i2s_std.h" #include "esp_wifi_types.h" #ifndef MICROPY_CONFIG_ROM_LEVEL @@ -147,8 +147,8 @@ #endif #define MICROPY_PY_MACHINE_I2S_INCLUDEFILE "ports/esp32/machine_i2s.c" #define MICROPY_PY_MACHINE_I2S_FINALISER (1) -#define MICROPY_PY_MACHINE_I2S_CONSTANT_RX (I2S_MODE_MASTER | I2S_MODE_RX) -#define MICROPY_PY_MACHINE_I2S_CONSTANT_TX (I2S_MODE_MASTER | I2S_MODE_TX) +#define MICROPY_PY_MACHINE_I2S_CONSTANT_RX (I2S_DIR_RX) +#define MICROPY_PY_MACHINE_I2S_CONSTANT_TX (I2S_DIR_TX) #define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/esp32/machine_uart.c" #define MICROPY_PY_MACHINE_UART_SENDBREAK (1)