Files
uartscope/README.md

316 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
- `<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
```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