# UARTScope Ein moderner UART-Monitor für Linux mit Qt6-Oberfläche. Gebaut als vollwertiger Ersatz für minicom – besonders nützlich bei der Entwicklung von Baremetal-Projekten wie [Chica](https://git.projekt-hirnfrei.de/diabolus/chica) (Amiga-Hardware-Nachbildung auf dem Raspberry Pi). --- ## Features | Feature | Beschreibung | |---|---| | **Serieller UND Netzwerk-Input** | Verbindung wahlweise über einen echten/virtuellen seriellen Port **oder** eine reine TCP-Verbindung – praktisch für Emulatoren wie FS-UAE, deren Debug-UART per `socat` auf einen TCP-Port gelegt wird | | **PTY-Erkennung** | Pseudo-Terminals unter `/dev/pts/` (z.B. von `qemu -serial pty`) werden im Port-Dropdown automatisch mitgelistet | | **Unbegrenzter Verlauf** | Kein Zeilenlimit – keine Daten gehen verloren, egal wie viel gesendet wird | | **Timestamps** | Jede Zeile im Raw-View bekommt automatisch einen `hh:mm:ss.zzz`-Timestamp | | **Auto-Scroll** | Standardmäßig aktiv – springt automatisch ans Ende neuer Ausgaben | | **H + V Scrolling** | Kein Zeilenumbruch, voller horizontaler Scrollbalken | | **Live-Logging** | Alle empfangenen Zeilen werden mit Timestamp in eine Datei geschrieben | | **Tag-Monitor mit Verlauf** | Zeilen mit `[TAG]` werden in eigenen Panels angezeigt; jedes Panel hat einen „Aktuell"-Tab (Live-Stand) und einen „Verlauf"-Tab (alle je empfangenen Werte, timestamped) | | **Listen-Werte** | `;`-getrennte Werte in einem Tag werden als mehrzeilige Liste dargestellt | | **Tag-Filter** | Tags können aus dem Raw-View ausgeblendet werden – wird dauerhaft gespeichert; auch Tag-Namen mit Bindestrich (z.B. `I2C-BUS`) werden korrekt erkannt | | **Tabellenansicht** | CSV-formatierte UART-Zeilen werden in einer Tabelle dargestellt | | **Suche mit Navigation** | Inkrementelle Volltextsuche im Raw-View mit Weiter/Zurück (Buttons, Enter, F3/Shift+F3) und Wrap-Around | | **Auto-Reconnect** | Bei Verbindungsabbruch wird automatisch neu verbunden (Intervall einstellbar) – funktioniert für seriell und TCP gleichermaßen | | **ANSI Clear-Screen** | `\033[2J\033[H` aus der Firmware leert Raw-View, Tabelle, Tag-Monitor und Video-Vorschau gleichzeitig | | **Copy-Buttons** | Raw-View und jedes Tag-Panel (Aktuell- oder Verlauf-Tab) haben einen „📋 Copy"-Button | | **V4L2 Live Video** | HDMI-Grabber direkt eingebunden – Live-Vorschau unter dem Tag-Monitor | | **Video-Aufzeichnung (MP4)** | Live-Vorschau per Knopfdruck als MP4 aufzeichnen (H.264, via `ffmpeg`) | | **Screenshot** | Aktuellen Frame des HDMI-Grabbers als PNG/JPG speichern | | **Automatischer Screenshot-Trigger** | `[SCREENSHOT] dateiname` als Steuertag: der Frame wird exakt im Moment des Empfangs gespeichert – ideal um z.B. einen kurz angezeigten Memory-Dump zuverlässig zu erwischen | | **Format-Referenz** | Eingebauter Guide (mit Kopieren-Button) für KI-kompatible UART-Formatierung | | **Fensterlayout** | Fenstergröße, Position, Splitter-Positionen und Tag-Filter werden beim Beenden gespeichert | --- ## Voraussetzungen ```bash # Arch (empfohlen) sudo pacman -S cmake qt6-base qt6-serialport ffmpeg # Ubuntu / Debian sudo apt install cmake qt6-base-dev qt6-serialport-dev libqt6serialport6-dev ffmpeg # Fedora sudo dnf install cmake qt6-qtbase-devel qt6-qtserialport-devel ffmpeg ``` V4L2 benötigt keine zusätzliche Library – `linux/videodev2.h` ist Teil der Standard-Kernel-Header. Das TCP-Netzwerk-Modul (`Qt6::Network`) ist üblicherweise Teil des `qt6-base`-Pakets und braucht keine separate Installation. `ffmpeg` ist **nur** für die Video-Aufzeichnung (MP4) nötig – ohne installiertes `ffmpeg` funktioniert der Rest von UARTScope normal, nur der „⏺ Record"-Button zeigt dann eine Fehlermeldung. --- ## Build ```bash git clone https://git.projekt-hirnfrei.de/diabolus/uartscope.git cd uartscope cmake -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j$(nproc) # Ausführen ./build/uartscope # Systemweit installieren (optional) sudo cmake --install build ``` --- ## Verbindung: Seriell oder Netzwerk (TCP) Im Connect-Dialog gibt es zwei Tabs: ### Seriell Wie gewohnt: Port aus der Liste wählen (echte Geräte **und** Pseudo-Terminals unter `/dev/pts/` werden angezeigt), Baudrate/Parität/Stopbits/Flow Control einstellen. **Virtuelle serielle Geräte (z.B. QEMU):** ```bash qemu-system-xxx -serial pty ... # QEMU gibt im Log den zugewiesenen Pfad aus, z.B.: # char device redirected to /dev/pts/4 ``` Den ausgegebenen Pfad im Seriell-Tab auswählen (ggf. vorher ↻ zum Neuladen der Liste drücken). Baudrate & Co. werden von virtuellen PTYs ignoriert – das ist unschädlich. ### Netzwerk (TCP) Host/IP und Port angeben statt eines seriellen Ports. Gedacht für Firmware/Emulatoren, die ihre Debug-UART über TCP senden statt über ein echtes serielles Gerät – zum Beispiel FS-UAE, dessen serielle Schnittstelle per `socat` auf einen TCP-Port gelegt wird: ```bash # Beispiel: FS-UAEs serielle Ausgabe per socat auf TCP-Port 1234 legen socat /tmp/fs-uae-serial TCP-LISTEN:1234,reuseaddr,fork ``` Danach im Netzwerk-Tab `localhost` und Port `1234` eintragen und verbinden. Auto-Reconnect funktioniert identisch zum seriellen Modus – bricht die TCP-Verbindung ab, wird automatisch neu verbunden. --- ## Video-Aufzeichnung (MP4) Die Live-Vorschau im Video-Widget lässt sich per „⏺ Record"-Button als MP4-Datei aufzeichnen. Dazu wird intern ein `ffmpeg`-Prozess gestartet, dem die rohen Frames als BGRA über eine Pipe zugeführt werden; `ffmpeg` encodiert sie zu H.264/MP4. - **Voraussetzung:** `ffmpeg` muss installiert und im `PATH` sein (siehe [Voraussetzungen](#voraussetzungen)) - Die Aufzeichnung läuft unabhängig vom Freeze-Status weiter – Freeze pausiert nur die Vorschau, nicht die Aufnahme - Timestamps basieren auf der Systemuhr (`-use_wallclock_as_timestamps`), damit die Aufnahme auch bei schwankender Framerate des Grabbers die reale Dauer korrekt wiedergibt - Ein Auflösungswechsel während der Aufnahme, ein Stopp der Capture oder ein Fehler beenden die Aufzeichnung automatisch sauber --- ## Automatischer Screenshot-Trigger Manuelles Klicken auf den Screenshot-Button trifft bei schnellen Hardware-Ereignissen (z.B. einem kurz angezeigten Memory-Dump) selten genau den richtigen Moment – menschliche Reaktionszeit liegt bei mehreren hundert Millisekunden, in der Hardware-Welt passieren in dieser Zeit unzählige Instruktionen. Dafür gibt es den Steuertag `[SCREENSHOT]`: ```c uart_printf("[SCREENSHOT] memdump_%lu.png\n", HAL_GetTick()); ``` Sobald diese Zeile empfangen wird, speichert UARTScope **sofort** den Frame, der zu diesem Zeitpunkt im V4L2-Vorschaupuffer liegt – kein Dialog, keine Nutzerinteraktion nötig. Die Verzögerung besteht nur noch aus UART-Übertragungszeit und einem Event-Loop-Tick (typischerweise einstellige Millisekunden), statt aus menschlicher Reaktionszeit. **Einrichtung:** 1. In der Toolbar auf „Screenshot folder…" klicken und den Zielordner wählen 2. Die Einstellung wird sofort gespeichert und bei jedem Programmstart wiederhergestellt **Verhalten:** - Ohne konfigurierten Ordner wird der Trigger zwar erkannt (erscheint im Tag-Monitor und Raw-View), aber es wird keine Datei geschrieben – das Ergebnis jedes Trigger-Versuchs (Erfolg oder Fehler, z.B. „kein Ordner konfiguriert" oder „noch kein Frame verfügbar") erscheint kurz in der Statusleiste **und** dauerhaft als `[UARTSCOPE] ...`-Zeile im Raw-View, direkt neben der eigentlichen `[SCREENSHOT]`-Zeile – so geht eine Fehlermeldung nie unbemerkt unter - `` kann die Endung weglassen (Standard: `.png`); eventuelle Pfadanteile in der Firmware-Angabe werden ignoriert – die Datei landet immer direkt im konfigurierten Ordner (kein Path-Traversal möglich) - Wird derselbe Dateiname mehrfach gesendet (z.B. immer `dump.png`), wird nichts überschrieben – UARTScope hängt automatisch `_1`, `_2`, … an - Die Zeile erscheint zusätzlich ganz normal im Tag-Monitor unter `[SCREENSHOT]` – inklusive „Verlauf"-Tab, der eine timestamped Liste aller Trigger-Ereignisse **und** deren Ergebnis zeigt: zuerst der angeforderte Dateiname, direkt danach das Resultat („Screenshot saved: /pfad/..." oder eine Fehlermeldung) – beides chronologisch im selben Panel - Funktioniert unabhängig vom Freeze-Status der Vorschau (wie der manuelle Screenshot-Button auch) **Falls kein Bild erscheint:** die häufigsten zwei Ursachen sind (1) der Screenshot-Ordner wurde noch nicht gesetzt, oder (2) die V4L2-Vorschau läuft nicht (▶ Start im Video-Widget noch nicht geklickt, es gibt also noch keinen Frame zum Speichern). In beiden Fällen steht die genaue Ursache als `[UARTSCOPE] ...`-Zeile im Raw-View. --- ## Berechtigungen ```bash # UART-Port sudo usermod -aG dialout $USER # HDMI-Grabber / V4L2 sudo usermod -aG video $USER # Einmal ausloggen / neu einloggen ``` Grabber testen: ```bash v4l2-ctl --list-devices # alle /dev/video* Geräte v4l2-ctl -d /dev/video0 --list-formats-ext # unterstützte Formate & Auflösungen ``` --- ## UART-Ausgabe formatieren Alles Folgende gilt unabhängig davon, ob die Verbindung über einen seriellen Port oder über TCP läuft (siehe Abschnitt „Verbindung: Seriell oder Netzwerk (TCP)" weiter oben) – UARTScope interpretiert den empfangenen Text in beiden Fällen identisch. ### Raw-View (immer aktiv) Jede Zeile erscheint im Raw-View mit Timestamp. Keine besondere Formatierung nötig. **Screen leeren** – von der Firmware aus Raw-View, Tabelle, Tag-Monitor und Video-Vorschau gleichzeitig leeren: ```c uart_printf("\033[2J\033[H"); ``` ### Tag-Monitor Zeilen mit `[TAGNAME]` werden im Tag-Monitor-Panel angezeigt **und** im Raw-View hervorgehoben (cyan), sofern der Tag nicht über den Tag-Filter ausgeblendet wurde. **Format:** `[TAGNAME] key1=value1 key2=value2 ...` - Tag-Name: Buchstaben, Ziffern, Underscore **und Bindestrich** – z.B. `WDG`, `VIDEO`, `KICKSTART`, `I2C-BUS` - Key=Value-Paare: Leerzeichen-getrennt, Werte ohne Leerzeichen - Ohne Key=Value-Paare wird der rohe String angezeigt Jedes Tag-Panel hat zwei Tabs: - **Aktuell** – der letzte empfangene Stand, aktualisiert sich in-place (wie bisher) - **Verlauf** – jeder je empfangene Wert dieses Tags, chronologisch mit Timestamp, mit eigenem „Verlauf leeren"-Button (löscht nur die Historie, das Panel bleibt bestehen) Der Copy-Button kopiert je nach aktivem Tab entweder den aktuellen Stand oder den kompletten Verlauf. **Listen-Werte:** Ein Wert mit `;`-getrennten Einträgen wird als mehrzeilige Liste unter dem Key dargestellt: ```c uart_printf("[KICKSTART] Devs=trackdisk.device;input.device\n"); ``` Im Tag-Monitor erscheint das als: ``` Devs trackdisk.device input.device ``` Jeder weitere Eintrag bekommt seine eigene Tabellenzeile, der Key wird nur einmal angezeigt. **Beispiele:** ```c uart_printf("[WDG] uptime=%lu free_heap=%lu temp=%d\n", HAL_GetTick(), xPortGetFreeHeapSize(), core_temp); uart_printf("[KICKSTART] Libs=graphics.library;intuition.library;dos.library\n"); uart_printf("[VIDEO] line=%d hblank=%d vblank=%d copper=%d\n", scanline, hblank_ticks, vblank_ticks, copper_dma); ``` Jeder einzigartige Tag bekommt automatisch ein eigenes Panel. Panels aktualisieren sich in-place – kein Scrollen nötig. Listen-Längen können sich von Update zu Update ändern, die Tabelle passt sich automatisch an. ### Tabellenansicht Optionale Header-Zeile mit `#`, dann CSV-Datenzeilen: ``` #time_ms,temperature,voltage,current 1000,23.5,3.30,0.42 2000,23.7,3.31,0.41 ``` Delimiter per Dropdown umschaltbar: `,` `;` `\t` `|` `Space` ### Suche im Raw-View Suchbegriff eingeben – der erste Treffer wird automatisch markiert. Weitere Treffer: - **▼** / `Enter` / `F3` → nächster Treffer - **▲** / `Shift+F3` → vorheriger Treffer - Ist kein weiterer Treffer in Suchrichtung vorhanden, springt die Suche automatisch an den Anfang (bzw. bei Rückwärtssuche ans Ende) und macht dort weiter (Wrap-Around) --- ## Tag-Filter Über „Tag filter…" in der Toolbar lassen sich Tags aus dem Raw-View ausblenden, sodass sie nur noch im Tag-Monitor erscheinen. Ein Tag pro Zeile, ohne Klammern (z.B. `WDG`). Groß-/Kleinschreibung spielt keine Rolle. Der Filter wird sofort beim Schließen des Dialogs gespeichert und beim nächsten Programmstart automatisch wiederhergestellt. --- ## Einstellungen Beim Beenden werden folgende Einstellungen automatisch gespeichert und beim nächsten Start wiederhergestellt: - Fenstergröße und -position - Splitter-Positionen (Haupt-Splitter und Tag/Video-Splitter) - Auto-Reconnect ein/aus und Intervall - Tag-Filter (ausgeblendete Tags) - Screenshot-Ordner für den `[SCREENSHOT]`-Steuertag Gespeichert unter `~/.config/ChicaDev/UARTScope.conf` (via `QSettings`). --- ## Projektstruktur ``` uartscope/ ├── CMakeLists.txt ├── README.md ├── resources.qrc ├── UartscopeLogo.png ├── uartscope.desktop.in ├── include/ │ ├── mainwindow.h ← Hauptfenster, koordiniert alle Komponenten, Screenshot-Ordner-Einstellung │ ├── serialworker.h ← Empfang im eigenen QThread (seriell ODER TCP), Auto-Reconnect, ANSI-Erkennung, [SCREENSHOT]-Steuertag │ ├── rawview.h ← Unbegrenzter Log mit Timestamps, Suche (Weiter/Zurück, Wrap-Around), Copy │ ├── tableview.h ← CSV-Parser → QTableWidget │ ├── tagwidget.h ← Container für Tag-Panels │ ├── tagpanel.h ← Ein Panel pro [TAG]: Aktuell-Tab + Verlauf-Tab, Listen-Support, Copy │ ├── connectdialog.h ← Seriell- und Netzwerk(TCP)-Konfiguration, PTY-Erkennung, Log-Datei │ ├── v4l2worker.h ← V4L2-Capture in std::thread, MJPEG/YUYV/NV12 │ └── videowidget.h ← Live-Vorschau, Freeze, Screenshot (manuell + automatisch via Tag), MP4-Aufzeichnung (ffmpeg) └── src/ ├── main.cpp ├── mainwindow.cpp ├── serialworker.cpp ├── rawview.cpp ├── tableview.cpp ├── tagwidget.cpp ├── tagpanel.cpp ├── connectdialog.cpp ├── v4l2worker.cpp └── videowidget.cpp ``` --- ## Erweiterungsideen - **Plot-Widget**: numerische Tag-Werte live als Graph darstellen (Qt Charts) - **UART senden**: TX-Eingabezeile für bidirektionale Kommunikation - **Hex-View**: rohe Bytes als Hex-Dump anzeigen - **Session-Replay**: gespeicherte Log-Dateien abspielen - **Regex-Filter**: Zeilen im Raw-View per regulärem Ausdruck ein-/ausblenden --- ## Changelog **1.2.0** - Automatischer Screenshot-Trigger via `[SCREENSHOT] dateiname`-Steuertag – speichert den Video-Frame exakt im Moment des Empfangs (z.B. für Memory-Dumps) - Neue Toolbar-Option „Screenshot folder…" zur Konfiguration des Zielordners - Format-Referenz-Dialog um Dokumentation des neuen Steuertags ergänzt - Erfolg/Fehler eines Screenshot-Triggers wird zusätzlich zur Statusleiste dauerhaft als Zeile im Raw-View **und** direkt im `[SCREENSHOT]`-Tag-Panel selbst (Aktuell + Verlauf) protokolliert **1.1.0** - Netzwerk-Input (TCP) als Alternative zum seriellen Port, inkl. Auto-Reconnect - PTY-Erkennung (`/dev/pts/`) im Seriell-Tab, z.B. für QEMU - Video-Aufzeichnung als MP4 (via `ffmpeg`) - Tag-Panels: zweiter „Verlauf"-Tab mit vollständiger, timestamped Historie - Suche im Raw-View: Weiter/Zurück-Navigation mit Wrap-Around - Tag-Namen mit Bindestrich werden jetzt korrekt erkannt und gefiltert - Bugfix: letzte Zeile ging bei einem ausbleibenden Folge-Byte-Strom manchmal verloren (Idle-Flush-Timer) **1.0.0** - Erste Veröffentlichung