клас I2S – протокол міжмікросхемної звукової шини

Клас I2S керує шиною Inter-IC Sound (I2S) у режимі контролера – мікроконтролер генерує тактовий сигнал розряду (SCK) і тактовий сигнал вибору слова (WS) та обмінюється даними зразків по лінії SD. Драйвер підтримує безперервний DMA у фоновому режимі, тому Python-код лише повинен підтримувати внутрішній буфер зразків заповненим. Периферійний режим і режим «лише приймання» не підтримуються.

Доступно на STM32 OpenMV Cam з підключеним периферійним пристроєм I2S, а також на OpenMV Cam RT1062. Не доступно на OpenMV Cam AE3 (порт alif).

I2S(2) на STM32 OpenMV Cam використовує ті самі виводи, що й SPI(2) – тактовий сигнал на P2 (SCK), вибір слова на P3 (NSS), а лінія послідовних даних відповідає конвенції напрямку даних SPI: TX використовує P0 (MOSI), RX використовує P1 (MISO).

Приклад – виведення (TX). Ініціалізація TX-шини для керування зовнішнім аудіо DAC на частоті 44,1 кГц, 16-бітні моно-зразки, DMA-буфер розміром 16384 байт (16 КіБ):

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

Приклад – введення (RX). Ініціалізація RX-шини для захоплення даних з мікрофона на частоті 22,05 кГц, 32-бітне стерео (ліво + право чергуються), DMA-буфер розміром 16384 байт (16 КіБ):

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

Методи передачі можна використовувати у трьох стилях:

Блокуючийwrite() та readinto() повертаються лише після завершення операції:

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

Неблокуючий – встановіть зворотний виклик через irq(), і методи передачі повертаються негайно. Зворотний виклик запускається з планувальника MicroPython, коли DMA спустошує TX-буфер або заповнює 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 є потоком і може бути обгорнутий у 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)

Конструктор

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)

Створити об’єкт I2S з вказаним ідентифікатором:

  • id визначає конкретну шину I2S; залежить від плати та порту

Параметри лише за ключовим словом, підтримувані на всіх портах:

  • sck – об’єкт виводу для лінії послідовного тактування

  • ws – об’єкт виводу для лінії вибору слова

  • sd – об’єкт виводу для лінії послідовних даних

  • mck – об’єкт виводу для лінії тактування майстра; частота тактування майстра = частота дискретизації × 256

  • mode – задає режим приймання або передавання

  • bits – задає розмір зразка (біти): 16 або 32

  • format – задає формат каналу: STEREO або MONO

  • rate – задає частоту дискретизації аудіо (Гц); це частота сигналу ws

  • ibuf – задає довжину внутрішнього буфера (байти)

На всіх портах DMA безперервно працює у фоновому режимі і дозволяє користувацьким програмам виконувати інші операції, поки дані зразків передаються між внутрішнім буфером і периферійним блоком I2S. Збільшення розміру внутрішнього буфера потенційно збільшує час, протягом якого користувацькі програми можуть виконувати операції, не пов’язані з I2S, до переповнення (наприклад, метод write) або переповнення буфера (наприклад, метод readinto).

Методи

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

дивіться опис аргументів у Конструкторі

deinit() None

Деініціалізувати шину I2S

readinto(buf: bytearray) int

Зчитати аудіозразки у буфер, вказаний у buf. buf має підтримувати протокол буфера, наприклад bytearray або array. «buf» byte ordering is little-endian. У форматі Stereo зразок лівого каналу передує зразку правого каналу. У форматі Mono використовуються дані зразків лівого каналу. Повертає кількість зчитаних байтів

write(buf: bytes) int

Записати аудіозразки, що містяться у buf. buf має підтримувати протокол буфера, наприклад bytearray або array. «buf» byte ordering is little-endian. У форматі Stereo зразок лівого каналу передує зразку правого каналу. У форматі Mono дані зразка записуються одночасно у правий і лівий канали. Повертає кількість записаних байтів

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

Встановити зворотний виклик. handler викликається, коли buf спустошується (метод write) або заповнюється (метод readinto). Встановлення зворотного виклику переводить методи write та readinto у неблокуючий режим роботи. handler викликається в контексті планувальника MicroPython.

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

Побітовий зсув усіх зразків у buf. bits задає розмір зразка у бітах. shift задає кількість бітів для зсуву кожного зразка. Позитивне значення – зсув вліво, від’ємне – зсув вправо. Зазвичай використовується для управління гучністю. Кожен бітовий зсув змінює гучність зразка на 6 дБ.

Константи

RX: int

для ініціалізації шини I2S mode у режим приймання

TX: int

для ініціалізації шини I2S mode у режим передавання

STEREO: int

для ініціалізації шини I2S format у стерео

MONO: int

для ініціалізації шини I2S format у моно