⚠️ Disclaimer / HaftungsausschlussEN: SimpleFT8 is a private feasibility study and personal hobby project. Use at your own risk. No liability is accepted for damage to hardware (radio, PA, antennas), data loss, or regulatory violations. The software is provided "AS IS" without warranty of any kind — see LICENSE (MIT) for full terms.
DE: SimpleFT8 ist eine private Machbarkeitsstudie und ein persoenliches Hobby-Projekt. Nutzung auf eigene Gefahr. Es wird keine Haftung uebernommen fuer Schaeden an Hardware (Funkgeraet, PA, Antennen), Datenverlust oder regulatorische Verstoesse. Die Software wird "AS IS" ohne jegliche Garantie bereitgestellt — siehe LICENSE (MIT) fuer vollstaendige Bedingungen.
No more manual ALC babysitting, no missed replies, no guessing the best antenna or frequency. SimpleFT8 automates your entire FT8/FT4/FT2 workflow with closed-loop power control, dual-mode diversity scoring, automatic CQ frequency optimization, and intelligent caller queuing.
Every feature explained in detail: How does it work? Why? Pros/Cons? Physics + formulas. German + English → docs/explained/ (5 features × 2 languages = 10 documents) In-app help: Press ? in the status bar for built-in feature documentation with language switcher.
Optimize yes — Automate no. SimpleFT8 is an operator-in-the-loop tool. All automated features — dead man's switch (15 min), semi-automatic CQ mode, manual hunt mode — ensure the operator retains final control. This reflects our commitment to responsible amateur radio software and regulatory compliance.
map.mp4
Live globe visualization: 16-sector propagation wedges per decoded station, color-coded by antenna (ANT1 / ANT2 / rescue), with 60-minute history retention. Recorded during a 40m FT8 session. Live-Karte mit 16 Richtungs-Sektor-Wedges pro Decode, Antennen-Farbcodierung (ANT1 / ANT2 / Rescue), 60-Min-Historie. Aufgenommen waehrend einer 40m-FT8-Session.
SimpleFT8 was built for the after-work operator. No endless configuration, no manual antenna switching, no staring at ALC levels. It talks directly to the FlexRadio, automatically picks the better of two antennas, regulates TX power in a closed loop, and finds a clear CQ frequency on its own. Multiple callers are queued and answered in turn. There's a live map with a rotatable globe showing where you're being heard, and a locator cache that remembers stations across app restarts. Fire it up, make a few QSOs, call it a day.
How is this different? Focuses on live propagation visualization and locator mining without configuration overhead. Not a WSJT-X replacement — runs alongside it.
-
FT2 Mode — Native Decodium-compatible FT2 decoder/encoder (3.8s cycles, 4-GFSK, 288 sps). Community frequencies pre-configured. QSOs successfully completed. Automatic RX filter widening to 4000 Hz.
-
DT Time Correction v2 — Cumulative correction from band consensus. 2-cycle measurement, 10-cycle operation, 70% damping. Per-mode persistence: correction values stored in
~/.simpleft8/dt_corrections.json— instant good correction on mode switch. DT values typically ±0.1s after convergence. -
🆕 Adaptive Diversity (v0.97) — Adjusts antenna ratio slot-by-slot in real time using a rolling 5-slot buffer. No more hourly 90-second measurement pause — reacts to propagation changes within seconds. 8% median-difference threshold prevents flapping; live switching between 30:70, 50:50, 70:30. Toggle in Settings: "Adaptive Diversity (Test Phase)". Static fallback remains available. See docs/explained/diversity-modes.md for the full Before/After comparison.
-
Dual-Mode Diversity — Two scoring strategies selectable at startup:
- Standard: Counts total decoded stations — best for CQ operation (maximize QSOs)
- DX: Counts weak stations (SNR < -10 dB) — best for DX hunting (Australia at -24 dB counts, local at +12 dB doesn't)
- 8% threshold, median over 3 cycles per antenna (6-slot fair 3:3), 70:30 or 50:50 ratio. Button shows "DIVERSITY DX" when in DX mode.
- Antenna Memory (learning): Every decode cycle, the system records per callsign which antenna heard it better and by how many dB. When you start a QSO with that callsign, the best antenna is selected automatically — overlaying the global Diversity rhythm for the duration of the QSO. No timeout, no persistence: a station you can hear right now is always the most precise value. The QSO panel shows "Calling DL3AQJ (ANT2, +6.3 dB)". → see Smart Antenna Selection for screenshot and details.
-
Bandpilot (v0.88) — On band change SimpleFT8 looks up the current UTC hour and compares the three RX modes (Normal / Diversity Standard / Diversity DX) directly — no aggregation. Three behaviour modes in settings: Off / Auto (3-second toast + auto-switch with 5% tolerance) / Manual (dialog appears only when a different mode wins). TX-protected: switch waits for
tx_finished. Hourly thresholds: ≥3 days + ≥20 slots per mode.⚠️ In field test.v0.87 → v0.88 Update: The Bandpilot now uses hourly direct values instead of a global aggregate
(S+D)/2. Existing settings migrate automatically (bandpilot_enabled=true→mode="auto"). -
Live Locator Mining (integrated, no external tool required) — While decoding, SimpleFT8 extracts Maidenhead grid squares directly from CQ calls and grid-reply messages (
CQ R9CA LO97,RA4ALY DL6YJB JO31) and writes them to a persistent JSON database (~/.simpleft8/locator_cache.json). Source priority:cq_6 > psk_6 > qso_log_6 > _4-Variants— a 6-digit locator from a live CQ call is never overwritten by a 4-digit ADIF entry. The map shows exact station positions, not country centroids. Bootstrap via ADIF bulk-import (LotW, QRZ, your own log) at startup. Auto-save every 5 min + on close — survives hard kill. Currently 9,366 calls and growing with every session. (External tools like GridTracker do similar mining from WSJT-X — this implementation just keeps it inside SimpleFT8 itself.) -
Auto TX Power Regulation — Set target wattage, SimpleFT8 reads actual FWDPWR and adjusts proportionally. No overdrive, no weak signals after band change.
-
Smart CQ Frequency — After diversity calibration, finds a free slot in the 800–2000 Hz sweet spot (where most stations listen) instead of the empty upper range.
-
Caller Waitlist — When multiple stations reply to CQ simultaneously, they are queued. Accepts both Grid and Report messages. After current QSO: auto-responds to next in queue.
-
RR73 Courtesy Repeat — After QSO complete, if the other station keeps sending R-Report (didn't receive our RR73), we resend RR73 automatically (max 2×).
-
Even/Odd Slot Display — [E]/[O] tags in both RX list and QSO panel. Immediately visible which slot each station uses and which slot we transmit in.
While Diversity decides the global ANT1/ANT2 RX rhythm (70:30, 50:50 or 30:70), Smart Antenna Selection is the second, finer layer: for every station the app learns — slot by slot — which antenna heard it better and by how many dB, with a 1 dB hysteresis to prevent ping-pong on marginal signals.
-
① RX panel
Antcolumn — shows the live preference per callsign:A1means ANT1 is the only one hearing the station,A2>1means ANT2 wins over ANT1 (and by how many dB),A1>2the reverse. In one screenshot you can see a mixed pattern — proof the app does not just sit on a fixed ratio but evaluates every station individually. -
② RX uses the better antenna actively per station — when you start a QSO, the receive path switches to whichever antenna heard that callsign best (here:
(ANT2 ↑2.0 dB)for IK4LZH) so the remote station is heard optimally throughout the entire QSO. TX always goes through ANT1 — the only transmit-rated antenna in the SimpleFT8 setup. ANT2 (gutter antenna) is receive-only and would risk hardware damage at 100 W TX. On rigs with two transmit-capable antennas this could be configured differently, but SimpleFT8 hardcodes TX = ANT1.
The memory has no timeout and no persistence — a station you can hear right now is always the most precise value. Combining Diversity reception with per-callsign antenna decisions inside one QSO is a detail most Diversity implementations don't offer — I haven't seen it in WSJT-X, JTDX or MSHV, but I can't guarantee no fork does it.
Auto-Hunt after two QSOs (G8KHF, HA1BF). HA1BF was received on ANT2 with +1.0 dB advantage (per-callsign antenna preference). Timer shows 6:55 min remaining. Bottom: clear CQ frequency indicator, dynamic diversity 50:50 active.
Both buttons live inside the Diversity Mode — they are hidden in Normal mode and appear automatically when Diversity is enabled.
OMNI-CQ runs a single-slot CQ that auto-rotates between Even and Odd parity every ~5 minutes (mode-dependent counter: FT8=10, FT4=20, FT2=40 attempts). The transmit duty cycle is the same as a normal CQ on one parity — OMNI just saves the manual Even/Odd switch click. For the same effect you can press the Even/Odd button yourself. The OMNI button is permanently visible when Diversity is active — no Easter egg anymore (was hidden until v0.97.29). All TX goes over ANT1, RX uses the global Diversity and per-callsign antenna preference. Known limitations: TX frequency is picked once at the first transmit of each parity block (no continuous gap re-evaluation within a block — see CQ-frequency feature for the dynamic search that runs only at block boundaries). The counter resets when an incoming QSO is received, so on a popular call sign the same parity slot can keep being extended. Tested on one station (DA1MHH) since 11.05.2026 — not independently field-validated.
Auto-Hunt picks the next CQ station from the RX list and initiates the QSO automatically — no manual click. Visible only in Diversity mode.
- Selection priority: new DXCC > rare callsign > good SNR (> −15 dB)
first reception today. Within the same score group, choice is random.
- Auto-stop after 10 minutes from activation, independent of mouse/ keyboard activity. After that, Auto-Hunt stops and requires a deliberate restart click. At most 3 QSO attempts per station.
- Hardware: RX uses per-callsign antenna preference (the better RX antenna). TX is always on ANT1, the only transmit-rated antenna. Band or mode changes immediately stop Auto-Hunt.
⚠️ Operator responsibility — read before use: SimpleFT8 is a private feasibility study by a single operator (DA1MHH), not a contest tool and not a remote-control product. Auto-Hunt initiates QSOs without a per-station click. The 10-minute auto-stop is a self-imposed limit — German amateur radio law (§ 13 AFuV) regulates remote-controlled or automatic stations separately and requires the operator to be able to switch off the station at any time. Use only while you are actively watching the station. WSJT-X and JTDX deliberately stop their automation short of picking the next station from the RX list — Auto-Hunt crosses that line on purpose. You take the responsibility for compliance with your own country's regulations.
Generated automatically from live session data via
scripts/generate_plots.py. X-axis = UTC hour of day, averaged across all measurement days. Data grows with every session.
40m FT8 — 8–9 measurement days, 27,200 cycles (ANT1 = trap dipole running off-band over tuner):
| Mode | Stations/15s (Pooled Mean) | vs Normal | Days | Cycles |
|---|---|---|---|---|
| Normal | 18.7 | — | 8 | 7,743 |
| Diversity Standard | 42.2 | +126% (off-band, suboptimal ANT1) | 9 | 10,172 |
| Diversity DX | 41.6 | +123% (off-band, suboptimal ANT1) | 6 | 9,285 |
Pooled mean over all cycles and all hours of all measurement days. No time-of-day filter — see methodology caveats below. The headline gain comes mostly from compensating a weak primary antenna, not from a generic diversity advantage — see 20m comparison for the resonant case. Rescue stations (ANT1 below −24 dB, saved by ANT2) are included in the Diversity totals. Detailed breakdown: PDF report (p.3).
Methodology caveats (honest)
- Pooled-mean across all cycles without confidence intervals, p-values or stratification for solar flux / weather / hour-of-day. 27,200 cycles sounds large but the data is time-autocorrelated within sessions — the effective sample size is much smaller.
- Measurement-day counts differ between modes (Normal=8, Standard=9, DX=6). Days are not randomized — they reflect whenever each mode happened to run. Selection bias is possible.
- Raw data is in
statistics/(one Markdown file per hour per mode) for anyone who wants to run a proper t-test, bootstrap CI, or solar-index normalization. I haven't done that work myself.- The PDF report (p.3) shows hourly breakdowns which are more honest than the single pooled headline number.
Take the percentage as rough order of magnitude, not as a clinical- trial result.
Note on Interpretation ANT1 (Kelemen DP-201510) is operated off-band on 40m and therefore significantly less efficient on this band. ANT2 (house gutter, ~15m) falls between λ/4 and λ/2 for 40m and works comparatively well. The measured gains (+126%/+123% stations) represent an upper bound for off-band operation — with two well-matched 40m-optimized antennas, a lower but still significant diversity gain is expected. The exact opposite happens when ANT1 is on its resonant band — see the 20m results below.
Station timeline — 40m FT8, all three modes over 24h UTC: (Dashed lines = Rescue Stations: received by ANT1 below −24 dB — ANT2 boosts the signal above the decoding threshold)
Direct mode comparison — stations per cycle, per hour:
| Diagram | Description |
|---|---|
| 📊 Diagram 1 — Stations 40m FT8 | Station count over 24h UTC — Normal vs Diversity Normal vs Diversity DX. Line = mean, dashed = + Rescue Stations (ANT1 below −24 dB, saved by ANT2). |
| 📊 Diagram 2 — Diversity Analysis 40m FT8 | Station count per cycle: Normal (grey), Diversity Standard (blue), Diversity DX (orange) + green rescue caps (+N) = stations ANT1 couldn't decode but ANT2 saved. |
| 📊 Detailed PDF Report | Full analysis report with summary table, all diagrams, and methodology notes. Auto-updated with each session. |
| 🗂 Raw Data (statistics/) | All raw cycle data as Markdown files — one file per hour per mode. Format: statistics/<Mode>/<Band>/<Protocol>/YYYY-MM-DD_HH.md. 214 files, every single cycle logged. Reproduce any number yourself. |
📊 Statistics in progress — target: 5 measurement days per mode/band slot for reliable results. Current: 4–5 days. Charts and PDF update automatically with each new session. The more days, the more stable the lines.
Live measurement results — 20m FT8, 7–9 measurement days, 19,936 cycles:
| Mode | Stations/15s (Pooled Mean) | vs Normal | Days | Cycles |
|---|---|---|---|---|
| Normal | 51.1 | — | 9 | 5,959 |
| Diversity Standard | 47.9 | −6% | 7 | 6,290 |
| Diversity DX | 47.1 | −8% | 7 | 7,687 |
Note: Earlier readings (fewer days) showed −18%/−22%. With more measurement days now covering all times of day, the numbers have stabilized at a smaller loss. Still negative — the resonant ANT1 advantage on 20m is real — but the picture is more nuanced.
Note on Interpretation — 20m On 20m, the Kelemen DP-201510 operates within its design band as a resonant half-wave dipole. ANT1 alone is already very efficient — Diversity overlays this good antenna with a non-optimized gutter (ANT2). The result is a slight loss in raw station count.
But the picture is more nuanced: in direct A1↔A2 comparisons the ANT2 wins in 79–86 % of cases with an average +4 dB advantage on individual signals — pattern and polarization diversity from the very different geometry of the two antennas. (Faraday rotation alone doesn't explain this — on HF it's mostly multi-path propagation modes, building coupling and pattern differences.) The resonant ANT1 still wins on raw station count because Diversity's time-sharing costs it some single-antenna decodes; the benefit on 20m is qualitative (different stations, especially weak DX) rather than quantitative.
The honest takeaway: Diversity is asymmetric with this antenna setup. On off-band-ANT1 bands (40m, 30m, 17m, 80m) it compensates the weak ANT1 → large station gain. On resonant-ANT1 bands (20m, 15m, 10m) it overlays an already strong ANT1 → small station loss but qualitative pol-diversity gain.
Station timeline — 20m FT8, all three modes over 24h UTC:
Direct mode comparison — stations per cycle, per hour:
| Diagram | Description |
|---|---|
| 📊 Detailed PDF Report — 20m | Full 20m analysis with the differential narrative — ANT2 win-rate, Faraday rotation theory, asymmetric advantage. |
| 🗂 Raw Data (statistics/) | All raw cycle data per mode/band/hour — reproduce any number yourself. |
Live measurement results — 30m FT8, preliminary data:
| Mode | Stations/15s (Pooled Mean) | vs Normal | Days | Cycles |
|---|---|---|---|---|
| Normal | 15.0 | — | 3 | 452 |
| Diversity Standard | 25.3 | +69% | 3 | 1,386 |
| Diversity DX | 23.9 | +59% (preliminary) | 1 | 214 |
Note: 30m data collection just started. Normal and Diversity Standard have 3 days each — already showing the expected off-band pattern (large gain, ANT1 suboptimal on 10 MHz). Diversity DX has only 1 day — not yet reliable. Data growing with each session.
If your station has one resonant antenna covering 1–2 bands plus everything else via tuner — exactly the situation Mike has on 40m — Diversity is likely to bring a substantial gain on the tuner-fed bands and a slight loss on your resonant bands. The 40m measurement is the "tuner-fed" archetype, the 20m measurement is the "resonant" archetype.
- 30m (off-band ANT1, data collection started — 3 days Normal/Standard, 1 day DX): confirmed gain pattern, see above
- 17m (off-band ANT1): data collection in progress, expected gain like 40m
- 15m / 10m (resonant): expected to lose like 20m
- 80m / 60m / 12m: pending
Each new band confirms or refutes the off-band/resonant hypothesis. All raw
data lives in statistics/, all PDFs auto-update with python3 scripts/generate_plots.py.
A common misconception among ham operators: "If my antenna transmits, it must receive equally well." Physically the antenna is reciprocal — losses are identical on transmit and receive. But in practice the picture is asymmetric, because two separate effects combine.
The path budget — your power minus path loss minus antenna losses — leaves very different reserves on each side:
- TX side has roughly 40–50 dB of headroom over the FT8 decode threshold. 100 W of transmit power into a tuner-matched non-resonant antenna delivers about +50 dBm at the feedpoint. Even with 5–10 dB tuner/mismatch loss, a distant station typically receives your signal 30–40 dB above the noise floor — well over the FT8 decode threshold (−24 dB SNR in 2500 Hz bandwidth).
- RX side has only 0–15 dB of headroom for weak DX. Receive signal strength is fixed by path loss and the DX station's power. A weak DX from 8000 km with 10 W can arrive at your antenna at −115 dBm. With 7 dB tuner loss it drops to −122 dBm — right at or below the decode threshold. Same loss, but on the RX side there is no reserve.
So with a non-resonant antenna on a tuner, transmit still works fine, but weak stations on receive simply disappear under the threshold.
The bigger reason two antennas beat one is physical diversity:
- Mike's ANT1 (Kelemen DP-201510) is a horizontal half-wave dipole.
- Mike's ANT2 (house gutter, L-shape ~15 m) acts partly as a vertical radiator.
- HF skywave propagation arrives in mixed polarization states through multi-path modes and ionospheric mode mixing. Stations whose signal arrives predominantly vertical are weakly heard by ANT1 (horizontal) but well by ANT2 — and vice versa. (Faraday rotation contributes here, but the dominant mechanism on HF is multi-path and mode-mixing, not pure Faraday rotation — that scales with 1/f² and is more relevant on VHF/UHF and SatComm.)
- The two antennas also have different azimuth patterns — directions ANT1 nulls out are covered by ANT2.
This is why the off-band diversity gain is large (see measurement section for current numbers): not just because the tuner loss is bypassed, but because ANT2 picks up entire signal paths ANT1 never sees.
FT8/FT4/FT2 have a hard mathematical decode threshold. Costas synchronization needs a defined minimum correlation, and the LDPC error correction has a sharp bit-error-rate cliff. A trained ear can still pick fragments of a −5 dB SNR SSB signal out of the noise; the FT8 decoder cannot.
Concretely: on FT8, every dB of receive sensitivity directly translates to more decoded stations. On SSB or CW, transmit power and antenna gain matter more for being heard — the human operator handles the rest.
Most hams have a resonant antenna for one or two favorite bands plus a tuner for everything else. The diversity benefit on tuner-fed bands is substantial:
| Band | ANT1 status | Diversity Standard vs Normal (see measurement section for current numbers) |
|---|---|---|
| 40m | off-band (tuner) | large gain (currently around +120%, off-band asymmetry) |
| 20m | resonant (design band) | ~ −6 % raw count (ANT1 alone already gets most stations) — but ANT2 wins 79–86 % of direct dual-receives → qualitative polarization gain |
| 30m, 17m, 12m | off-band (data growing) | expected sizable gain (off-band similar to 40m) |
With 70–100 W, the transmit side is rarely the bottleneck. The receive side is. Diversity directly attacks that bottleneck — and the two-antenna effect (polarization + pattern) compounds the tuner-loss recovery.
Note on terminology dBm = power level relative to 1 milliwatt (0 dBm = 1 mW). SNR = signal-to-noise ratio. Link budget = balance of all gains and losses from transmitter PA output to receiver decode threshold.
ANT1 — Kelemen DP-201510 (multiband trap dipole for 20m / 15m / 10m) A center-fed multiband dipole with coaxial trap resonators (Sperrkreise) — not a fan dipole. Each band uses only the wire section up to the corresponding trap, all three bands resonant on 50 Ω directly via a 1:1 balun (no tuner needed). Feed point at the dormer window, 3rd floor: one arm runs diagonally up to the roof ridge, the other diagonally down via the porch roof to the balcony — a vertically-oriented half-wave dipole with the feed point at the center. On 40m this antenna operates off its design band — see interpretation note above.
ANT2 — House gutter (random wire antenna, ~15m) Never installed as an antenna — just clamped on. The gutter runs ~5m horizontal along the roof edge, ~8m vertical as the downspout, ~2m horizontal toward the front entrance. This L-shape falls between λ/4 and λ/2 for 40m (7 MHz). Different geometry, different polarization, building-coupled mounting — the ideal complement for diversity reception.
CQ mode with DT correction, Propagation bars, Operator Presence timer, PSKReporter spots — DT values ±0.2 (auto-corrected), 20m band:
| Diversity 20m (DT-corrected, A1/A2) | Comparison Test 40m (+37%) |
|---|---|
![]() |
![]() |
Caller Waitlist in action — F1IQH calls while QSO with DL3AQJ is in progress → automatically queued → served next. Real QSO, 40m FT8. (Screenshot courtesy of DL3AQJ — thank you!)
Tested & Working (v0.97.2):
- ✅ FT8 / FT4 / FT2 modes — all three with dedicated frequencies, auto RX filter, mode-dependent timing
- ✅ Auto TX Power Regulation: Closed-loop FWDPWR feedback, clipping protection, per-band calibration
- ✅ Dual-Mode Diversity: Standard (station count) + DX (weak signal count), 8% threshold, 70:30/50:50
- ✅ Smart Antenna Selection: Per-station antenna preference during QSO — switches to best-SNR antenna per callsign.
- ✅ DT Time Correction v2: Per-mode persistence, 2-cycle measurement, 70% damping, ±0.1s convergence
- ✅ Propagation Bars: HamQSL solar data + time-of-day correction. Verified against HAM-Toolbox
- ✅ Operator Presence (Anti-Bot): 15 min timeout, mouse reset, legal requirement DE
- ✅ Smart CQ Frequency: 800–2000 Hz sweet spot via spectrum histogram. Freq counter in status bar.
- ✅ Caller Waitlist: Queue for Grid + Report callers, auto-respond after QSO
- ✅ RR73 Courtesy Repeat: Auto-resend max 2× if other station didn't get it
- ✅ Even/Odd Slot Display: [E]/[O] in RX list + QSO panel (FT2 3.75s display sync under investigation)
- ✅ Signal Processing: 5-pass signal subtraction, spectral whitening, sinc anti-alias resampling
- ✅ QSO State Machine: Hunt + CQ mode, retry logic, ADIF 3.1.7 logging
- ✅ Integrated Logbook: Search, DXCC counter, QSO detail overlay, delete
- ✅ Help Dialog: Built-in feature docs (DE + EN) via ? button in status bar
- ✅ Direction Map with Live Propagation Sectors (v0.66/v0.71/v0.72): Rotatable 3D globe (orthographic projection) with 16 directional sector wedges that visualize where propagation is actually opening right now: in RX-mode wedge length = unique stations heard from that bearing, in TX-mode wedge length = max distance reached in that direction (v0.71 — a single VK6 spot at 16,000 km counts more than 50 Iberian spots). Antenna color-coding (ANT1/ANT2/rescue) makes diversity contributions instantly visible. One look at the map tells you "no vector pointing west today — don't bother trying NA on this band right now" — operational insight, not just decoration. Aurora + Dark theme toggle (v0.72), persistent.
- ✅ Live Locator Mining (v0.67/v0.70 — integrated): While decoding, Maidenhead locators are extracted directly from CQ calls and QSO replies (
CQ R9CA LO97,RA4ALY DL6YJB JO31) and written to a persistent JSON database (~/.simpleft8/locator_cache.json). Source priority:cq_6 > psk_6 > qso_log_6 > _4-variants— a 6-digit locator from a live CQ call is never overwritten by a 4-digit ADIF entry. The map therefore shows exact station positions instead of country centroids. Bootstrap via ADIF bulk-import (LotW, QRZ, your own log) at startup. Auto-save every 5 min + on close — survives hard kill. Currently 9,366 calls, growing with every session. (External tools like GridTracker do similar mining from WSJT-X — this implementation just keeps it inside SimpleFT8 itself.) - ✅ Automated regression suite: QSO state transitions, diversity merge logic, protocol message encoding/decoding, DT correction, OMNI-CQ counters, Bandpilot recommendations, locator DB priority, settings migration, and dialog/UI interactions. Mock-based for radio-hardware independence — field-hardening relies on real QSO sessions and band measurements (see statistics section). Unit tests cover internal logic; some serious bugs (e.g. SIGBUS in v0.97.38, OMNI-CQ phase bug in v0.97.22) only showed up in live field tests and were hotfixed there.
- ✅ Station Statistics: Per-cycle logging (Normal + Diversity), 6-cycle warm-up exclusion. Raw Markdown data, no in-file summaries — analyzed by
scripts/generate_plots.py. - ✅ Diversity Analysis Plots:
python3 scripts/generate_plots.py→auswertung/— dark-theme PNGs: station timeline (Normal vs Diversity) + ANT2 wins + Rescue-Events per hour. → Aktuelle Auswertungen - ✅ Per-Station SNR Logging: Every A1↔A2 comparison logged with both SNR values, Δ dB, winner and ★ Saved-Event when one antenna is below FT8 decode threshold (−24 dB) and the other above. Proves "ANT2 made this QSO possible."
- ✅ Ant2 Superiority Counter: Quantifies diversity gain (A2 > A1 frequency)
- ✅ TX Safety: TX halted immediately before Gain Measurement — no accidental transmit during calibration
- ✅ Gain Measurement: Audio input calibration tool (GAIN-MESSUNG button). Finds optimal RX level before statistics or diversity sessions.
- ✅ Auto-Hunt (v0.75): Automatically selects the next CQ station from the waitlist and initiates QSO without manual clicking. Independent dead man's switch (not mouse-triggered — bot protection). Diversity-only mode: visible only when Diversity is active, stops automatically on mode switch.
- ✅ Auto-Close Calibration Dialog (v0.83): After gain measurement completes, the confirmation dialog closes automatically after 3 seconds — no click required.
- ✅ Double-Report Bug Fix (v0.82): Fixed: app used to resend the signal report after already receiving RR73. Root cause was decoder signal ordering (
cycle_finishedmust fire after allmessage_decodedevents). Fully resolved and confirmed in real QSO. - ✅ Diversity Tertile Analysis (v0.84): Statistics plots show 33rd/67th percentile shaded band (actual slot-to-slot variation) instead of flat min/max bars.
- ✅ UI Polish: Info dialogs with "Don't show again" option. DT correction preserved across mode switches. Button labels reflect active state.
- ✅ Debug Console: Ctrl+D, live filter, font 11pt, Copy/Clear buttons
In Field Test:
⚠️ AP-Lite v2.2: Weak QSO rescue via coherent addition of two failed decode attempts. Threshold 0.75 calibration in progress.- ✅ OMNI-CQ (v0.96.4 + v0.96.7 + v0.97.30): Single-slot CQ with automatic parity switching (mode-dependent down-counter, FT8=10/FT4=20/FT2=40 attempts ≈ 5 min wallclock per parity). Diversity-only — button is permanently visible when Diversity is active (no more Easter egg since v0.97.30, P55). Field-validated 11.05.2026. → see Diversity Active Features above.
⚠️ Bandpilot (v0.88): Hourly RX-mode recommendation per band — three direct values, no aggregation. 31 unit tests passing, live validation over extended operating time pending.
| Band | FT8 | FT4 | FT2 |
|---|---|---|---|
| 80m | 3.573 | 3.575 | 3.578 |
| 40m | 7.074 | 7.047 | 7.052 |
| 20m | 14.074 | 14.080 | 14.084 |
| 15m | 21.074 | 21.140 | 21.144 |
| 10m | 28.074 | 28.180 | 28.184 |
git clone https://github.com/mikewanne/SimpleFT8.git
cd SimpleFT8
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python3 main.pyRequirements: macOS, Python 3.12+, FlexRadio SDR (FLEX-6000/8000 series). Two antenna ports for Diversity mode (optional).
SimpleFT8/
├── main.py # Entry point
├── config/settings.py # Settings, band frequencies, language
├── core/
│ ├── decoder.py # FT8/FT4/FT2 decode + signal subtraction
│ ├── encoder.py # FT8/FT4/FT2 encode → VITA-49 TX
│ ├── qso_state.py # QSO state machine (Hunt + CQ + Waitlist)
│ ├── protocol.py # FT8/FT4/FT2 protocol constants (frozen dataclass)
│ ├── station_accumulator.py # Shared station logic (Normal + Diversity)
│ ├── station_stats.py # Async cycle + per-station SNR logging
│ ├── diversity.py # Diversity controller (Standard/DX scoring)
│ ├── diversity_merger.py # Merge ANT1+ANT2 decodes, SNR-winner selection
│ ├── diversity_cache.py # 2h preset cache (skip re-calibration)
│ ├── locator_db.py # Persistent Maidenhead locator cache (JSON)
│ ├── antenna_pref.py # Per-callsign antenna preference (1 dB hysteresis)
│ ├── ntp_time.py # DT correction v2 (per-mode persistence)
│ ├── propagation.py # Band conditions (HamQSL + time correction)
│ ├── ap_lite.py # AP-Lite v2.2 (field test)
│ └── timing.py # UTC clock, mode-dependent cycle timing
├── radio/
│ ├── base_radio.py # RadioInterface ABC
│ ├── radio_factory.py # create_radio(settings) → FlexRadio
│ └── flexradio.py # SmartSDR TCP + VITA-49 + auto RX filter
├── ft8_lib/ # C library (MIT, FT8+FT4+FT2 native)
├── log/ # ADIF writer, QRZ.com API
├── ui/
│ ├── main_window.py # 3-panel layout + Mixins
│ ├── mw_cycle.py # Cycle processing + diversity accumulation
│ ├── mw_qso.py # QSO callbacks, CQ, logbook
│ ├── mw_radio.py # Radio, band, diversity, DX tuning
│ ├── help_dialog.py # Feature docs viewer (DE/EN)
│ └── ... # Control panel, RX panel, QSO panel
├── docs/explained/ # 10 feature docs (5 × DE + EN)
├── scripts/generate_plots.py # Auswertungs-Script: statistics/ → auswertung/ PNGs
├── auswertung/ # Generierte Diagramme (stationen_*.png, diversity_*.png)
└── tests/ # Automated regression suite (QSO, Diversity, Protocol, AP-Lite, Threading, ...)
Tested: FLEX-8400M. Expected compatible: FLEX-6300/6400/6500/6600/6700/8400/8600 series.
Radio-agnostic architecture (v0.28+): New radios can be added by implementing a single file (radio/ic7300.py etc.). Currently prepared: ICOM IC-7300 (CI-V + USB Audio).
MIT License (c) 2026 DA1MHH (Mike Hammerer)
SimpleFT8 ist für den Feierabend-Funk entstanden. Kein stundenlanges Konfigurieren, kein manuelles Antennen-Rangieren, kein Dauer-Blick auf den ALC-Pegel. Die Software spricht direkt mit dem FlexRadio, wählt automatisch die bessere von zwei Antennen aus, regelt die Sendeleistung im geschlossenen Regelkreis und sucht sich selbstständig eine freie CQ-Frequenz. Mehrere Anrufer landen in einer Warteschlange und werden nacheinander bedient. Dazu gibt's eine Live-Karte mit drehbarem Globus, die zeigt, wo man gehört wird — und ein Locator-Cache, der Stationen auch nach einem Neustart nicht vergisst. Einfach anschalten, ein paar QSOs machen, Feierabend.
Was ist anders? Fokus auf Live-Propagations-Visualisierung und Locator-Mining ohne Konfigurations-Overhead. Kein WSJT-X-Ersatz — laeuft daneben.
Automatisch generiert aus Live-Sitzungsdaten via
scripts/generate_plots.py. X-Achse = UTC-Stunde des Tages, gemittelt über alle Messtage. Daten wachsen mit jeder Session.
40m FT8 — 8–9 Messtage, 27.200 Zyklen (ANT1 = Trap-Dipol off-band über Tuner):
| Modus | Stationen/15s (Pooled Mean) | vs Normal | Tage | Zyklen |
|---|---|---|---|---|
| Normal | 18,7 | — | 8 | 7.743 |
| Diversity Standard | 42,2 | +126% (off-band, suboptimale ANT1) | 9 | 10.172 |
| Diversity DX | 41,6 | +123% (off-band, suboptimale ANT1) | 6 | 9.285 |
Pooled Mean über alle Zyklen und alle Tageszeiten aller Messtage — siehe Methodik-Caveats unten. Der Headline-Gewinn entsteht primär durch Kompensation einer schwachen Hauptantenne, nicht durch einen generischen Diversity-Vorteil — siehe 20m-Vergleich für den resonanten Fall. Rescue-Stationen (ANT1 unter −24 dB, von ANT2 gerettet) sind in den Diversity-Werten enthalten. Detaillierte Aufschlüsselung: PDF-Bericht (S.3).
Methodik-Caveats (ehrlich)
- Pooled-Mean über alle Zyklen ohne Konfidenzintervalle, p-Werte oder Stratifizierung für Solarflux / Wetter / Tageszeit. 27.200 Zyklen klingt gross, aber die Daten sind zeitlich autokorreliert innerhalb von Sessions — die effektive Stichprobengrösse ist deutlich kleiner.
- Anzahl Messtage unterscheidet sich zwischen Modi (Normal=8, Std=9, DX=6). Tage sind nicht randomisiert — sie spiegeln wann welcher Modus lief. Auswahl-Bias möglich.
- Rohdaten in
statistics/(eine Markdown-Datei pro Stunde pro Modus) für jeden der einen sauberen t-Test, Bootstrap-CI oder Solar-Index- Normalisierung machen will. Ich habe das selbst nicht gemacht.- PDF-Bericht (S.3) zeigt stündliche Aufschlüsselungen — ehrlicher als die eine Pooled-Headline-Zahl.
Die Prozentangabe ist als grobe Grössenordnung zu lesen, nicht als klinisches Studienergebnis.
Hinweis zur Interpretation ANT1 (Kelemen DP-201510) ist auf 40m außerhalb seines Auslegungsbandes und damit deutlich suboptimal für diesen Frequenzbereich. ANT2 (Regenrinne, ~15m) liegt zwischen λ/4 und λ/2 für 40m und arbeitet dort vergleichsweise gut. Die gemessenen Gewinne (+126%/+123% Stationen) sind als Obergrenze für Off-Band-Betrieb zu verstehen — bei zwei gleichwertigen, für 40m optimierten Antennen ist ein geringerer, aber dennoch signifikanter Diversity-Gewinn zu erwarten. Auf einem resonanten Band kehrt sich das Bild um — siehe 20m-Ergebnisse weiter unten.
Stationen über 24h UTC — 40m FT8, alle drei Modi: (Gestrichelte Linien = Rescue Stationen: von ANT1 unter −24 dB empfangen — ANT2 hebt das Signal über die Dekodiergrenze)
Direktvergleich — Stationen pro Zyklus, stündlich:
| Diagramm | Beschreibung |
|---|---|
| 📊 Diagramm 1 — Stationen 40m FT8 | Stationszahl über 24h UTC — Normal vs Diversity Normal vs Diversity DX. Linie = Mittelwert, gestrichelt = + Rescue Stationen (ANT1 unter −24 dB, von ANT2 gerettet). |
| 📊 Diagramm 2 — Diversity Analyse 40m FT8 | Stationen/Zyklus: Normal (grau), Diversity Standard (blau), Diversity DX (orange) + grüne Rescue-Kappen (+N) = Stationen die ANT1 nicht decodieren konnte, aber ANT2 rettete. |
| 📊 Ausführlicher PDF-Bericht | Vollständiger Auswertungsbericht mit Zusammenfassungstabelle, allen Diagrammen und Methodik-Hinweisen. Wird automatisch mit jeder Session aktualisiert. |
| 🗂 Rohdaten (statistics/) | Alle Rohdaten als Markdown-Dateien — eine Datei pro Stunde pro Modus. Format: statistics/<Modus>/<Band>/<Protokoll>/YYYY-MM-DD_HH.md. 214 Dateien, jeder einzelne Zyklus geloggt. Jede Zahl ist nachrechenbar. |
📊 Statistiken in Arbeit — Ziel: 5 Messtage pro Modus/Band-Slot für belastbare Ergebnisse. Aktuell: 4–5 Tage. Diagramme und PDF aktualisieren sich automatisch mit jeder neuen Session. Je mehr Tage, desto stabiler die Linien.
Live-Messergebnisse — 20m FT8, 7–9 Messtage, 19.936 Zyklen:
| Modus | Stationen/15s (Pooled Mean) | vs Normal | Tage | Zyklen |
|---|---|---|---|---|
| Normal | 51,1 | — | 9 | 5.959 |
| Diversity Standard | 47,9 | −6% | 7 | 6.290 |
| Diversity DX | 47,1 | −8% | 7 | 7.687 |
Hinweis: Frühere Messungen (weniger Tage) zeigten −18%/−22%. Mit mehr Messtagen, die alle Tageszeiten abdecken, haben sich die Zahlen bei einem kleineren Verlust eingependelt. Negativ bleibt es — der resonante ANT1-Vorteil auf 20m ist real — aber das Bild ist differenzierter.
Hinweis zur Interpretation — 20m Auf 20m arbeitet der Kelemen DP-201510 in seinem Auslegungsband als resonanter Halbwellen-Dipol. ANT1 ist alleine schon sehr effizient — Diversity überlagert eine bereits gute Antenne mit der nicht-optimierten Regenrinne (ANT2). Resultat: leichter Verlust in der reinen Stationsanzahl.
Aber das Bild ist differenzierter: in direkten A1↔A2-Doppelempfängen gewinnt ANT2 in 79–86 % der Fälle mit Ø +4 dB Vorteil — reine Polarisations- und Pattern-Diversity aus der sehr unterschiedlichen Geometrie beider Antennen. (Faraday-Rotation allein erklaert das nicht — auf KW dominieren Multi-Path- Ausbreitungsmoden, Gebaeude-Kopplung und Pattern-Unterschiede.) Die resonante ANT1 gewinnt trotzdem bei der reinen Stationsanzahl, weil das Diversity-Zeit- Sharing einzelne Decodes kostet die ANT1-allein gehabt haette. Der Nutzen auf 20m ist qualitativ (andere Stationen, vor allem schwaches DX), nicht quantitativ.
Die ehrliche Erkenntnis: Diversity ist mit diesem Antennen-Setup asymmetrisch. Auf Off-Band-ANT1-Bändern (40m, 30m, 17m, 80m) gleicht sie die schwache ANT1 aus → großer Stations-Gewinn. Auf Resonant-ANT1-Bändern (20m, 15m, 10m) überlagert sie eine bereits starke ANT1 → kleiner Stations- Verlust, aber qualitativer Pol-Diversity-Gewinn.
Stationen über 24h UTC — 20m FT8, alle drei Modi:
Direktvergleich — Stationen pro Zyklus, stündlich:
| Diagramm | Beschreibung |
|---|---|
| 📊 Ausführlicher PDF-Bericht — 20m | Vollständige 20m-Analyse mit dem differenzierten Narrativ — ANT2-Win-Rate, Faraday-Rotations-Theorie, asymmetrischer Vorteil. |
| 🗂 Rohdaten (statistics/) | Alle Rohdaten pro Modus/Band/Stunde — jede Zahl ist nachrechenbar. |
Live-Messergebnisse — 30m FT8, vorläufige Daten:
| Modus | Stationen/15s (Pooled Mean) | vs Normal | Tage | Zyklen |
|---|---|---|---|---|
| Normal | 15,0 | — | 3 | 452 |
| Diversity Standard | 25,3 | +69% | 3 | 1.386 |
| Diversity DX | 23,9 | +59% (vorläufig) | 1 | 214 |
Hinweis: 30m-Datensammlung läuft erst seit Kurzem. Normal und Diversity Standard haben je 3 Messtage — zeigen bereits das erwartete Off-Band-Muster (großer Gewinn, ANT1 auf 10 MHz suboptimal). Diversity DX hat erst 1 Tag — noch nicht belastbar. Daten wachsen mit jeder Session.
Wenn deine Station eine resonante Antenne für 1–2 Bänder hat plus alles andere über Tuner — genau Mike's Situation auf 40m — wird Diversity auf den Tuner- Bändern wahrscheinlich einen substanziellen Gewinn bringen, auf den resonanten Bändern einen leichten Verlust. Die 40m-Messung ist der „Tuner-Archetyp", die 20m-Messung ist der „Resonant-Archetyp".
- 30m (off-band ANT1, Datensammlung gestartet — 3 Tage Normal/Standard, 1 Tag DX): bestätigt Gewinn-Muster, siehe oben
- 17m (off-band ANT1): Datensammlung läuft, erwarteter Gewinn wie 40m
- 15m / 10m (resonant): erwarteter Verlust wie 20m
- 80m / 60m / 12m: anstehend
Jedes neue Band bestätigt oder widerlegt die Off-Band/Resonant-Hypothese.
Alle Rohdaten in statistics/, alle PDFs aktualisieren sich automatisch
mit python3 scripts/generate_plots.py.
Verbreiteter Funker-Irrtum: „Wenn meine Antenne sendet, empfaengt sie auch genauso gut." Physikalisch stimmt das fuer die Antenne selbst — das Reziprozitaetsprinzip besagt: Verluste sind beim Senden und Empfangen gleich. Aber in der Praxis ist das Bild asymmetrisch, weil zwei verschiedene Effekte zusammenkommen.
Die Bilanz der Uebertragungsstrecke — deine Sendeleistung minus Pfadverlust minus Antennen-Verluste — hat auf beiden Seiten ganz unterschiedliche Reserven:
- TX-Seite hat etwa 40–50 dB Reserve ueber der FT8-Decode-Schwelle. 100 W Sendeleistung in eine ueber Tuner angepasste, nicht-resonante Antenne liefern rund +50 dBm an der Klemme. Selbst mit 5–10 dB Tuner-/Mismatch-Verlust kommt dein Signal bei einer entfernten Gegenstation typisch 30–40 dB ueber dem Rauschen an — weit ueber der FT8-Decode-Schwelle (−24 dB SNR in 2500 Hz Bandbreite).
- RX-Seite hat nur 0–15 dB Reserve fuer schwache DX-Stationen. Die empfangene Signalstaerke ist durch Pfadverlust und Sendeleistung der Gegenstation festgelegt. Ein schwaches DX aus 8000 km mit 10 W kann bei dir mit nur −115 dBm an der Antennenklemme ankommen. Mit 7 dB Tuner-Verlust sind es −122 dBm — genau an oder unter der Decode-Schwelle. Gleicher Verlust, aber auf der RX-Seite ohne Spielraum.
Konsequenz: Wenn du eine nicht-resonante Antenne ueber Tuner betreibst, funktioniert das Senden noch problemlos, aber schwache Stationen im Empfang verschwinden einfach unter der Schwelle.
Der groessere Grund warum zwei Antennen besser sind als eine ist die physikalische Diversity:
- Mike's ANT1 (Kelemen DP-201510) ist ein horizontaler Halbwellendipol.
- Mike's ANT2 (Dachrinne, L-Form ~15 m) wirkt teilweise vertikal.
- KW-Skywave-Ausbreitung trifft in gemischten Polarisations-Zustaenden ein ueber Multi-Path-Moden und ionosphaerische Mode-Mischung. Stationen deren Signal vorwiegend vertikal eintrifft werden von ANT1 (horizontal) nur schwach empfangen — aber gut von ANT2, und umgekehrt. (Reine Faraday- Rotation skaliert mit 1/f² und ist eher auf UKW/SHF/SatComm relevant — auf KW dominieren Multi-Path und Mode-Mischung.)
- Die beiden Antennen haben ausserdem unterschiedliche Richtcharakteristik — Richtungen die ANT1 unterdrueckt, deckt ANT2 ab.
Deswegen ist der Off-Band-Diversity-Gewinn gross (siehe Mess-Sektion fuer aktuelle Zahlen): nicht nur weil der Tuner-Verlust umgangen wird, sondern weil ANT2 ganze Signalpfade hoert die ANT1 ueberhaupt nicht sieht.
FT8/FT4/FT2 haben eine harte mathematische Decode-Schwelle. Die Costas- Synchronisation braucht eine definierte Minimal-Korrelation, und die LDPC- Fehlerkorrektur hat eine scharfe Bit-Error-Rate-Kante. Ein geuebtes Ohr kann bei −5 dB SNR im SSB-Signal noch Wortfetzen erkennen — der FT8-Decoder nicht.
Konkret: bei FT8 zaehlt jedes dB Empfangs-Empfindlichkeit direkt mehr decodierte Stationen. Bei SSB oder CW sind Sendeleistung und Antennengewinn wichtiger fuers Gehoert-werden — den Rest macht der Mensch.
Die meisten Funker haben eine resonante Antenne fuer ein, zwei Lieblings-Baender plus Tuner fuer alles andere. Der Diversity-Gewinn auf den Tuner-Baendern ist betraechtlich:
| Band | ANT1-Status | Diversity Standard vs Normal (siehe Mess-Sektion fuer aktuelle Zahlen) |
|---|---|---|
| 40m | off-band (Tuner) | grosser Gewinn (aktuell ~+120%, off-band Asymmetrie) |
| 20m | resonant (Design-Band) | ~ −6 % Stationsanzahl (ANT1 allein bekommt schon fast alles) — aber ANT2 gewinnt 79–86 % der direkten Doppelempfaenge → qualitativer Pol-Diversity-Gewinn |
| 30m, 17m, 12m | off-band (Daten wachsen) | erwartet grosser Gewinn (off-band aehnlich 40m) |
Mit 70–100 W ist die Sende-Seite selten der Engpass. Der Empfang ist es. Diversity adressiert genau diesen Engpass — und der Zwei-Antennen-Effekt (Polarisation + Richtung) verstaerkt die Tuner-Verlust-Kompensation noch.
Begriffs-Hinweis dBm = Leistungs-Pegel bezogen auf 1 Milliwatt (0 dBm = 1 mW). SNR = Signal-Rausch-Abstand. Link-Budget = Bilanz aller Gewinne und Verluste von der PA-Endstufe bis zur Decode-Schwelle des Empfaengers.
ANT1 — Kelemen DP-201510 (Multiband-Sperrkreisdipol für 20m / 15m / 10m) Ein zentral gespeister Multiband-Dipol mit koaxialen Sperrkreisen (Trap-Dipol) — kein Fächer-Dipol. Pro Band wirkt nur der Drahtabschnitt bis zum jeweils resonanten Sperrkreis, alle drei Bänder direkt 50 Ω über einen 1:1-Balun (kein Tuner nötig). Einspeisepunkt an der Dachgaube im 3. OG: ein Arm führt schräg nach oben zur Dachspitze, der andere schräg nach unten über das Vordach zum Balkon — vertikal gespannter Halbwellendipol mit Einspeisepunkt in der Mitte. Auf 40m arbeitet diese Antenne außerhalb ihres Auslegungsbandes — siehe Interpretationshinweis oben.
ANT2 — Regenrinne des Hauses (Zufalls-Längenantenne, ~15m) Nie als Antenne installiert — einfach angeklemmt. Die Regenrinne verläuft ~5m waagerecht entlang der Dachkante, ~8m senkrecht als Fallrohr, ~2m waagerecht zum Hauseingang. Diese L-Form liegt zwischen λ/4 und λ/2 für das 40m-Band (7 MHz). Andere Geometrie, andere Polarisierung, gebäudegebundene Befestigung — die ideale Ergänzung für Diversity.
-
FT2-Modus — Nativer Decodium-kompatibler FT2 Decoder/Encoder (3.8s Zyklen, 4-GFSK, 288 sps). Community-Frequenzen vorkonfiguriert. QSOs erfolgreich abgeschlossen. Automatische RX-Filterverbreiterung auf 4000 Hz.
-
DT-Zeitkorrektur v2 — Kumulative Korrektur aus Band-Konsens. 2-Zyklen-Messung, 10-Zyklen-Betrieb, 70% Daempfung. Pro Modus gespeichert: Korrekturwerte in
~/.simpleft8/dt_corrections.json— sofort gute Korrektur beim Modus-Wechsel. DT-Werte typisch ±0.1s nach Konvergenz. -
🆕 Adaptive Diversity (v0.97) — Passt das Antennen-Verhaeltnis slot-fuer-slot in Echtzeit ueber einen rollenden 5-Slot-Puffer an. Keine stuendliche 90-Sekunden-Messpause mehr — reagiert binnen Sekunden auf Ausbreitungsaenderungen. 8 %-Schwelle verhindert Flackern; dynamische Umschaltung zwischen 30:70, 50:50, 70:30. Toggle in Einstellungen: „Adaptive Diversity (Testphase)". Die statische Mess-Methode bleibt als Fallback verfuegbar. Volle Vorher/Nachher-Erklaerung: docs/explained/diversity-modes_de.md.
-
Dual-Mode Diversity — Zwei Scoring-Strategien:
- Standard: Zaehlt dekodierte Stationen — ideal fuer CQ-Betrieb
- DX: Zaehlt schwache Stationen (SNR < -10 dB) — ideal fuer DX-Jagd (Australien bei -24 dB zaehlt, Bochum bei +12 dB nicht)
- 8% Schwelle, Median ueber 3 Zyklen pro Antenne (6-Slot fair 3:3). Button zeigt "DIVERSITY DX" im DX-Modus.
- Lernendes Antennen-Gedaechtnis: Nach jedem Dekodier-Zyklus merkt sich das System pro Rufzeichen, welche Antenne besser empfangen hat und um wieviel dB. Beim QSO-Aufbau wird automatisch die beste Antenne gewaehlt — das ueberlagert den globalen Diversity-Rhythmus fuer die QSO-Dauer. Kein Timeout, keine Persistenz: eine Station die du gerade jetzt hoerst, ist immer der praeziseste Wert. Das QSO-Fenster zeigt z.B. "Antworte DL3AQJ (ANT2, +6.3 dB)".
-
Diversity-Aktivfunktionen — OMNI-CQ und Auto-Hunt
Auto-Hunt nach zwei abgeschlossenen QSOs (G8KHF, HA1BF). HA1BF wurde auf ANT2 mit +1.0 dB Vorteil empfangen (Pro-Rufzeichen-Antennen- praeferenz). Timer zeigt 6:55 min Restlaufzeit. Unten: freier CQ- Frequenz-Bereich, dynamische Diversity 50:50 aktiv.
Beide Buttons leben im Diversity-Mode — im Normal-Mode versteckt, bei Aktivierung von Diversity automatisch sichtbar.
-
OMNI-CQ ist ein Single-Slot-CQ der automatisch alle ~5 Minuten zwischen Even- und Odd-Paritaet wechselt (modus-abhaengiger Counter: FT8=10, FT4=20, FT2=40 Versuche). Der TX-Duty-Cycle ist derselbe wie bei einem normalen CQ auf einer Paritaet — OMNI spart nur den manuellen Even/Odd-Klick. Denselben Effekt erreichst du auch mit dem Even/Odd-Button selbst. Der OMNI-Button ist fest sichtbar wenn Diversity aktiv ist — kein Easter Egg mehr (war so bis v0.97.29). TX ueber ANT1, RX nutzt globale Diversity und Pro- Rufzeichen-Antennenpraeferenz. Bekannte Limitationen: TX-Frequenz wird einmalig am ersten TX jedes Paritaets-Blocks gewaehlt (keine fortlaufende Luecken-Pruefung innerhalb eines Blocks — die dynamische Frequenz-Suche laeuft nur an Block-Grenzen). Der Counter setzt sich bei eingehendem QSO zurueck — bei einer populaeren Station kann derselbe Paritaets-Slot also immer wieder verlaengert werden. Getestet an einer Station (DA1MHH) seit 11.05.2026 — nicht unabhaengig field-validiert.
-
Auto-Hunt waehlt automatisch die naechste CQ-Station aus der RX- Liste und startet das QSO — kein manueller Klick noetig. Sichtbar nur im Diversity-Mode.
- Auswahl nach Score: neues DXCC > seltenes Call > guter SNR (> −15 dB) > Erstempfang heute. Bei gleichem Score zufaellig.
- Auto-Stop nach 10 Minuten ab Aktivierung, unabhaengig von Maus/Tastatur. Danach Stopp und bewusster Neustart per Klick erforderlich. Maximal 3 QSO-Versuche pro Station.
- Hardware: Der Empfang nutzt die Pro-Rufzeichen-Antennen- praeferenz (bessere RX-Antenne). TX laeuft IMMER ueber ANT1, die einzige sendetaugliche Antenne. Band- oder Moduswechsel stoppen Auto-Hunt sofort.
⚠️ Operator-Verantwortung — vor Verwendung lesen: SimpleFT8 ist eine private Machbarkeitsstudie eines einzelnen Funkers (DA1MHH), kein Contest-Tool und kein Fernsteuerungs-Produkt. Auto-Hunt startet QSOs ohne Pro-Station-Klick. Der 10-Min-Auto-Stop ist eine selbst gesetzte Grenze — deutsches Amateurfunkrecht (§ 13 AFuV) regelt fernbediente oder automatisch arbeitende Stationen separat und verlangt dass der Operator die Station jederzeit abschalten kann. Nur verwenden waehrend du aktiv vor der Station sitzt. WSJT-X und JTDX stoppen ihre Automatik bewusst vor der Auswahl der naechsten Station aus der RX-Liste — Auto-Hunt ueberschreitet diese Grenze absichtlich. Die Verantwortung fuer die Einhaltung deiner nationalen Vorschriften liegt bei dir. -
-
Automatische TX-Leistungsregelung — Zielwatt einstellen, SimpleFT8 regelt den FWDPWR-Wert automatisch.
-
Smart CQ-Frequenz — Findet freien Platz im 800–2000 Hz Sweet Spot statt im leeren oberen Bereich.
-
Warteliste — Gleichzeitige Anrufer werden gequeued (Grid + Report). Nach QSO: automatische Antwort an naechste Station.
-
RR73-Hoeflichkeit — Nach QSO: wenn Gegenstation weiter R-Report sendet, wird RR73 nochmal gesendet (max 2×).
-
Even/Odd Anzeige — [E]/[O] Tags in RX-Liste + QSO-Panel. Sofort sichtbar welcher Slot aktiv ist.
-
Bandpilot (v0.88) — Bei Bandwechsel prueft SimpleFT8 die aktuelle UTC-Stunde und vergleicht die drei RX-Modi (Normal / Diversity Standard / Diversity DX) direkt — ohne Aggregation. Drei Settings-Modi: Aus / Auto (3s-Toast + Auto-Wechsel mit 5%-Toleranz) / Manuell (Dialog nur wenn ein anderer Modus gewinnt). TX-geschuetzt: Wechsel wartet auf
tx_finished. Stunden-Schwellen: ≥3 Tage + ≥20 Slots pro Modus.⚠️ Im Feldtest.v0.87 → v0.88 Update: Der Bandpilot nutzt jetzt stunden-genaue Direkt-Werte statt globalem Aggregat
(S+D)/2. Bestehende Settings werden automatisch migriert (bandpilot_enabled=true→mode="auto").
Getestet & funktionsfaehig (v0.97.2):
- ✅ FT8 / FT4 / FT2 — alle drei Modi mit eigenen Frequenzen, Auto-RX-Filter, modus-abhaengigem Timing
- ✅ Auto TX-Leistungsregelung: Regelkreis mit FWDPWR-Feedback, Clipping-Schutz
- ✅ Dual-Mode Diversity: Standard (Stationsanzahl) + DX (schwache Signale), 8% Schwelle
- ✅ Bandpilot (v0.88): Stunden-genaue RX-Modus-Empfehlung pro Band aus Statistik (siehe oben, im Feldtest)
- ✅ Smart Antenna Selection: Pro-Station Antennen-Praeferenz waehrend QSO — wechselt auf beste SNR-Antenne je Callsign.
- ✅ DT-Zeitkorrektur v2: Pro Modus gespeichert, 2-Zyklen-Messung, 70% Daempfung
- ✅ Propagation-Balken: HamQSL-Solardaten + Tageszeit-Korrektur. Geprueft gegen HAM-Toolbox
- ✅ Operator-Praesenz (Anti-Bot): 15 Min Timeout, gesetzl. Pflicht DE
- ✅ Smart CQ-Frequenz: 800–2000 Hz Sweet Spot via Histogramm. Freq-Zaehler in Statusleiste.
- ✅ Warteliste: Grid + Report, automatische Antwort nach QSO
- ✅ RR73-Hoeflichkeit: Automatisch max 2× wiederholen
- ✅ Even/Odd Anzeige: [E]/[O] in RX-Liste + QSO-Panel (FT2 3.75s Sync in Untersuchung)
- ✅ Signalverarbeitung: 5-Pass Subtraction, Whitening, Sinc-Resampling
- ✅ QSO-Zustandsmaschine: Hunt + CQ, Retry, ADIF 3.1.7
- ✅ Logbuch: Suche, DXCC, Detail-Overlay, Loeschen
- ✅ Hilfe-Dialog: Feature-Doku (DE + EN) via ? Button in Statusleiste
- ✅ Richtungs-Karte mit Live-Propagations-Sektoren (v0.66/v0.71/v0.72): Drehbarer 3D-Globus (Orthographic-Projection) mit 16 Richtungs-Sektor-Wedges die zeigen wohin die Ausbreitung gerade jetzt geht: im RX-Modus = Wedge-Laenge nach Anzahl gehoerter Stationen aus dieser Richtung, im TX-Modus = Wedge-Laenge nach max-Reichweite (v0.71 — ein einziger VK6-Spot mit 16.000 km zaehlt mehr als 50 Iberien-Spots). Antennen-Farbcodierung (ANT1/ANT2/Rescue) macht Diversity-Beitraege sofort sichtbar. Ein Blick auf die Karte sagt: „kein Vektor nach Westen heute — auf diesem Band brauche ich NA gar nicht erst zu versuchen" — operative Information, keine Deko. Aurora + Dark Theme-Toggle (v0.72), persistent.
- ✅ Live Locator Mining (v0.67/v0.70 — integriert): Während des Empfangs werden Maidenhead-Locators direkt aus CQ-Rufen und QSO-Antworten (
CQ R9CA LO97,RA4ALY DL6YJB JO31) extrahiert und in einer persistenten JSON-Datenbank (~/.simpleft8/locator_cache.json) gespeichert. Source-Prioritaet:cq_6 > psk_6 > qso_log_6 > _4-Varianten— ein 6-stelliger Locator aus einem Live-CQ wird nie von einem 4-stelligen ADIF-Eintrag ueberschrieben. Die Karte zeigt damit exakte Stationspositionen statt Land-Mittelpunkte. Bootstrap via ADIF-Bulk-Import (LotW, QRZ, eigenes Logbuch) beim Start. Auto-Save alle 5 Min + bei Schliessen — uebersteht Hard-Kill. Aktuell 9.366 Calls, waechst mit jeder Session. (Externe Tools wie GridTracker machen aehnliches Mining aus WSJT-X — diese Implementierung haelt es einfach intern in SimpleFT8.) - ✅ Automatisierte Regressions-Suite: QSO-Zustandsübergänge, Diversity-Merge-Logik, Protokoll-Encoding/Decoding, DT-Korrektur, OMNI-CQ-Counter, Bandpilot-Empfehlungen, Locator-DB-Priorität, Settings-Migration und Dialog/UI-Interaktionen. Mock-basiert für Radio-Hardware-Unabhängigkeit — Feldhärtung erfolgt durch echte QSO-Sessions und Band-Messungen (siehe Statistik-Sektion). Unit-Tests decken interne Logik ab; einige ernsthafte Bugs (z.B. SIGBUS in v0.97.38, OMNI-CQ-Phase-Bug in v0.97.22) traten erst bei Live-Field-Tests auf und wurden dort gehotfixt.
- ✅ Stations-Statistik: Pro-Zyklus Logging (Normal + Diversity), 6-Zyklen Warmup-Ausschluss. Rohdaten im Markdown, keine In-File-Zusammenfassungen — Auswertung via
scripts/generate_plots.py. - ✅ Diversity Auswertungs-Diagramme:
python3 scripts/generate_plots.py→auswertung/— Dark-Theme PNGs: Stationen-Zeitverlauf (Normal vs Diversity) + ANT2-Wins + Rescue-Events. → Aktuelle Auswertungen - ✅ Per-Station SNR-Logging: Jeder A1↔A2 Vergleich wird mit beiden SNR-Werten, Δ dB, Gewinner und ★ Saved-Event geloggt — wenn eine Antenne unter der FT8-Dekodierschwelle (−24 dB) liegt und die andere darüber. Beweist: "ANT2 hat dieses QSO erst möglich gemacht."
- ✅ Ant2 Superiority Counter: Quantifiziert Diversity-Gewinn (Ant2 > Ant1)
- ✅ TX-Sicherheit: TX stoppt sofort vor Gain-Messung — kein versehentliches Senden bei Kalibrierung
- ✅ Gain-Messung: Audio-Eingangspegel kalibrieren (Button "GAIN-MESSUNG"). Findet optimalen RX-Pegel vor Statistik- oder Diversity-Sitzungen.
- ✅ Auto-Hunt (v0.75): Wählt automatisch die nächste CQ-Station aus der Warteliste und startet QSO ohne manuellen Klick. Eigener Totmannschalter (nicht mausausgelöst — Bot-Schutz). Diversity-only: sichtbar nur bei aktivem Diversity, stoppt automatisch bei Modus-Wechsel.
- ✅ Auto-Close Kalibrierungs-Dialog (v0.83): Nach abgeschlossener Gain-Messung schließt der Bestätigungs-Dialog automatisch nach 3 Sekunden — kein Klick nötig.
- ✅ Doppel-Report-Bug behoben (v0.82): Behoben: App sendete Signal-Report erneut, nachdem bereits RR73 empfangen wurde. Ursache war die Decoder-Reihenfolge (
cycle_finishedmuss nach allenmessage_decoded-Events feuern). Im echten QSO bestätigt. - ✅ Diversity Tertile-Analyse (v0.84): Statistik-Diagramme zeigen 33./67.-Perzentil Schattierung (echte Slot-zu-Slot-Streuung) statt flacher Min/Max-Balken.
- ✅ UI-Verbesserungen: Info-Dialoge mit "Nicht mehr anzeigen". DT-Korrektur bleibt beim Modus-Wechsel erhalten. Button-Labels spiegeln aktiven Zustand.
- ✅ Debug-Konsole: Ctrl+D, Live-Filter, Schrift 11pt, Copy/Clear
Im Feldtest:
⚠️ AP-Lite v2.2: Schwache QSOs retten via kohaerenter Addition zweier fehlgeschlagener Dekodier-Versuche. Schwellwert-Kalibrierung laeuft.- ✅ OMNI-CQ (v0.96.4 + v0.96.7 + v0.97.30): Single-Slot-CQ mit automatischem Paritaets-Wechsel (modus-spezifischer Down-Counter, FT8=10/FT4=20/FT2=40 Versuche ≈ 5 Min Wallclock pro Paritaet). Diversity-only — Button fest sichtbar wenn Diversity aktiv (kein Easter Egg mehr seit v0.97.30, P55). Feldvalidiert 11.05.2026. → siehe Diversity-Aktivfunktionen oben.
⚠️ Bandpilot (v0.88): Stunden-genaue RX-Modus-Empfehlung pro Band — drei Direkt-Werte ohne Aggregation. 31 Unit-Tests gruen, Live-Validierung ueber laengere Funkzeit ausstehend.
| Band | FT8 | FT4 | FT2 |
|---|---|---|---|
| 80m | 3.573 | 3.575 | 3.578 |
| 40m | 7.074 | 7.047 | 7.052 |
| 20m | 14.074 | 14.080 | 14.084 |
| 15m | 21.074 | 21.140 | 21.144 |
| 10m | 28.074 | 28.180 | 28.184 |
git clone https://github.com/mikewanne/SimpleFT8.git
cd SimpleFT8
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python3 main.pyVoraussetzungen: macOS, Python 3.12+, FlexRadio SDR (FLEX-6000/8000 Serie). Zwei Antennenanschluesse fuer Diversity (optional).
SimpleFT8/
├── main.py # Einstiegspunkt
├── config/settings.py # Einstellungen, Frequenzen, Sprache
├── core/
│ ├── decoder.py # FT8/FT4/FT2 Decode + Signal Subtraction
│ ├── encoder.py # FT8/FT4/FT2 Encode → VITA-49 TX
│ ├── qso_state.py # QSO-Zustandsmaschine (Hunt + CQ + Warteliste)
│ ├── protocol.py # FT8/FT4/FT2 Protokoll-Konstanten (frozen dataclass)
│ ├── station_accumulator.py # Gemeinsame Station-Logik (Normal + Diversity)
│ ├── station_stats.py # Async Zyklus- + Per-Station SNR-Logging
│ ├── diversity.py # Diversity Controller (Standard/DX Scoring)
│ ├── diversity_merger.py # ANT1+ANT2 Decodes zusammenfuehren, SNR-Gewinner
│ ├── locator_db.py # Persistenter Maidenhead Locator-Cache (JSON)
│ ├── antenna_pref.py # Pro-Callsign Antennen-Praeferenz (1 dB Hysterese)
│ ├── ntp_time.py # DT-Korrektur v2 (pro Modus gespeichert)
│ ├── propagation.py # Bandbedingungen (HamQSL + Tageszeit)
│ └── timing.py # UTC-Takt, modus-abhaengige Zyklen
├── radio/
│ ├── base_radio.py # RadioInterface ABC
│ ├── radio_factory.py # create_radio(settings) → FlexRadio
│ └── flexradio.py # SmartSDR TCP + VITA-49 + Auto RX-Filter
├── ft8_lib/ # C-Library (MIT, FT8+FT4+FT2 nativ)
├── log/ # ADIF Writer, QRZ.com API
├── ui/
│ ├── main_window.py # 3-Panel Layout + Mixins
│ ├── help_dialog.py # Feature-Doku (DE/EN)
│ └── ... # Control Panel, RX, QSO, Logbuch
├── docs/explained/ # 10 Feature-Docs (5 × DE + EN)
└── tests/ # Automated regression suite (QSO, Diversity, Protocol, AP-Lite, Threading, ...)
Getestet: FLEX-8400M. Voraussichtlich kompatibel: FLEX-6300/6400/6500/6600/6700/8400/8600.
Radio-agnostische Architektur (v0.28+): Neue Radios durch eine Datei (radio/ic7300.py etc.) hinzufuegbar. Vorbereitet: ICOM IC-7300 (CI-V + USB Audio).
MIT License (c) 2026 DA1MHH (Mike Hammerer)
- ft8_lib — FT8/FT4 encode/decode C library (MIT)
- Decodium / IU8LMC — FT2 protocol reference
- FlexRadio Systems — SmartSDR TCP API
- WSJT-X — Pioneering digital weak-signal modes
SimpleFT8: Because weak signals deserve a fighting chance. / Weil schwache Signale eine faire Chance verdienen.














