Pace the pump on what MMTTY says it has left
The engine probe answered two questions on the air, and they point opposite
ways.
TxBufLen is the number of characters left to transmit. Seventeen characters
pushed, five decoded back, and it read 12, counting down to 0 as the message
went out. So the pump no longer counts character times off the clock: it asks
the engine, feeds while the answer is under Lead, and asks again. The baud rate
is now only the fallback for an engine that will not answer.
A backspace is not an edit. Pushed in as a character it made the count go up by
four and the text went out unchanged, so text the engine has been given cannot
be taken back, only aborted. EngineTypeAhead was built on the opposite belief
and is gone, along with the setting that chose it and the interface that existed
to switch between the two.
A count that stops going down means the engine is holding what it has: MMTTY set
to Word out keeps a word until the space after it. The pump feeds one character
per look while that lasts, so the space arrives and the word goes out rather
than the message sitting there.
The probe kept two bugs of its own that this run showed: it read the count a
millisecond after pushing, saw 0 and called the message finished, and it started
a step while the previous unkey was still in flight, so that step ran with the
engine down. It now needs two empty answers in a row and waits for the engine to
say it has stopped. It also asks what {RX} does to a word the engine is holding,
which decides whether a macro without a trailing space loses its last word.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RtspmWmS7f8kUvcyaHpRWZ
This commit is contained in:
@@ -17,7 +17,7 @@ is still sitting there undiscovered.
|
||||
| `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` |
|
||||
| `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.
|
||||
@@ -44,57 +44,53 @@ 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.
|
||||
**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.
|
||||
|
||||
*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.
|
||||
How far the engine has got comes from the engine. MMTTY answers `TxBufLen` with
|
||||
the number of characters it still has to transmit, so the pump asks, feeds while
|
||||
the answer is under `Lead`, and asks again, 50 ms at a time. An engine that will
|
||||
not answer is paced by the clock at the baud rate in the digital settings
|
||||
instead, which drifts; that is what the baud setting is still for.
|
||||
|
||||
*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.
|
||||
What the engine probe established on 2026-09-01, with MMTTY 1.70 under Wine on a
|
||||
machine with a sound card:
|
||||
|
||||
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 |
|
||||
| What | Answer |
|
||||
|---|---|
|
||||
| `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 |
|
||||
| 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. |
|
||||
| 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. |
|
||||
| How long after a push does the count include it? | Not immediately. A count read a millisecond after the push still read 0, so one empty answer is not the end of a message. |
|
||||
|
||||
`tools/Nonemm.EngineProbe` asks the engine all three and writes the answers to a
|
||||
file. It has to run where MMTTY runs:
|
||||
Two things the probe has still to answer, and it now asks both:
|
||||
|
||||
- **Way to send.** MMTTY set to Word out holds a word until the space after it,
|
||||
which the first run appeared to show but could not confirm, because the engine
|
||||
was not keyed for that step. The pump handles it either way: a count that
|
||||
stops going down means the engine is holding what it has, so the pump feeds
|
||||
one character per look until it moves again.
|
||||
- **Whether `{RX}` sends a held word.** `SetMmttyPTT(1)` stops once the buffer is
|
||||
empty. If a held word does not count as buffer, a macro whose last word has no
|
||||
space after it loses that word.
|
||||
|
||||
```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.
|
||||
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.
|
||||
|
||||
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.
|
||||
The receive side is worth watching in the report 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 it is the demodulator hearing the transmission, which
|
||||
arrives about half a second late and can carry decode errors, so the count is
|
||||
what the pump uses.
|
||||
|
||||
**Voice keying.** `MessageSender` was written to cover a voice keyer playing a
|
||||
recording, and nothing implements it. Each operator's recordings folder is
|
||||
|
||||
Reference in New Issue
Block a user