Audio Recording mit LinkIt Smart 7688 und I2S-Mikro

Im Beitrag System für kontinuierliche Audio-Aufzeichnung (BOB Projekt, Phase 1) sowie unter DIY Ambisonic Aufzeichnung haben wir Anforderungen für die kontinuierliche Audiotelemetrie gesammelt und diverse Möglichkeiten diskutiert.

Hier soll es darum gehen, dies konkret mit einem LinkIt Smart 7688 und einem ICS43432 I2S-Mikro zu realisieren.

Zwei boards sind heute schon angekommen:

@Andreas: Das zweite (nicht auf dem Bild) ist für dich ;-)

Steps to get the LinkIt Smart 7688 running

  1. How to accesss your board
    Sign-in to the web UI
    Access the System Console
  2. (optional) firmware update
    Update the firmware with Web UI
  3. Configure internet access
    Connect to the internet
  4. Run your first Python program
    Create and run your first example …

Wiring the ICS43432

Acording to the pin out diagram for the LinkIt Smart [PDF file] we have to use

LinkIt Smart   Arduino
7688           ICS43432 
[board]        [mic]

GND        --  GND
3V3        --  3V3 
P10        --  WS 
P11        --  CLK 
P13        --  SD 

ics43432-arduino-breakout

picture: CC BY-SA 3.0 arduino.cc

@Andreas, auf den LinkIt Smart läuft ja OpenWrt. Hast du dir schon Gedanken gemacht, wie wir die Dinger für die audio chain programmieren, sprich welche Sprache? Die LinkIt Smart können C/C++, Python, Node.js. Willst du mit batch-Dateien ran oder doch lieber Python? ;-) Dann würde ich mal schauen, wie wir an den I2S-Bus rankommen.

Ja, danke dass Du nachfragst. Wir haben vor, GStreamer zu verwenden und haben bereits erste baby steps in diese Richtung unternommen: Saraswati (s.u.) hält kleine Beispiele für Python und Rust bereit, für beide gibt es solide bindings für das GStreamer Framework. Derzeit favorisieren wir Rust.


Wir müssen nicht zwingend I2S verwenden, sondern erstmal ganz normal USB, da das deutlich universeller ist. Alle weiteren Schritte sind dann Optimierungsmöglichkeiten.

Falls die I2S Schnittstelle bereits vom Linux Kernel per ALSA oder PulseAudio ordentlich erschlossen ist, müsste es uns eigentlich auch innerhalb der GStreamer Umgebung zur Verfügung stehen.

Die scheint da zu sein
Edit: Leider nur für den WM8960, nicht für unser Mic, siehe das Posting von @weef

root@mylinkit:~# arecord -l

**** List of CAPTURE Hardware Devices ****
card 0: I2S [MTK APSoC I2S], device 0: WMserious PCM wm8960-hifi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Laut dem Beispiel unter https://docs.labs.mediatek.com/resource/linkit-smart-7688/en/tutorials/audio-playback-and-recording sind Audio-Aufnahmen – im ersten Abschnitt steht I2S – recht einfach möglich mit

# arecord -f cd -t wav -M /Media/USB-A1/my_recording.wav

Falls das tatsächlich so funktionier wäre das deutlich einfacher als mit der USB-Audio-Soundkarte wie von @einsiedlerkrebs hier erschlossen: Research: audio stream with Linkit 7688

1 Like

Out of the box läuft es bei mir nicht. Nach dem Start mit arecord hängt sich das Audio-Modul auf.

root@mylinkit:~# arecord -d 5 -f cd -t wav -M /Media/SD-P1/simple-test3.wav
Recording WAVE '/Media/SD-P1/simple-test3.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

wenn ich nun mit Ctrl + C abbreche

Aborted by signal Interrupt...
arecord: pcm_read:2031: read error: Interrupted system call

Habe mal hier nachgefragt

https://en.forum.labs.mediatek.com/t/audio-recording-with-linkit-smart-7688-and-i2s-microphone/2598

Im Abschnitt limitations der LinkIt Doku hint es den Hinweis “mono (1 channel) is not supported” hmm, kann ich dann einfach Stereo aufnehmen und ein Kanal ist Müll? Oder ist das das Problem weshalb das Audio-Modul sich aufhängt?

Eine ausschließliche Stereoaufnahme wäre für uns erst mal doof, weil das automatisch die doppelte Datenmenge produzieren würde. Wir könnten aber ggf. beim Postprocessing noch nach Mono konvertieren.

