classe I2S – protocollo del bus Inter-IC Sound

La classe I2S pilota un bus Inter-IC Sound (I2S) in modalità controller – l’MCU genera il clock di bit (SCK) e il clock di selezione della parola (WS) e scambia i dati dei campioni sulla linea SD. Il driver supporta il DMA continuo in background, quindi il lato Python deve solo mantenere alimentato il buffer interno dei campioni. Le modalità periferica / solo-ricezione non sono supportate.

Disponibile sulle OpenMV cam STM32 che collegano una periferica I2S e sulla OpenMV Cam RT1062. Non esposto sulla OpenMV Cam AE3 (port alif).

I2S(2) sulle OpenMV cam STM32 condivide i suoi pin con SPI(2) – il clock di bit su P2 (SCK), la selezione della parola su P3 (NSS), e la linea dei dati seriali segue la convenzione di direzione dati di SPI: TX usa P0 (MOSI), RX usa P1 (MISO).

Esempio – uscita (TX). Costruisce un bus TX per pilotare un DAC audio esterno a 44,1 kHz, campioni mono a 16 bit, con un buffer di supporto DMA da 16384 byte (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,
)

Esempio – ingresso (RX). Costruisce un bus RX che acquisisce da un microfono a 22,05 kHz, stereo a 32 bit (sinistro + destro interlacciati), con un buffer di supporto DMA da 16384 byte (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,
)

I metodi di trasferimento possono essere usati in tre stili:

Bloccantewrite() e readinto() ritornano solo una volta completata l’operazione:

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

Non bloccante – installa una callback con irq() e i metodi di trasferimento ritornano immediatamente. La callback viene eseguita dallo scheduler di MicroPython quando il DMA svuota il buffer TX o riempie il buffer 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 è uno stream e può essere incapsulato da 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)

Costruttore

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)

Costruisce un oggetto I2S con l’id specificato:

  • id identifica un particolare bus I2S; dipende dalla scheda e dal port

Parametri solo per parola chiave supportati su tutti i port:

  • sck è un oggetto pin per la linea del clock seriale

  • ws è un oggetto pin per la linea di selezione della parola

  • sd è un oggetto pin per la linea dei dati seriali

  • mck è un oggetto pin per la linea del clock master; la frequenza del clock master è frequenza di campionamento * 256

  • mode specifica ricezione o trasmissione

  • bits specifica la dimensione del campione (bit), 16 o 32

  • format specifica il formato dei canali, STEREO o MONO

  • rate specifica la frequenza di campionamento audio (Hz); questa è la frequenza del segnale ws

  • ibuf specifica la lunghezza del buffer interno (byte)

Su tutti i port, il DMA viene eseguito in modo continuo in background e consente alle applicazioni utente di eseguire altre operazioni mentre i dati dei campioni vengono trasferiti tra il buffer interno e l’unità periferica I2S. Aumentare la dimensione del buffer interno può aumentare il tempo durante il quale le applicazioni utente possono eseguire operazioni non I2S prima di un underflow (ad es. il metodo write) o di un overflow (ad es. il metodo readinto).

Metodi

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

vedere il Costruttore per le descrizioni degli argomenti

deinit() None

Deinizializza il bus I2S

readinto(buf: bytearray) int

Legge i campioni audio nel buffer specificato da buf. buf deve supportare il protocollo buffer, come bytearray o array. L’ordinamento dei byte di «buf» è little-endian. Per il formato Stereo, il campione del canale sinistro precede quello del canale destro. Per il formato Mono, vengono usati i dati del campione del canale sinistro. Restituisce il numero di byte letti

write(buf: bytes) int

Scrive i campioni audio contenuti in buf. buf deve supportare il protocollo buffer, come bytearray o array. L’ordinamento dei byte di «buf» è little-endian. Per il formato Stereo, il campione del canale sinistro precede quello del canale destro. Per il formato Mono, i dati del campione vengono scritti su entrambi i canali destro e sinistro. Restituisce il numero di byte scritti

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

Imposta una callback. handler viene chiamato quando buf viene svuotato (metodo write) o diventa pieno (metodo readinto). Impostare una callback cambia i metodi write e readinto in operazioni non bloccanti. handler viene chiamato nel contesto dello scheduler di MicroPython.

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

scorrimento bit a bit di tutti i campioni contenuti in buf. bits specifica la dimensione del campione in bit. shift specifica il numero di bit di cui scorrere ciascun campione. Positivo per lo scorrimento a sinistra, negativo per quello a destra. Tipicamente usato per il controllo del volume. Ogni scorrimento di un bit cambia il volume del campione di 6 dB.

Costanti

RX: int

per inizializzare il mode del bus I2S in ricezione

TX: int

per inizializzare il mode del bus I2S in trasmissione

STEREO: int

per inizializzare il format del bus I2S a stereo

MONO: int

per inizializzare il format del bus I2S a mono