klasa I2S – protokół magistrali Inter-IC Sound

Klasa I2S steruje magistralą Inter-IC Sound (I2S) w trybie kontrolera – mikrokontroler generuje zegar bitowy (SCK) oraz zegar wyboru słowa (WS) i wymienia dane próbek na linii SD. Sterownik obsługuje ciągłe DMA w tle, więc strona Pythona musi jedynie zapewniać uzupełnianie wewnętrznego bufora próbek. Tryby urządzenia peryferyjnego / wyłącznie odbioru nie są obsługiwane.

Dostępna na kamerach STM32 OpenMV, które wyprowadzają urządzenie peryferyjne I2S, oraz na OpenMV Cam RT1062. Nieudostępniona na OpenMV Cam AE3 (port alif).

I2S(2) na kamerach STM32 OpenMV współdzieli piny z SPI(2) – zegar bitowy na P2 (SCK), wybór słowa na P3 (NSS), a linia danych szeregowych podąża za konwencją kierunku danych SPI: TX używa P0 (MOSI), RX używa P1 (MISO).

Przykład – wyjście (TX). Konstruowanie magistrali TX do sterowania zewnętrznym przetwornikiem audio DAC z częstotliwością 44,1 kHz, próbkami mono 16-bitowymi, z buforem DMA o rozmiarze 16384 bajtów (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,
)

Przykład – wejście (RX). Konstruowanie magistrali RX, która przechwytuje dane z mikrofonu z częstotliwością 22,05 kHz, w trybie stereo 32-bitowym (lewy + prawy z przeplotem), z buforem DMA o rozmiarze 16384 bajtów (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,
)

Metody transferu mogą być używane w trzech stylach:

Blokującywrite() i readinto() zwracają sterowanie dopiero po zakończeniu operacji:

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

Nieblokujący – zainstaluj wywołanie zwrotne za pomocą irq(), a metody transferu zwrócą sterowanie natychmiast. Wywołanie zwrotne jest uruchamiane przez harmonogram MicroPython, gdy DMA opróżni bufor TX lub zapełni bufor 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 jest strumieniem i może zostać opakowane przez 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)

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)

Konstruuje obiekt I2S o podanym id:

  • id identyfikuje konkretną magistralę I2S; jest specyficzny dla płytki i portu

Parametry przekazywane wyłącznie jako słowa kluczowe, obsługiwane na wszystkich portach:

  • sck to obiekt pinu dla linii zegara szeregowego

  • ws to obiekt pinu dla linii wyboru słowa

  • sd to obiekt pinu dla linii danych szeregowych

  • mck to obiekt pinu dla linii zegara nadrzędnego; częstotliwość zegara nadrzędnego to częstotliwość próbkowania * 256

  • mode określa odbiór lub nadawanie

  • bits określa rozmiar próbki (bity), 16 lub 32

  • format określa format kanałów, STEREO lub MONO

  • rate określa częstotliwość próbkowania audio (Hz); jest to częstotliwość sygnału ws

  • ibuf określa długość wewnętrznego bufora (bajty)

Na wszystkich portach DMA działa nieprzerwanie w tle i pozwala aplikacjom użytkownika wykonywać inne operacje podczas transferu danych próbek między wewnętrznym buforem a urządzeniem peryferyjnym I2S. Zwiększenie rozmiaru wewnętrznego bufora może wydłużyć czas, w którym aplikacje użytkownika mogą wykonywać operacje niezwiązane z I2S przed wystąpieniem niedomiaru (np. metoda write) lub przepełnienia (np. metoda readinto).

Metody

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

opisy argumentów znajdują się w sekcji Konstruktor

deinit() None

Deinicjalizuje magistralę I2S

readinto(buf: bytearray) int

Wczytuje próbki audio do bufora określonego przez buf. buf musi obsługiwać protokół bufora, taki jak bytearray lub array. Kolejność bajtów w „buf” jest little-endian. W formacie Stereo próbka lewego kanału poprzedza próbkę prawego kanału. W formacie Mono używane są dane próbki lewego kanału. Zwraca liczbę wczytanych bajtów

write(buf: bytes) int

Zapisuje próbki audio zawarte w buf. buf musi obsługiwać protokół bufora, taki jak bytearray lub array. Kolejność bajtów w „buf” jest little-endian. W formacie Stereo próbka lewego kanału poprzedza próbkę prawego kanału. W formacie Mono dane próbki są zapisywane zarówno do prawego, jak i lewego kanału. Zwraca liczbę zapisanych bajtów

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

Ustawia wywołanie zwrotne. handler jest wywoływany, gdy buf zostaje opróżniony (metoda write) lub zapełniony (metoda readinto). Ustawienie wywołania zwrotnego zmienia metody write i readinto na działanie nieblokujące. handler jest wywoływany w kontekście harmonogramu MicroPython.

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

bitowe przesunięcie wszystkich próbek zawartych w buf. bits określa rozmiar próbki w bitach. shift określa liczbę bitów, o jaką przesunąć każdą próbkę. Wartość dodatnia oznacza przesunięcie w lewo, ujemna w prawo. Zazwyczaj używane do regulacji głośności. Każde przesunięcie o jeden bit zmienia głośność próbki o 6dB.

Stałe

RX: int

do inicjalizacji mode magistrali I2S na odbiór

TX: int

do inicjalizacji mode magistrali I2S na nadawanie

STEREO: int

do inicjalizacji format magistrali I2S na stereo

MONO: int

do inicjalizacji format magistrali I2S na mono