take the SX1262 model from its own repository - #14
Merged
Merged
Conversation
The chip model was a file in this variant, beside the firmware build, and three
other things wanted it: QEMU's sx1262 device, Renode's C# peripheral and the
simulator. They reached it by talking to radioserver over a socket, because that
was the only way in.
It now lives in MeshBench/virtual-sx1262 with a C ABI and its own tests, and
comes in here as a submodule. Nothing about how this repository builds changes:
the native node still links the class in process and radioserver still wraps it.
What changes is that there is one copy and one history. Two copies of a chip
model drift, and the day they do a native node and an emulated one stop being
comparable, which is the whole reason both backends exist.
The extracted model carries two fixes this copy did not have, both found while
chasing why emulated boards received every advert and relayed none:
- The detection flags were raised at RxDone, asserting that a carrier was
present at the instant it stopped. MeshCore's isReceiving reads HEADER_VALID
as "the channel is busy", so a repeater holding a packet to forward never saw
a clear channel. They are raised as the signal arrives now and cleared when
it goes.
- A frame handed over while the chip was not listening waited in the inbox
indefinitely, so a packet could arrive seconds after the air that carried it
went quiet. It is bounded now, with a grace long enough for the driver's own
standby-configure-SetRx re-arm and no longer.
Both are covered by tests in that repository, which is the point of it having a
bench of its own: these took a four minute emulated boot to see from here.
Checked: radioserver and simple_repeater both build for linux-amd64 against the
submodule.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6
Picks up the fix to how long an undeliverable frame waits for the chip to start listening. It was a fixed ten milliseconds, which is a simulator-time constant imposed on hosts that advance the clock at their own rate, and it could drop a frame the firmware would have received. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6
Two changes upstream matter here. The model is split into the datasheet, the radio and the wire, which is why build.sh globs its sources rather than naming one: a library splitting a file should not break a build in a repository its author is not in. And a frame is now handed over when the firmware arms its receiver as well as on a tick, which is the fault that made an emulated board relay less often than a native one - delivery on a tick alone made every reception depend on a tick landing after the SetRx, and radioserver's ticks arrive from the engine over a socket rather than from the same process. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6
Two faults, one of which would have broken the next release. build.yml's two compiling jobs checked out the repository without submodules. With the model vendored that is a bare gitlink, so build.sh would stop on its own guard and every platform's radioserver would fail to build - loudly, which is the guard working, but at release time. And nothing verified a pull request here: build.yml runs on a tag or a button only. That is how a change to build.sh and a new submodule got as far as a merge with no evidence they compiled. pr.yml builds radioserver on one platform, which is the whole of what this repository adds around the vendored model and needs no MeshCore checkout, so it costs about a minute. The submodule's presence is asserted before the build rather than inside it, so an empty submodule reads as an empty submodule instead of as a compile error in a file that is not there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6
The glob added in the last commit picks up abi.cpp, which includes the C ABI header from include/ rather than the class header from src/, and only src/ was on the include path. Caught by the pull request check in that same commit, on its first run, which is the argument for having it. Both roots are on the path now. Carrying the ABI in these binaries costs a few unreferenced symbols and means radioserver already exports the surface QEMU and Renode link against. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6
radioserver and a native role link the same vendored model through different include paths and different source lists, and the glob two commits ago broke exactly one of them. Checking one and not the other would have found that fault by luck rather than by design. The native job takes MeshCore at its default branch rather than a pinned commit. This job asks whether our own wiring compiles; a second MeshCore pin to keep honest buys nothing, and a break caused by upstream moving is worth seeing on a pull request as well as at release time. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6
The fault that made an emulated board hear every advert and relay one in three. SetDioIrqParams carries an IRQ enable mask and then a DIO1 routing mask; the model read the first and used it for the pin. RadioLib enables HeaderValid in the status register but routes only RxDone to DIO1, so the pin went high twelve symbols into the carrier and was still high when RxDone arrived - no rising edge, and RadioLib attaches that pin on the rising edge, so recvRaw never ran. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6
This was referenced Sep 3, 2026
A13xB0
added a commit
that referenced
this pull request
Sep 3, 2026
This repository builds MeshCore for this host. radioserver was here only because the chip model used to be here too: it wrapped VirtualSX1262 behind a socket so QEMU and Renode could reach the same model a native node links. The model moved to MeshBench/virtual-sx1262 in #14, and both emulators now load it directly, so nothing calls this and nothing needs to. What that arrangement cost, beyond the round trips: it framed SPI a byte at a time, which is how the model came to answer GetRssiInst correctly for a native node and with zero for an emulated one for months; it left DIO1 pollable only, because the protocol was request-response; and it put three clocks in three processes in front of anybody asking what happened when. The submodule stays. A native node compiles the model in, which is what keeps it the same chip as the one the emulators load, from the same commit. Gone: bridge/radioserver.cpp, the radioserver branch of build.sh, its two release jobs, its pull-request job, RADIOSERVER_PLATFORMS, the radioserver_only input and radioserver.version. The published radioserver-v1..v3 releases stay where they are; nothing new is cut. A native role still builds: simple_repeater for linux-amd64, from this tree. Claude-Session: https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6 Co-authored-by: R0ck <random@email.com> 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.
The chip model was a file in
variants/host/, beside the firmware build, and three other things wanted it: QEMU'ssx1262device, Renode's C# peripheral, and the simulator. They reached it by talking toradioserverover a socket, because that was the only way in.It now lives in MeshBench/virtual-sx1262 with a C ABI and its own test suite, and arrives here as a submodule at
vendor/virtual-sx1262.Nothing about how this repository builds changes. The native node still links the class in process;
radioserverstill wraps it. What changes is that there is one copy and one history. Two copies of a chip model drift, and the day they do, a native node and an emulated one stop being comparable, which is the whole reason both backends exist.It brings two fixes this copy did not have
Both found while chasing why emulated boards received every advert and relayed none:
RxDone, asserting a carrier was present at the instant it stopped. MeshCore'sCustomSX1262::isReceivingreadsHEADER_VALIDas "the channel is busy", so a repeater holding a packet to forward never saw a clear channel. They are now raised as the signal arrives and cleared when it goes.SetRxre-arm and no longer.Both are covered by tests over there, which is the point of it having a bench of its own: these took a four minute emulated boot to see from here.
Checked
radioserverandsimple_repeaterboth build for linux-amd64 against the submodule.Note for reviewers:
git submodule update --initafter checkout, and the build says so plainly if the submodule is empty rather than failing further down.🤖 Generated with Claude Code
https://claude.ai/code/session_01Q9HbD44EKWWTRYgxbFGxf6