GNU Radio Companion
Daten in GRC
Woher Daten im Flowgraph stammen, wie sie gepuffert werden und wie der Scheduler den Datenfluss steuert.
Gnu Radio Companion unterstützt unterschiedliche Datentypen, die je nach Verarbeitungszweck bereitgestellt werden.
Über den Source Block wird festgelegt, woher die Ausgangsdaten stammen sollen. Folgende Sources kommen dabei zum Einsatz:
- Selbst erzeugte Signalformen. Verschiedene Signalformen wie Sinus, Dreieck oder Rechteck Signale können in GRC selbst erzeugt werden. Diese Signale lassen sich mit anderen Signalen überlagern, um bestimmte Effekte zu erzeugen.
- Aufgezeichnete Signale. Es ist möglich, Signale aufzuzeichnen und als WAV-File abzuspeichern. Das ist insbesondere dann interessant, wenn man verschiedene Demodulationstechniken erlernen will, ohne über eigene Signalquellen zu verfügen. Im SigWiki ist eine Vielzahl von „Konserven" verfügbar, die so analysiert werden können.
- Signale empfangen. Für den Empfang eigener Signale werden verschiedene SDR-Hardwarekomponenten unterstützt.
Der Hardware Source Block gibt Daten normalerweise in Form von komplexen I/Q-Samples aus, wobei jedes Sample eine Kombination von In-Phase (I) und Quadrature (Q)-Komponenten ist. Die Daten werden mit einer eingestellten Abtastrate ausgegeben, die bestimmt, wie viele Samples pro Sekunde erfasst und verarbeitet werden.
Der WAV Block dagegen liefert Floating-Point-Werte. Bei einer Mono-Datei ist das ein einzelner Float-Stream. Eine verbreitete Praxis für IQ-Aufnahmen ist jedoch eine Stereo-WAV-Datei, bei der der linke Kanal die I-Komponente und der rechte Kanal die Q-Komponente trägt — der WAV-Source-Block liefert dann zwei getrennte Float-Streams, die erst über einen Float To Complex-Block zu einem komplexen IQ-Stream zusammengeführt werden müssen. Bei den internen Signalquellen kann der Typ der Ausgabewerte direkt eingestellt werden.
Datenfluss im Überblick
graph LR
subgraph Source["Quelle (z.B. SDR/WAV)"]
A[Hardware Source]
end
subgraph Buffer1["Buffer (Memory)"]
B1[Items I/Q]
end
subgraph Processing["Verarbeitungs-Block"]
P[work-Funktion]
end
subgraph Buffer2["Buffer (Memory)"]
B2[Verarbeitete Daten]
end
subgraph Sink["Ziel (z.B. Audio/Plot)"]
S[Sink Block]
end
A --> B1
B1 --> P
P --> B2
B2 --> S
style B1 fill:#f9f,stroke:#333,stroke-width:2px
style B2 fill:#f9f,stroke:#333,stroke-width:2px
Buffer
GNU Radio verwendet Buffer, um die Daten, die zwischen den Blöcken übertragen werden, zu speichern und weiterzugeben. Jedes Mal, wenn ein Block ein Signal verarbeitet, schreibt er das Ergebnis in einen Puffer, der dann von nachgeschalteten Blöcken gelesen wird.
Der Buffer dient als Zwischenspeicher für die Daten und ermöglicht es GNU Radio, asynchron zu arbeiten, wobei jeder Block so schnell arbeitet, wie er kann, unabhängig von den anderen.
Diese Pufferung ist auch notwendig, um Daten zwischen Blöcken mit unterschiedlicher Verarbeitungsgeschwindigkeit zu synchronisieren.
Die Größe der Puffer in GNU Radio ist variabel und wird vom System dynamisch verwaltet — sie richtet sich nach der Item-Größe und wird als Vielfaches der Betriebssystem-Page-Size angelegt, standardmäßig in einer Größenordnung von rund 32.768 Items.
work() wird vom Scheduler nicht aufgerufen), bis wieder Platz frei ist. Unverarbeitete Daten gehen dabei nie verloren — sonst würde jede Signalkette bei ungleich schnellen Blöcken stillschweigend Daten verlieren. Der Begriff „Ringpuffer" bezieht sich stattdessen auf einen Implementierungstrick: GNU Radio bildet denselben physischen Speicherbereich zweimal hintereinander im virtuellen Adressraum ab, sodass Lese-/Schreibzugriffe über die Pufferende hinaus ohne Sonderbehandlung als zusammenhängender Speicher erscheinen.Der zeitliche Ablauf dieser Backpressure sieht so aus, wenn ein konsumierender Block langsamer arbeitet als der produzierende:
sequenceDiagram
participant S as Scheduler
participant B1 as Produzierender Block
participant Buf as Buffer (Voll)
participant B2 as Konsumierender Block
Note over B2: Arbeitet langsam...
B2->>Buf: Liest Daten
Buf->>S: Pufferkapazität frei
S->>B1: Trigger work()
B1->>Buf: Schreibt neue Daten
Note over Buf: Buffer erreicht Limit
Buf-->>S: Signal: "Full"
S->>B1: Stoppe Ausführung (Backpressure)
Note over B1: Block pausiert
Scheduler
Der Scheduler in GNU Radio ist dafür verantwortlich, dass die Blöcke im Flowgraph in der richtigen Reihenfolge und mit der richtigen Geschwindigkeit arbeiten. Der Scheduler stellt sicher, dass:
- Blöcke Daten aus den Puffern lesen, sobald sie verfügbar sind.
- Blöcke nur dann schreiben, wenn der Puffer des nächsten Blocks bereit ist, neue Daten zu empfangen.
Der Scheduler verwaltet dabei die Kommunikation zwischen den Blöcken so, dass keine Daten verloren gehen und dass Blöcke mit unterschiedlichen Verarbeitungsanforderungen dennoch effizient miteinander arbeiten.