Files
Nonemm/docs/unfinished.md
ericek111 7ae60be4a0 Write down what the count lag and the symbol count measure
The third probe run puts numbers on both. TxBufLen lags by 100 to 150 ms, about
one character at 45.45 baud: twenty-one characters pushed at 2496 ms read 0 at
2497, 2547 and 2597, then 26 at 2647. It moves once per symbol transmitted, so
readings 50 ms apart repeat.

It read 26 for 21 characters because it counts Baudot symbols, and the message
carried two digits: a shift to figures and a shift back each time, plus one at
the start. That is the case the cap was needed for and I had not seen. A contest
exchange is mostly digits, so the engine always has more to transmit than the
clock thinks, and the clock alone would run ahead of it on every QSO.

Slack of three characters covers both, so nothing changes in the pump. The
count reaching 0 does not cut the end of a message off either: it emptied 350 ms
before the last character was decoded back and the engine held the transmitter
up for another 900 ms.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RtspmWmS7f8kUvcyaHpRWZ
2026-09-01 23:20:11 +00:00

245 lines
16 KiB
Markdown

# What is not finished, and what has not been tested
Two separate lists. A feature can be finished and untested, or half-built and
exercised every day. Written 2026-08-27, updated 2026-08-31.
## Never run against the real thing
Everything below is written from a published protocol or from N1MM's source and
tested against a fake that speaks the same protocol. A fake agrees with whatever
the person who wrote it believed, so these are the places where a wrong belief
is still sitting there undiscovered.
| What | Tested against | What has never happened |
|---|---|---|
| `RigctldRadio` | a stand-in for `rigctld` over a real socket | no real `rigctld`, no real radio. The extended answer format, the `+` prefix and the split commands are from the documented protocol. If the format is wrong, nothing works rather than something being subtly off — check this first. |
| `OtrspBox` | a `MemoryStream`, checking the bytes | no real SO2R box. Command forms are from N1MM's `N1MMPort.cs`. |
| `ClusterClient` | a node fake over a real socket, sending the telnet negotiation, the login prompt and spot lines | no live cluster node. Which nodes send bare CR, and which send option negotiation, is guessed from N1MM's code. |
| `StationNetwork` | the message format, round-tripped | no second station, and no N1MM on the same network. |
| `CwDaemonSender` | the UDP messages, and a fake daemon that answers the `<ESC>h` reply request | no `cwdaemon`, no radio keyed. |
| `MmttyEngine` and the Wine bridge | MMTTY 1.70 under Wine 10 on a machine with a sound card: started, keyed, a message transmitted and decoded back off the air, and stopped | no radio. No FSK through EXTFSK, no PTT on a serial port, and 2Tone has never been run. Keying was wrong until 2026-09-01: `SetMmttyPTT` stops a transmission and does not start one, which is why nothing ever went out before then. `docs/digital-bridge.md` |
| `WinkeyerSender` | the status-byte reader, on its own | no test of the serial side, and no WinKeyer. The host-mode open sequence is from the WinKeyer datasheet; the status bits are from N1MM's `Winkey.cs`. |
The Cabrillo output has not been put in front of a contest sponsor's robot.
## Half-built
**The digital window: what N1MM has and this does not.** The window is here —
receive pane in both of N1MM's scroll modes, the Letters/Figs and MouseOver
readouts, the pause bar, coloured callsigns with N1MM's validity routines, grab
list, call stacking, hover mode, the message buttons, the engine controls, the
text file in and out — and the function keys, ESM and the QTC window send
through the engine on a digital mode. Left out: the waterfall, the spectrum and
the XY scope, which the engine reports and nothing draws; more than one receive
pane, which is MMVARI's multi-channel decoding rather than MMTTY's; N1MM's
AutoTRXUpdate, which offsets the frequency the entry window and the log record
rather than only the one in the title bar; and N1MM's Send All, which keys a
whole QTC series at once. The other interfaces N1MM offers — fldigi, MMVARI, the
hardware TNCs — are not here either, though `DigitalEngine` is the place to add
them.
The receive pane has been driven with a stand-in bridge that prints prepared
text, which is how the printing, the colouring, the Letters/Figs box and the
type-ahead transmit pane were checked. Nothing has been decoded from a real
signal and nothing has gone on the air: this machine has no sound card, and
MMTTY does not start on it.
**What paces the type-ahead pump.** The text is held in `TypeAhead` and the
engine is kept `Lead` characters ahead: one being transmitted and one behind it,
so it never runs dry and never transmits idle in the middle of a message. Those
two characters cannot be taken back; everything behind them can still be
rewritten.
The pace comes from the clock at the baud rate in the digital settings. The
engine's own count of what it has left is a check on that rather than the pace
itself, for the reason in the table below: it is used as a cap, so the engine is
never given more than `Lead + Slack` characters however fast the clock says to
feed, and as the end of a message, together with the clock estimate. A count
that neither goes down nor is being added to means the engine is holding what it
has, and the pump feeds a character every `HoldingPatience` until it moves.
What the engine probe established, with MMTTY 1.70 under Wine on a machine with
a sound card:
| What | Answer |
|---|---|
| Does the control answer `TxBufLen`? | Yes, and a name it does not know fails with `DISP_E_UNKNOWNNAME`, so the two are distinguishable. |
| What does it count? | Characters left to transmit. Seventeen were pushed; a second later, with five decoded back off the air, it read 12, and it counted down to 0 as the message went out. |
| How current is that number? | It lags by 100 to 150 ms, about one character at 45.45 baud. Twenty-one characters pushed at 2496 ms read 0 at 2497, 2547 and 2597, then 26 at 2647. That is why the count cannot be the pace: a pump that fed on a fresh 0 would hand over a whole message in half a second and put all of it beyond reach. |
| What is it counting? | Baudot symbols, not the characters handed over. Twenty-one characters read as 26, and the message was `CQ TEST DE OM5M OM5M `: two digits, each needing a shift to figures and a shift back, plus one shift at the start. It also only moves once per symbol transmitted, so four readings 50 ms apart are the same number. |
| Does a backspace take back a character the engine has not transmitted? | No. Pushed in as a character it made the count go **up** by four, and the text went out unchanged. MMTTY's help describes its backspace key doing this in its own window; through `PostMmttyMessage(4, 8)` it is just another character. So text in the engine cannot be retracted, only aborted. |
| Way to send | This engine is set to Character out: `ABCD` with no space after it went out at once. MMTTY's help says Word out is the usual setting, which would hold that word, so the pump copes with both. |
| Does the count reaching 0 cut the end of a message off? | No. It reached 0 about 350 ms before the last character was decoded back, and the engine held the transmitter up for another 900 ms after that, so `{RX}` straight after the count empties does not truncate anything. |
Counting symbols rather than characters is what makes the cap earn its place. A
contest exchange is full of digits, so the engine has more to transmit than the
pump's clock thinks: `599 001` is seven characters and eleven symbols. The clock
would run ahead of the engine on every exchange; the cap is what stops it.
The report is worth reading for the receive side as well. With MMTTY's sound
loopback off, its help says the receive window is fed from the transmit window,
which would be a per-character report of what has gone out with no polling at
all. With loopback on, which is how this station runs it, the decoded text
arrives about 420 ms after the character goes out and matches what was sent.
```sh
./build.sh run --project tools/Nonemm.EngineProbe -- \
--engine ~/mmtty/MMTTY.EXE --prefix ~/.wine-nonemm --out engine-probe.log
```
It transmits on the sound card for about twenty seconds and keys no serial port
unless `--ptt` names one. `EngineProbe` states what each answer means.
**Voice keying.** `MessageSender` was written to cover a voice keyer playing a
recording, and nothing implements it. Each operator's recordings folder is
stored with the rest of his settings and waits on the same thing. No DVK support either, so the second radio
of an SO2R station cannot call CQ by voice. Alternating CQ therefore works on CW
only, though nothing in it is CW-specific: a voice keyer that reports when the
recording has finished would drive it as it stands.
**The QTC window transmits on CW only.** The header, the lines, the QRV, the TU
and the again messages go out through the keyer, with N1MM's messages and
N1MM's defaults. Nothing goes out on SSB or RTTY: N1MM plays four recordings on
SSB — QRV, Agn, Cfm and TU — and sends RTTY from its digital window, and this
program has neither a voice keyer nor a digital window. N1MM's Send All, which
keys a whole series at once, belongs to that RTTY window and is not here
either.
**Cut numbers are not sent.** N1MM can key a serial number as letters — `N` for
9, `T` for 0 — and offers several styles. Nothing here does, in a QTC line or in
any other message.
**Two WAE numbers do not agree with N1MM, both from 2020 and 2021 logs.** The
disagreements are the country file of the day, not the rules: 4U1A counted as
`4U1V` then and as `OE` in today's `wl_cty.dat`, `KP2BH` counted as `KP2` then
and is listed as a US call now, and China was not split by call area yet. The
2022 to 2025 logs agree to the contact.
**Telnet window: what N1MM has and this does not.** Left out: the special-calls
list, and saving received spots to a database — N1MM keeps those spots in its
admin database, which is not the log file the two programs share, so there is
nothing to be compatible with and nothing asks to read them back. The band plan
tab is not repeated either, because Config ▸ Sub bands already edits the same
numbers.
The node list is downloaded from the public NG3K page rather than from N1MM's
own web service, which asks the operator to opt in to data collection and is
N1MM's to run. A page that changes shape would stop the download working; the
reading only needs `telnet://` links in a table, and the old list stays in place
when a download brings back something unreadable.
**Not every action macro is acted on.** The text macros and the action macros
that this program can carry out are listed in the README. What is read and
passed over: the `{CAT…}` and radio-hex families, the audio and rotator macros,
`{STEREOON}` and `{STEREOOFF}`, `{CONDJUMP}`,
`{QSYCQ}`, `{FORCELOG}`, `{SwapContests}`, the digital TNC macros (`{ENTER}`,
`{ESC}`, `{CTRL-A}`…), and the wav-directory macros, which wait on voice keying.
A message holding any of them still sends the right characters.
The CW keyer macros are not read either: `<` and `>` for speed, `~` for a half
space, and the prosign characters `]`, `[`, `+` and `=`. They belong to the
keyer rather than to the expander — cwdaemon and a WinKeyer each have their own
way of saying them — and they go out as the characters they are.
**The busted-spot check is one character wide.** N1MM offers two. Every call one
character away from the spotted one is looked up in the callsign database, which
is a few hundred lookups per spot; two characters away is a few hundred thousand,
which is too much work per spot for the little it would add.
**Two BARTG contests share one set of rules.** N1MM has a class each for the
March HF RTTY contest, `BARTGSRTTY`, and the September sprint, `BARTGRTTYS`.
This program has one contest, named `BARTGRTTYS`, holding the March rules — the
ones the station's log needs — and both of N1MM's names open a log with it. A
sprint log would be scored by the wrong rules, and a log started here writes
`BARTGRTTYS` into the contest name, which N1MM would read as the sprint.
**Digital modes.** A contact can be logged as RTTY or another digital mode, and
the contest rules score it, but there is no digital window: no decoding, no
transmitting, no interface to fldigi, MMTTY or similar.
**Contest coverage.** Twenty-five families are built in, plus whatever `.udc` files
are in the user-defined folder. N1MM ships well over a hundred. Opening a log
from a contest that is in neither place fails with the contest name, which is
the right answer but it is still a wall.
Most of what is missing does not need code. A contest whose exchange is a
report and one value, scored by band, mode, continent or country, and counted
by country, zone, section or prefix, is a `.udc` file, and the file published
for N1MM is read as it is. Code is for the ones `.udc` has no words for: WAE
needs QTC traffic, IOTA needs island references as multipliers, and CQ WW RTTY
needed a third multiplier and its own points table because it shares a name
with the CW and SSB running of the contest.
`.udc` settings that are still passed over. `MultiplierBands` and
`QsoErrorString`, which are about the windows rather than the score.
`GenericPrintString`, which is the layout of a printed log rather than a
Cabrillo one.
`MultWindowType` is read as far as the score goes: it names the list a section
multiplier is checked against. Four of N1MM's lists are held here — the ARRL
sections, the US states, the Canadian provinces and the OK/OM districts — and a
file naming any of the hundred-odd others falls back to counting any exchange
that is not all digits.
`CabrilloString` and `CabrilloVersion` are read: a contest whose sponsor asks
for its own columns gets them, in N1MM's shape — the operator's callsign in the
first 13 columns, then every column padded to the width the file gives with one
space after it, and a value longer than its column cut rather than pushed. The
numbered `CabrilloFormat` layouts 2, 3, 4 and 5 — the NAQP, NA Sprint,
Sweepstakes and section-and-serial lines — are read as well, in N1MM's columns.
The exchange those layouts split into columns is built from the boxes the file
defines, in the order it defines them; N1MM builds it from the section box
alone, which writes only half of a two-box exchange. Layout 6, the ARRL RTTY
Roundup line, is not read, and a file asking for it gets the default line; no
published `.udc` file asks for it, because the Roundup has a contest class of
its own. `CabrilloFormat = 0` means the sponsor takes no Cabrillo log at all,
and nothing here stops the operator writing one.
N1MM's `.udc` format has no way to say that the exchange itself differs by the
other station's country. OK/OM DX is written in code for that reason — it asks
a county from OK and OM stations and a serial number from everyone else — and
`Contest.SkipsField` steps over the box that does not apply. REF, ARRL 10M, the
Ukrainian DX contest and the Russian DX RTTY contest ask their exchange the same
way, and are written in code for the same reason.
Every contest in the station's own logs can now be opened, and its 78 contest
instances score contact for contact as N1MM did apart from the cases below.
What still differs, and why:
- **The EU DX Contest** is written from N1MM's own class. The station's logs
were made with the `EU_DXC.udc` file instead, which scores a contact inside
your own country 1 point where the class scores 2, and counts a district code
once in the contest where the class counts it once per band.
- **Field Day Region 1**: every contact in that log holds 1 point and no
multiplier, which is not what N1MM's own class works out, so the log looks
like it was never scored. The rules here follow the class: 5 points for a
portable station, 2 for one in Region 1 at home and 3 from outside it.
- **SA 10 and OK/OM DX on SSB** are not written in code at all: both are
published as `.udc` files, and with those files in the user-defined contests
folder the station's logs score to the contact. N1MM's OK/OM DX class is the CW running only and says so; the SSB
running has different rules and its own pair of files, one for each side of
the contest.
- **Two OK/OM DX contacts** whose district code was stored with a trailing
space. N1MM checks the code against its list without trimming it, finds
nothing and counts no multiplier; the code is trimmed here and counts. Both
contacts are the same station in the 2026 log.
## Known rough edges
**The band plan covers 160M to 2M only.** 60M and everything above 2M get no
CW, digital or phone shading on the bandmap, because N1MM's own numbers for
those bands contradict themselves — its CW top for 1.25M is below its phone
start, and its 70CM CW top is above the band. Config ▸ Sub bands cannot add a
band that has no default.
**Available mults and Qs is only as good as the bandmap.** It lists what is
spotted, so a multiplier nobody has spotted is not there. N1MM's window also
shows the mults a contest has and nobody has worked, which needs a list of every
multiplier the contest counts. Only the section and state lists are held here,
so the zone and country lists would have to come from the country file first.
**Two entry windows and one keyer.** The SO2R box is told which radio to key
before each message, but nothing stops both radios sending at once if the
operator asks them to.