Nothing was ever transmitted. SetMmttyPTT does not start a transmission: N1MM
calls it with 1 to stop once the buffer is empty, which is its XmitOff, and with
0 to stop now, which is its AbortXmit. A transmission starts by setting the
control's PTT property, in XmitOn.
So the bridge learns `key <0|1>` for that property, and MmttyEngine now keys
with it, ends a message with SetMmttyPTT(1) so the buffer still goes out, and
aborts with SetMmttyPTT(0). This is the digital {TX} in the entry window and the
digital window as well as the probe: none of them could key the engine before.
The probe checks that the engine keys before it measures anything, and stops
with a plain statement if it does not, rather than reporting numbers from an
engine sitting still. It also asks a new question: whether the engine holds a
word until the space after it, which is MMTTY's Way to send. Received characters
are marked as noise while the engine is not transmitting, since a machine with a
sound card decodes the band all the way through the run.
The first run on a real engine says MMTTY 1.70 connects, the control answers
TxBufLen and refuses NotAProperty with DISP_E_UNKNOWNNAME. What TxBufLen counts
is still open: read while nothing was transmitting it rose over time and rose by
four after four backspaces, which is not what characters-left would do.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RtspmWmS7f8kUvcyaHpRWZ
251 lines
16 KiB
Markdown
251 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, started and stopped through `XMMT.ocx`; on a machine with a sound card it connects and decodes noise off the input | nothing has been transmitted yet. Keying was wrong until 2026-09-01 — `SetMmttyPTT` stops a transmission, it does not start one, and N1MM starts one by setting the control's `PTT` property — so no `tx` line has ever come from a real transmission. No FSK through EXTFSK, no PTT on a serial port, and 2Tone has never been run. `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.
|
|
|
|
**Who holds the text waiting to go out.** There are two answers in the code and
|
|
a setting to pick between them: Config ▸ Digital ▸ "Let the engine hold the text
|
|
waiting to go out". Off is what runs today.
|
|
|
|
*Off — `TypeAhead`.* The text is held here and the engine is kept two characters
|
|
ahead: one being transmitted and one behind it, so it never runs dry and never
|
|
transmits idle in the middle of a message. When the engine has room is worked
|
|
out from the clock at the baud rate in the digital settings, corrected whenever
|
|
the engine reports that it has stopped transmitting. The last two characters
|
|
cannot be taken back. The one error left is the baud rate: if it does not match
|
|
what the engine transmits at, the drift shows up as a small gap between
|
|
characters near the end of a long message.
|
|
|
|
*On — `EngineTypeAhead`.* MMTTY has a type-ahead buffer of its own, which is what
|
|
its own keyboard drives, so everything is pushed straight into it and an edit is
|
|
expressed as backspaces followed by the new text. MMTTY paces itself, so no baud
|
|
rate is needed and there is no gap by construction. `TxBufLen` says how many
|
|
characters are left, which is what splits the pane into what has gone and what
|
|
can still be changed. One character more than the count says is held back
|
|
(`EngineTypeAhead.Guard`), because the count is a poll old and a backspace over a
|
|
transmitted character is refused, which would put the text after it on the air
|
|
twice.
|
|
|
|
Three things it rests on have never been seen with a real engine, and MMTTY does
|
|
not start on this machine:
|
|
|
|
| What is assumed | Where it comes from |
|
|
|---|---|
|
|
| `TxBufLen` counts the characters left to transmit | the name, and a probe showing the control answers to it. The first probe run, before keying worked, read it while the engine was not transmitting: it rose over time and rose by four after four backspaces, which is not what a count of characters left would do. Nothing is settled until it is read while a message is actually going out |
|
|
| a backspace pushed in as a character deletes one the engine has not transmitted | MMTTY's help, which says the backspace key does it and works only until the letter is transmitted; and N1MM printing a received `\b` by deleting the last character, which can only come from MMTTY's transmit side |
|
|
| backspaces over transmitted characters are refused rather than doing something else | nothing — this is the guess with the most to lose |
|
|
|
|
`tools/Nonemm.EngineProbe` asks the engine all three and writes the answers to a
|
|
file. It has to run where MMTTY runs:
|
|
|
|
```sh
|
|
./build.sh run --project tools/Nonemm.EngineProbe -- \
|
|
--engine ~/mmtty/MMTTY.EXE --prefix ~/.wine-nonemm --out engine-probe.log
|
|
```
|
|
|
|
It transmits for about half a minute on the sound card and keys no serial port
|
|
unless `--ptt` names one. The report says, step by step, what the engine
|
|
answered; `EngineProbe` states what each answer means.
|
|
|
|
There is a fourth question in the report that is not needed for either buffer,
|
|
but decides whether `TxBufLen` can be dropped later: what comes back on the
|
|
receive side while transmitting, and when. 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. With loopback on it
|
|
is the demodulator hearing the transmission instead, which is late and can
|
|
contain decode errors, so the count is what the pane uses.
|
|
|
|
**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.
|