Lass uns nochmal überlegen, ob das mit den USB-Mikros Sinn macht. Wir bräuchten dann zu den Micros auch USB-Soundkarten, oder? Ich würde gerne die selbe Hardware - bei den MIcs - für 24/7 und später im Feld verwenden. “Draußen” ist Stromverbrauch und die Größe der Dinger relevant. Denke da haben die I2S-Mics Vorteile.

Vielleicht finde ich auch noch etwas zum Stromverbrauch.

“Wenig Stromverbrauch” ist an dieser Stelle eine Optimierungsgröße. Und beim Prototypen gilt erstmal: “Premature optimization is the root of all evil”. USB ist und bleibt am universellsten über die gesamte Klasse der SoC Geräte hinweg.

Ganz normale USB Soundkarten mit ganz normalen Mikros, ja.

Falls unterschiedliche Micros einen signifikanten Einfluss auf die Daten haben könnte das eine Störgröße sein, besser wäre gleiche Mics für Phase 1 und Phase 2. Weiter werden wir für den Node im Feld eh keine USB-Soundkarte verwenden können weil der ESP oder ein anderer MC das nicht unterstützt.

Kann man den I2S nicht ähnlich wie einen Soundkarten-Eingang verwenden, auch mit gstreamer?

@weef du hast offline angemerkt, dass die I2S-Mikros vermutlich nicht direkt mit dem LinkIt Smart funktionieren würden.

Ich habe vorgestern mal eines angeschlossen und der LinkIt bzw. das Audio-Modul hängt sich dann beim Starten der Aufnahme auch auf.

Das Beispiel ist für das Zusatz-Board auf dem ein I2S-Chip ist. Da kann man dann wieder ein analoges Mic anschließen - so wie ich es verstanden habe.

Btw. das Zusatz-Board habe ich nicht!

So wie du es oben gemacht hast – nur anschließen – klappt das leider nicht, und der Weg dahin wird steinig…

Genau. Auf dem breakout-PCBA ist ein WM8960 verbaut (Cirrus Logic Redirect).

Zwei analoge Mics kann man an den da anschließen. - Auf dem break-out gibt es noch einen AUX audio in (der ist ohne elektret-biasing, also dynamische Mikros oder Line-In).

Den hattest Du gefunden:

Hardware limitations

I2S

  • Mono (1 channel) is not supported.
    […]

(aus: https://docs.labs.mediatek.com/resource/linkit-smart-7688/en/limitations-and-known-issues)

Ob das ein echter issue ist zw. wie die das genau meinen, kann ich noch nicht beurteilen, wäre aber unproblematisch; einen leeren Kanal zwar abzutasten, aber nicht aufzuzeichen oder zu übertragen, ginge immer.

Zu Deinem verwendeten (von Mediatek stammenden) Beispiel-Befehl:

  • dort fehlt arecord die device-Angabe. Das geht solange gut, wie ein default für den snd_core -Treiber des kernels definiert ist - wie im Falle des OpenWRT auf dem LinkIt 7688, nämlich der WM8960! Nur deshalb geht das Beispielt in deren wiki.
    Normalerweise muß da sowas hin wie hw1:0 oder plughw:1, es liest sich auch besser. ;)

  • device tree -Schnipsel für das ICS43432

    Invensense ICS-43432 MEMS microphone with I2S output.

    There are no software configuration options for this device, indeed, the only host connection is the I2S interface. Apart from requirements on clock frequency (460 kHz to 3.379 MHz according to the data sheet) there must be 64 clock cycles in each stereo output frame; 24 of the 32 available bits contain audio data. A hardware pin determines if the device outputs data on the left or right channel of the I2S frame.

    Du müßtest also 32bit aufzeichen, von denen 24 genutzt werden. I2S ist zwar big-endian, Dein PCM-Ziel will es aber anders, daher explizit (und nix shortcuts wie “cd” oder “dat”):

    arecord -D hw:1.0 -c 1 -r 48000 -f S32_LE -t wav <DeinFile>

    Es kann sein, daß -c 2 nötig ist! ;)


Aktuelles OpenWRT baut für das Teil, es gibt ein target und sub-target und sogar ein spezifisches target profile, - aber das weißt Du ja schon von @einsiedlerkrebs ! ,) Ich konnte sogar ganz ansehliche Stücke Python und gstreamer anmachen, und das image war gebaut gerade 13 MB.

lede-menuconfig-mt7688

