# 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 `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. **The entry window's function keys on a digital mode.** They are the digital macros, not the CW file: N1MM loads its send buttons from the RTTYBTN set on a digital mode, and the CW messages carry no `{TX}`, so a key pressed there fed the engine without keying the transmitter and nothing went out. The first ten digital macros are F1 to F10; F11 and F12 stay Spot and Wipe, as in every other mode, and the macros past the tenth are on the digital window's own buttons. Right-clicking a key still opens the CW or phone messages, so the digital macros are edited from the digital window. **How the transmit pane works.** The pane is one editable box holding the whole message: what the engine has transmitted, coloured red, then what is still to go. The red stops where the air is, not where the feeder is: the last characters handed over are still in the engine, and colouring those too turned every character red as it was typed once the transmission had caught up. An edit that reaches into the red is undone, and so is one into the characters the engine holds but has not sent yet: the engine cannot give a character back. The two are one text, so they wrap together and neither takes width from the other. A character moving from one half to the other only moves the colour boundary, so the caret and what is being typed stay where they are. Nothing goes on the air until the transmitter is keyed, which is the TX button, Ctrl+Enter or Alt+T. From then on the pane goes out and so does whatever is typed into it, and a function key pressed meanwhile goes on the end of what is already waiting. Enter is a new line in the message. The message ends when the transmitter has been told to drop and the engine says it has: what went out is cleared off the pane, what was typed ahead is kept, and nothing goes out again until TX is pressed. A new message clears the pane the same way, for the case where two of them run close enough together that the transmitter never drops. `{RX}` runs when the message it stands in has been handed over, wherever it stands in the macro. Every other action macro runs before the text unless it stands after `{END}`, but the transmitter cannot drop before the text has gone out. Running it in place, in front of the text, was what made the first click on a CQ button beep for half a second, unkey, then send the rest: the stop was issued while the engine held the two characters of the feeder's lead, so MMTTY sent them and dropped, and nothing was left to stop the transmitter at the end. The bridge log showed `> ptt 1` one millisecond after `> key 1` and before the first character. N1MM does the same as this now: it takes `{RX}` out of the text wherever it is, sends the text, then calls `StopTX`. The transmitter drops on `{RX}`, on the RX button or on Alt+T, and all three do what N1MM does at the end of a message, which is not what it does anywhere else. N1MM hands MMTTY the whole message in one `SendString` and calls `SetMmttyPTT(1)` with the message still in the engine's buffer. MMTTY then ends the transmission itself, at the last character. It never asks MMTTY how much is left; `TxBufLen` does not appear in N1MM at all. What sits between the text and the stop there is nothing at two of N1MM's three MMTTY send paths (`DigitalInterface.cs:19177` and `:19451`) and `sSleep(400)` at the third, the macro buttons (`:21553`). The sleep is not the mechanism — a full buffer is — and as a wait it is both too long on a long message and wrong on a short one: `TU` is 330 ms of air at 45.45 baud, so 400 ms of sleeping puts the stop after the buffer has emptied, which is where it does nothing. This program asks instead. `TypeAhead.WhenHoldingAsync` sends the stop as soon as the count says the engine holds something, and gives up after N1MM's 400 ms. So `{RX}` stops feeding: `TypeAhead.TakePending` hands over everything that is left in one piece, and the stop goes out 400 ms behind it. Nothing after that can be rewritten, which is what `{RX}` means. The feeder still paces the middle of a message, which is what makes type-ahead work; only the ending is N1MM's. `{RX}` runs as soon as the message has been given to the keyer, not after the message has gone out. That is the whole point: waiting for the feeder to hand the last character over leaves the engine empty, and a stop that reaches an empty engine does nothing. `EntryWindow.SendThenAsync` takes `{RX}` out of what stands after `{END}` and runs it there; the rest of `{END}` still waits for the message to go out. What the ending costs on the air, from a bridge log of one CQ: the last character was fed at 9616 ms and went out at about 10606 ms, and the transmitter did not drop until 11549 ms. That is 950 ms of dead carrier per transmission paid on the old timer. The key-down fallback brings it to about 230 ms. N1MM's ending costs nothing, because MMTTY drops the transmitter on the last character itself. The reason is that `SetMmttyPTT(1)` does nothing at an engine that has been fed one character at a time and is therefore nearly empty. Probe question 9 sent it with `TxBufLen` at 0 and MMTTY transmitted for another eight seconds; a bridge log of three CQs shows the same on the air, with the transmitter staying up until this program forced it down. Whether it is the empty buffer or the way the text arrives that MMTTY objects to is not settled: probe question 11 sent N1MM's exact sequence and it did not drop either, but that machine has no sound card, so MMTTY never really transmits and its buffer reads 0 whatever it is given. If the engine still does not drop the transmitter, the key goes down here: the control's `PTT` property back to false, which took 251 ms in the probe. What it waits for is the engine, not a clock: `StopPatience` is how long the engine may make no progress, not how long the whole wait may take. Measured against the whole wait it cut a CQ off with 21 symbols still in the engine, because a flushed message is seconds of transmission and the engine is entitled to all of it. Two things had to be right before the flush worked at all, and both were wrong first. The flush takes the same turn the feeder takes, so a character the feeder had already taken and was still handing over cannot end up behind the rest of the message — it did once, and the CQ went out with its first letter at the end. And what the engine holds is counted across feeders rather than reset when one starts: a feeder that started after a flush forgot a whole message the engine was still holding, called the transmission over and put the key down in the middle of it. `TypeAhead.WhenEmptyAsync` waits for `Aired` first, which is two things at once: the engine's own count at 0, and the clock saying the characters the engine held have had time to go out. `StopPatience` caps the wait for an engine that never reports itself empty. One character time is held after that and no more, because the count reaching 0 is late news rather than early. In a bridge log the count read 0 at 10670 ms and the last character came back decoded at 11026 ms, and the decoder runs about 420 ms behind the air, so that character went out at about 10606 ms — before the count read 0. What the character time covers is the reading, which happens every `TypeAhead.PollInterval`, not the transmission. Turnaround time is worth more than padding in a contest. MMTTY has no stop character to send instead. Its macro language ends a transmission with `\` at the end of a macro and stops the carrier with `~`, but those are read by the macro interpreter, and the only way into the engine from here is `PostMmttyMessage(4, ...)`, one typed character. Probe question 10 typed both at the end of a message: both were swallowed and the transmitter stayed up. Before this the stop was `AbortXmit` a fixed `StopPatience` after the polite stop, which is a race. It was lost once in the log: on one of three CQs the abort fired 4 ms before the count reached 0 and the carriage return at the end of the message never went out. Escape is the one that stops now: what has not gone to the engine is dropped and the engine drops what it holds. **What paces the feeder.** The clock, at one Baudot symbol every symbol time for the baud rate in the digital settings, with the engine kept `Ahead` characters ahead: one on the air and one in hand for when that one finishes. RTTY runs at a fixed speed, so the clock is right. A character is not a symbol. Most are one, but a digit sent while the engine is in the letters shift costs a shift symbol and the digit, and the letter after it costs a shift back: `OM5M` is six symbols, not four. Pacing one character per symbol time ran ahead of the air by about one part in nine — 26 characters of one CQ went out in 29 symbols — which showed up as the red text in the transmit pane running ahead of the transmission, and as the engine's count building up until the brake caught it. `TypeAhead.Symbols` prices a character against the shift the engine is in, and both the feeder and the model of what is on the air use it. They keep separate shift states, because the feeder is `Ahead` characters in front of what is being transmitted. **What a character costs cannot be calculated, so it is bounded.** The shift a character needs depends on settings this program cannot see: unshift-on-space is `TXUOS` in MMTTY's `UserPara.ini`, written per profile, and it is also a button on MMTTY's own display that the operator can press during a contest. The FIG button is another. `Symbols` assumes unshift-on-space is on, because MMTTY's help says that is the usual setting and because assuming it charges a symbol too many, which leaves the pane behind the air rather than in front of it. The engine's count is what settles it, and it needs no setting to be read. The count is in symbols and falls as they are transmitted, so what it drops between two answers is what went on the air between them. That is the air's own rate, measured rather than reckoned: `WentOutByCount` spends those symbols on the characters at the front of what has not gone out and marks them as gone. Two things make it self-correcting. The rate comes from the engine, so a clock that runs a little fast or slow cannot drift. And a count of 0 means the engine holds nothing, so everything it was given has gone out, whatever the symbols added up to along the way — a wrong guess about the shift is squared off at the end of every message rather than accumulating over a contest. The one thing to be careful of is that the count trails what the engine was last given by 100 to 150 ms, which the probe measured. A 0 newer than `CountLag` is the answer not having caught up, not an empty engine, and is passed over. An engine that does not count at all falls back to the clock. Not the decoder. MMTTY hears its own transmission with sound loopback on and reports it back, which would be the air itself, but that is the receive path: it is off at many stations, and with a receiver actually listening another station's `CQ` matches ours by chance. The transmit buffer count is the transmitter's own report and has neither problem. `MmttyEngine` has to declare `EngineBuffer` for any of the count to be used. Without it the sender falls back to the plain path: whole `SendString` calls instead of `PostMmttyMessage(4, ...)` one character at a time, and no count at all. It ran that way for a while, and a bridge log of a CQ shows what it costs. The feeder put 26 characters out at 165 ms each; MMTTY put them on the air at 183 ms each, because the digits in the callsign cost a shift to figures and the letter after each one a shift back. By the end of the message the engine was 1.5 s behind, and `{RX}` was answered by the hard stop rather than by MMTTY running dry. The brake is what holds that gap down. The clock advances by exactly one symbol time per symbol handed over, never from the time the poll happened. A poll is up to 50 ms late, and starting the next character from there made every character a little late, the lateness added up, and the engine ran dry and transmitted the idle tone between the characters of a long word. The engine's own count cannot be the pace, which the probe log shows twice over. `TxBufLen` read 0 for the first 150 ms after twenty-one characters were pushed and were already going out, and it read 0 for three seconds while the engine sat holding `ABCD` on Word out. The count is only to be believed while it is large and going down, and the feeder keeps the engine nearly empty on purpose — that is what leaves the message editable — so it lives in the range where the count reads 0. A feeder that took that 0 as room fed on it every poll and handed the engine about three characters for every one on the air, which is what put the red text ahead of the transmission. So the count is a brake. `Slack` is how many symbols the engine may be behind before the feeder waits for it: MMTTY answers in symbols, which is more than the characters it was given, so an exchange full of digits is slower than the clock thinks and this is what stops the clock running away on it. A count that is not going down means the engine is holding what it has, and the brake lets go after `HoldingPatience` so the space that releases a held word can get there. What the engine probe established, with MMTTY 1.70 under Wine on a machine with a sound card: The answer being in symbols is why `Slack` is in symbols and the feeder keeps no character count of its own to compare against 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. **The protocol log.** Every line in and out of the bridge is written to `Diagnostics/digital-.log` under the settings folder, one file per run of the engine, with a millisecond stamp on each. The buffer question is left out and its answer written only when the count changes, so what is left is the keying, the characters and the transmit reports. It is what says who dropped the transmitter and when, which nothing else in the program can answer: the engine probe cannot, because it runs the engine rather than the window. ```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. **The transmitter dropping, and what ends a message.** `DigitalEngineSender` holds three states — `Down`, `Keyed`, `Ending` — and its class comment carries the transition table. The state is there rather than a flag because ending a message takes as long as the engine takes to transmit what it holds, which is seconds, and the operator can key again inside that time. With a flag, the ending of one message went on running and put the key down in the middle of the message after it. Each ending now belongs to one transmission and checks after every step that it is still that transmission. Coming back out of `Ending` costs something too. By then the stop is inside the engine, waiting for its buffer to empty, and MMTTY fed while that stands stayed keyed and transmitted nothing — the characters went in and never came out, and the pane coloured them because `TxBufLen` answered 0, which is what an engine that has transmitted everything also answers. So a macro pressed while the last one is ending waits for what the engine holds to go out, clears the stop with `AbortXmit`, and keys again. The wait is nothing at all in the case that shows it: the last message has finished playing, which is why the operator pressed the next key. A message ends when `{RX}` or an abort has told the engine to stop and the engine then reports the transmitter down. A report nobody asked for is ignored. MMTTY reports the transmitter down at other times — the buffer hands it one character at a time and keeps it nearly empty — and taking that as the end cleared the pane and shut the gate two or three characters into a message, leaving the rest of it to go out on the next function key. That report is not the only thing that starts the pane again, because it does not always come. Two macros pressed one after the other keep the transmitter up from the first to the last character, so the engine never reports a drop between them, and the pane kept both messages. Everything the engine has been given is locked — it cannot be taken back — so a run of macros left a pane with nothing in it that could be edited. `DigitalEngineSender.StartAsync` now calls `TypeAhead.Started` whenever it keys a new transmission, which drops the last message off the pane and keeps whatever was typed ahead. `TypeAhead.Ended` is called while the state lock is held, for the same reason. The drop arrives from the engine on a thread of its own, and a macro pressed on the last character of a message got as far as handing its own text over in the gap between reading the state and clearing the pane: the new text was wiped off the pane while the engine transmitted it. The order was found by reading the code, not on the air, and the fix has not been tested against a real engine. Which of the control's two paths carries the transmit state has not been settled. The bridge takes it from `OnPttEvent`, and N1MM's `DigitalInterface` binds an empty handler there and reads MMTTY's window message 32772 out of `OnTranslateMessage` instead. Both are in the same class, so one of them is a leftover, and `docs/digital-bridge.md` argues 32772 cannot reach `OnTranslateMessage` at all while the control has an event for it. `OnPttEvent` does report drops here, so nothing is missing; it is worth measuring only if the reports turn out to be coarser than the message. Keying is the keyer's, not the window's: `{TX}` and the TX button both go through `DigitalEngineSender.Transmit`, so the order to key is always the first thing the engine is told. MMTTY keys itself off a character given to it while the transmitter is down and drops again when it has sent it, so a key that arrived behind the text put a keyed-up gap in the middle of the message. A drop in the middle of a message that is still going out also keys the transmitter again, so what is left of the message does not go out into a transmitter that is down. The idle tone between what the operator types is MMTTY's own diddle, the Diddle setting on its TX tab: LTR, the standard one, is what `mmtty/UserPara.ini` carries here. Nothing is fed to produce it, so it needs the transmitter to stay keyed. Whether MMTTY holds it there with an empty buffer has not been measured: the probe run that says it does was on a machine with no sound card, where MMTTY does not really transmit. **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 sends on CW and RTTY, not on SSB.** On CW 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. On RTTY the station reading traffic out has Send All, which is N1MM's: the whole series as one message, the heading, then every line with the operator's spacing between them, then the ending, and `{TX}` and `{RX}` around the lot so it keys the transmitter and drops it again. A line is the three fields joined with hyphens, which is how N1MM writes them and it offers no setting for it. Snd n sends one line again for a station that missed it. The heading, the ending and the spacing are settings, N1MM's `WAESendAllHeadingText`, `WAESendAllEndingText` and `WAESQTCSpacing`, with its defaults; `{ENTERLF}` in them is new to the expander and stands for a carriage return and a line feed. A whole series is the best part of a minute of transmission at 45 baud, which is why it is one message rather than a button per line: the type-ahead buffer holds it and paces the engine, and the operator presses one button. This has been tested as text — what the message comes out as — and not on the air. What is not here: N1MM's four SSB recordings — QRV, Agn, Cfm and TU — which need a voice keyer, and its RTTY messages for the station taking traffic down, which are `WAERXReadyText`, `WAEAllAgnText`, `WAEAGNText` and `WAESaveQTCText`. Those four are typed into the digital window's transmit pane here. **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 interfaces other than MMTTY.** A contact can be logged as RTTY or another digital mode and the contest rules score it, and the digital window decodes and transmits through MMTTY over the Wine bridge. What is not here: fldigi, MMVARI, 2Tone and the hardware TNCs, all of which N1MM drives. `DigitalEngine` is the place to add them. **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.