clase I2S – protocolo de bus Inter-IC Sound

La clase I2S controla un bus Inter-IC Sound (I2S) en modo controlador: el MCU genera el reloj de bits (SCK) y el reloj de selección de palabra (WS) e intercambia datos de muestra en la línea SD. El controlador admite DMA continuo en segundo plano, por lo que la parte de Python solo necesita mantener alimentado el búfer interno de muestras. No se admiten los modos periférico ni solo receptor.

Disponible en las cámaras OpenMV STM32 que conectan un periférico I2S y en la OpenMV Cam RT1062. No está expuesto en la OpenMV Cam AE3 (puerto alif).

I2S(2) en las cámaras OpenMV STM32 comparte sus pines con SPI(2): el reloj de bits en P2 (SCK), la selección de palabra en P3 (NSS), y la línea de datos serie sigue la convención de dirección de datos de SPI: TX usa P0 (MOSI), RX usa P1 (MISO).

Ejemplo – salida (TX). Construye un bus TX para controlar un DAC de audio externo a 44,1 kHz, con muestras mono de 16 bits y un búfer de respaldo DMA de 16384 bytes (16 KiB):

from machine import I2S, Pin

audio_out = I2S(
    2,
    sck=Pin("P2"), ws=Pin("P3"), sd=Pin("P0"),
    mode=I2S.TX,
    bits=16,
    format=I2S.MONO,
    rate=44100,
    ibuf=16384,
)

Ejemplo – entrada (RX). Construye un bus RX que captura desde un micrófono a 22,05 kHz, en estéreo de 32 bits (izquierda + derecha intercaladas), con un búfer de respaldo DMA de 16384 bytes (16 KiB):

from machine import I2S, Pin

audio_in = I2S(
    2,
    sck=Pin("P2"), ws=Pin("P3"), sd=Pin("P1"),
    mode=I2S.RX,
    bits=32,
    format=I2S.STEREO,
    rate=22050,
    ibuf=16384,
)

Los métodos de transferencia pueden usarse de tres maneras:

Bloqueantewrite() y readinto() solo regresan una vez que la operación se completa:

num_written = audio_out.write(buf)   # blocks until buf is drained
num_read = audio_in.readinto(buf)    # blocks until buf is filled

No bloqueante – instala una función de retorno (callback) con irq() y los métodos de transferencia regresan de inmediato. La función de retorno se ejecuta desde el planificador de MicroPython cuando el DMA vacía el búfer TX o llena el búfer RX:

audio_out.irq(i2s_callback)
num_written = audio_out.write(buf)   # returns immediately

audio_in.irq(i2s_callback)
num_read = audio_in.readinto(buf)    # returns immediately

asyncioI2S es un flujo y puede envolverse con asyncio.StreamReader / asyncio.StreamWriter:

swriter = asyncio.StreamWriter(audio_out)
swriter.write(buf)
await swriter.drain()

sreader = asyncio.StreamReader(audio_in)
num_read = await sreader.readinto(buf)

Constructor

class machine.I2S(id: int, *, sck: Pin, ws: Pin, sd: Pin, mck: Pin | None = None, mode: int, bits: int, format: int, rate: int, ibuf: int)

Construye un objeto I2S con el id dado:

  • id identifica un bus I2S concreto; es específico de la placa y del puerto

Parámetros exclusivos por palabra clave que se admiten en todos los puertos:

  • sck es un objeto pin para la línea de reloj serie

  • ws es un objeto pin para la línea de selección de palabra

  • sd es un objeto pin para la línea de datos serie

  • mck es un objeto pin para la línea de reloj maestro; la frecuencia del reloj maestro es la frecuencia de muestreo * 256

  • mode especifica recepción o transmisión

  • bits especifica el tamaño de muestra (bits), 16 o 32

  • format especifica el formato de canal, STEREO o MONO

  • rate especifica la frecuencia de muestreo de audio (Hz); esta es la frecuencia de la señal ws

  • ibuf especifica la longitud del búfer interno (bytes)

En todos los puertos, el DMA se ejecuta de forma continua en segundo plano y permite que las aplicaciones de usuario realicen otras operaciones mientras se transfieren los datos de muestra entre el búfer interno y la unidad periférica I2S. Aumentar el tamaño del búfer interno puede incrementar el tiempo durante el cual las aplicaciones de usuario pueden realizar operaciones ajenas a I2S antes de un subdesbordamiento (p. ej. el método write) o un desbordamiento (p. ej. el método readinto).

Métodos

init(*, sck: Pin, ws: Pin, sd: Pin, mck: Pin | None = None, mode: int, bits: int, format: int, rate: int, ibuf: int) None

consulta el Constructor para ver las descripciones de los argumentos

deinit() None

Desinicializa el bus I2S

readinto(buf: bytearray) int

Lee muestras de audio en el búfer especificado por buf. buf debe admitir el protocolo de búfer, como bytearray o array. El orden de bytes de «buf» es little-endian. Para el formato estéreo, la muestra del canal izquierdo precede a la del canal derecho. Para el formato mono, se utilizan los datos de muestra del canal izquierdo. Devuelve el número de bytes leídos

write(buf: bytes) int

Escribe las muestras de audio contenidas en buf. buf debe admitir el protocolo de búfer, como bytearray o array. El orden de bytes de «buf» es little-endian. Para el formato estéreo, la muestra del canal izquierdo precede a la del canal derecho. Para el formato mono, los datos de muestra se escriben en ambos canales, derecho e izquierdo. Devuelve el número de bytes escritos

irq(handler: Callable[[I2S], None]) None

Establece una función de retorno (callback). handler se llama cuando buf se vacía (método write) o se llena (método readinto). Establecer una función de retorno cambia los métodos write y readinto a un funcionamiento no bloqueante. handler se llama en el contexto del planificador de MicroPython.

static shift(*, buf: bytearray, bits: int, shift: int) None

desplazamiento de bits de todas las muestras contenidas en buf. bits especifica el tamaño de muestra en bits. shift especifica el número de bits que se desplaza cada muestra. Positivo para desplazamiento a la izquierda, negativo para desplazamiento a la derecha. Normalmente se usa para el control de volumen. Cada desplazamiento de bit cambia el volumen de la muestra en 6 dB.

Constantes

RX: int

para inicializar el mode del bus I2S en recepción

TX: int

para inicializar el mode del bus I2S en transmisión

STEREO: int

para inicializar el format del bus I2S en estéreo

MONO: int

para inicializar el format del bus I2S en mono