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 (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

# 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

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

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:

# 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)
  • 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]:

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
  • <dateiname> 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

# UART-Port
sudo usermod -aG dialout $USER

# HDMI-Grabber / V4L2
sudo usermod -aG video $USER

# Einmal ausloggen / neu einloggen

Grabber testen:

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:

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:

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:

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
Description
Tool zu debuggen von Baremetal Projekten auf dem Raspberry Pi mittels UART
Readme 2 MiB
Languages
C++ 81.6%
Shell 14.5%
Perl 2.9%
CMake 1%