Key MMTTY the way N1MM does, with the control's PTT property

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
This commit is contained in:
2026-09-01 22:51:43 +00:00
parent 54b9181c06
commit 917a05b898
6 changed files with 198 additions and 79 deletions

View File

@@ -86,15 +86,18 @@ public sealed class MmttyEngine : DigitalEngine
public Task AskBufferedAsync(string property = "", CancellationToken cancellation = default) =>
bridge.SendAsync(BridgeLine.Write("buffer", property), cancellation);
/// N1MM's abort, which is what its RX button and Escape do: drop PTT and
/// let the engine stop where it is.
/// Escape and the RX button: stop now and leave what has not gone out
/// unsent. N1MM's `AbortXmit`.
public Task AbortAsync(CancellationToken cancellation = default) =>
SetPttAsync(false, cancellation);
bridge.SendAsync(BridgeLine.Write("ptt", "0"), cancellation);
/// N1MM's `{TX}` and `{RX}`. MMTTY sends what is in its buffer before it
/// drops PTT, so a macro that ends with `{RX}` still goes out in full.
/// N1MM's `{TX}` and `{RX}`. Keying is the control's `PTT` property;
/// unkeying is `SetMmttyPTT(1)`, which waits for the buffer to empty first,
/// so a macro that ends with `{RX}` still goes out in full.
public Task SetPttAsync(bool on, CancellationToken cancellation = default) =>
bridge.SendAsync(BridgeLine.Write("ptt", on ? "1" : "0"), cancellation);
bridge.SendAsync(
on ? BridgeLine.Write("key", "1") : BridgeLine.Write("ptt", "1"),
cancellation);
public Task ReturnToReceiveAsync(CancellationToken cancellation = default) =>
SetPttAsync(false, cancellation);