Let MMTTY hold the text waiting to go out, behind a setting
MMTTY has a type-ahead buffer of its own: characters go into it, a backspace takes back one it has not transmitted, and TxBufLen says how many are left. Used that way it paces itself, so there is no gap between characters to tune and no baud rate to keep in step with the engine. EngineTypeAhead does that, and Config > Digital picks between it and the pump that is there now. Off is still the default: three things it rests on have never been seen with a real engine. tools/Nonemm.EngineProbe asks the engine those three questions and writes the answers to a file. It starts MMTTY through the bridge, pushes a message, polls TxBufLen while it goes out, backspaces over text that has and has not been transmitted, and logs what came back on the receive side and when. The bridge learns one verb for it: `buffer` reads TxBufLen and answers with the count, or -1 when the control will not say. A property the control does not know is a log line rather than an error, since it stops nothing. TypeAhead and EngineTypeAhead share the TransmitBuffer interface, which is what the digital window now works through, so the window does not know which one it has. docs/unfinished.md states what each buffer assumes and how to run the probe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RtspmWmS7f8kUvcyaHpRWZ
This commit is contained in:
@@ -32,6 +32,7 @@ To the bridge:
|
||||
| `send <text>` | `SendString` |
|
||||
| `ptt <0\|1>` | `SetMmttyPTT` |
|
||||
| `post <message> <parameter>` | `PostMmttyMessage`, for everything in `MmttyMessage` |
|
||||
| `buffer [property]` | reads `TxBufLen`, or the property named instead, and answers `buffer` |
|
||||
| `close` | shuts the engine down and leaves the bridge running |
|
||||
| `quit` | shuts the engine down and exits |
|
||||
|
||||
@@ -46,9 +47,17 @@ From the bridge:
|
||||
| `tx <0\|1>` | the engine started or stopped transmitting |
|
||||
| `mark <hz>`, `space <hz>` | the tone pair moved |
|
||||
| `switch <bits>`, `view <bits>` | AFC (4), net (8) and reverse (256), and the engine's view state |
|
||||
| `buffer <n>` | how many characters the engine still has to transmit, or -1 when the control would not say |
|
||||
| `log <text>`, `error <text>` | anything the bridge has to say |
|
||||
|
||||
Each of those comes from an event of the control's own: `OnCharRcvd`,
|
||||
`buffer` is the one thing that is asked for rather than reported: the control
|
||||
has no event for the length of the transmit buffer, so it is polled. A property
|
||||
name in the request is only for finding out what the control answers to; a name
|
||||
it does not know fails with `DISP_E_UNKNOWNNAME`, which comes back as a `log`
|
||||
line and `buffer -1` rather than an `error`, because a property the control will
|
||||
not answer stops nothing.
|
||||
|
||||
Each of the others comes from an event of the control's own: `OnCharRcvd`,
|
||||
`OnPttEvent`, `OnFreqChanged` (mark and space in one event), `OnSwitchChanged`
|
||||
and `OnViewChanged`. The control raises `OnTranslateMessage` only for the
|
||||
MMTTY messages it has no event for — width, resolution, thread and the like —
|
||||
|
||||
@@ -44,23 +44,58 @@ 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 pump keeps two characters in the
|
||||
engine and counts character times off the clock at the baud rate in the digital
|
||||
settings to work out when the engine has room for the next one. Two characters
|
||||
is what stops the engine running dry between characters, which would make it
|
||||
transmit idle and add that idle to the time the message takes; the price is that
|
||||
the last two characters cannot be taken back. The estimate is corrected when the
|
||||
engine reports that it has stopped transmitting, which means its buffer is
|
||||
empty.
|
||||
**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.
|
||||
|
||||
The engine can be asked instead of estimated: `XMMT.ocx` has a `TxBufLen`
|
||||
property, and a probe against the control shows it answers, though what it
|
||||
answers while a message is going out could not be measured here because the
|
||||
engine will not start. Reporting it from the bridge would make the red text
|
||||
exact and would take out the one error the estimate can still make: a baud rate
|
||||
that does not match what the engine transmits at leaves a small gap between
|
||||
*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 |
|
||||
| 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
|
||||
|
||||
Reference in New Issue
Block a user