Klasse I2S – Inter-IC-Sound-Bus-Protokoll

Die Klasse I2S steuert einen Inter-IC-Sound-Bus (I2S) im Controller-Modus – der MCU erzeugt den Bittakt (SCK) und den Word-Select-Takt (WS) und tauscht die Sample-Daten auf der Leitung SD aus. Der Treiber unterstützt kontinuierliches DMA im Hintergrund, sodass die Python-Seite nur den internen Sample-Puffer gefüllt halten muss. Peripherie- bzw. reine Empfangsmodi werden nicht unterstützt.

Verfügbar auf STM32-OpenMV-Cams, die ein I2S-Peripheriegerät verdrahten, sowie auf der OpenMV Cam RT1062. Nicht verfügbar auf der OpenMV Cam AE3 (Alif-Port).

I2S(2) auf STM32-OpenMV-Cams teilt sich seine Pins mit SPI(2) – der Bittakt liegt auf P2 (SCK), das Word-Select auf P3 (NSS), und die serielle Datenleitung folgt der Konvention für die SPI-Datenrichtung: TX nutzt P0 (MOSI), RX nutzt P1 (MISO).

Beispiel – Ausgabe (TX). Konstruieren eines TX-Busses, um einen externen Audio-DAC mit 44,1 kHz und 16-Bit-Mono-Samples anzusteuern, mit einem 16384 Byte (16 KiB) großen DMA-Stützpuffer:

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,
)

Beispiel – Eingabe (RX). Konstruieren eines RX-Busses, der von einem Mikrofon mit 22,05 kHz und 32-Bit-Stereo (links + rechts verschachtelt) aufnimmt, mit einem 16384 Byte (16 KiB) großen DMA-Stützpuffer:

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,
)

Die Übertragungsmethoden können in drei Stilen verwendet werden:

Blockierendwrite() und readinto() kehren erst zurück, wenn der Vorgang abgeschlossen ist:

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

Nicht-blockierend – installieren Sie einen Callback mit irq(), und die Übertragungsmethoden kehren sofort zurück. Der Callback wird vom MicroPython-Scheduler ausgeführt, wenn das DMA den TX-Puffer leert oder den RX-Puffer füllt:

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 ist ein Stream und kann von asyncio.StreamReader / asyncio.StreamWriter umhüllt werden:

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

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

Konstruktor

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)

Konstruiert ein I2S-Objekt mit der angegebenen id:

  • id identifiziert einen bestimmten I2S-Bus; es ist board- und portspezifisch

Keyword-only-Parameter, die auf allen Ports unterstützt werden:

  • sck ist ein Pin-Objekt für die serielle Taktleitung

  • ws ist ein Pin-Objekt für die Word-Select-Leitung

  • sd ist ein Pin-Objekt für die serielle Datenleitung

  • mck ist ein Pin-Objekt für die Master-Clock-Leitung; die Master-Clock-Frequenz ist Abtastrate * 256

  • mode legt Empfangen oder Senden fest

  • bits legt die Sample-Größe (Bits) fest, 16 oder 32

  • format legt das Kanalformat fest, STEREO oder MONO

  • rate legt die Audio-Abtastrate (Hz) fest; dies ist die Frequenz des ws-Signals

  • ibuf legt die interne Pufferlänge (Bytes) fest

Auf allen Ports läuft das DMA kontinuierlich im Hintergrund und erlaubt es Benutzeranwendungen, andere Operationen durchzuführen, während Sample-Daten zwischen dem internen Puffer und der I2S-Peripherieeinheit übertragen werden. Eine Vergrößerung des internen Puffers kann die Zeit erhöhen, in der Benutzeranwendungen Nicht-I2S-Operationen durchführen können, bevor es zu einem Underflow (z. B. write-Methode) oder Overflow (z. B. readinto-Methode) kommt.

Methoden

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

siehe Konstruktor für die Beschreibung der Argumente

deinit() None

Deinitialisiert den I2S-Bus

readinto(buf: bytearray) int

Liest Audio-Samples in den durch buf angegebenen Puffer. buf muss das Pufferprotokoll unterstützen, etwa bytearray oder array. Die Byte-Reihenfolge von „buf“ ist Little-Endian. Beim Stereoformat geht das Sample des linken Kanals dem des rechten Kanals voraus. Beim Monoformat werden die Sample-Daten des linken Kanals verwendet. Gibt die Anzahl der gelesenen Bytes zurück

write(buf: bytes) int

Schreibt die in buf enthaltenen Audio-Samples. buf muss das Pufferprotokoll unterstützen, etwa bytearray oder array. Die Byte-Reihenfolge von „buf“ ist Little-Endian. Beim Stereoformat geht das Sample des linken Kanals dem des rechten Kanals voraus. Beim Monoformat werden die Sample-Daten sowohl in den rechten als auch in den linken Kanal geschrieben. Gibt die Anzahl der geschriebenen Bytes zurück

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

Setzt einen Callback. handler wird aufgerufen, wenn buf geleert wird (write-Methode) oder voll wird (readinto-Methode). Das Setzen eines Callbacks ändert die write- und readinto-Methoden in einen nicht-blockierenden Betrieb. handler wird im Kontext des MicroPython-Schedulers aufgerufen.

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

Bitweise Verschiebung aller in buf enthaltenen Samples. bits legt die Sample-Größe in Bits fest. shift legt die Anzahl der Bits fest, um die jedes Sample verschoben wird. Positiv für Linksverschiebung, negativ für Rechtsverschiebung. Wird typischerweise zur Lautstärkeregelung verwendet. Jede Bitverschiebung ändert die Sample-Lautstärke um 6 dB.

Konstanten

RX: int

zum Initialisieren des I2S-Bus-mode auf Empfangen

TX: int

zum Initialisieren des I2S-Bus-mode auf Senden

STEREO: int

zum Initialisieren des I2S-Bus-format auf Stereo

MONO: int

zum Initialisieren des I2S-Bus-format auf Mono