Skip to content

SunSDR2 QRP: 96 kHz, zwei Stroeme, Uebersteuerung und Mikrofon-PTT - #167

Open
oe5sos wants to merge 50 commits into
mainfrom
feat/sunsdr-mikrofon-ptt
Open

oe5sos wants to merge 50 commits into
mainfrom
feat/sunsdr-mikrofon-ptt

Conversation

@oe5sos

@oe5sos oe5sos commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

Worum es geht

Der Abend des 2026-10-03 hat an der QRP drei Dinge beantwortet, die vorher als „offen" im Paritätsplan standen — und die Antworten lagen teils seit dem 23. September auf der Platte, in ~/Longpath/werkzeug/mitschnitte/.

Der Fund: die Abtastrate steht im Rahmen 0x01, den Longpath längst schickt

Im Mitschnitt rate-umschalten.pcap wurde die Rate zweimal umgeschaltet. Der einzige Rahmen, der sich dabei ändert, ist 0x01 — der Stromstart, den dieser Treiber seit dem 2026-08-26 beim Verbinden sendet:

Nutzlast am Gerät gemessen
Longpath bisher 01000000 0c080403 02020202 239 Nummern/s → ein Strom, 48 kHz
neu 02000000 0c080403 02020202 480 Nummern/s → zwei Ströme, je 48 kHz
neu 02010000 0a060403 02020201 958 Nummern/s → zwei Ströme, je 96 kHz

Erstes Byte = Zahl der Ströme, zweites = Ratenstufe. Der gebaute Rahmen ist bitgleich mit dem aufgezeichneten; das prüft tst_sunsdr_protocol gegen stateSyncFrameForTest().

Was dieser PR einbaut

  1. Der Strompfad versteht Kanäle und Fortsetzungen. Der Kanal kommt aus byte9, nicht mehr fest 0. Ein zweites Paket mit derselben Nummer ist nicht automatisch eine Wiederholung — der Inhalt entscheidet (bytegleich = Wiederholung, verschieden = nächste Proben).
  2. setSampleRate ist kein No-op mehr. 48000 und 96000 wählen den gemessenen Rahmen; jede andere Rate ändert nichts und warnt. Zur Laufzeit umgestellt startet das Gerät den Strom neu, und der Zähler erkennt das als Neuanfang.
  3. setActiveReceiverCount ist kein No-op mehr — die Verbindung weiß, für wie viele Kanäle es oben einen Empfänger gibt, und verwirft die anderen (erst nach der Nummernzählung, siehe unten).
  4. Gerätefähigkeiten: 48 und 96 kHz. maxSampleRate = 96000.
  5. Übersteuerung (adcOverflow) aus dem I/Q, ohne Protokollwissen — am Gerät auf drei Bändern ohne Fehlalarm.
  6. Mikrofon-PTT aus dem Stromkopf (0xFE/0xFD), Flanke statt Dauermeldung; nicht am Gerät gegengeprobt, das braucht Senden.
  7. Quittungsbuchführung, alle Sendestellen über eine Funktion, Mithör-Übersicht auch beim Geräteausfall, Werkzeug-Fixes.

Drei eigene Fehler, die das Gerät aufgedeckt hat

Alle drei hatte der Prüfstand bestätigt — weil die Annahme von mir stammte:

  • „Zwei Ströme haben eigene Nummernräume." Falsch: sie laufen global fortlaufend, byte9 wechselt dabei (0(K1) 1(K2) 2(K1) 3(K2) …). Je Kanal gezählt meldete der Zähler 50 % Verlust bei gesundem Strom.
  • Die Raten je Kanal. Aus dem Mitschnitt sah es nach 48+96 kHz aus; mit nur diesem Rahmen kommen beide Kanäle gleich schnell. Die Modusnamen heißen jetzt je48/je96.
  • Das Verwerfen stand vor der Nummernzählung — dieselbe 50-%-Meldung, ein zweites Mal, an anderer Stelle.

Geprüft

9/9 SunSDR-Pruefstaende gruen (89 Faelle in tst_sunsdr_radio_connection,
34 in tst_sunsdr_protocol)

Am echten Gerät gemessen: alle drei Strommodi, Verlust null; Ratenumstellung zur Laufzeit mit erkanntem Neustart; Übersteuerung ohne Fehlalarm auf 80/40/20 m; Quittungen 1212 von 1212.

