# phasen-test — DCF77-PZF-Demodulation

Praktische Umsetzung der korrelativen Phasenauswertung (PZF) des DCF77-Signals,
dokumentiert auf der Homepage unter „Projekte → DCF77 → Stufe 4: PZF-Demodulation
in der Praxis".

## Dateien

- `phasentest.grc` / `dcf77_3.py` — Flowgraph: IQ-Aufnahme → Frequency Xlating
  FIR Filter (1000/400 Hz, Dezimation 2 → 6 kHz) → Feed Forward AGC → Costas
  Loop (Ordnung 2, `w=0.02`) → Complex To Imag (Phasenabweichung ohne
  atan2-Wickelpunkt) → Korrelation gegen die zeitgespiegelte 512-Chip-PZF-
  Referenz. Complex To Arg + Grad bleibt nur als Diagnoseanzeige erhalten.
  Zusätzlich ein Embedded-Python-Block (`epy_block_0`, Peak-Detektor mit
  Hysterese und Sperrzeit) hinter der normierten Korrelation, der pro
  erkanntem Peak eine PMT-Message (Wert + Sample-Index) auf Port `peak`
  sendet — verbunden mit einem `Message Debug`-Block zur Anzeige.
  Dimensionierung (an der Referenzaufnahme per Sweep ermittelt):
  `schwelle_hoch=0.026`, `schwelle_tief=0.016`, `sperrzeit_samples=5000`
  (0,83 s). Verifiziert: exakt 1 Message/Sekunde, Abstand 1,000 s ± 0,0001 s
  über 65 Zyklen (Batch) bzw. 0,999 s ± 0,01 s über 70 Zyklen (Echtzeitlauf
  über die kompilierte Klasse).
- `korrelation_check.py` — headless Verifikation derselben Kette (kein GUI,
  kein Throttle): Costas-Lock (Wraps/s auf geglätteter Phase), Korrelations-SNR,
  Sekundenraster-Prüfung inkl. Taktdrift-Schätzung, Einschwing-Sprung-Erkennung.
- `signalparameter.py` — erste Sichtung unbekannter WAV-Konserven.
- `SND.178.63.122.223_2026-07-25T11_29_19Z_77.50_iq.wav` — 75 s Web-Empfänger-
  Mitschnitt (77,5 kHz, 12 kHz Stereo-IQ), **aktuelle Referenzaufnahme**:
  SNR 6,8 σ, 15/15 Peaks auf dem 1-s-Raster, Taktdrift ≈ −400 ppm, kein
  Einschwing-Sprung, unempfindlich gegenüber center_frequency (−8…+8 Hz
  getestet).
- `SND.178.63.122.223_2026-07-25T11_25_13Z_77.50_iq.wav` — zweiter Mitschnitt
  desselben Empfängers, 4 Minuten früher.
- `SND.df0twn.dnsuser.de_2026-07-25T08_27_05Z_77.50_iq.wav` — ältere
  Testaufnahme, zeigte einen Einschwing-Sprung nach ~19–20 s (siehe
  Erkenntnis 5 unten); besteht die Prüfungen ab Sekunde 20 mit SNR 7,2 σ,
  15/15 Raster.
- `dcf77_2_iq.wav` — älteste Aufnahme, Trägerablage ≈ −5 Hz.

## Wichtigste Dimensionierungs-Erkenntnisse

1. BESTÄTIGT: PZF-Chiprate 77500/120 = 645,83 Chips/s (0,7927 s Sequenzdauer)
   deckt sich mit der offiziellen PTB-Quelle (Piester 2004, PTB-Mitteilungen
   114(4), S.345; https://www.ptb.de/cms/ptb/fachabteilungen/abt4/fb-44/
   ag-442/verbreitung-der-gesetzlichen-zeit/dcf77/phasenmodulation.html):
   512 Chips dauern dort laut Diagramm ≈793 ms, nicht die volle Sekunde -
   passend zur hier verwendeten Annahme. Phasenhub laut derselben Quelle:
   ±15,6° (nicht die frueher grob geschaetzten ±13°).
2. Das Vorfilter muss die Modulation durchlassen (Hauptkeule ±512-646 Hz,
   je nach Chipraten-Hypothese) — ein trägerschmales Filter verbessert den
   Costas-Lock und zerstört gleichzeitig die Korrelation.
3. Costas-Bandbreite: Messreihe 0.0005–0.1 zeigt einen breiten funktionierenden
   Bereich. Gewählt: `w = 0.02` (bester gemessener Wert an der aktuellen
   Referenzaufnahme, 6.8σ, 15/15 Raster).
4. Phasenextraktion: NICHT Complex To Arg (Grad) + DC Blocker verwenden - ein
   Costas Loop 2. Ordnung rastet mit 50% Wahrscheinlichkeit auf 180° statt 0°
   ein, dann liegt complex_to_arg auf der atan2-Wickelgrenze und ein
   nachfolgender linearer Filter (DC Blocker) erzeugt Klingelartefakte bis
   ±250°. Stattdessen Complex To Imag (Im(z) ~= theta[rad] fuer kleine Winkel)
   direkt in den Matched Filter - kein atan2, kein Wickelpunkt.
5. Manche Aufnahmen zeigen einen Einschwing-Sprung: Korrelation bleibt einige
   Sekunden nach Aufnahmestart auffällig schwach und springt dann abrupt auf
   volles Niveau - unabhängig von der Costas-Bandbreite, also kein Bug in der
   Kette, sondern vermutlich AGC-/Rauschsperren-Einschwingen des jeweiligen
   Web-Empfängers. `korrelation_check.py` erkennt und meldet das automatisch.
   Die aktuelle Referenzaufnahme zeigt diesen Effekt nicht.

## Ausführen

```bash
gnuradio-companion phasentest.grc
# oder headless:
python3 korrelation_check.py SND.178.63.122.223_2026-07-25T11_29_19Z_77.50_iq.wav
```