Im aktuellen LEDE (die sind wieder zusammen: jetzt also wieder: OpenWRT) ist alles für I2S -support im kernel sowie einige Geräte, soweit bekannt und erschlossen, angelegt. Man findet mediatek’s github-feeds, die aus einem MT7688 einen LinkIt machen (inkl. dieser vorgeschalteten WebGUI vor OpenWRT) - die man aber nicht mehr braucht, denn der Wifi-Treiber ist inzwischen ein offener (MT76), die MT-GUI braucht man eh nicht! ;)

Es wird nichts drumherum führen, daß Du dieses Teil hier als kernel-Treiber für MIPS24KEc brauchst:

… und es muß im device tree eingeragen werden, daß dieses Mikrofon angeschlossen ist… und es muß der MT8960-Treiber rausgeschmissen werden… und es braucht zwingend einen 4.x kernel.

@einsiedlerkrebs oder ich könnten mal dieses file crosscompilen für den LinkIt, und dann muß noch ein passender device tree -Eintrag adaptiert werden. @clemens, fühlst Du Dich in der Lage, ein fertiges aktuelles Image von https://downloads.lede-project.org/releases/18.06.0-rc1/targets/ramips/mt76x8/ (gleich das erste oben) uber die LuCi (OpenWRT/LEDE-webgui) auf das Ding einzuspielen? Dann könnten wir weitersehen.

Du könntest einen Teil davon am RasPi üben, mit dem Vorteil, daß Du da direkt auf dem target bauen kannst: Add an I2S mic using device tree & simple-audio-card - Raspberry Pi Forums .

Wie ich im thread lese, kannst Du aber mit ctrl-C abbrechen, dann hat sich da nix aufgehangen. Der WM8960 ist bereits ein komplexer Stein mit aufwendigem Treiber (WM8960 audio codec - NXP Community), er benutzt daher ein I2C als control interface: genau dort hat nichts geantwortet, und arecord konnte den fehler an die alle Schichten darunter schieben.


… nee, @einsiedlerkrebs’ deployment ist einfacher, denn USB ist PnP, und einen USB-Treiber nachzuinstallieren, ist einfacher, als ein passendes i2s--kernel-Modul zu bauen, es einzubinden und neustart-fest zu machen. (Unabhängig davon streamt seine Lösung, das läßt sich kaum einacher machen, als so.) Den kernel + sinnvollen user space selbst zu bauen oder einen entsprechend existierenden zu modifizieren, wirst Du nicht umhinkommen. - @einsiedlerkrebs ist da dichter am Thema, denn im Gegensatz zu mir hat der solch ein MT7688!


Grundsätzliches zu diesem SoC (geht da um den Onion2 von omega.io, die verbauen den gleichen Chip auch):

I think we should precisely differentiate three areas:

  • There are bugs in the Mediatek MT7688, affecting SPI, I2S and I2C, see link in @György-Farkas’ post above. If you blame Onion for using this chip, then please name a better one in the same price range having at least partially open specs. The MT7688 is nothing more than a slightly IoT-zed router chip. Its ethernet, USB, UART and WiFi hardware is solid, but its SPI was originally designed to connect the flash chip only, and things like PWM and I2C seem to have been added without much care. Sad, but certainly MediaTek’s fault.

  • There’s not enough open documentation for the MT7688 to write solid drivers without a lot of try and error. As said, at least there is a publicly available datasheet (there was none for the Omega1’s AR9331!), but it is little more than a list of register addresses and bits. No conceptual descriptions of any of the function blocks, very little context. So the drivers that exist in the open source LEDE stack have shortcomings just because the hardware is not documented properly. On the other hand, those developers who do have more information, are bound by NDAs so can’t contribute to the open drivers, e.g. WiFi. This is the sad state of affairs around a only semi-open SoC chip.

  • […]

(aus: Omega2 current defects | Community)

Genau, das ist das Ziel eines solchen Kerneltreibers für den MT7688: Sobald der ordentlich läuft, muß das Audiogerät ebenfalls per ALSA (und PulseAudio) als hw (oder plughw) ansprechbar sein. Dann kann man alles damit anstellen, was man von anderen Audiogeräten unter Linux kennt.

1 Like

Ich werde versuchen, heute Abend mit deinen Hinweisen weiter zu kommen. Beim Yun hatte ich das OS schon mal aktualisiert, so i’ll try my very best! … und reporte dann wie weit ich gekommen bin.

Schade, dass es nicht so geht wie gedacht. Hätte ich das schon mit “arecord -l” sehen müssen / können?

