Two entry windows and an SO2R box

LoggingSession mixed two things: the contest, which one station has one of,
and what the operator is typing, which belongs to a radio. It is now
ContestSession and RadioPosition. Two positions share one log, one score and
one run of serial numbers, so a station worked on radio 1 is a dupe on radio 2.
Frequency, mode, split, what is typed and whether you are running belong to
each radio on its own.

A second radio opens a second entry window. It has no menu of its own: it is
another view of the same contest, not another program. Only the window for
radio 1 opens the database and the connections.

Ctrl+Tab moves the operator to the other radio and the keyboard follows.
Ctrl+Shift+Tab puts both radios in the headphones.

OtrspBox speaks OTRSP to an SO2R box over a serial port: TX1/TX2 for the key,
RX1/RX2 and RX1S for the headphones, AUXnnn for an output line. It follows the
active radio, and every message points the box at this radio before keying, so
a message cannot go out of the radio the operator has just left. A command that
would change nothing is not sent, because the box works relays; N1MM does the
same. The box takes a Stream, so what it sends is tested without a serial port.

Still missing: alternating CQ, and voice keying on the second radio.

Looked at under Xvfb with two fake radios, one of them split: both windows up,
radio 1 showing 14008.00 into 14020.0, radio 2 on 14030.00, Ctrl+Tab moving the
keyboard between them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 16:49:24 +00:00
parent 43be3816c3
commit 1185faed78
22 changed files with 714 additions and 208 deletions

View File

@@ -140,15 +140,28 @@ and the bandmap draws a red bar at the transmit frequency. A radio that cannot
do split answers `RPRT -11`; that is an answer, not a broken connection, and
everything else it reported still counts.
A second radio makes the station SO2R. Both are read and both show on the
bandmap — the one you are on in green, the other in orange — but only the one
you are on drives the entry window, so the second radio moving cannot drag you
off the station you are working. Ctrl+Tab moves you to the other radio; contacts
record which one made them.
A second radio makes the station SO2R and opens a second entry window. The two
windows share one log, one score and one run of serial numbers, so a station
worked on radio 1 is a dupe on radio 2. What is typed, the frequency, the mode
and whether you are running belong to each radio on its own.
Not there yet: a second entry window, alternating CQ, and audio switching. What
is here is two radios read and logged correctly, not a full two-radio operating
position.
| Key | What it does |
|---|---|
| Ctrl+Tab | moves you to the other radio: the keyboard, the entry window and the box all follow |
| Ctrl+Shift+Tab | puts both radios in the headphones, and back |
Both radios show on the bandmap — the one you are on in green, the other in
orange — but only the one you are on drives its entry window, so the second
radio moving cannot drag you off the station you are working.
An SO2R box speaking OTRSP routes the key and the headphones. Name its serial
port in **Config → Radios** and it follows: `TX2` when you move to radio 2,
`RX1S` when you ask for both radios, and `TX` again before every message goes
out, so a message cannot go out of the radio you have just left. A command that
would change nothing is not sent, because the box works relays. Without a box
the logger just keeps track of which radio it is on and you switch by hand.
Not there yet: alternating CQ, and voice keying on the second radio.
### The bandmap
@@ -211,11 +224,11 @@ itself keys a contact on.
| `Nonemm.Contests` | Contest rules, the scoring engine, `.udc` files |
| `Nonemm.Formats` | Cabrillo out, ADIF in and out |
| `Nonemm.Storage` | The N1MM-compatible `.s3db` |
| `Nonemm.Rig` | Radio control over `rigctld` |
| `Nonemm.Rig` | Radio control over `rigctld`, and the SO2R box |
| `Nonemm.Spotting` | Spots, the bandmap, the DX cluster client |
| `Nonemm.Network` | Contacts shared between the stations of a multi-operator entry |
| `Nonemm.Keying` | CW through `cwdaemon` or a WinKeyer |
| `Nonemm.Session` | What the operator is typing and what the log says about it — no UI toolkit |
| `Nonemm.Session` | The contest in progress, and one entry position per radio — no UI toolkit |
| `Nonemm.App` | The Avalonia windows |
The split at `Nonemm.Session` is the important one: it references no UI