الفئة I2S -- بروتوكول ناقل الصوت بين الدوائر المتكاملة (Inter-IC Sound)

تتحكم الفئة I2S في ناقل الصوت بين الدوائر المتكاملة (I2S) في وضع المتحكم -- حيث يولّد المتحكم الدقيق ساعة البتات (SCK) وساعة اختيار الكلمة (WS) ويتبادل بيانات العينات على خط SD. يدعم المشغّل عمل DMA المستمر في الخلفية بحيث لا يحتاج جانب Python إلا إلى إبقاء مخزن العينات الداخلي ممتلئاً. وأوضاع الطرفية / الاستقبال فقط غير مدعومة.

متاح على كاميرات OpenMV من نوع STM32 التي توصّل طرفية I2S وعلى OpenMV Cam RT1062. غير متوفر على OpenMV Cam AE3 (منفذ alif).

يشارك I2S(2) على كاميرات OpenMV من نوع STM32 دبابيسه مع SPI(2) -- ساعة البتات على P2 (SCK)، واختيار الكلمة على P3 (NSS)، ويتبع خط البيانات التسلسلية اصطلاح اتجاه بيانات SPI: يستخدم الإرسال P0 (MOSI)، ويستخدم الاستقبال P1 (MISO).

مثال -- الإخراج (TX). أنشئ ناقل إرسال لتشغيل DAC صوتي خارجي بمعدل 44.1 kHz، وعينات أحادية بطول 16 بت، مع مخزن دعم DMA بحجم 16384 بايت (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,
)

مثال -- الإدخال (RX). أنشئ ناقل استقبال يلتقط من ميكروفون بمعدل 22.05 kHz، وعينات ثنائية القناة (ستيريو) بطول 32 بت (يسار + يمين متداخلان)، مع مخزن دعم DMA بحجم 16384 بايت (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,
)

يمكن استخدام طرق النقل بثلاثة أساليب:

الحظر (Blocking) -- لا تعود write() و readinto() إلا بعد اكتمال العملية:

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

عدم الحظر (Non-blocking) -- ثبّت دالة رد نداء باستخدام irq() وتعود طرق النقل فوراً. تعمل دالة رد النداء من مجدول MicroPython عندما يفرّغ DMA مخزن الإرسال أو يملأ مخزن الاستقبال:

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

asyncio -- I2S هي تدفّق ويمكن تغليفها بواسطة 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)

أنشئ كائن I2S بالمعرّف المحدد:

  • يحدد id ناقل I2S معيّناً؛ وهو خاص باللوحة والمنفذ

المعاملات المسماة فقط (Keyword-only) المدعومة على جميع المنافذ:

  • sck هو كائن دبوس لخط الساعة التسلسلية

  • ws هو كائن دبوس لخط اختيار الكلمة

  • sd هو كائن دبوس لخط البيانات التسلسلية

  • mck هو كائن دبوس لخط الساعة الرئيسية؛ وتردد الساعة الرئيسية يساوي معدل أخذ العينات * 256

  • يحدد mode الاستقبال أو الإرسال

  • يحدد bits حجم العينة (بالبتات)، 16 أو 32

  • يحدد format تنسيق القناة، STEREO أو MONO

  • يحدد rate معدل أخذ العينات الصوتية (Hz)؛ وهذا هو تردد إشارة ws

  • يحدد ibuf طول المخزن الداخلي (بالبايتات)

في جميع المنافذ، يعمل DMA بشكل مستمر في الخلفية ويتيح لتطبيقات المستخدم إجراء عمليات أخرى أثناء نقل بيانات العينات بين المخزن الداخلي ووحدة طرفية I2S. زيادة حجم المخزن الداخلي قد تزيد من الوقت الذي يمكن لتطبيقات المستخدم خلاله إجراء عمليات غير متعلقة بـ I2S قبل حدوث نقص في التدفق (underflow) (مثل طريقة write) أو فيضان (overflow) (مثل طريقة 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" هو little-endian. بالنسبة لتنسيق ستيريو، تسبق عينة القناة اليسرى عينة القناة اليمنى. بالنسبة لتنسيق مونو، تُستخدم بيانات عينة القناة اليسرى. تُعيد عدد البايتات المقروءة

write(buf: bytes) int

اكتب العينات الصوتية الموجودة في buf. يجب أن يدعم buf بروتوكول المخزن المؤقت، مثل bytearray أو array. ترتيب بايتات "buf" هو little-endian. بالنسبة لتنسيق ستيريو، تسبق عينة القناة اليسرى عينة القناة اليمنى. بالنسبة لتنسيق مونو، تُكتب بيانات العينة إلى كلتا القناتين اليمنى واليسرى. تُعيد عدد البايتات المكتوبة

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 عدد البتات المراد إزاحة كل عينة بها. موجب للإزاحة اليسرى، وسالب للإزاحة اليمنى. يُستخدم عادةً للتحكم في مستوى الصوت. كل إزاحة بتة واحدة تغيّر مستوى صوت العينة بمقدار 6dB.

الثوابت

RX: int

لتهيئة mode لناقل I2S على الاستقبال

TX: int

لتهيئة mode لناقل I2S على الإرسال

STEREO: int

لتهيئة format لناقل I2S على ستيريو

MONO: int

لتهيئة format لناقل I2S على مونو