Vielen Dank für die Hilfe und Deine lange Antwort! ;-) Auch wenn “einfacher” besser wäre und der Weg steinig ist, lernt man mit deinen Antworten immer viel!

So, das firmware-update ging irgendwie schief. Der LinkIt bleit beim booten hängen (WLAN-LED geht nicht aus). Ich setzte mich morgen nochmal dran.

Woran machst Du das fest?

Die WLAN-LED ist nur ein GPIO, daher kann das ein normales Verhalten dieser LED unter diesem Treiber sein (den MT76 -wifi-Treiber benutze ich nicht mangels Notwendigkeit, sonst wüßte ich es genauer). Vorher war ja der proprietäre Treiber darin, und der wird ziemlich sicher anders geblinkt haben. - Also das allein ist noch kein Indiz.

Was sagt denn die console, schick’ doch mal den kompletten Mitschnitt des boot-Vorgangs von der seriellen Schnitte! Da meldet sich der bootloader, der das image reinzieht, entpackt und versucht, den Kernel anzustarten usw. Im besten Fall kommen irgendwann keine Protokollzeilen mehr, und Du kannst Enter drücken, um eine root shell zu erhalten. Wenn er vorher anhält, kann ich nur mit einem bootlog irgendwas dazu sagen.

Wie hast Du geupdated: über serielle, USB-Stick oder Ethernet? Hast Du das von der OpenWRT-Oberfläche aus gemacht oder aus der shell auf dem linkit mit sysupgrade? Du solltest auch immer die sha256 für das file mit der angegebenen verifizieren und neu downloaden, wenn es da eine Abweichung gibt!

BTW, Yun ist ne gute Idee, das ist der gleiche Target-core: ein mips24Kc (mips32r2-Code). Das bedeutet, daß Du für den Yun gebaute Pakete per ipkg komfortabel nachinstallieren kannst. - Ich nutze ja die Carambola2, das ist auch mips24kc. Der SoC ist ein anderer Hersteller (Atheros AR9331), aber wiederum der gleiche wie im Yun. Das heißt, ich habe dafür bereits die gebaute toolchain zum crosscompilen (und muß sie nicht erst bauen). Das beschert relativ schnell den ics43432-Treiber, - was aber noch nicht ausreicht…

Ja. Müssen nicht, können schon. ;)

Das update habe ich über die LuCI-Weboberfläche gemacht, wie unter Via Web-Oberfläche (weiter unten auf der Seite) beschrieben.

Der LinkIt war dabei im lokalen WLAN, die (bestehende) Konfiguration habe ich nicht übernommen (Option beim update). Dann habe ich damit gerechnet, dass der LinkIt in den AP-Mode wechselt und ein WLAN-Netzwerk mit “LinkIt irgendwas …” aufmacht. Ok, ist kein “original” LinkIt-Image, vielleicht macht er das gar nicht. Ich versuche mal über die Konsole ran zu kommen.

Um den boot-Prozess zu debuggen und auf den LinkIt – ohne WLAN – zuzugreifen muss man ihn über die serielle Schnittstelle ansprechen. Anleitung unter Bootloader and kernel console … hilfreich dabei auch das Pin-out Diagramm

LinkIt Smart 7688   FTDI
[board]             [cable]

GND             --  GND
P8 (UART TX2)   --  RX 
P9 (UART RX2)   --  TX

, und die baud-Rate auf 57600 einstellen!

Nun kann man mit PuTTY auf den LinkIt zugreifen. Wenn man nur am output interessiert ist kann man alternativ auch den seriellen Monitor der Arduino-IDE verwenden.

Et voila! Alive!

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 OpenWrt 18.06.0-rc1, r7090-d2aa3a1b62
 -----------------------------------------------------

D.h. die dauerangeschaltetet WLAN-LED, die mit der Original Linkit-Firmware einen Fehler signalisiert scheint – wie von @weef oben geschrieben – hier keinen Fehler zu signalisieren. ;-)

Nun muss ich noch WLAN konfigurieren.

WLAN ist bei OpenWRT per default deaktiviert, man muss es erst anschalten.

Nun spannt OpenWRT auch einen AccessPoint mit der SSID OpenWrt auf, mit dem kann man sich nun verbinden. Hat man die Verbindung hergestellt kommt man über http://192.168.1.1 auf LuCI.

A post was merged into an existing topic: Developing Saraswati: A robust, multi-channel audio recording, transmission and storage system

@weef gibt es ein image für den LinkIt, das die I2S-Schnittstelle unterstützt?