Noch nicht belegt: wie 96 kHz klingt. Die Zahlen stimmen, aber am 2026-09-24 haben richtige Zahlen schon einmal zu falschem Klang geführt (48k-Daten in einem 192k-Kanal, vom Betreiber als „schlechtes Rauschen" erkannt). Das entscheidet das Ohr am Gerät.

144 kHz ist bewusst nicht in der Fähigkeitenliste, obwohl belegt: der zweite Kanal hat oben noch keinen Empfänger.

🤖 Generated with Claude Code

oe5sos and others added 6 commits October 3, 2026 19:12
…uecke

Die zweite der zwei Empfangsluecken, und sie geht genauso ohne
Protokollwissen wie die Uebersteuerung: P1 und P2 lesen das PTT aus einem
Statusbit, die QRP schickt keine Statusrahmen -- aber ihr Stromkopf traegt
den Betriebszustand. 0xFE heisst Empfang, 0xFD heisst SENDEN. Drueckt
jemand am Geraet die Mikrofontaste, wechselt der Opcode, und dieser
Treiber hat ihn bisher nur dazu benutzt, solche Pakete wegzuwerfen.

Gemeldet wird die FLANKE, nicht jedes Paket: P1/P2 melden den Zustand mit
jedem Statusrahmen und MoxController::onMicPttFromRadio ist gegen
Wiederholungen gleichgueltig -- bei 240 Strompaketen je Sekunde waeren
240 Signale ueber eine QueuedConnection aber nichts als Last.

Nicht gemeldet wird, was Longpath selbst ausgeloest hat: steht MOX auf
uns, ist der Sendezustand unser eigener. Heute kann der Fall nicht
eintreten (kein Byte des Sendepfads erreicht den Draht), aber die
Unterscheidung gehoert an die Stelle, die sie trifft.

Dazu: ein haengendes PTT ueberlebt die Sitzung nicht. Bricht die
Verbindung ab, waehrend das Geraet sendet, wird das PTT zurueckgenommen
-- "Taste gedrueckt" ist der falsche Zustand, in dem man einen Sender in
Erinnerung behaelt.

NICHT AM GERAET GEGENGEPROBT: dazu muesste am Geraet die Mikrofontaste
gedrueckt werden, und das heisst senden -- ohne Antenne verboten. Drei
Pruefungen im Pruefstand (Flanke hin und zurueck, eigenes MOX gilt nicht,
haengendes PTT wird beim Trennen zurueckgenommen), 84/84 gruen. Die
Live-Bestaetigung gehoert zum ersten Sendeversuch mit 50-Ohm-Abschluss.

Liegt auf einem eigenen Zweig, damit #154 gruen bleibt und gemergt werden
kann.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…Verlustrate null von 1212

Der leere Akku hat einen Fall geschenkt, der sonst schwer herzustellen
ist: ein frisch eingeschaltetes Geraet.

EINKANAL-ZUSTAND, A/B am selben Geraet, Minuten auseinander:
  A ohne Frequenzrahmen: Q ungleich null = 0,0 %, 1 Quittung
  B mit  Frequenzrahmen: Q ungleich null = 21,9 %, 3 Quittungen

Damit ist die Eingrenzung vom 2026-09-25 ("ein einziger 0x07-Rahmen
schaltet echtes I/Q ein, 0 % -> 21 %") als A/B-Messung am frisch
eingeschalteten Geraet bestaetigt -- vorher war das Geraet jeweils schon
laenger an, und der Zustand liess sich nur aus der Erinnerung beschreiben.

VERLUSTRATE VON STEUERRAHMEN: viermal 150 Frequenzwechsel (je zwei
Rahmen), also 1212 Rahmen mit den Verbindungsrahmen -- 0 unbeantwortet.

Das korrigiert meine eigene Begruendung von vorhin: "etwa einer von
fuenfzehn Laeufen" war aus einem Einzelfall geschlossen. Ueber 1212
Rahmen ist die Rate null. Das Nachschicken bleibt eine sinnvolle
Versicherung -- eine verlorene Frequenz bleibt sonst unbemerkt, und
einmal ist es passiert --, aber es ist NICHT dringend.

Dazu im Messlauf zwei Schalter: LONGPATH_SUNSDR_KEINE_FREQ laesst den
Frequenzrahmen aus (Einschaltzustand messen) und LONGPATH_SUNSDR_WECHSEL
schickt N Frequenzwechsel (Verlustrate messen).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…slauf hat sich selbst gemessen

Der Betreiber hat Longpath um 17:50 neu gestartet und die QRP verbunden;
seine Instanz sammelt selbst mit. Ihr Log widerlegt zwei Dinge aus meinen
Messlaeufen.

1. KOPIEN JE NUMMER: mein Messlauf 1,20, echter Betrieb 1,00. Der
   Unterschied ist der Pruefstand -- er liess die Ereignisschleife in
   500-ms-Bloecken laufen, dadurch gingen die Blockantworten verspaetet
   hinaus, und das Geraet WIEDERHOLTE. Die "rund 50 bytegleichen
   Wiederholungen je Sekunde" sind keine Eigenschaft des Geraets, sondern
   eine Folge meiner Messung. Behoben: der Messlauf tickt in 20 ms.

   Merksatz: ein Messgeraet, das den Takt der Antworten verschiebt, misst
   sich selbst. Das ist feedback-messung-schlaegt-nicht-das-geraet in der
   Gegenrichtung -- nicht das Geraet war schuld, sondern das Messgeraet.

2. "MELDET VON SICH AUS NICHTS": im Log des Betreibers steht 88 s nach dem
   Verbinden ein 0x01-Rahmen mit 51c300004928 -- das ist das Ende der
   BEACON-ANTWORT. Das Geraet hat auf eine Rundfrage geantwortet, nicht
   gemeldet. Der Befund bleibt richtig, genauer gefasst: die QRP ANTWORTET
   (Quittungen, Abfragen, Rundfragen), aber sie MELDET nicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…begrenzt weiter

disconnect() schickt dem Geraet keinen einzigen Rahmen: Sockets zu, Timer
aus, aufgeraeumt. Dem Funkgeraet wird nie gesagt, dass der Strom aufhoeren
soll. Mit tcpdump nach einem Longpath-Ende gemessen (46 s, niemand hoerte
zu): 1940 Pakete/s, 8,1 Kopien je Folgenummer, 2,3 MB/s ins Leere -- und
der Mac antwortet auf jedes Paket mit ICMP "port unreachable".

Daraus zwei Dinge:

1. DIE ACHTFACHUNG IST ABSCHLIESSEND ERKLAERT. Sie ist keine Eigenart des
   Geraets, sondern die Folge fehlender Quittierung: 8,1 Kopien ohne
   Blockantwort, 1,00 mit. Die Frage vom 2026-09-23 ist zu.

2. Die QRP streamt nach dem Trennen UNBEGRENZT weiter. Bekannt war das
   als Kuriosum ("85 leftover I/Q packets") -- es sind aber nicht 85
   Pakete, sondern ein Dauerzustand bis zum Ausschalten. Sehr
   wahrscheinlich ist das auch der Grund, warum ExpertSDR2 am selben
   Abend nicht verbinden konnte: das Geraet stand noch im
   Streaming-Zustand der vorigen Sitzung.

Was fehlt, ist der Stopp-Befehl. ArtemisSDR fuehrt fuer die DX
SUNSDR_OP_POWER_OFF 0x02; die QRP-Nummer ist unbekannt und wird nicht
geraten. Der Mitschnitt dafuer ist der leichteste von allen: ExpertSDR2
verbinden lassen und BEENDEN -- der letzte Rahmen vor dem Verstummen ist
es.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…r taugt nicht

Beim ersten Einsatz an einem ECHTEN Mitschnitt (2026-10-03) hielt
sunsdr_handshake_diff.py alle zehn Steuerrahmen fuer ausgehend -- auch die
fuenf Quittungen des Geraets. Ursache: die Richtung kam aus
"dport == 50001", und beide Seiten sprechen Port 50001. Der Zielport ist
hier also kein Merkmal.

Jetzt entscheidet die ADRESSE, und welche der Rechner ist, ergibt sich aus
dem Mitschnitt selbst: die Suchanfrage (Opcode 0x00) geht immer vom
Rechner aus. Fehlt sie, entscheidet der Datenstrom (die 1210-Byte-Pakete
kommen aus dem Geraet); bleibt auch das offen, sagt es --rechner.

Am selben Mitschnitt gegengeprueft -- und das Ergebnis ist zugleich eine
unabhaengige Bestaetigung der Quittungsmessung von heute, diesmal von
AUSSEN am Draht statt aus dem Treiber:

  ->  0x00 Suchanfrage          <-  0x01 Beacon-Antwort
  ->  0x01 Zustandsrahmen       <-  0x01 Quittung
  ->  0x04 Vorverstaerker       <-  0x04 Quittung
  ->  0x07 DDC-Frequenz         <-  0x07 Quittung
  ->  0x08 VFO-Frequenz         <-  0x08 Quittung

Vier Rahmen, vier Quittungen, in 101 ms. Genau das, was der Treiber
intern berichtet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ie der zweite Empfaenger

In ~/Longpath/werkzeug/mitschnitte/ lagen seit dem 2026-09-23 zwei
ExpertSDR2-Mitschnitte. Aus ihnen wurden damals die dreizehn Rahmen fuer
die CRC-Pruefung gezogen; auf den VERBINDUNGSABLAUF hat sie niemand
ausgewertet. Nachgeholt -- und es beantwortet die zwei groessten offenen
Fragen:

1. DIE QRP KANN 96 kHz. expert-rate.pcap: 28 561 Strompakete in 59,6 s =
   479 Bloecke/s = 96 kHz. BoardCapabilities fuehrt maxSampleRate = 48000;
   das ist widerlegt.

2. DIE "DOPPELTE DATENRATE" IST ERKLAERT, und es war nie der zweite
   Empfaenger. Bei 96 kHz schickt die QRP ZWEI Pakete je Folgenummer:
   Nummern 0,0,0,1,2,2,3,3,4,4 -- 4000 Pakete, 2000 Nummern, Differenzen
   0 und 1. Je 200 Probenpaare, zusammen 400 je Nummer, bei 240
   Nummern/s also 96 000 Proben/s. Die beiden sind NICHT markiert (beide
   Zustandsbytes 0100), nur die Reihenfolge trennt sie.

   KONSEQUENZ, und sie ist unangenehm: der Folgenummern-Zaehler von heute
   behandelt das zweite Paket als Wiederholung -- richtig bei 48 kHz (dort
   bytegleich, am Geraet belegt), FALSCH bei 96 kHz. Longpath wuerde dort
   die Haelfte der Daten lautlos wegwerfen. Wer die Rate umstellt, muss
   processStreamDatagram mitumbauen: bei 96 kHz zaehlt die Reihenfolge,
   nicht die Nummer.

3. Der vollstaendige Verbindungsablauf: 33 Rahmen, SIEBZEHN Opcodes, die
   Longpath nie schickt -- und das Geraet quittiert jeden einzelnen. Damit
   sind diese Nummern als "dem Geraet bekannt" bestaetigt. Dazu: ZWEI
   Abfragen (0x0c und 0x0d, je 320 Byte Antwort), und 0x05/0x12 tragen
   Speicherabbilder von ExpertSDR2 (0x00c1b77f-Zeiger, schwankende
   Laenge) -- keine Protokollfelder zum Nachbauen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
oe5sos and others added 3 commits October 3, 2026 19:37
…ickt ihn laengst

Mitschnitt rate-umschalten.pcap (118 550 Pakete), ExpertSDR2 verbunden,
zweimal die Rate umgeschaltet: 720 -> 1200 -> 720 Pakete/s. Im
Steuerkanal aendert sich an genau diesen zwei Stellen EIN Rahmen -- 0x01,
der Stromstart:

  Longpath heute:         01000000 0c080403 02020202
  ExpertSDR2 Phase A/C:   02000000 0c080403 02020202
  ExpertSDR2 Phase B:     02010000 0a060403 02020201

ES SIND ZWEI STROEME, unterschieden durch byte9 im Stromkopf:

  Phase A/C:  byte9=0 -> 240 Pakete/s, 1 je Nummer  =  48 kHz
              byte9=1 -> 480 Pakete/s, 2 je Nummer  =  96 kHz
  Phase B:    byte9=0 -> 480 Pakete/s, 1 je Nummer  =  96 kHz
              byte9=1 -> 720 Pakete/s, 1,5 je Nummer = 144 kHz

Longpath bekommt EINEN Strom mit 48 kHz, und der Unterschied ist das
erste Byte des 0x01-Rahmens: 01 gegen 02. Dasselbe Byte erscheint im
Stromkopf als byte8 wieder (Longpath 0100, ExpertSDR2 0200/0201).

Damit ist auch die Beobachtung vom 2026-09-23 endgueltig erklaert
("zwei verschiedene Pakete je Nummer"): zwei Stroeme, beim 96-kHz-Strom
zusaetzlich zwei Pakete je Nummer.

FOLGEN:
* Die QRP kann 48, 96 UND 144 kHz (gemessen). maxSampleRate = 48000 ist
  widerlegt.
* Die QRP kann zwei Stroeme gleichzeitig, unabhaengig geratet -- und 0x07
  adressiert passend zwei Unterempfaenger.
* Longpath braucht KEINEN neuen Opcode dafuer, nur eine andere Nutzlast
  in einem Rahmen, den es schon schickt.
* ABER: vorher muss processStreamDatagram umgebaut werden. Heute landen
  die Proben beider Kanaele in einem Topf, und das zweite Paket einer
  Nummer gilt als Wiederholung und wird verworfen -- es ist aber die
  zweite Haelfte der Proben. Einfach den Rahmen umstellen wuerde den
  Empfang KAPUTTMACHEN, nicht verbessern.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vorarbeit fuer 96/144 kHz, und zwar die, ohne die das Umstellen des
0x01-Rahmens den Empfang KAPUTTMACHEN wuerde (siehe
docs/architecture/2026-10-02-sunsdr-verbindungsablauf.md):

* Der KANAL kommt jetzt aus dem Stromkopf (byte8 = Zahl der Stroeme,
  byte9 = Index) und geht als hwReceiverIndex nach oben. Vorher stand
  dort fest 0 -- bei zwei Stroemen waeren die Proben beider in einem Topf
  gelandet.
* Ein zweites Paket mit derselben Folgenummer ist nicht mehr automatisch
  eine Wiederholung: der INHALT entscheidet. Bytegleich = Wiederholung
  (bei 48 kHz am Geraet belegt, 1683 von 1683), verschieden =
  FORTSETZUNG, also die naechsten Proben derselben Nummer (so kommt der
  96-kHz-Strom). Verglichen wird nur bei wiederkehrender Nummer, also
  selten.
* Die Folgenummern werden JE KANAL gezaehlt. Zwei Stroeme haben eigene
  Nummernraeume -- dieselbe Nummer auf beiden ist keine Wiederholung.
  Das hat der eigene Pruefstand gefunden; die Fensterzahlen
  (Verlust/Luecken) bleiben gemeinsam, denn sie messen den Netzweg.

AM HEUTIGEN BETRIEB AENDERT SICH NICHTS: bei byte8 = 1 ist der Kanal
immer 0, auch wenn byte9 etwas anderes sagt, und jede bytegleiche
Wiederholung bleibt eine Wiederholung. Dafuer gibt es eine eigene
Pruefung.

Zwei weitere Fehler im eigenen Umbau gefunden und behoben: der
Kanalzustand wurde beim Verbinden nicht zurueckgesetzt (das erste Paket
der neuen Verbindung galt dann als Spaetling), und die
Folgenummern-Zaehlung lief zunaechst weiter global.

Vier neue Pruefungen, 88/88 gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e Datenmenge

Der Stromstart-Rahmen 0x01 setzt die Zahl der Stroeme und die Ratenstufe.
Die drei Nutzlasten stammen byte-fuer-byte aus dem ExpertSDR2-Mitschnitt
vom 2026-10-03; der gebaute Rahmen ist bitgleich mit dem
aufgezeichneten (eigene Pruefung in tst_sunsdr_protocol).

AM ECHTEN GERAET DURCHGEMESSEN, alle drei Modi, Verlust null:

  01000000 0c080403 02020202   239 Nummern/s  ein Strom,    48 kHz   (1x)
  02000000 0c080403 02020202   480 Nummern/s  zwei Stroeme, je 48 kHz (2x)
  02010000 0a060403 02020201   958 Nummern/s  zwei Stroeme, je 96 kHz (4x)

Also: erstes Byte = Zahl der Stroeme, zweites = Ratenstufe. Longpath kann
damit die VIERFACHE Datenmenge holen. Im je96-Modus steigt auch der
Q-Anteil von 22 auf 90 % -- voller I/Q-Inhalt statt duennem.

Gewaehlt wird das NUR ueber die Umgebung (LONGPATH_SUNSDR_STROMMODUS=
48|je48|je96), Vorgabe bleibt das heutige Verhalten, und ein anderer
Modus schreibt eine Warnung ins Log: die Oberflaeche bekommt das erst,
wenn der zweite Kanal oben einen Empfaenger hat (BoardCapabilities fuehrt
weiter maxReceivers = 1).

ZWEI EIGENE ANNAHMEN HAT DAS GERAET WIDERLEGT, beide heute:

1. "Zwei Stroeme haben eigene Nummernraeume." Falsch -- sie laufen
   GLOBAL fortlaufend, byte9 wechselt dabei:
     0(Kanal1) 1(Kanal2) 2(Kanal1) 3(Kanal2) ...
   Je Kanal gezaehlt sah jeder Kanal nur jede zweite Nummer, und der
   Zaehler meldete 50 % VERLUST bei einem vollkommen gesunden Strom. Der
   Pruefstand hatte meine Annahme bestaetigt, weil ich sie
   hineingeschrieben hatte; das Geraet hat sie widerlegt.

2. Die Modusnamen. Aus dem Mitschnitt sah es nach 48+96 bzw. 96+144 kHz
   aus (verschiedene Raten je Kanal); mit NUR diesem Rahmen kommen beide
   Kanaele gleich schnell. Die Namen heissen jetzt je48/je96, nach dem
   Gemessenen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
oe5sos and others added 2 commits October 3, 2026 20:12
…e belegt

setSampleRate war seit dem 2026-08-26 ein No-op. Jetzt waehlt es den
Stromstart-Rahmen: 48000 -> ein Strom, 96000 -> zwei Stroeme je 96 kHz,
davon geht Kanal 0 an den Empfaenger. Steht die Verbindung schon, geht
der Rahmen sofort hinaus; das Geraet startet den Strom neu und faengt die
Folgenummern bei null an -- auditStreamSeq erkennt das als Neuanfang (im
Lauf zu sehen: "Folgenummern fangen neu an (368 -> 2)").

Nur die zwei gemessenen Raten, jede andere aendert NICHTS und schreibt
eine Warnung: ein geratener Rahmen bedeutet nicht "geht nicht", sondern
Daten einer Rate in einem Kanal einer anderen -- genau das ist am
2026-09-24 passiert (48k in einem 192k-Kanal) und wurde am Geraet als
"schlechtes Rauschen" gehoert.

setActiveReceiverCount ist ebenfalls kein No-op mehr: die Verbindung
merkt sich, fuer wie viele Kanaele es oben einen Empfaenger gibt, und
verwirft die anderen. Nicht um dem Geraet etwas zu sagen -- welcher
Rahmen die Empfaengerzahl stellt, ist offen -- sondern damit ein zweiter
Strom nicht nach oben geht, wo er bestenfalls ignoriert und
schlimmstenfalls mit Kanal 0 vermischt wuerde.

EIN EIGENER FEHLER, ZWEIMAL AN DERSELBEN STELLE: das Verwerfen stand
zuerst VOR der Folgenummern-Zaehlung. Weil die Nummern global ueber alle
Stroeme laufen, fehlte jede uebersprungene Nummer im Nummernraum, und der
Zaehler meldete 50 % VERLUST bei einem vollkommen gesunden Strom. Jetzt
wird erst gezaehlt, dann verworfen -- und der Messlauf sagt
"Folgenummern sauber, 960/s, 0 Spaetlinge".

Live am Geraet, ganze Kette: mit 48 kHz verbunden, zur Laufzeit auf
96 kHz umgestellt, Kanal 0 mit 747 Pakete/s an den Empfaenger, Kanal 1
verworfen, kein Verlust. 89/89 gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nn es jetzt anbieten

sampleRates = {48000, 96000}, maxSampleRate = 96000. Beides am
2026-10-03 am Geraet gemessen und durch die ganze Kette belegt: der
Stromstart-Rahmen 0x01 stellt die Rate, setSampleRate waehlt ihn, und
Kanal 0 kommt mit 480 Folgenummern je Sekunde = 96 kHz beim Empfaenger
an -- ohne Verlust, mit erkanntem Stromneustart.

Bis heute stand dort 48 000 mit dem Vermerk "nicht verhandelt". Das war
die Grenze unseres Wissens, nicht die des Geraets.

144 000 waere ebenfalls belegt (zwei Stroeme je 96 kHz = 192 kHz
zusammen), steht aber NICHT in der Liste: ein Eintrag dort heisst, dass
die Oberflaeche die Rate anbietet, und was angeboten wird, muss durch den
ganzen Weg stimmen. Einmal Daten einer Rate in einem Kanal einer anderen,
und der Betreiber hoert "schlechtes Rauschen" (2026-09-24). Erst wenn
der zweite Kanal oben einen Empfaenger hat, kommt mehr dazu.

Die zwei Pruefungen, die "die QRP kann nur 48 kHz" festhielten, sind auf
das Gemessene umgestellt -- und der Punkt, auf den sie eigentlich zielen,
ist geschaerft: was die QRP NICHT kann (192 kHz, 144 kHz), bleibt
gesperrt, und genau das ist am 2026-09-24 schiefgegangen.

9/9 SunSDR-Pruefstaende gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oe5sos oe5sos changed the title SunSDR QRP: Mikrofon-PTT am Gerät erkennen — die letzte Empfangslücke SunSDR2 QRP: 96 kHz, zwei Stroeme, Uebersteuerung und Mikrofon-PTT Oct 3, 2026
oe5sos and others added 16 commits October 3, 2026 20:29
Bis heute schickte disconnect() dem Funkgeraet GAR NICHTS -- Sockets zu,
Timer aus, fertig. Gemessen am 2026-10-03: die QRP streamt danach
unbegrenzt weiter, 1940 Pakete/s und 2,3 MB/s ins Leere, bis sie
ausgeschaltet wird, und der Mac antwortet auf jedes Paket mit ICMP. In
diesem Zustand laesst sie sich auch schlecht neu verbinden -- sehr
wahrscheinlich der Grund, warum ExpertSDR2 am selben Abend zweimal nicht
durchkam.

Der Rahmen stand im Mitschnitt: beim Beenden schickt ExpertSDR2 0x06 mit
0 (MOX aus) und 0x02 mit vier Nullbytes -- und das LETZTE Strompaket liegt
in derselben Millisekunde wie 0x02. ArtemisSDR fuehrt 0x02 als
SUNSDR_OP_POWER_OFF, was dazu passt.

Der gebaute Rahmen ist BITGLEICH mit dem aufgezeichneten
(03ff0200040000000000010000000d99f99d00000000, dreimal im Mitschnitt,
immer derselbe); eine Pruefung haelt das fest.

AM GERAET GEGENGEMESSEN: nach dem Trennen 0 Pakete/s auf der
Schnittstelle. Vorher 1940.

Geschickt wird nur, wenn die Verbindung wirklich stand -- vor dem
Handschlag gibt es keine Gegenstelle, und ein Stopp an eine Adresse, die
wir nicht kennen, waere ein Paket ins Nichts. Dafuer gibt es eine eigene
Pruefung. 0x06 (MOX aus) schickt Longpath NICHT mit: der Strom verstummt
schon auf 0x02, und fuer den MOX-Opcode gilt weiter die Sperre, bis seine
Bedeutung an der QRP bestaetigt ist.

35/35 und 91/91 gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e heraus

Alle Antworten des Geraets aus ALLEN drei Mitschnitten zusammengetragen
(23.09. und 03.10., also ueber zehn Tage):

  0x0c: 5 Antworten, 1 verschieden, 320 Byte
  0x0d: 5 Antworten, 1 verschieden, 320 Byte
  0x12: 5 Antworten, 1 verschieden,  20 Byte

Bitgleich, ueber zehn Tage, ueber Neustarts und Bandwechsel hinweg. Das
sind Werksdaten -- Kalibrierung, Typ, Version --, keine Momentanwerte.
Dazu passt, dass das Geraet unaufgefordert gar nichts schickt und die
Zustandsbytes im Stromkopf konstant bleiben.

Abschliessend fuer die Paritaetsliste: im Empfang gibt es bei der QRP
KEINE Geraetemesswerte. Nicht ueber 0x0c, nicht ueber 0x0d, nicht ueber
0x12, nicht unaufgefordert, nicht im Stromkopf. Das ist kein Mangel von
Longpath, sondern eine Eigenschaft des Geraets -- und was P1/P2 dort
melden, ist ohnehin senderseitig (Vorwaerts-/Rueckwaertsleistung,
PA-Temperatur). Ob die QRP das beim SENDEN herausgibt, ist eine eigene
Frage und gehoert zum Dummy-Load.

Damit ist die Meldeseite im Empfang vollstaendig, ohne dass das Geraet
einen einzigen Messwert liefert: S-Meter rechnet Longpath aus dem I/Q,
Uebersteuerung kommt aus dem Signal, Mikrofon-PTT aus dem Stromkopf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beide Seiten fassen SunSdrRadioConnection an denselben Stellen an, und
alle Konflikte waren rein additiv: Mitglieder, ...ForTest-Zugriffe, der
Ruecksetzblock in connectToRadio und zwei Paare von Pruefungen, die sich
ihre Aufbauzeilen teilten. Beide Seiten bleiben vollstaendig.

Der Hinweis der Nebensitzung war richtig und wichtig: solange der
Konflikt bestand, hat GitHub fuer #167 GAR KEINEN CI-Lauf gestartet --
bei pull_request wird gegen den Verschmelzungs-Verweis gebaut, und den
kann es bei Konflikten nicht anlegen. Die 11 "pending", die ich den
ganzen Abend gesehen habe, waren also nie ein laufender Bau.

Beim Aufloesen selbst ein Fehler gemacht und behoben: die erste Fassung
hat den Bereich ZWISCHEN den verschachtelten Konfliktbloecken
mitueberschrieben, und damit acht Pruefungen (Kanaele, Strommodus,
Mikrofon-PTT) verloren. Gemerkt an der Zahl -- 85 statt der erwarteten
93 --, aus dem Stand vor dem Merge zurueckgeholt und gegengezaehlt.

9/9 SunSDR-Pruefstaende gruen, 93 Faelle in tst_sunsdr_radio_connection.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…#171)

Eine Nebensitzung hat gemessen, dass sich Logzeilen gegenseitig
zerschreiben, wenn mehrere Faeden gleichzeitig schreiben: 7 bis 55 % der
Zeilen gingen GANZ verloren (behoben in PR #171, dort noch offen). Das
betrifft alles, was auf dem Blatt aus Longpaths Logdatei gelesen wurde,
und gehoert dazugesagt.

Durchgegangen, welcher Befund an Logzeilen haengt: die Zahlen (Raten,
Kanaele, Pakete) kommen aus Zaehlern im Treiber, der Verbindungsablauf
und der Stopp-Rahmen aus tcpdump -- beides nicht von der Logdatei
betroffen. ANFAELLIG war genau ein Schluss: "das Geraet meldet von sich
aus nichts", denn fehlende Zeilen haetten wie fehlende Meldungen
ausgesehen. Der ist unabhaengig bestaetigt: der Mitschnitt zeigt jedes
Paket am Draht, und dort kommt zwischen den Quittungen nichts.

Regel daraus: ein Negativ-Schluss ("es kommt nichts") darf nicht allein
auf einer Logdatei stehen. Zaehler im Code oder ein Mitschnitt am Draht
zaehlen, was wirklich ankam.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… wacht

Hinweis aus einer Nebensitzung: ein Pruefstand KANN widersprechen, wenn
man ihn zuerst gegen die alte Fassung laufen laesst. "Gruen mit der
Behebung sagt nichts, rot ohne sie sagt alles."

Genau das fehlte hier: alle Pruefungen zu den drei Fehlern, die das Geraet
heute aufgedeckt hat, wurden NACH der Behebung geschrieben. Nachgeholt,
indem der Code jeweils zurueckgebaut und derselbe Pruefstand erneut
gefahren wurde:

  zweiStroemeLandenAufVerschiedenenKanaelen      rot (seqLost = 1)
  wiederholungMitAbstandIstKeinSpaetling         rot
  stromneustartWirdErkanntUndNichtZumDauerzustand rot
  einzelnerSpaetlingIstKeinNeuanfang             gruen in BEIDEN

Die ersten drei fangen wirklich. Die vierte ist kein Faenger, sondern ein
Waechter -- sie soll in beiden Fassungen gruen sein und schlaegt erst an,
wenn die Neuanfang-Erkennung zu frueh greift. Beides ist nuetzlich, aber
nicht dasselbe, und wer es nicht prueft, haelt Waechter fuer Faenger.

93/93 nach der Wiederherstellung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
96 kHz war bisher nur ueber LONGPATH_SUNSDR_STROMMODUS gemessen, also
nicht ueber den Weg, den die Oberflaeche nimmt (setSampleRateLive ->
setSampleRate bei stehender Verbindung). Nachgemessen, zwei Laeufe:

  48 kHz    240 Nummern/s, 1200 angenommen, 0 verloren, Kopf nur 0100
  96 kHz    400 Nummern/s, 4797 angenommen, 0 verloren, Kopf 0100 -> 0200/0201

Der Stromkopf ist der Beleg: das Geraet hatte einen Strom (byte8=01) und
hat nach EINEM Rahmen zwei (byte8=02, byte9 wechselt). Kein Neuverbinden,
kein Umgebungsschalter, und kein verlorenes Paket dabei.

Offen und als offen notiert: die Kanalzaehler kommen ungleich heraus
(724/s gegen 1014/s). Teils Buchfuehrung -- sie laufen ab dem Verbinden,
Kanal 0 enthaelt also noch die 48-kHz-Phase. Der Rest ist unerklaert; es
ist aber kein Verlust (0 von 4797 im selben Zeitraum).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An der echten QRP gefunden, nicht am Pruefstand: die Oberflaeche stellt
96 kHz ein, Longpath meldet "Connecting with sampleRate= 96000",
inSize= 128 -- und das Geraet streamt weiter mit 48 (Stromkopf 0100,
240 Nummern/s). WDSP lief also auf 96 kHz, waehrend die Daten mit 48
ankamen. Genau der Fall, vor dem die Warnung in setSampleRate selbst
steht ("Daten einer Rate in einem Kanal einer anderen", am 2026-09-24
als schlechtes Rauschen gehoert).

Ursache: RadioModel::connectToRadio schiebt setSampleRate und
setActiveReceiverCount AUSDRUECKLICH VOR dem Verbindungsaufruf in die
Warteschlange des Verbindungsfadens -- mit eigener Begruendung an der
Stelle. Der Sitzungs-Reset in connectToRadio hat beide danach wieder auf
die Vorgabe gesetzt. Mein eigener Kommentar dort behauptete die
umgekehrte Reihenfolge ("setSampleRate stellt danach um"); der Code
hatte sie nie.

Behebung: der Reset nimmt die Umgebungsvorgabe nur noch, wenn
LONGPATH_SUNSDR_STROMMODUS tatsaechlich gesetzt ist, und ruehrt die
Empfaengerzahl nicht mehr an.

Warum es keine Pruefung gefangen hat: die vorhandene
setSampleRateStelltDenStromstartRahmenUm ruft setSampleRate NACH
connectToRadio -- in der Reihenfolge, die geht, nicht in der, die die
Anwendung nimmt. Zwei neue Pruefungen in der echten Reihenfolge, beide
zuerst gegen die unbehobene Fassung gefahren und dort ROT:

  rateVorDemVerbindenUeberlebtDenSitzungsReset          rot -> gruen
  empfaengerzahlVorDemVerbindenUeberlebtDenSitzungsReset rot -> gruen

Danach am Geraet nachgemessen: Stromkopf 0200 statt 0100, 960 Nummern/s
statt 240, 13,2 Mbit/s herunter. 95/95.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Ring hielt 128 Nummern, verglichen wurde aber nur die NUMMER. Die
Inhaltspruefung in processStreamDatagram sah nur die unmittelbar vorige
Nummer desselben Kanals an. Kehrte eine Nummer mit Abstand wieder, galt
sie ungeprueft als bytegleiche Kopie.

Der Ring traegt jetzt ein Merkmal des Inhalts mit. Gleiche Nummer +
gleicher Inhalt = Kopie (daran haengt die Achtfachungs-Erkennung).
Gleiche Nummer + anderer Inhalt = der Zaehler ist umgelaufen, also ein
neuer Block: weder Kopie noch Verlust.

EHRLICH DAZU: diese Aenderung bewegt die gemessene Zahl NICHT. Ich hatte
sie aus einem Mitschnitt begruendet (0 bytegleiche Kopien auf dem Draht
gegen 1,41 gemeldet) -- und der Schluss war falsch. Der Mitschnitt
stammt aus einer anderen Betriebsart (609 Pakete/s, streng +1), nicht
aus je96. Am Geraet nachgemessen meldet die geraeteeigene Sonde:

  480 Folgenummern/s | 1x bei 390, 2x bei 70, 3x bei 20 Nummern
  Wiederholungen 114, davon GANZ bytegleich 114, verschieden 0

Die Wiederholungen sind also echt. Die Aenderung bleibt trotzdem, weil
sie die Groesse belastbar macht: eine wiederkehrende Nummer wird nur
noch dann als Kopie gezaehlt, wenn sie eine ist. Ohne das haette ein
umlaufender Zaehler dieselbe Zahl erzeugt wie eine echte
Verschlechterung, und an dieser Zahl erkennen wir die Achtfachung.

Pruefung zuerst gegen die unbehobene Fassung gefahren und dort ROT
(gleicheNummerMitAnderemInhaltIstKeineKopie). 96/96.

Offen und notiert: bei 96 kHz liegt die Kopienzahl bei 1,5, bei 48 kHz
bei 1,0 -- die Blockantwort kommt bei vierfacher Datenmenge nicht mehr
ganz nach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ng widerlegt

Bei 48 kHz 1,00 Kopien je Nummer, bei 96 kHz 1,2 bis 1,5 -- rund 105
ueberfluessige Pakete je Sekunde.

A/B am Geraet (je 8 s, je96):

  BLOCKANTWORT=0   877 Pakete/s, 401 Wiederholungen/s, 1,84 Kopien
  Vorgabe (an)     582 Pakete/s, 105 Wiederholungen/s, 1,22 Kopien

Die Quittung wirkt also, sie ist nur nicht vollstaendig. Nebenbei: ohne
Quittung sind es bei 96 kHz 1,84, nicht die 8,1 von 48 kHz -- das
Wiederholverhalten haengt selbst von der Betriebsart ab.

WIDERLEGT: den Kopf des Geraets in der Blockantwort spiegeln. Als
Schalter eingebaut, gemessen, kein Unterschied (147/117/104/99 gegen
150/127/101/100), Schalter wieder entfernt. byte8/byte9 beschreiben im
Hinweg unseren eigenen Strom, nicht den des Geraets.

Offen, mit Hinweisen notiert: das Einschwingen (147 -> 99 ueber die
ersten Sekunden), der nur 32 Nummern grosse Antwort-Ring (~54 ms bei
96 kHz, Nummern laufen darin um) und die ungeprueften zwei
Stille-Stroeme. Kein Richtigkeitsfehler -- 0,02 bis 0,04 % Verlust, der
Ton laeuft. Netzlast.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ts am Lautsprecher

Vom Betreiber am 2026-10-04 gemeldet: "ton war bei der app da, aber hier
beim mac nicht" -- die Handy-App bekam den Ton ueber TCI, aus den
Lautsprechern des Macs kam nichts.

Im Log steht die Ursache:

  07:24:21  PortAudioBus: output via [Core Audio] on "MacBook Air-..."
  07:57:45  AudioEngine started ( speakers bus open )

Der Ausgang wurde beim Programmstart geoeffnet und 33 Minuten spaeter
beim Verbinden wiederverwendet. AudioEngine::ensureSpeakersOpen() prueft
mit isOpen(), und das ist bei PortAudioBus ein ZEIGERVERGLEICH:

  bool isOpen() const override { return m_stream != nullptr; }

Stirbt der Strom darunter -- Geraet gewechselt, Abtastrate umgestellt
(auf dem Rechner laufen BoomAudio und DeskFx als virtuelle Treiber; das
Standardgeraet stand auf 44 100, der Strom auf 48 000), Ruhezustand --,
bleibt der Zeiger stehen. ensureSpeakersOpen kehrt sofort zurueck,
Longpath schreibt weiter in einen toten Strom, und nichts faellt auf.

IAudioBus bekommt isAlive() mit isOpen() als Vorgabe, damit jeder Bus
ohne eigene Auskunft sich verhaelt wie bisher. PortAudioBus beantwortet
es mit Pa_IsStreamActive -- nur 1 heisst, es kommt wirklich etwas
heraus; 0 und jeder negative Fehlercode (etwa paDeviceUnavailable)
gelten als tot. ensureSpeakersOpen raeumt einen toten Bus weg, meldet es
und oeffnet darunter neu.

Zwei Pruefungen, zuerst gegen die unbehobene Fassung gefahren:

  lebenderAusgangBleibtStehen    gruen in BEIDEN -- Waechter: ein
                                 lebender Bus darf nicht bei jedem Start
                                 neu geoeffnet werden, sonst klickt es
  toterAusgangWirdWeggeraeumt    ROT ohne die Behebung, gruen mit ihr

4/4.

Nicht geprueft und deshalb nicht behauptet: ob das am Geraet des
Betreibers wirklich die Ursache war. Das Log zeigt den Aufbau, nicht den
Tod des Stroms -- PortAudio meldet ihn nirgends. Genau deshalb gibt es
die Meldung jetzt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…an einer toten Sitzung

Der Vorfall vom 2026-10-04: der Betreiber kam eine halbe Stunde lang
nicht mehr an die QRP ("no beacon reply"). Einzeln geprueft und einzeln
in Ordnung: Funkgeraet, Netz, Port im Eintrag, TCI-Server, der
MANUAL-Schluessel, seine Einstellungsdatei und seine installierte
Fassung -- die beiden letzten habe ich mit SEINEN Dateien und SEINEM
Binary nachgefahren, beide verbanden. Erst Aus- und Einschalten half.

Ursache: die QRP bedient EINEN Client und haelt die Sitzung fest. Ich
hatte Pruefinstanzen hart beendet, und in einem Lauf stand im Log

  WRN: SunSdr: beim Verbindungsende noch unquittiert: 0x02

Kommt der Stopp nicht an, bleibt das Geraet an den Toten gebunden und
antwortet auf neue Suchmeldungen nicht mehr.

Zwei Aenderungen:

1. disconnect() schickt den Stopp nach, solange er unquittiert bleibt --
   drei Versuche a 150 ms, dabei wird wirklich gelesen (der
   Ereignisschleife laeuft an der Stelle nichts mehr zu). Der Stopp
   verstellt nichts, er meldet nur ab, also ist mehrfach unschaedlich.
   Bleibt er nach drei Versuchen offen, sagt das Log, dass nur noch Aus-
   und Einschalten hilft.

2. Die Fehlermeldung nennt jetzt alle drei Ursachen in der Reihenfolge,
   in der man sie pruefen soll -- die haengende Sitzung zuerst. Der alte
   Text ("radio unreachable or discovery blocked") hat heute die halbe
   Stunde gekostet, weil er genau den Fall nicht nannte, der vorlag.

Pruefung zuerst gegen die unbehobene Fassung gefahren und dort ROT
(bleibtDerStoppUnquittiertWirdErNachgeschickt: nur 1 Stopp geschickt).
trennenSchicktDenStopp erwartet jetzt ">= 1" statt genau 1. 97/97.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
setAntennaRouting() war ein leerer Rumpf, obwohl der Rahmenbauer
(buildAntennaSelectFrame) seit Langem fertig und belegt ist. Jetzt ist
der Weg vollstaendig verdrahtet: trxAnt 1..3 auf A1/A2/A3, Richtung aus
routing.tx, einschliesslich der Falle, derentwegen die Byte-Tabelle
ueberhaupt existiert -- A3 traegt je Richtung ein ANDERES Byte
(RX 0x03, TX 0x02).

Es geht aber NICHTS hinaus. Die Auswahlbytes stammen aus ArtemisSDR,
also von der DX/PRO, und am 2026-10-03 hat sich am Geraet gezeigt, dass
die Opcode-Nummern der QRP andere sind: Vorverstaerker 0x04 statt 0x05,
DDC 0x07 statt 0x08, erstes Byte des Rahmens 0x03 statt 0x32. Damit ist
0x15 ein Verdachtsfall, kein Fakt -- und ungepruefte Bytes gehen nicht
ungefragt an fremde Hardware.

Stattdessen steht im Log, was hinausgegangen WAERE, mit den Bytes:

  SunSdr: Antennenwahl A2 (Empfang) waere 03 ff 15 00 04 00 ... --
  NICHT geschickt. ... scharf mit LONGPATH_SUNSDR_ANTENNE=1 und einem
  50-Ohm-Abschluss.

Drei Pruefungen: stumm als Vorgabe, scharf schickt, Buchse ausserhalb
1..3 wird nicht geraten. 100/100.

Zur Gegenprobe: die scharfe Pruefung habe ich NICHT gegen die alte
Fassung gefahren -- der alte Rumpf war buchstaeblich  und kann
nichts geschickt haben. Das ist am Code ablesbar, nicht erschlossen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der erste Tag, an dem Longpath selbst gegen die QRP lief statt nur
Pruefstand und Messlauf. Drei Fehler, die kein Pruefstand gezeigt hat --
einer davon an einer Stelle, die gestern als erledigt galt:

  8884494  die eingestellte Rate wurde beim Verbinden weggeworfen
  c876185  ein toter Lautsprecher-Ausgang galt als offen
  9c48cb5  der Abmelde-Rahmen wurde nicht nachgeschickt

Dazu an der Liste nachgezogen: der veraltete 312-500-Hz-Kommentar ist
beim Umbau verschwunden, und setAntennaRouting ist verdrahtet, aber
stumm (8e54dec).

Im Empfang fehlt unveraendert genau eines: micPttFromRadio, und das
braucht den Mitschnitt.

Zwei offene Beobachtungen festgehalten, beide ohne Antenne messbar: die
Wiederholungen bei 96 kHz (1,2 statt 1,0) und die Lautstaerke -- bei
letzterer ist nachgerechnet, dass die Probenumrechnung stimmt und keine
geraeteeigene Pegel-Eichung fehlt; der Vergleich gegen die Anvelina ist
auf Wunsch des Betreibers vertagt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…schluss

Zwei Dinge.

ERSTENS eine Korrektur an mir selbst: ich hatte heute in die
Lueckenliste geschrieben, im Empfang fehle "unveraendert eines:
micPttFromRadio". Das war falsch -- ich hatte eine aeltere Aussage
abgeschrieben, ohne den Code zu pruefen. Das Mikrofon-PTT ist seit
1e4eb06 gebaut und wird OHNE Protokollwissen aus dem Stromkopf
abgeleitet (0xFD sendet, 0xFE empfaengt), mit Flankenerkennung und
Abgrenzung gegen eigenes MOX, geprueft in sendezustandAmGeraetMeldetPtt.

Damit ist der Empfang funktional vollstaendig. Offen ist nur die
Bestaetigung am Geraet, und die braucht keinen Mitschnitt, sondern einen
50-Ohm-Abschluss: wer die Mikrofontaste drueckt, bringt das Geraet in
den Sendezustand.

ZWEITENS der Pruefplan dafuer. Alles Restliche haengt an diesem einen
Abschluss, also soll es in EINEM Durchgang gehen:

  A  Mikrofon-PTT bestaetigen (genau zwei Logzeilen je Tastendruck)
  B  die vermuteten Sende-Opcodes EINZELN pruefen, gegen die Quittung
     des Geraets (15-50 ms, am 2026-10-03 gemessen) -- die Antennenwahl
     zuerst, weil sie als einzige nichts erzeugt
  C  erst dann tasten, eine Sekunde

Der Grund fuer die Einzelpruefung steht dort auch: die QRP benutzt
nachweislich ANDERE Opcodes als die DX/PRO, aus der alle unbestaetigten
Zahlen stammen (0x04 statt 0x05, 0x07 statt 0x08, 0x03 statt 0x32).
Jede Sende-Zahl ist damit Verdacht, nicht Fakt.

Und der Hinweis, der sonst im Betrieb ueberrascht: setTxDrive ist ein
leerer Rumpf. Longpath kann die Leistung nicht stellen -- es gilt, was
zuletzt in ExpertSDR2 stand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
setTxDrive war ein leerer Rumpf -- und bedient ein Bedienelement. Der
Betreiber dreht die Leistung herunter, sieht die Zahl sinken, und am
Geraet aendert sich nichts. Beim Senden ist das kein
Schoenheitsfehler, sondern eine Falle.

Jetzt meldet Longpath einmal je Sitzung (nicht bei jedem Reglerschritt),
dass der Wert NICHT hinausgegangen ist und dass gilt, was zuletzt in
ExpertSDR2 eingestellt war.

Warum nicht gleich verdrahten: der Rahmenbauer fuer 0x17 liegt fertig,
aber die Nummer stammt von der DX/PRO, und die QRP benutzt nachweislich
andere (0x04 statt 0x05 beim Vorverstaerker, 0x07 statt 0x08 bei der
DDC, 0x03 statt 0x32 als erstes Byte). Verdrahtet wird sie, wenn sie am
Geraet quittiert wurde -- der Weg dahin steht in
docs/development/sunsdr-abschluss-pruefplan.md.

100/100.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… ihn weggeworfen

Der Betreiber hat heute richtiggestellt: "es waren immer beide rx und
rx2". In ExpertSDR2 liefen also immer BEIDE Empfaenger -- und damit war
der zweite Datenstrom, den Longpath bei zwei Stroemen bekommt, nie ein
Raetsel, sondern schlicht RX2.

Aus seinem Mitschnitt nachgerechnet, Kanal gegen Kanal:

  Kanal 0   -130,0 dBFS   Q ungleich null 21,2 %
  Kanal 1   -127,9 dBFS   Q ungleich null 31,5 %

Kanal 1 traegt echtes I/Q, sogar etwas KRAEFTIGER als Kanal 0. Die
Lueckenliste nannte ihn "wird angenommen, bleibt aber stumm" -- das war
falsch, und zwar seit dem 2026-10-03.

Zwei Aenderungen:

1. BoardCapabilities: maxReceivers 1 -> 2, maxSlices 1 -> 2. Bis dahin
   verwarf processStreamDatagram jeden Kanal >= m_aktiveEmpfaenger, und
   das war immer 1.

2. Der Stromstart-Modus haengt jetzt an BEIDEM -- Empfaengerzahl UND
   Rate -- statt nur an der Rate:

     1 Empfaenger, 48 kHz   ein Strom
     2 Empfaenger, 48 kHz   zwei Stroeme, je 48
     1 oder 2,     96 kHz   zwei Stroeme, je 96

   Ohne das konnte ein zweiter Empfaenger bei 48 kHz gar nie Daten
   bekommen: der Rahmen haette weiter einen Strom angefordert.

Dabei ist ein toter Zweig in setSampleRate weggefallen, den mein eigener
Zwischenstand erzeugt hatte.

Zwei Pruefungen, 102/102. Live am Geraet noch nicht bestaetigt -- das
steht als naechstes an und wird angekuendigt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
oe5sos and others added 23 commits October 4, 2026 09:49
Schalter LONGPATH_SUNSDR_EMPFAENGER im Messlauf, und damit der Beleg,
der db9cf49 noch fehlte. Am 2026-10-04 an der QRP gemessen:

                  ein Empfaenger   zwei Empfaenger
  Folgenummern        240/s            480/s
  nach oben           250/s            499/s
  Kanal 0        300/s, 0 verworfen  347/s, 0 verworfen
  Kanal 1             --             297/s, 0 verworfen
  Verlust              --              0,00 %

Im Log die ganze Kette: aktive Empfaenger -> 2, Stromstart-Rahmen ->
zwei Stroeme je 48 kHz, und das Geraet startet den Strom neu
(Folgenummern fangen neu an, 368 -> 2 -- die Neuanfang-Erkennung aus
der Nacht greift dabei und meldet keinen Verlust).

Beide Kanaele kommen oben an, nichts wird mehr verworfen. Der zweite
Empfaenger der QRP ist damit in Betrieb -- er war nie stumm, Longpath
hat ihn nur weggeworfen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…gestellt

Der Betreiber hat den nativen Empfang mehrfach als zu leise gemeldet --
"ich muss voll aufdrehen, dass ich etwas hoere", "bei der haelfte,
sprich 50 % faengt man an, etwas zu hoeren" --, waehrend ExpertSDR2 am
SELBEN Geraet ohne Antenne "perfekt" laut war. Damit war belegt, dass
es nicht an der fehlenden Antenne liegt.

Ursache: die +20,0 dB im QRP-Profil wurden am 2026-09-25 ueber den
TCI-Weg gemessen (rx_sensors). Der native Treiber ist ein anderer Weg
mit anderer Skalierung, und dort reichen sie bei Weitem nicht.

Statt eine Zahl zu RATEN wurde der Abgleich einstellbar gemacht
(LONGPATH_SUNSDR_PEGEL, dazu der Schluessel SunSdrRxLevelTrimDb). Der
Betreiber hat 40 gefahren und bestaetigt: "die lautstaerke passt". Im
Log seines Laufs steht "SunSdr: Pegelabgleich 40.0 dB (eingestellt)".
Seine Anforderung dazu, woertlich: "rauschen muss immer zu hoeren sein".

Die vorhandene Pruefung qrpSamplesAreRaisedByTheMeasuredTwentyDb hat die
alte Zahl festgehalten und ist beim Umstellen ROT geworden -- genau ihre
Aufgabe. Sie heisst jetzt ...FortyDb und traegt die neue Messung samt
Begruendung. Dazu eine zweite Pruefung in tst_sunsdr_protocol, die die
Zahl im Profil festhaelt (DX und PRO bleiben bei 0 -- nie an dieser
Hardware gemessen).

AUSSERDEM ZURUECKGENOMMEN: die Antennenwahl von 8e54dec. Beim Bauen lief
ich in einen Waechter, den dieses Projekt genau dafuer hat --
tst_sunsdr_protocol prueft, dass die DX-staemmigen Sende-Rahmenbauer
KEINE Aufrufstelle haben:

  buildAntennaSelectFrame() traegt eine DX-Opcode-Nummer, die fuer die
  QRP nicht bestaetigt ist. Erst bestaetigen, dann verdrahten.

Der Waechter hat recht, und ein Schalter, der standardmaessig aus ist,
hebt ihn nicht auf: verdrahtet ist verdrahtet. setAntennaRouting ist
wieder ein leerer Rumpf, jetzt mit der Begruendung und dem Verweis auf
den Pruefplan, wo 0x15 der erste zu bestaetigende Befehl ist.

99/100 bzw. 36/36.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… des Betreibers

Der zweite Empfaenger war nie stumm (db9cf49, b33072d), und die
Lautstaerke war eine ueber den falschen Weg geeichte Zahl (c873538).
Dazu die Ruecknahme der Antennenwahl, weil ein Waechter zu Recht
angeschlagen hat.

Beide Funde kamen aus Saetzen von Martin, nicht aus eigener Analyse --
und zu beiden Punkten stand in diesem Dokument eine Behauptung, die nie
am Geraet geprueft worden war. Das steht jetzt auch so da.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…fener Befund

Der Betreiber kam am Vormittag mehrfach nicht an die QRP ("no beacon
reply", Abbruch nach 3 s). Einzeln am Geraet ausgeschlossen: Geraet und
Netz (mein Pruefstand verbindet Sekunden spaeter in 51 ms), haengende
Sitzung (Stopp war quittiert), Port 1024 im Eintrag, MANUAL-Schluessel,
TCI-Server auf 50001, seine Einstellungsdatei und seine installierte
Fassung -- die letzten beiden mit SEINEN Dateien und SEINEM Binary
nachgefahren, beide verbanden.

Ein Socket-Beobachter (10 Abfragen/s) hat im Moment seines Klicks beide
Ports gesehen, UDP *:50001 und *:50002, ohne Bindefehler.

Der entscheidende Befund kommt aus einem tcpdump waehrend eines
Fehlversuchs: VIER Beacon-Antworten des Geraets, korrekt adressiert an
192.168.16.100:50001 -- genau den gebundenen Port. Die App hat keine
einzige verarbeitet.

Die Datagramme erreichen also den Rechner, aber nicht den Socket der
App. Beide Ports werden mit ShareAddress|ReuseAddressHint gebunden; bei
SO_REUSEPORT stellt der Kern ein Unicast-Datagramm genau EINEM Socket
zu. Wer der zweite waere, ist offen.

Zweiter offener Punkt aus demselben Mitschnitt: der Code schickt die
Anfrage laut sendDiscoveryBroadcast AUCH direkt an m_radioInfo.address.
Im Mitschnitt steht davon nichts -- dieses Paket ging nie hinaus.

Werkzeug fuers naechste Mal notiert: Start mit
QT_LOGGING_RULES='longpath.sunsdr.debug=true', dann steht jedes
empfangene Steuerdatagramm im Protokoll.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Am 2026-10-04 stand in einem tcpdump waehrend eines Fehlversuchs KEIN
einziges Paket an die Adresse des Geraets -- obwohl
sendDiscoveryBroadcast die Anfrage laut Code auch direkt dorthin
schickt, nicht nur als Rundruf. Dieses Paket ging nie hinaus, und nichts
hat es gesagt: der Rueckgabewert von writeDatagram wurde nirgends
geprueft.

Nach einer halben Stunde Suche war das der einzige Hinweis, der uebrig
blieb -- und er kam aus einem Mitschnitt, nicht aus dem Programm.

Jetzt meldet der Treiber drei Dinge, die vorher still blieben:

  * die direkte Anfrage ging nicht hinaus (mit errorString)
  * im Geraeteeintrag steht keine Adresse, es geht nur der Rundruf
  * keine Schnittstelle hatte eine Rundsendeadresse

Kein Pruefstand dazu: der Fehlerfall ist ein fehlschlagendes
writeDatagram, und das laesst sich ohne Socket-Attrappe nicht
herbeifuehren. Das ist eine Meldung, kein Verhalten -- sie aendert
nichts, ausser dass man es naechstes Mal im Log sieht statt im tcpdump.

99/99.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…chweigen

Beim Warten auf den Beacon wurde jedes nicht passende Datagramm still
verworfen. Am 2026-10-04 stand deshalb eine halbe Stunde die Frage im
Raum, ob im Socket ueberhaupt etwas ankommt -- erst ein tcpdump zeigte
vier Beacon-Antworten des Geraets, die im Programm nie angekommen sind.

Mit eingeschaltetem Protokoll steht der Unterschied zwischen "nichts
empfangen" und "etwas empfangen, aber verworfen" jetzt in einer Zeile:

  QT_LOGGING_RULES='longpath.sunsdr.debug=true'

Debug-Stufe, kostet im Betrieb nichts.

99/99.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
setPreamp(bool) war ein leerer Rumpf -- derselbe Fehler wie bei
setTxDrive: ein Bedienelement, das nichts bewirkt und nichts sagt.

Dieses Geraet kennt keinen An/Aus-Schalter fuer den Vorverstaerker. Es
hat vier feste Stufen (-20/-10/0/+10 dB, Opcode 0x04, am 2026-09-25 in
ExpertSDR2 durchgeschaltet und bestaetigt), gebaut als
setPreampModeIndex(). Der OpenHPSDR-Weg passt hier schlicht nicht.

Meldung einmal je Sitzung, nicht bei jedem Klick. 99/99.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Dreizehn leere Ruempfe standen als eine Liste da, ohne Unterschied
zwischen "gibt es an diesem Geraet nicht" und "noch nicht gebaut". Die
Lueckenliste nannte sie pauschal "16 leere Pflichtmethoden" -- eine
Zahl, die mehr Arbeit suggeriert als da ist.

Jetzt in drei Gruppen, je mit Grund:

  gibt es nicht        setTrxRelay, setUserDigOut, setPuresignalRun,
                       setWatchdogEnabled
  Senden, offen        setAntennaRouting, sendTxIq
  Mikrofonweg, offen   setMicBoost, setLineIn, setMicTipRing, setMicBias,
                       setLineInGain, setMicPTTDisabled, setMicXlr

Bei den offenen steht auch, warum nicht einfach gebaut wird: die
Opcode-Nummern stammen von der DX/PRO, und die QRP benutzt nachweislich
andere. Dazu der Verweis auf den Abschluss-Pruefplan und die Notiz, dass
ich am 2026-10-04 genau diese Regel mit setAntennaRouting verletzt habe
und zu Recht aufgelaufen bin.

Reine Kommentare, kein Verhalten geaendert. 99/99.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Kopftabelle vom 2026-10-02 (1500 Zeilen, 4 Signale, 16 leere
Methoden) war ueberholt und hat die Lage schlechter dargestellt, als sie
ist. Am 2026-10-04 nachgezaehlt:

                    ANAN   Anvelina   QRP
  Zeilen            4385     3774    2692
  Signale             10       12       8
  Leere Ruempfe        0        0      14

Dazu der Hinweis, dass die leeren Ruempfe nicht alle Arbeit sind: vier
gibt es an diesem Geraet nicht, zwei gehoeren zum Senden, sieben zum
Mikrofonweg -- und die beiden letzten Gruppen warten nicht auf Arbeit,
sondern auf Bestaetigung der Opcode-Nummern.

Die alte Tabelle bleibt stehen, mit dem Vermerk, dass sie ueberholt ist
-- sie ist datiert und gehoert zum Verlauf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… gesetzt

Selbst eingebaut und selbst gefunden. RadioModel schob
setActiveReceiverCount nur fuer Protokoll 1 hinaus -- fuer die SunSDR
also nie. Solange der Treiber beim Verbinden auf 1 zuruecksetzte, fiel
das nicht auf. Dieser Reset musste heute weg (8884494), weil er auch
die gerade gesetzte Rate wegwarf.

Damit blieb im Treiber stehen, was die VORIGE Sitzung gesetzt hatte:
eine Sitzung mit zwei Empfaengern vererbte den zweiten Strom an die
naechste, und ueber die Oberflaeche liess sich der zweite Empfaenger
beim Verbinden ueberhaupt nicht einschalten -- nur nachtraeglich.

Die SunSDR gehoert hier auf dieselbe Seite wie P1: ihr
setActiveReceiverCount setzt keine DDCs frei, sondern waehlt den
Stromstart-Modus (ein Strom oder zwei). Der Grund, aus dem P2 hier
ausgenommen ist, trifft auf sie nicht zu.

Keine neue Pruefung: der Fehler liegt in RadioModel::connectToRadio und
braucht eine echte Verbindung, um sichtbar zu werden. Die Treiberseite
ist durch zweiterEmpfaengerStelltAufZweiStroemeUm abgedeckt, und am
Geraet ist der Weg am 2026-10-04 gemessen (b33072d).

99/99 und 9/9.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Luecke im eigenen Beleg geschlossen. Am Geraet gemessen war bisher nur
die Treiberseite (b33072d: beide Kanaele, 0 verworfen) -- ob der Kanal
oben auch bei einem zweiten Empfaenger landet, haengt an
ReceiverManager::rebuildHardwareMapping und war ungeprueft.

Zwei Pruefungen, ohne Funkgeraet:

  kanalEinsOhneZweitenEmpfaengerLandetNirgends   Waechter: ein zweiter
      Strom, den niemand hoert, darf NICHT in den ersten Empfaenger
      laufen
  kanalEinsLandetBeimZweitenEmpfaenger           und zwar mit SEINEN
      Daten, nicht zweimal denselben

Beim Schreiben gelernt: createReceiver() legt den Empfaenger nur an,
activateReceiver() macht ihn aktiv -- ohne das baut
rebuildHardwareMapping gar keine Abbildung, und auch Kanal 0 kommt
nirgends an. Die erste Fassung der Pruefung ist genau darueber
gestolpert.

4/4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Beleg vom Nachmittag war halb: gemessen war die TREIBERSEITE (beide
Kanaele an, 0 verworfen). Am Geraet nachgeholt, mit activeRxCount = 2 und
EINER Scheibe:

  SunSdr: aktive Empfaenger -> 2
  SunSdr: Stromstart-Rahmen -> zwei Stroeme, je 48 kHz
  ReceiverManager: first feedIqData forwarded; hw= 0 -> rx0
  ReceiverManager: first feedIqData DROPPED; hw= 1  map= "hw0->rx0"

Geraet schickt zwei Stroeme, Treiber reicht beide hoch, WDSP hat zwei
Kanaele -- und ReceiverManager kennt einen Empfaenger.

Das ist kein Fehler, sondern die Bauweise: ein Empfaenger entsteht in
RadioModel::syncReceiverToStream, und die wird gerufen, wenn sich eine
SCHEIBE an einen Strom bindet. RX2 erscheint mit der zweiten Scheibe --
dafuer steht maxSlices seit heute auf 2.

Die Meldung dazu sagte nur . Jetzt sagt sie, dass es
oben keinen Empfaenger gibt und woran das liegt.

Offen und notiert: mit einer Scheibe und activeRxCount = 2 fordert
Longpath zwei Stroeme an und wirft den zweiten eine Ebene hoeher weg --
doppelte Netzlast ohne Gegenwert. Sauberer waere, den Modus an die Zahl
der GEBUNDENEN Stroeme zu haengen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ill -9

Der Befund von heute Vormittag ("Beacon kommt am Rechner an, aber nicht
in der App") hatte eine einfachere Ursache. Gemessen:

  Pruefstand verbindet und trennt sauber     Geraet nach  3 s wieder da
  App: disconnect, dann SIGTERM              sofort
  App: disconnect, dann kill -9              ~60 s

In allen drei Faellen war der Abmelde-Rahmen quittiert. Der Unterschied
ist nicht der Stopp, sondern das abrupte Schliessen der Sockets: nach
kill -9 schickt das Geraet weiter an einen Port, den der Rechner mit
ICMP zurueckweist -- und danach schweigt es eine Weile.

Damit ist Martins Vormittag erklaert: jeder Fehlversuch lag in diesem
Fenster, weil er sofort wieder geklickt hat. Das Aus- und Einschalten
half nicht, weil es den Zustand loeste, sondern weil es Zeit kostete.

Gefunden hat es die Protokollzeile aus 0cf3e35, die waehrend der Suche
verworfene Datagramme meldet -- vorher war an der Stelle Stille.

Dazu in diesem Commit: RadioModel schickt der SunSDR beim Verbinden
nicht mehr den GESPEICHERTEN Empfaengerwert, sondern die Zahl der
Empfaenger, die es oben wirklich gibt. Mit activeRxCount = 2 und einer
Scheibe forderte Longpath sonst zwei Stroeme an und warf den zweiten
eine Ebene hoeher weg.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vorher nannte sie drei Ursachen und als erste "haengt an einer frueheren
Sitzung -- hilft nur Aus- und Einschalten". Das war die Vermutung von
heute Vormittag, und sie war falsch: gemessen sperrt das Geraet nach
einem abrupten Programmende rund EINE MINUTE und kommt dann von selbst
zurueck. Nach einem sauberen Beenden sperrt es gar nicht.

Die Meldung sagt das jetzt zuerst, mit der Zahl -- und vor allem, was zu
tun ist: warten statt gleich wieder klicken. Genau das hat den Vormittag
gekostet.

99/99.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ohne das haengt jede Live-Pruefung mit zwei Empfaengern an einem
Mausklick auf das Plus -- und genau die stand heute an: der zweite Strom
der QRP kommt oben erst an, wenn sich eine zweite Scheibe an ihn bindet.

Verb: addSlice. Antwort traegt die neue Scheibennummer.

Beim ersten Versuch mit Qt::BlockingQueuedConnection gebaut und damit
sofort in eine Selbstblockade gelaufen: der Handler laeuft bereits im
Hauptfaden (steht so an doConnect), und ein blockierender Aufruf in
denselben Faden kommt nie zurueck -- die Antwort blieb aus, die Instanz
hing. Jetzt direkt gerufen.

Was der Lauf danach gezeigt hat, und was noch fehlt: die zweite Scheibe
entsteht (slice: 1), teilt sich aber den Strom mit der ersten. Das ist
die Platzierungslogik -- ein DDC kann mehrere Scheiben tragen, und
solange beide im selben Ausschnitt liegen, braucht es keinen zweiten
Strom. Fuer den Live-Beleg von RX2 muesste die zweite Scheibe weit genug
weg liegen; die Bruecke kann die Frequenz noch nicht stellen.

Die Routenfuehrung selbst ist geprueft
(tst_sunsdr_zweiter_empfaenger_oben) und die Treiberseite am Geraet
gemessen (b33072d).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s letzte Glied

Die Kette stand bis auf ein Glied: BoardCapabilities::userDdcCount war
1. Damit hat der Strompool (SliceStreamAllocator::configure) genau einen
Platz, und eine zweite Scheibe kann nie einen eigenen Strom bekommen --
am Geraet sichtbar als

  Placement: slice 1 freq=14.1 MHz -> Rejected stream=-1

obwohl das Geraet zwei Stroeme liefert, der Treiber beide hochreicht und
ReceiverManager sie richtig verteilt.

Mit userDdcCount = 2 laeuft es durch, am 2026-10-04 am echten Geraet:

  Placement: slice 1 freq=14.1 MHz -> NewStream stream=1
  SunSdr: aktive Empfaenger -> 2
  SunSdr: Stromstart-Rahmen -> zwei Stroeme, je 48 kHz
  SunSdr: Folgenummern sauber -- 2401 Nummern in 5.0 s (480/s), 1.00 Kopien

480 Nummern/s statt 240, kein einziges "fallen weg" im Protokoll.

Moeglich wurde der Beleg durch das neue Verb setFreq in der
Automationsbruecke -- ohne Frequenzwechsel teilt sich die zweite Scheibe
den Strom der ersten, und das ist richtig so (ein DDC traegt mehrere
Scheiben, solange sie im selben Ausschnitt liegen).

9/9, 42/42, 32/32, 99/99, 4/4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…erlegt

Der als naechster Versuch notierte Gedanke -- bei zwei Stroemen auch
ZWEI Stille-Stroeme zurueckschicken statt einem -- bringt nichts. A/B
ueber je 10 s bei je96:

  eine Antwort:   111 / 115 / 101 Wiederholungen je Sekunde
  zwei Antworten: 108 / 117 / 106

Ununterscheidbar, Schalter wieder entfernt. Das ist etwas anderes als
das Spiegeln des Kopfes von heute frueh (dort ein Paket mit fremdem
Kopf, hier zwei kohaerente Stroeme) -- beide Wege sind jetzt gemessen
und negativ.

Damit sind beide Vermutungen aus diesem Dokument erledigt. Wer
weitermacht, soll nicht noch einmal am Kopf der Blockantwort drehen. Der
naechste sinnvolle Schritt waere ein Mitschnitt von ExpertSDR2 BEI
96 kHz: wiederholt es dort auch, ist es die Eigenart des Geraets und
kein Mangel von Longpath.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beim Durchlesen des eigenen Diffs aufgefallen: replyToBlock() steht
HINTER dem Verwerfen. Bei zwei Stroemen und einem Empfaenger wird Kanal 1
verworfen und damit nie quittiert -- und unquittierte Bloecke sind
genau das, was dieses Geraet wiederholt. Klang nach der Ursache.

Gemessen (je96, ein Empfaenger, je 10 s):

  vorher:  111 / 115 / 101 Wiederholungen je Sekunde
  nachher: 110 / 109 / 107 / 103

Kein Unterschied. Zurueckgenommen, weil die Aenderung ohne Nutzen nur
zusaetzliche Pakete nach oben erzeugt.

Drei Vermutungen sind damit gemessen und negativ: Kopf spiegeln, zwei
Stille-Stroeme, Quittung vor dem Verwerfen. Naechster Schritt ist ein
Mitschnitt von ExpertSDR2 BEI 96 kHz.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Betreiber: "das soll automatisch funktionieren".

Bisher gab die Verbindung nach drei Sekunden auf, wenn kein Beacon kam.
Am 2026-10-04 ist gemessen, dass das Geraet nach einem ABRUPTEN
Programmende rund eine Minute sperrt und dann von selbst zurueckkommt
(60 s nach kill -9, sofort nach einem sauberen Beenden). Der Betreiber
hat an dem Vormittag eine halbe Stunde verloren, weil jeder neue Klick
wieder in dasselbe Fenster fiel.

Jetzt wartet die Verbindung die Sperre ab und sucht von selbst erneut:
fuenf Anlaeufe im Abstand von 18 s decken die gemessene Minute ab. Der
Zustand bleibt dabei Connecting -- die Oberflaeche zeigt weiter
"verbinde", und wer nicht warten will, drueckt Trennen. Nur wenn
ueberhaupt KEIN Beacon kam; kam einer und nur der Strom fehlt, ist das
ein anderer Fehler und laeuft wie bisher in den Fehlschlag.

Drei vorhandene Prueflinien, die den Fehlschlag pruefen, haben das
richtigerweise gemeldet (sie warteten ploetzlich 90 s). Sie schalten die
Wiederholung jetzt ueber eine Pruef-Naht ab. Dazu zwei neue:

  ohneBeaconWirdDieSucheWiederholtStattAufzugeben  -- kein Fehlschlag mehr
  ohneWiederholungGibtEsDenFehlschlagSofort        -- Waechter: ohne die
      Wiederholung MUSS er noch kommen, sonst koennte die erste Linie
      auch dann gruen sein, wenn gar kein Fehlschlag mehr moeglich waere

AUSSERDEM die drei Funde der Durchsicht behoben:

  * die Logzeile beim Handschlag sagte "Strommodus aus der Umgebung",
    obwohl der Modus im Normalfall aus Rate und Empfaengerzahl der
    Bedienung kommt -- sie nennt jetzt die wirkliche Herkunft, dazu Rate
    und Empfaengerzahl
  * ein per Umgebungsvariable gesetzter Modus konnte Rate und
    Empfaengerzahl widersprechen (setSampleRate kehrte bei unveraenderter
    Rate frueh zurueck und liess den Modus stehen) -- beide werden jetzt
    mitgezogen
  * die Obergrenze von rund einer Sekunde beim Trennen steht jetzt im
    Kopf, mit der Begruendung, warum sie in Kauf genommen wird

101/101.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Abschnitt von heute abend behauptete, das Geraet sperre nach einem
abrupten Programmende rund eine Minute. Die Zahlen stammten aus JE EINEM
Durchgang, und daraus habe ich eine Regel gemacht.

Nachgemessen, drei Durchgaenge: verbinden, mitten im Strom kill -9,
sofort wieder verbinden -- dreimal sofort wieder da. Dazu ein vierter
ueber die ganze Anwendung: 6 Sekunden.

Was wirklich gilt: der Aussetzer tritt MANCHMAL auf (zweimal am
2026-10-04 belegt), loest sich von selbst innerhalb etwa einer Minute,
und die Ursache ist UNBEKANNT.

An der Behebung aendert das nichts -- die selbsttaetige Wiederholung
(43747cc) wartet die Sperre ab, gleich warum sie entsteht. Es aendert,
was wir behaupten duerfen.

Zweimal an einem Tag habe ich aus einer Einzelmessung eine Ursache
gemacht (vorher die Wiederholungen bei 96 kHz). Das steht jetzt als
Warnung im Dokument.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…n sind weg

Die Anleitung schickte den Betreiber noch nach zwei Dingen, die
inzwischen ohne Mitschnitt geklaert sind:

  * der zweite Empfaenger -- es ist derselbe Rahmen 0x01, erstes Byte;
    zwei Empfaenger laufen seit 38988a8 von Ende zu Ende, am Geraet
    belegt
  * die Abtastrate -- ebenfalls 0x01, zweites Byte, drei Nutzlasten
    durchgemessen

Uebrig bleiben zwei Fragen, und eine davon ist neu: wiederholt
ExpertSDR2 bei 96 kHz auch? Longpath bekommt dort ~110 bytegleiche
Wiederholungen je Sekunde, und drei Gegenmassnahmen sind gemessen und
wirkungslos. Zeigt der Mitschnitt dasselbe bei ExpertSDR2, ist die Frage
erledigt statt offen -- dafuer muss ExpertSDR2 aber auf 96 kHz stehen,
das steht jetzt dabei.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Empfang ist gleichwertig. Die Tabelle nennt je Posten, WIE er belegt
ist -- am Geraet oder am Pruefstand -- und die zweite, woran das Offene
haengt: 50-Ohm-Abschluss fuer alles Sendeseitige, zwei Minuten
ExpertSDR2 mit Mitschnitt fuer den Rest.

Dazu ausdruecklich, was niemand mehr versuchen soll: Kopf der
Blockantwort spiegeln, zwei Stille-Stroeme, Quittung vor dem Verwerfen.
Alle drei sind gemessen und wirkungslos.

Und die Mahnung, die der Tag zweimal gekostet hat: aus EINER Messung
wurde eine Ursache gemacht, bei den Wiederholungen und beim
Verbindungsaussetzer. Beide Male war die Zahl richtig und der Schluss
falsch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…fene Frage

Longpath bekommt bei 96 kHz rund 110 bytegleiche Wiederholungen je
Sekunde, bei 48 kHz keine. Drei Gegenmassnahmen sind gemessen und
wirkungslos (Kopf spiegeln, zwei Stille-Stroeme, Quittung vor dem
Verwerfen). Die Frage ist damit: wiederholt ExpertSDR2 bei 96 kHz AUCH?

  python3 tools/sunsdr_handshake_diff.py --wiederholungen <mitschnitt>

zaehlt sie und sagt, was das Ergebnis bedeutet -- statt dass jemand die
Auswertung nochmal von Hand schreibt.

Gegen Martins vorhandenen Mitschnitt geprueft (der stammt aus einer
anderen Betriebsart, 609 Pakete/s, zwei Kanaele zu je 305/s):

  bytegleiche Wiederholungen: 0 (0,0/s)

Das ist der erwartete Wert fuer diesen Mitschnitt und zeigt, dass die
Auswertung nicht einfach alles als Wiederholung zaehlt. Der Lauf, auf
den es ankommt, muss von ExpertSDR2 BEI 96 kHz stammen -- so steht es
auch in der Mitschnitt-Anleitung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant