Feat/two way radio communication - #34
Merged
Merged
Conversation
The test suites did not build in the west-workspace layout: - BOARD_ROOT in both test CMakeLists pointed outside the manifest repo, so the ubcrocket_polarity board was never found. - The integration testcase.yaml referenced the old board name ubcrocket_fc_2526_r1. - The state_machine suite compiled state_machine_common.c without any implementation of pyro_fire_drogue/pyro_fire_main; add test stubs. - transition_to_main_descent never waited for the drogue-fire delay, so the main-deploy check counter was reset every time (the drogue-before- main condition from #33); step past DROGUE_DEPLOY_DELAY_MS first. State machine suite now passes 9/9 (run on qemu_cortex_m3).
Downlink additions (Phase 0): - Generate GroundCommand.pb from falcon-protos (and drop the deleted HelloWorldPacket from the nanopb list, which broke the build). - Add shared camera status (struct camera_data) alongside the other cross-thread snapshots and report runcam_power / runcam_recording in every telemetry packet. Uplink receive path (Phase 1): - gnss_spi: single mutex-guarded access point for the three consumers of the GNSS/radio board on SPI1 (telemetry TX, GPS RX, command RX). - command_thread: RX poller (COBS decode -> CRC16 -> pb_decode) feeding a k_msgq consumed by an executor thread; replayed command_ids are ignored and command effects are acked implicitly via the telemetry fields. - The radio-RX SPI opcode (0x06) is a PLACEHOLDER pending the bidirectional GNSS firmware spec; see firmware/src/uplink_config.h. VTX/RunCam control (Phases 2-3): - vtx_power: GPIO switch driver, powered on by default at boot. PLACEHOLDER pin PB0 in the devicetree until hardware confirms. - runcam: RunCam Device Protocol frames over UART (PLACEHOLDER: USART2 on PA2/PA3 @115200 until hardware/David confirm; recording state is optimistic since CAMERA_CONTROL defines no response). - Both fall back to simulated implementations when the devicetree alias is absent (native_sim). RFD900x remote reconfiguration (Phase 4) is intentionally NOT implemented: rfd_config commands are logged and ignored, per the proto comment marking them ground-local. To be revisited once the team resolves the discrepancy with the checklist. Landed shutdown (Phase 5): - state_action_landed() stops the recording, then cuts VTX/RunCam power; covered by a new state-machine test and a landed-phase assertion in the integration test. Simulation support: - New zephyr,sim-radio SPI emulator so the full firmware (including the radio, GPS and command threads) builds and runs on native_sim. Verified: ubcrocket_polarity builds (firmware + both test suites), state_machine suite 10/10 on qemu_cortex_m3, native_sim build + smoke run in the zephyr-build container.
Hardware confirmations from the team lead: - VTX/RunCam power switch is PD6 (was placeholder PB0). Active level still assumed high. - RunCam UART is UART4 (was placeholder USART2); USART2 is disabled again. The UART4 pin pair is still unconfirmed -- PA0/PA1 assumed, see the PLACEHOLDER comment in the DTS for the alternatives. RunCam recording decision: the camera has auto-recording enabled, so recording follows the power rail and no start command is needed. The runcam module is kept but dormant until the protobufs are reworked to carry RunCam commands: - The command executor acts only on vtx_runcam_power; camera_recording commands are logged and ignored. - Landed shutdown just cuts the PD6 rail (no UART stop frame). - runcam_init() is still called at boot to validate the UART wiring. Note: telemetry runcam_recording now always reads false -- nothing sets it while recording is inferred from the power rail. Revisit with the protobuf rework. Verified: ubcrocket_polarity firmware builds; state_machine suite 10/10 on qemu_cortex_m3 (landed test updated: no RunCam command sent, power cut exactly once).
ivan-lyf
force-pushed
the
feat/two-way-radio-communication
branch
from
July 26, 2026 18:17
2ebc14f to
bad9d53
Compare
FALCON now applies an uplinked RfdConfig to the rocket-side RFD900x through an AT command session (team decision: supersedes the stale ground-local comment in GroundCommand.proto). Safety design -- a half-applied config must never brick comms: - config validated (ranges, min<=max) before the modem is touched - every AT command must be acknowledged with OK before the next one - every S-register is read back (ATSn?) and compared after writing - AT&W (EEPROM write) is only sent after all writes verified; ATZ only after AT&W is acknowledged; any earlier failure aborts with ATO so the modem keeps the config the link was established with - telemetry TX is suspended during the session so the +++ guard time sees a silent serial line The AT session engine (rfd900x_at.c) is transport-agnostic; the UART transport (rfd900x.c, rfd-uart alias, USART2 PA2/PA3 @57600 placeholder) can be swapped for GNSS-board AT-passthrough once the physical path is confirmed. Tested with a scripted mock modem (firmware/tests/rfd900x): happy path, partial/zero-value configs, echo+noise tolerance, validation rejects, entry timeout, ERROR reply, mid-sequence silence, readback mismatch, and unacknowledged AT&W -- 12/12 passing on native_sim.
ivan-lyf
marked this pull request as ready for review
July 26, 2026 18:24
Contributor
There was a problem hiding this comment.
Untested, do tests on native sim with this in the future if needed
jasonkwok475
approved these changes
Jul 26, 2026
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.
Implements the rocket side of two-way radio communication: FALCON now receives GroundCommand protobufs uplinked through the RFD900x/GNSS board, acts on camera-control commands (VTX/RunCam power), reports camera status in telemetry, shuts the cameras down on landing by cutting the camera power rail, and reconfigures the rocket-side RFD900x modem from an uplinked RfdConfig through a fail-safe AT command session.
Downlink
Uplink receive path
Camera control
vtx_runcam_power;camera_recordingcommands are logged and ignored until the protobufs are reworked to carry RunCam commands.runcam_init()still runs at boot to validate the UART wiring.Landed shutdown
RFD900x remote reconfiguration
Resolved: FALCON applies
rfd_configto the rocket-side modem (the "ground-local" comment in GroundCommand.proto is stale). A half-applied config would kill the link permanently, so the session is built so it can never commit a partial config:+++→OK, then per populated fieldATSn=v(S2 air speed, S3 net id, S4 power, S8/S9 min/max freq, S10 channels), each requiringOKand a matchingATSn?readback, thenAT&W→OK, thenATZ.AT&Wis only sent after every write is verified;ATZonly afterAT&Wis acknowledged. Any earlier failure (timeout,ERROR, readback mismatch) aborts withATO, so EEPROM keeps the config the link was established with.rfd-uartdevicetree alias; suspends telemetry TX for the session (radio_tx_suspend()) so the+++guard time sees a silent serial line. Simulated when the alias is absent (native_sim).OK/ all-digit value line counts.OKafter+++,ERRORreply, mid-sequence silence, readback mismatch, and unacknowledgedAT&W(assertsATZis never sent).Assumed — still needs an answer
Everything unconfirmed is centralized in
firmware/src/uplink_config.h(constants) andboards/ubcrocket/polarity/ubcrocket_polarity.dts(pins), so each answer is a one-line change.0x06and its framing (assumed to mirror the GPS read0x05:[CMD:1][DUMMY:4][PAYLOAD:256], COBS frame zero-filled when nothing is pending).rfd-uartalias). If the real path is AT-passthrough via the GNSS board, only the transport inrfd900x.cchanges — the AT session engine is transport-agnostic.uplink_config.h(902–928 MHz, NETID ≤ 499, power ≤ 30 dBm, air speed 4–750, 1–50 channels) follow the RFD900x/SiK S-register docs — confirm against the actual modem firmware limits and the finalized command list.Known limitations
runcam_recordingcurrently always reads false — recording is inferred from the power rail and nothing sets the flag. Revisit with the protobuf rework (or set it optimistically on power-on if the ground station needs it sooner).sim_radio) accepts telemetry TX and returns all-zero reads, so uplink commands cannot be injected in sim yet — the decode path (COBS/CRC/protobuf/dedup) runs only on real hardware. An injection hook is future work.