Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The comparator's own two channel outputs had nowhere to go: `FrontEndOutput` is crate-private and only its `|mark − space|` magnitude reached the squelch. `rx/monitor.rs` names the pair `ChannelLevels` and hands it out two ways — `ReceivePipeline::channels` for the newest one, which is the signed tuning figure a receive column's header reads, and a decimated bounded ring behind `set_monitor`/`drain_monitor` for an XY scope to draw. Both are settings rather than construction arguments: a scope is opened and closed while a reception runs, and rebuilding the pipeline to open one would throw away the reception being watched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The application is started from apps/wefax, as the memo records: main.rs, the menu renderers, the identity, the locales machinery, the configuration document, the paths, and the WAV source are that application's, and what is new is the receive path itself. One `ReceivePipeline` per column, every one of them fed the same PCM, with a header carrying what that path is hearing — the pair after any AFC movement, which tone the comparator is on, the case, and the signal reading. There is one decode path because the core has one demodulator; `DecodePath` is the list the columns are built from, so a second discriminator is a variant and a pipeline rather than a layout. A receiver cannot be retuned in place, so a settings change rebuilds the paths. That costs a few milliseconds of filter settling and nothing else: the text lives in the interface. The pane collapses a run of carriage returns and line feeds into one break, because a teleprinter line ends with CR CR LF and honouring each of them would double-space everything. Transmit, the scope window, and the macro engine are the milestones after this one and are not here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The three touch-points a new application drags with it, each hard-coded per application: the core job's exclusion list and a third leg of the app matrix in ci.yml, an rtty case in package/build-app.sh with its own microphone sentence, and release-rtty.yml on the rtty-v* tag pattern. Automatic frequency control now starts off in the application. Running it against a real capture device is what found this: on an empty band the search takes the two strongest peaks it can find, which are the receiver's own hum near the 300 Hz floor, and they snap to a 170 Hz shift as readily as a transmission does — a watch left running walks off the pair it was put on. The demodulator squelch cannot gate the correction, because a pair far enough off to need AFC is exactly the pair that fails to open it; that is written down in rtty.md along with what the real fix would be. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The fourth step of the RTTY application's plan: a window the operator opens from the panel beside the text or from the View menu, showing the band the receiver is listening across and the two channels it is comparing. It is a deferred viewport with the always-on-top flag, because it is read while the panel behind it is worked and because the main window sleeps between the frames a reception gives it. The band is transformed in the receive worker rather than in the interface. That departs from the plan and not from its reasons: the raw PCM is already there, the publish interval is the thirty-a-second throttle the plan asked for, and a closed window then costs nothing whatever, because neither the transform nor the samples it reads exist while it is closed. It is 2048 points of its own, deliberately not the frequency control's, and it is published to 4000 Hz — MMTTY's wider display ceiling, which is what a 3000 Hz mark and an 850 Hz shift need. The channel pairs come from the monitor tap the core grew for this. The tap is opened through a control of the worker's own rather than through WorkerSettings, because a settings change rebuilds every pipeline and opening a window must not throw away the reception being watched. Only the first decode path is tapped, every column being fed the same audio, and the pairs are decimated to about four thousand a second, which is more than the width of the picture they are drawn into. Two things the picture does that the plan did not say. The trace is scaled by the strongest pair on it, because a channel carries a rectified envelope whose height depends on how much of the band-pass the tones fill, and what is read off the picture is the shape rather than the level. And the line where the two channels are equal is drawn under it, because that line is the comparator's own decision. Every frame carries a sequence number: nothing on a scope is compared against a threshold, so a trace that looks like the last one is still a new trace, and without it the interface's own change comparison would sleep through a band that had not moved. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The application needs to underline text as it is keyed, echo it into the received text a character at a time, report how long is left, and hand back whatever an aborted transmission did not send. All four want the same figure and none of them can derive it: the encoder inserts a shift wherever the case changes and a carriage return before a bare line feed, so codes outnumber characters, and the lead-in idles before any of them. TxSchedule walks the encoder the transmitter is fed from and accumulates per-code durations, reporting the sample position at which each character of the source text finishes. Timing -- samples per bit, the length of one framed character, and the lead-in, tail, and ramp -- moves out of Transmitter so both are laid out from the same arithmetic; a test asserts the scheduled length against what the transmitter actually produces across gap, parity, stop, and lead-in variations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Transmission is buffered: a message is written in a field along the bottom, Ctrl+Enter queues it, and it goes out when whatever is ahead of it has finished. Enter writes a line, the way it does on a teleprinter, so reaching for a new line cannot put half a message on the air. Stop cuts the carrier where it was pressed and gives the unsent remainder back to the field, because an aborted call is finished by editing it and sending again. The field only ever holds what can be sent. A keystroke with no Baudot code simply does not appear, which is the answer a teleprinter with no such key gives; pasted and expanded text keeps what it cannot send and draws it in red, because a block that silently lost part of itself would hide the loss. Both paths upper case what they take, so the field shows what leaves. What is sent is printed into the received text in a colour of its own, following the playback position rather than the generated audio, so the transcript reads as the band heard it and a stopped transmission says what actually went out. The same positions drive the underline on the message being keyed and the time remaining. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Macros carry what an exchange repeats: the callsigns, the name, the report,
the date. MMTTY's ConvString is the reference for what they can say but not
for how they say it. Percent letters are replaced by the ${...} names the
family's other application already interpolates its templates with, so an
operator who has written one has written both, and a misspelled name survives
the expansion into the field where its braces are refused and the send button
is held -- the mistake stops where it can be seen.
The buttons answer to F1 through F12. A press writes the message in at the
caret rather than sending it, so what is about to go out can still be read and
edited; a macro marked to send in the configuration goes out as a message of
its own and leaves a half-written reply alone. Definitions live in the
configuration, written once on first run and then left alone, because the file
is where they are edited and rewriting the array on every save would reformat
what the operator had put in it.
The fields the macros read are beside the received text, where they are filled
in from: a callsign is double-clicked out of the line that printed it, and a
report is judged against the meter above it. They run the same keyboard filter
the message field does, since what is typed into them is typed to be sent.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A message leaves the queue before its playback stream is opened, so a stream that would not open dropped it: the operator was told the device was missing, but not that the text they had written went with it. What could not be started now comes back to the message field along with everything queued behind it, the same way stopping a transmission does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The implementation memo described transmit as unwritten, and the four places
the interface departed from it are worth the record: Enter writing a line
rather than sending, the field that only holds what can go on the air, the
sent text printed into the received text, and the unsent remainder coming back
to the operator.
The macros departed further. The placeholders are the ${...} names apps/sstv
already interpolates its templates with rather than a second convention
invented here, an unknown name is left where it was written so the field's own
red marking reports it, and no macro editor was built because there is nothing
left for one to validate. The memo's claim that the dollar sign is outside
ITA2 was wrong, which matters only in that it is FIGS-D and so sendable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Several test literals carried an actual line break where the escape was meant. They compiled to the same bytes, so nothing was wrong with what they asserted, but a string split across four lines to hold one newline is unreadable and rustfmt had nothing to bring it back to. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A callsign, a name, and a QTH are entered when the application is first set up and then left for years, while everything else on the panel beside the text is worked at every exchange. Having them share a panel made the one that is never touched as prominent as the ones that always are. They move into a modal window on the Settings menu, which is where the SSTV application already keeps the same three. The contact fields stay on the panel, because those are filled in from the line that just printed. The window runs the same keyboard filter the message field does, since what is typed into it reaches the air through the macros that read it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A station says things about itself that no application can know to ask for: a
grid square, a club, a rig. The SSTV application already lets those be named
and read back from a template, and RTTY macros want the same.
They are edited in the window that already names the station, rather than in a
second dialog: the list is short and everything in it is the same kind of
thing, something this station signs with. A field is reached from a macro as
${custom.<name>}, and the prefix is what keeps the operator's names apart from
the built-in ones, so adding a built-in later cannot take a name out from
under a macro already using it.
A name is taken up when the field is left rather than on every keystroke,
because half a name is a different field, and one no expression could hold is
marked and kept out of what the macros see while staying on screen to be
fixed. The value runs the sendable-character filter and the name does not: the
value goes on the air, the name never leaves the configuration.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The RTTY macros interpolate the same expressions the SSTV templates do, and had grown a second reader for them: one that understood the braces but not the $$ escape or the :format suffix, and that answered an unknown name by leaving it where it stood. Two readers of one syntax drift, and an operator who has written a template should have written a macro. grayline-variables now holds the expression syntax, the rule for what may be named, and the values a name can stand for. What the names are stays with whoever is being written for: this crate has no opinion about callsigns. grayline-sstv-template keeps its public API by re-exporting the three items that moved, and its MissingVariable and VariableFormat variants become one Variable variant carrying the new crate's error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The macros understood the braces and nothing else: no $$ escape, no :format suffix, and an unknown name left where it stood. They now go through grayline-variables, so all three behave the way a template does. A name nothing was provided for is refused and reported by name, rather than putting a message with a hole where a callsign belongs into the field. The names are the templates' too. The two RSTs become report.sent and report.received, the date and time become one tx.timestamp.utc that a macro formats however it likes, and station.grid and application.version arrive with them. Three of SSTV's are missing because this application has nothing to answer with -- radio.* wants rig control, rx.timestamp.* wants a reception with a beginning and an end, and report.number wants the contest serial that was deferred. One is added: greeting, which is MMTTY's and which no template ever wanted. contact.name keeps MMTTY's OM fallback. That is not the kind of placeholder the templates refuse, which is the word Name standing in for a name; OM is what an operator actually says to a station whose name they have not been told. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
U+23CE is the return symbol, and a face that has no drawing for it puts a box in the middle of the message it was meant to punctuate. U+21B5 is the older character and the one a text face is far likelier to carry. The mark was written out at all three places that draw a message on one line; it is now named once. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The mark a transmit message shows a line ending with was never drawn by the coding font. Neither Consolas, Courier New, nor Segoe UI carries U+21B5, so on Windows it fell through the whole monospace chain to one of egui's bundled faces, which are installed with a scale tweak of 0.81 and 0.90 -- the arrow was drawn smaller than the text around it and sat off the underline it was supposed to sit on. Monaspace has the character and now leads the list on every platform. It is the one family there an operator installs on purpose rather than finds already present, and the one that covers what a teleprinter transcript gets annotated with. A machine without it still falls through to the bundled faces. That is worth knowing rather than working around: the alternative is a mark chosen for the poorest font on the list. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The window was written against the branch point of the transmit work, so the two touched the same settings record, the same side panel, and the same view. Both sides are kept wherever they met: - `Settings` carries the transmit fields, the station, the contact options, and the remembered scope state together, and the TOML store writes and reads all of them. - The side panel's action row opens the scope above Clear and Resync, under the transmit and contact sections the other branch added. - `view` draws the scope after the dialogs, so it is still shown after everything it can be opened from. - `AudioState` keeps the playback half beside the capture tap. The two progress notes are reconciled rather than picked: steps 1 through 5 of the implementation order are now done, and what is left is the aligned save, the history log, and the rig frequency readout. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.