From 91a3f183916e1514fbb8dc58ca5b77acc59d4346 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Oct 2023 16:44:02 +1100 Subject: [PATCH] extmod/machine_i2s: Factor comments, some enums and macros. Signed-off-by: Damien George --- extmod/machine_i2s.c | 46 +++++++++++++++++++++++++++++++++++ ports/esp32/machine_i2s.c | 49 +------------------------------------- ports/mimxrt/machine_i2s.c | 49 ++------------------------------------ ports/rp2/machine_i2s.c | 47 ++---------------------------------- ports/stm32/machine_i2s.c | 49 +------------------------------------- 5 files changed, 52 insertions(+), 188 deletions(-) diff --git a/extmod/machine_i2s.c b/extmod/machine_i2s.c index bbff560a0ddd..cc97f011a6d4 100644 --- a/extmod/machine_i2s.c +++ b/extmod/machine_i2s.c @@ -32,6 +32,52 @@ #include "extmod/modmachine.h" +// The I2S class has 3 modes of operation: +// +// Mode1: Blocking +// - readinto() and write() methods block until the supplied buffer is filled (read) or emptied (write) +// - this is the default mode of operation +// +// Mode2: Non-Blocking +// - readinto() and write() methods return immediately +// - buffer filling and emptying happens asynchronously to the main MicroPython task +// - a callback function is called when the supplied buffer has been filled (read) or emptied (write) +// - non-blocking mode is enabled when a callback is set with the irq() method +// - implementation of asynchronous background operations is port specific +// +// Mode3: Asyncio +// - implements the stream protocol +// - asyncio mode is enabled when the ioctl() function is called +// - the state of the internal ring buffer is used to detect that I2S samples can be read or written +// +// The samples contained in the app buffer supplied for the readinto() and write() methods have the following convention: +// Mono: little endian format +// Stereo: little endian format, left channel first +// +// I2S terms: +// "frame": consists of two audio samples (Left audio sample + Right audio sample) +// +// Misc: +// - for Mono configuration: +// - readinto method: samples are gathered from the L channel only +// - write method: every sample is output to both the L and R channels +// - for readinto method the I2S hardware is read using 8-byte frames +// (this is standard for almost all I2S hardware, such as MEMS microphones) + +#define NUM_I2S_USER_FORMATS (4) +#define I2S_RX_FRAME_SIZE_IN_BYTES (8) + +typedef enum { + MONO, + STEREO +} format_t; + +typedef enum { + BLOCKING, + NON_BLOCKING, + ASYNCIO +} io_mode_t; + // Arguments for I2S() constructor and I2S.init(). enum { ARG_sck, diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c index 9a5e5c60335b..89d460e452ff 100644 --- a/ports/esp32/machine_i2s.c +++ b/ports/esp32/machine_i2s.c @@ -29,8 +29,6 @@ #include "py/mphal.h" -#if MICROPY_PY_MACHINE_I2S - #include "driver/i2s.h" #include "soc/i2s_reg.h" #include "freertos/FreeRTOS.h" @@ -38,38 +36,9 @@ #include "freertos/queue.h" #include "esp_task.h" -// The I2S module has 3 modes of operation: -// -// Mode1: Blocking -// - readinto() and write() methods block until the supplied buffer is filled (read) or emptied (write) -// - this is the default mode of operation -// -// Mode2: Non-Blocking -// - readinto() and write() methods return immediately. -// - buffer filling and emptying happens asynchronously to the main MicroPython task -// - a callback function is called when the supplied buffer has been filled (read) or emptied (write) -// - non-blocking mode is enabled when a callback is set with the irq() method +// Notes on this port's specific implementation of I2S: // - a FreeRTOS task is created to implement the asynchronous background operations // - a FreeRTOS queue is used to transfer the supplied buffer to the background task -// -// Mode3: Asyncio -// - implements the stream protocol -// - asyncio mode is enabled when the ioctl() function is called -// - the I2S event queue is used to detect that I2S samples can be read or written from/to DMA memory -// -// The samples contained in the app buffer supplied for the readinto() and write() methods have the following convention: -// Mono: little endian format -// Stereo: little endian format, left channel first -// -// I2S terms: -// "frame": consists of two audio samples (Left audio sample + Right audio sample) -// -// Misc: -// - for Mono configuration: -// - readinto method: samples are gathered from the L channel only -// - write method: every sample is output to both the L and R channels -// - for readinto method the I2S hardware is read using 8-byte frames -// (this is standard for almost all I2S hardware, such as MEMS microphones) // - all sample data transfers use DMA #define I2S_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) @@ -82,20 +51,6 @@ // The size of 240 bytes is an engineering optimum that balances transfer performance with an acceptable use of heap space #define SIZEOF_TRANSFORM_BUFFER_IN_BYTES (240) -#define NUM_I2S_USER_FORMATS (4) -#define I2S_RX_FRAME_SIZE_IN_BYTES (8) - -typedef enum { - MONO, - STEREO -} format_t; - -typedef enum { - BLOCKING, - NON_BLOCKING, - ASYNCIO -} io_mode_t; - typedef enum { I2S_TX_TRANSFER, I2S_RX_TRANSFER, @@ -510,5 +465,3 @@ STATIC void mp_machine_i2s_irq_update(machine_i2s_obj_t *self) { } MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_AUTO]); - -#endif // MICROPY_PY_MACHINE_I2S diff --git a/ports/mimxrt/machine_i2s.c b/ports/mimxrt/machine_i2s.c index dcdebd4c7edf..077c9e76fa8e 100644 --- a/ports/mimxrt/machine_i2s.c +++ b/ports/mimxrt/machine_i2s.c @@ -37,38 +37,8 @@ #include "fsl_edma.h" #include "fsl_sai.h" -#if MICROPY_PY_MACHINE_I2S -// The I2S module has 3 modes of operation: -// -// Mode1: Blocking -// - readinto() and write() methods block until the supplied buffer is filled (read) or emptied (write) -// - this is the default mode of operation -// -// Mode2: Non-Blocking -// - readinto() and write() methods return immediately -// - buffer filling and emptying happens asynchronously to the main MicroPython task -// - a callback function is called when the supplied buffer has been filled (read) or emptied (write) -// - non-blocking mode is enabled when a callback is set with the irq() method -// - the DMA callback is used to implement the asynchronous background operations -// -// Mode3: Asyncio -// - implements the stream protocol -// - asyncio mode is enabled when the ioctl() function is called -// - the state of the internal ring buffer is used to detect that I2S samples can be read or written -// -// The samples contained in the app buffer supplied for the readinto() and write() methods have the following convention: -// Mono: little endian format -// Stereo: little endian format, left channel first -// -// I2S terms: -// "frame": consists of two audio samples (Left audio sample + Right audio sample) -// -// Misc: -// - for Mono configuration: -// - readinto method: samples are gathered from the L channel only -// - write method: every sample is output to both the L and R channels -// - for readinto method the I2S hardware is read using 8-byte frames -// (this is standard for almost all I2S hardware, such as MEMS microphones) +// Notes on this port's specific implementation of I2S: +// - the DMA callback is used to implement the asynchronous background operations, for non-blocking mode // - all 3 Modes of operation are implemented using the peripheral drivers in the NXP MCUXpresso SDK // - all sample data transfers use DMA // - the DMA ping-pong buffer needs to be aligned to a cache line size of 32 bytes. 32 byte @@ -88,8 +58,6 @@ #define NON_BLOCKING_RATE_MULTIPLIER (4) #define SIZEOF_NON_BLOCKING_COPY_IN_BYTES (SIZEOF_HALF_DMA_BUFFER_IN_BYTES * NON_BLOCKING_RATE_MULTIPLIER) -#define NUM_I2S_USER_FORMATS (4) -#define I2S_RX_FRAME_SIZE_IN_BYTES (8) #define SAI_CHANNEL_0 (0) #define SAI_NUM_AUDIO_CHANNELS (2U) @@ -105,17 +73,6 @@ typedef enum { TX, } i2s_mode_t; -typedef enum { - MONO, - STEREO -} format_t; - -typedef enum { - BLOCKING, - NON_BLOCKING, - ASYNCIO -} io_mode_t; - typedef enum { TOP_HALF, BOTTOM_HALF @@ -766,5 +723,3 @@ STATIC void mp_machine_i2s_irq_update(machine_i2s_obj_t *self) { } MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]); - -#endif // MICROPY_PY_MACHINE_I2S diff --git a/ports/rp2/machine_i2s.c b/ports/rp2/machine_i2s.c index 9df0f09f2447..68a0f296a01f 100644 --- a/ports/rp2/machine_i2s.c +++ b/ports/rp2/machine_i2s.c @@ -37,37 +37,8 @@ #include "hardware/dma.h" #include "hardware/irq.h" -// The I2S class has 3 modes of operation: -// -// Mode1: Blocking -// - readinto() and write() methods block until the supplied buffer is filled (read) or emptied (write) -// - this is the default mode of operation -// -// Mode2: Non-Blocking -// - readinto() and write() methods return immediately -// - buffer filling and emptying happens asynchronously to the main MicroPython task -// - a callback function is called when the supplied buffer has been filled (read) or emptied (write) -// - non-blocking mode is enabled when a callback is set with the irq() method -// - the DMA IRQ handler is used to implement the asynchronous background operations -// -// Mode3: Asyncio -// - implements the stream protocol -// - asyncio mode is enabled when the ioctl() function is called -// - the state of the internal ring buffer is used to detect that I2S samples can be read or written -// -// The samples contained in the app buffer supplied for the readinto() and write() methods have the following convention: -// Mono: little endian format -// Stereo: little endian format, left channel first -// -// I2S terms: -// "frame": consists of two audio samples (Left audio sample + Right audio sample) -// -// Misc: -// - for Mono configuration: -// - readinto method: samples are gathered from the L channel only -// - write method: every sample is output to both the L and R channels -// - for readinto method the I2S hardware is read using 8-byte frames -// (this is standard for almost all I2S hardware, such as MEMS microphones) +// Notes on this port's specific implementation of I2S: +// - the DMA IRQ handler is used to implement the asynchronous background operations, for non-blocking mode // - the PIO is used to drive the I2S bus signals // - all sample data transfers use non-blocking DMA // - the DMA controller is configured with 2 DMA channels in chained mode @@ -86,9 +57,6 @@ #define NON_BLOCKING_RATE_MULTIPLIER (4) #define SIZEOF_NON_BLOCKING_COPY_IN_BYTES (SIZEOF_HALF_DMA_BUFFER_IN_BYTES * NON_BLOCKING_RATE_MULTIPLIER) -#define NUM_I2S_USER_FORMATS (4) -#define I2S_RX_FRAME_SIZE_IN_BYTES (8) - #define SAMPLES_PER_FRAME (2) #define PIO_INSTRUCTIONS_PER_BIT (2) @@ -97,17 +65,6 @@ typedef enum { TX } i2s_mode_t; -typedef enum { - MONO, - STEREO -} format_t; - -typedef enum { - BLOCKING, - NON_BLOCKING, - ASYNCIO -} io_mode_t; - typedef enum { GP_INPUT = 0, GP_OUTPUT = 1 diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c index 6d195432fd7f..dbcd9352d5bd 100644 --- a/ports/stm32/machine_i2s.c +++ b/ports/stm32/machine_i2s.c @@ -33,39 +33,8 @@ #include "pin.h" #include "dma.h" -#if MICROPY_PY_MACHINE_I2S - -// The I2S module has 3 modes of operation: -// -// Mode1: Blocking -// - readinto() and write() methods block until the supplied buffer is filled (read) or emptied (write) -// - this is the default mode of operation -// -// Mode2: Non-Blocking -// - readinto() and write() methods return immediately -// - buffer filling and emptying happens asynchronously to the main MicroPython task -// - a callback function is called when the supplied buffer has been filled (read) or emptied (write) -// - non-blocking mode is enabled when a callback is set with the irq() method +// Notes on this port's specific implementation of I2S: // - the DMA callbacks (1/2 complete and complete) are used to implement the asynchronous background operations -// -// Mode3: Asyncio -// - implements the stream protocol -// - asyncio mode is enabled when the ioctl() function is called -// - the state of the internal ring buffer is used to detect that I2S samples can be read or written -// -// The samples contained in the app buffer supplied for the readinto() and write() methods have the following convention: -// Mono: little endian format -// Stereo: little endian format, left channel first -// -// I2S terms: -// "frame": consists of two audio samples (Left audio sample + Right audio sample) -// -// Misc: -// - for Mono configuration: -// - readinto method: samples are gathered from the L channel only -// - write method: every sample is output to both the L and R channels -// - for readinto method the I2S hardware is read using 8-byte frames -// (this is standard for almost all I2S hardware, such as MEMS microphones) // - all 3 Modes of operation are implemented using the HAL I2S Generic Driver // - all sample data transfers use DMA // - the DMA controller is configured in Circular mode to fulfil continuous and gapless sample flows @@ -86,20 +55,6 @@ #define NON_BLOCKING_RATE_MULTIPLIER (4) #define SIZEOF_NON_BLOCKING_COPY_IN_BYTES (SIZEOF_HALF_DMA_BUFFER_IN_BYTES * NON_BLOCKING_RATE_MULTIPLIER) -#define NUM_I2S_USER_FORMATS (4) -#define I2S_RX_FRAME_SIZE_IN_BYTES (8) - -typedef enum { - MONO, - STEREO -} format_t; - -typedef enum { - BLOCKING, - NON_BLOCKING, - ASYNCIO -} io_mode_t; - typedef enum { TOP_HALF, BOTTOM_HALF @@ -618,5 +573,3 @@ STATIC void mp_machine_i2s_irq_update(machine_i2s_obj_t *self) { } MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_MAX_I2S]); - -#endif // MICROPY_PY_MACHINE_I2S