76e33a91bb6d80c6746cd386a44172187e1b1b05
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
18b2d0efe6 |
[feat](trx-rs): keep a station log, and a layout to work the bands from
The logbook of issue #54, in the shape the proposal settled on. A new crate, trx-logbook, holds the contact, the ADIF reader and writer, the file, and the rules for telling one contact from two. ADIF because it is the only thing the ecosystem reads: LoTW, eQSL, Club Log, QRZ and every other logger take it and nothing else, so a log that cannot write .adi cannot be uploaded, confirmed or moved. The reader is forgiving in the ways real files are irregular -- lowercase tags, CRLF, missing header, unknown fields, a declared length that is the only thing ending a value -- and carries what it does not model through to the export, so a round trip does not strip what another program wrote. The file is JSON Lines, appended one line per contact. A log is the one thing here that cannot be regenerated, and the bookmark store's whole-file dump would rewrite megabytes to log one contact and lose all of them if the power went halfway; an append costs the record being written and no more, which a test tears a line in half to prove. Edits append revisions, deletes append tombstones, and the file compacts when the superseded outnumber the live. The panel is its own tab and stands in every layout. An entry opens with six fields and no more -- frequency, mode, rig name, time, and the callsign and locator of whatever decode it was started from. A report stays empty: an FT8 SNR is not what was sent. Times come from the server, because the browser may be a phone in another timezone, and the panel says so when the two disagree by more than a second. Worked-before answers as a callsign is typed. A decode is not a contact, so the Log button on an FT8 or APRS row opens an entry and logs nothing by itself. The ham layout is the fifth operator layout, opening on the logbook with the radio controls around it, offered only where the rig can transmit. Two bugs found on the way, both in code written here: a frequency of a whole number of megahertz ending in a zero rendered as a tenth of itself, in Rust and in TypeScript alike, because trimming trailing zeros from "20.000000" walks back through the point. The API also sits under /api/logbook rather than /logbook, so it cannot shadow its own page the way /bookmarks does. Closes #54 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SyX26FCpMQxiBoC7r5K1A7 Signed-off-by: Stan Grams <sjg@haxx.space> |
||
|
|
da58a004fe |
[refactor](trx-config): extract client/server config into a shared crate
The setup wizard, the server and the client each carried their own idea of what a valid config looks like: trx-configurator validated with hand-written toml_edit key lists while the binaries validated with serde plus their own validate(). Nothing kept the three in sync. Move ServerConfig, ClientConfig, the section loader, the shared validators and the endpoint-URL parsing into a new trx-config crate that all three depend on, so there is one definition of the config to drift from. The binaries keep a thin crate::config re-export so their internal paths are unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SyX26FCpMQxiBoC7r5K1A7 Signed-off-by: Stan Grams <sjg@haxx.space> |
||
|
|
a0b0c0ed81 |
[feat](trx-sstv): decode SSTV pictures
CI / test (pull_request) Successful in 7m40s
CI / lint (pull_request) Failing after 14m36s
CI / frontend (pull_request) Successful in 3m12s
CI / reuse (pull_request) Successful in 3s
CI / test (push) Successful in 7m32s
CI / frontend (push) Failing after 1m21s
CI / reuse (push) Successful in 2s
CI / lint (push) Successful in 2m16s
A new decoder crate covering the modes SSTV is actually sent in: Martin M1/M2, Scottie S1/S2/DX, Robot 36/72, PD50 through PD290, and Wraase SC2-180. The mode comes from the VIS header every transmission opens with, so nothing has to be told what is arriving. Modes are a table rather than code: a list of segments -- sync, gaps, and one scan per colour channel -- plus a colour model and a geometry. The decoder reads the offset of each scan straight off that list, which is what makes fifteen modes cost about as much as one, and a new mode a table entry. The segment lists are checked against the published line durations in a test, because both are transcribed by hand from the same specification and a digit wrong in one is unlikely to be wrong identically in the other. Signal path: band-pass over the SSTV band, Hilbert FIR, instantaneous frequency by phase difference, then a state machine that walks the transmission a line at a time. Each line is looked for where the mode says it should be and nudged into place by the sync pulse found near it -- two sound cards never agree exactly, and over the two minutes of a Martin M1 frame an uncorrected error of a few parts per million shears the picture visibly. Rows are emitted as they decode, so a picture can be watched arriving, which is most of the appeal of the mode. Four things this cost, each now the reason a piece of it is shaped the way it is: The per-sample frequency estimate ripples by ±95 Hz at 1200 Hz, where the Hilbert approximation is weakest, though its mean is exact. Pixels average over their own window and were always right; the VIS bits and the sync detector classify individual samples and were reading the ripple. Both now read short means. Pixels deliberately still do not, so edges stay where they are. Broadband noise cost the whole picture, not part of it: a phase-difference detector answers whatever is loudest, and there was no input filter. Hence the band-pass, which is what every real decoder does first. A sync search window shorter than a sync pulse rejected every pulse arriving late in it, for being short. The first line's sync search locked onto the VIS stop bit -- 30 ms at exactly the sync frequency, immediately before the picture starts. The header already says where the picture begins, so the first line no longer searches. Tests: nine modes are encoded from a test card and decoded back, compared pixel by pixel, alongside silence around the signal, a transmission cut off part way, two transmissions back to back, 20 dB of noise, and a transmitter clock 0.1% fast. The encoder that produces those signals reads the same table as the decoder, so a round trip tests the decoder and not the timings; the timings are held to the published line durations separately. Nothing is wired into the server or the web UI yet: this is the decoder alone. Signed-off-by: Stan Grams <sjg@haxx.space> |
||
|
|
ba48de2d30 |
Initial commit
Sync docs to Wiki / wiki (push) Has been cancelled
Signed-off-by: Stan Grams <sjg@haxx.space> |