-
Notifications
You must be signed in to change notification settings - Fork 18
feat: UHF radio port to Semtech USP — v5e board, UspRadio integration, carried patches (central tracking PR) #439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
6123816
52264f9
986fa02
5c17352
8782fb4
1360ccb
ad10ef6
32a30ba
394d739
48f0775
aa264fd
2b3b8f7
871eee4
ee87a00
682d9b2
edc03f5
65d96bd
8d40fd9
ef37630
b1e80f9
eaac48f
fc7bc14
09b9613
468db15
3381f42
f5a0e3b
aaff8dc
8078c2a
071f78a
fc0a514
d7102b6
14a84ae
ef19015
a7d0e7d
a628591
11ec659
39bc693
976d510
d83cd91
c03173b
7839061
39e5857
2cb083c
33424fa
7ce4fda
dcd0b61
f46d533
c896de2
220d357
2b997f8
b7931b1
71ceaf3
d704fd3
c6df588
60eb485
12056fc
1560dce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # CONTEXT: PROVES Flight Radio | ||
|
|
||
| Glossary for the flight-software radio domain. Terms here are canonical; use them in code, docs, commands, and telemetry names. | ||
|
|
||
| ## Radio paths | ||
|
|
||
| - **USP Radio Path**: the radio stack built on Semtech's Unified Software Platform (USP). Applies to SX126x-class boards (FCB v5e onward). Multi-modulation capable. | ||
| - **Legacy Radio Path**: the existing loramac-node-backed Zephyr `drivers/lora` stack wrapped by the `Zephyr::LoRa` component. Applies to SX127x-class boards (FCB v5/v5c/v5d). LoRa modulation only. | ||
| - **USP (Unified Software Platform)**: Semtech's radio software platform (radio drivers + RAL + radio access arbitration + LoRa Basics Modem). `usp_zephyr` is its Zephyr integration module. | ||
| - **LBM (LoRa Basics Modem)**: Semtech's modem library bundled inside USP. Its LoRaWAN stack is unused; PROVES flies raw CCSDS point-to-point. | ||
| - **RAL (Radio Abstraction Layer)**: USP's chip-agnostic radio API. The seam the flight component talks to, and the seam mocked in unit tests. | ||
|
|
||
| ## Link configuration | ||
|
|
||
| - **Link Profile**: a complete, named radio configuration: modulation plus every parameter needed for two radios to interoperate (e.g. for GFSK: bitrate, deviation, BT, sync word, CRC, preamble). Identified by index into the Profile Table. Profiles are switched atomically; individual RF parameters are never commanded piecemeal in operations. | ||
| - **Profile Table**: the versioned, checked-in list of Link Profiles shared verbatim by flight and ground builds. Both ends must be built from the same table version for a profile index to mean the same thing. | ||
| - **TX Profile / RX Profile**: the Link Profile currently applied to the transmit and receive directions independently. The link is asymmetric by design (e.g. robust LoRa uplink, high-rate GFSK downlink). | ||
| - **Boot-Default Profile**: the profile each direction starts in at boot, and the profile RX Auto-Revert falls back to. Chosen for maximum link robustness, not throughput. | ||
| - **RX Auto-Revert**: safety mechanism: after an RX Profile change, if no valid frame is received within the commanded revert window, the RX Profile reverts to the Boot-Default Profile. Receiving a valid frame on the new profile confirms it. | ||
|
|
||
| ## Modulations | ||
|
|
||
| - **CW (Continuous Wave)**: unmodulated carrier transmission for beacons, range testing, and RF debug. A test mode, not a Link Profile. | ||
| - **GFSK**: Gaussian FSK packet modulation; the high-throughput downlink option on the USP Radio Path. Capped at 75 kbps, with fdev of 25 kHz, by the Band Constraint. | ||
| - **Band Constraint**: IARU coordination limits PROVES UHF emissions to 125 kHz occupied bandwidth or less. Every Link Profile must satisfy it. | ||
| - **LR-FHSS**: long-range frequency-hopping modulation. SX126x can transmit but never receive it, so it is out of scope until gateway-grade or LR20xx receive hardware exists in the ground segment. | ||
|
|
||
| ## Ground segment | ||
|
|
||
| - **GRC (Ground Radio Controller)**: the station-local Zephyr radio box (SX1262) that terminates the RF link. Must consume the same Profile Table as flight. | ||
| - **RadioHead Header**: the 4-byte `[destination, source, identifier, flags]` prefix the RadioHead LoRa ecosystem (adafruit_rfm9x, legacy `Zephyr::LoRa`) puts on every LoRa packet. The USP Radio Path radiates raw F´ frames; the `RADIOHEAD_COMPAT` parameter on `UspRadio` (default: enabled) prepends/strips this header so USP boards interoperate with RadioHead peers such as the CI CircuitPython passthrough board. Both ends of a link must agree; GFSK profiles are always raw. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,11 +5,33 @@ | |
| # AUTOCODER_INPUTS: list of files to be passed to the autocoders | ||
| # DEPENDS: list of libraries that this module depends on | ||
| # | ||
| # More information in the F´ CMake API documentation: | ||
| # https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ | ||
| # | ||
| # Per-board radio selection: | ||
| # CONFIG_LORA_BASICS_MODEM_DRIVERS set (v5e): Radio*.fppi -> Radio*_Usp.fppi (Zephyr::UspRadio) | ||
| # CONFIG_LORA_BASICS_MODEM_DRIVERS unset (v5c/v5d): Radio*.fppi -> Radio*_Lora.fppi (Zephyr::LoRa) | ||
| # FPP `include` resolves relative to the including file, so the links are | ||
| # created in the source tree at configure time. COPY_ON_ERROR falls back to a | ||
| # file copy where symlinks are not supported. The links are gitignored. | ||
| #### | ||
|
|
||
| if(DEFINED CONFIG_LORA_BASICS_MODEM_DRIVERS) | ||
| set(RADIO_SUFFIX "Usp") | ||
| else() | ||
| set(RADIO_SUFFIX "Lora") | ||
| endif() | ||
|
Comment on lines
+16
to
+20
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '--- PROVESFlightControllerReference/ReferenceDeployment/Top/CMakeLists.txt ---\n'
cat -n PROVESFlightControllerReference/ReferenceDeployment/Top/CMakeLists.txt
printf '\n--- Search for CONFIG_LORA_BASICS_MODEM_DRIVERS and related guards ---\n'
rg -n "CONFIG_LORA_BASICS_MODEM_DRIVERS|if\\(DEFINED CONFIG_|if\\(CONFIG_" PROVESFlightControllerReference -g 'CMakeLists.txt' -g '*.cmake' -g '*.txt' -g '*.hpp' -g '*.cpp'
printf '\n--- Nearby CMake/Kconfig integration files ---\n'
git ls-files 'PROVESFlightControllerReference/**/Kconfig*' 'PROVESFlightControllerReference/**/prj.conf' 'PROVESFlightControllerReference/**/overlay*.conf' 'PROVESFlightControllerReference/**/CMakeLists.txt'Repository: Open-Source-Space-Foundation/proves-core-reference Length of output: 279 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- PROVESFlightControllerReference/ReferenceDeployment/Top/CMakeLists.txt ---'
cat -n PROVESFlightControllerReference/ReferenceDeployment/Top/CMakeLists.txt
echo
echo '--- Search for CONFIG_LORA_BASICS_MODEM_DRIVERS and related guards ---'
rg -n "CONFIG_LORA_BASICS_MODEM_DRIVERS|if\\(DEFINED CONFIG_|if\\(CONFIG_" PROVESFlightControllerReference -g 'CMakeLists.txt' -g '*.cmake' -g '*.txt' -g '*.hpp' -g '*.cpp'
echo
echo '--- Nearby CMake/Kconfig integration files ---'
git ls-files 'PROVESFlightControllerReference/**/Kconfig*' 'PROVESFlightControllerReference/**/prj.conf' 'PROVESFlightControllerReference/**/overlay*.conf' 'PROVESFlightControllerReference/**/CMakeLists.txt'Repository: Open-Source-Space-Foundation/proves-core-reference Length of output: 7341 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- PROVESFlightControllerReference/project/config/CMakeLists.txt ---'
cat -n PROVESFlightControllerReference/project/config/CMakeLists.txt
echo
echo '--- PROVESFlightControllerReference/ReferenceDeployment/CMakeLists.txt ---'
cat -n PROVESFlightControllerReference/ReferenceDeployment/CMakeLists.txt
echo
echo '--- PROVESFlightControllerReference/ReferenceDeployment/Main.cpp ---'
sed -n '1,140p' PROVESFlightControllerReference/ReferenceDeployment/Main.cpp
echo
echo '--- PROVESFlightControllerReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp ---'
sed -n '1,220p' PROVESFlightControllerReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cppRepository: Open-Source-Space-Foundation/proves-core-reference Length of output: 22403 🌐 Web query:
💡 Result: In CMake, the if command evaluates variables based on specific truthiness rules [1][2]. When you use if(CONFIG_VAR), CMake checks the value of the variable named CONFIG_VAR [1][2]. The following values are considered false in CMake [1][2]: - The constants: 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND [1][2]. - The empty string "" [1][2]. - Any value ending in the suffix -NOTFOUND [1][2]. - Undefined variables are also considered false [3][1][2]. If a variable is defined to any other value, it is considered true [3][1][2]. Regarding Zephyr and Kconfig: When Zephyr processes Kconfig symbols, symbols set to n are typically treated in a way that aligns with these CMake rules [4]. Specifically, Kconfig boolean symbols set to n correspond to unset variables or variables explicitly set to n in the resulting configuration output used by CMake [4]. Because CMake treats both undefined variables and the constant n as false, if(CONFIG_VAR) will correctly evaluate to false for symbols that are disabled (n) or unset [1][4][2]. If you are dealing with a scenario where you expect a symbol to be false but it is evaluating to true, ensure the variable is not being set to a non-false string (e.g., a literal "n" that is being treated as a string or a value like "0" that might have been converted) and verify the definition state of the variable within your CMake scope [1][5][2]. Citations:
Use a value check for 🤖 Prompt for AI Agents |
||
|
|
||
| # Instance and topology snippets. | ||
| foreach(_kind "Instances" "Topology") | ||
| set(_src "${CMAKE_CURRENT_LIST_DIR}/Radio${_kind}_${RADIO_SUFFIX}.fppi") | ||
| set(_dst "${CMAKE_CURRENT_LIST_DIR}/Radio${_kind}.fppi") | ||
| file(CREATE_LINK "${_src}" "${_dst}" SYMBOLIC COPY_ON_ERROR) | ||
| endforeach() | ||
| # Packet snippets (they reference the per-board instance names). | ||
| foreach(_kind "BytesReceived" "Radio") | ||
| set(_src "${CMAKE_CURRENT_LIST_DIR}/RadioPackets${_kind}_${RADIO_SUFFIX}.fppi") | ||
| set(_dst "${CMAKE_CURRENT_LIST_DIR}/RadioPackets${_kind}.fppi") | ||
| file(CREATE_LINK "${_src}" "${_dst}" SYMBOLIC COPY_ON_ERROR) | ||
| endforeach() | ||
|
|
||
| register_fprime_module( | ||
| AUTOCODER_INPUTS | ||
| "${CMAKE_CURRENT_LIST_DIR}/instances.fpp" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Radio instances for v5c / v5d (Zephyr LoRa driver). | ||
| # Included by instances.fpp inside module ReferenceDeployment { }. | ||
| # Selected by Top/CMakeLists.txt per board. | ||
|
|
||
| instance lora: Zephyr.LoRa base id 0x1001F000 | ||
|
|
||
| instance loraRetry: Svc.ComRetry base id 0x10063000 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # Radio instances for v5e (Semtech USP driver). | ||
| # Included by instances.fpp inside module ReferenceDeployment { }. | ||
| # Selected by Top/CMakeLists.txt per board. | ||
| # | ||
| # UspRadio is an active component. Priority 11 is above the rate groups. | ||
|
|
||
| instance uspRadio: Zephyr.UspRadio base id 0x1001F000 \ | ||
| queue size Default.QUEUE_SIZE * 2 \ | ||
| stack size Default.STACK_SIZE \ | ||
| priority 11 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| lora.BytesReceived |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| uspRadio.BytesReceived |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| packet Radio id 8 group 2 { | ||
| lora.LastRssi | ||
| lora.LastSnr | ||
| lora.BytesSent | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| packet Radio id 8 group 2 { | ||
| uspRadio.LastRssi | ||
| uspRadio.LastSnr | ||
| uspRadio.BytesSent | ||
| uspRadio.TxProfile | ||
| uspRadio.RxProfile | ||
| uspRadio.RxReverts | ||
| uspRadio.RxDropped | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Radio connections for v5c / v5d (Zephyr LoRa driver). | ||
| # Included by topology.fpp inside topology ReferenceDeployment { }. | ||
| # Selected by Top/CMakeLists.txt per board. | ||
|
|
||
| instance lora | ||
| instance loraRetry | ||
|
|
||
| connections CommunicationsRadio { | ||
| lora.allocate -> ComCcsdsLora.commsBufferManager.bufferGetCallee | ||
| lora.deallocate -> ComCcsdsLora.commsBufferManager.bufferSendIn | ||
|
|
||
| # ComDriver <-> FrameAccumulator (Uplink) | ||
| lora.dataOut -> ComCcsdsLora.frameAccumulator.dataIn | ||
| ComCcsdsLora.frameAccumulator.dataReturnOut -> lora.dataReturnIn | ||
|
|
||
| # ComStub <-> ComDriver (Downlink) with ComRetry shim | ||
| ComCcsdsLora.framer.dataOut -> loraRetry.dataIn | ||
| loraRetry.dataOut -> lora.dataIn | ||
|
|
||
| lora.dataReturnOut -> loraRetry.dataReturnIn | ||
| loraRetry.dataReturnOut -> ComCcsdsLora.framer.dataReturnIn | ||
|
|
||
| lora.comStatusOut -> loraRetry.comStatusIn | ||
| loraRetry.comStatusOut -> downlinkDelay.comStatusIn | ||
| downlinkDelay.comStatusOut -> ComCcsdsLora.framer.comStatusIn | ||
|
|
||
| # Startup and sequence wiring (same in RadioTopology_Usp.fppi) | ||
| startupManager.runSequence -> cmdSeq.seqRunIn | ||
|
|
||
| # StartupManager receives sequence status from CmdSeq | ||
| cmdSeq.seqStartOut -> startupManager.startupsequenceStarted | ||
| cmdSeq.seqDone -> startupManager.startupCompleteSequence | ||
|
|
||
| # StartupManager receives sequence status from PayloadSeq | ||
| payloadSeq.seqStartOut -> startupManager.payloadSequenceStarted | ||
| payloadSeq.seqDone -> startupManager.payloadCompleteSequence | ||
|
|
||
| # StartupManager receives sequence status from SafeModeSeq | ||
| # seqDone is owned by ModeManager; completion is forwarded via sequenceDoneNotify | ||
| safeModeSeq.seqStartOut -> startupManager.safeModeSequenceStarted | ||
|
|
||
| # StartupManager drives radio TX enable/disable around quiescence | ||
| startupManager.enableTransmit -> lora.enableTransmit | ||
| startupManager.disableTransmit -> lora.disableTransmit | ||
|
|
||
| # --- Radio ever enabled this boot? --- | ||
| lora.loraFirstStart -> startupManager.loraFirstStart | ||
|
|
||
| modeManager.runSequence -> safeModeSeq.seqRunIn | ||
| safeModeSeq.seqDone -> modeManager.completeSequence | ||
| modeManager.sequenceDoneNotify -> startupManager.safeModeCompleteSequence | ||
|
|
||
| # RTC time change cancels running sequences | ||
| rtcManager.cancelSequences[0] -> cmdSeq.seqCancelIn | ||
| rtcManager.cancelSequences[1] -> payloadSeq.seqCancelIn | ||
| rtcManager.cancelSequences[2] -> safeModeSeq.seqCancelIn | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # Radio connections for v5e (Semtech USP driver). | ||
| # Included by topology.fpp inside topology ReferenceDeployment { }. | ||
| # Selected by Top/CMakeLists.txt per board. | ||
| # | ||
| # UspRadio is active, so its queue provides back-pressure and no ComRetry shim is needed. | ||
|
|
||
| instance uspRadio | ||
|
|
||
| connections CommunicationsRadio { | ||
| uspRadio.allocate -> ComCcsdsLora.commsBufferManager.bufferGetCallee | ||
| uspRadio.deallocate -> ComCcsdsLora.commsBufferManager.bufferSendIn | ||
|
|
||
| # UspRadio <-> FrameAccumulator (Uplink) | ||
| uspRadio.dataOut -> ComCcsdsLora.frameAccumulator.dataIn | ||
| ComCcsdsLora.frameAccumulator.dataReturnOut -> uspRadio.dataReturnIn | ||
|
|
||
| # UspRadio <-> Framer (Downlink) | ||
| ComCcsdsLora.framer.dataOut -> uspRadio.dataIn | ||
| uspRadio.dataReturnOut -> ComCcsdsLora.framer.dataReturnIn | ||
| uspRadio.comStatusOut -> downlinkDelay.comStatusIn | ||
| downlinkDelay.comStatusOut -> ComCcsdsLora.framer.comStatusIn | ||
|
|
||
| # Startup and sequence wiring (same in RadioTopology_Lora.fppi) | ||
| startupManager.runSequence -> cmdSeq.seqRunIn | ||
|
|
||
| # StartupManager receives sequence status from CmdSeq | ||
| cmdSeq.seqStartOut -> startupManager.startupsequenceStarted | ||
| cmdSeq.seqDone -> startupManager.startupCompleteSequence | ||
|
|
||
| # StartupManager receives sequence status from PayloadSeq | ||
| payloadSeq.seqStartOut -> startupManager.payloadSequenceStarted | ||
| payloadSeq.seqDone -> startupManager.payloadCompleteSequence | ||
|
|
||
| # StartupManager receives sequence status from SafeModeSeq | ||
| # seqDone is owned by ModeManager; completion is forwarded via sequenceDoneNotify | ||
| safeModeSeq.seqStartOut -> startupManager.safeModeSequenceStarted | ||
|
|
||
| # StartupManager drives radio TX enable/disable around quiescence | ||
| startupManager.enableTransmit -> uspRadio.enableTransmit | ||
| startupManager.disableTransmit -> uspRadio.disableTransmit | ||
|
|
||
| # Both ports are Fw.Signal, so the names may differ. | ||
| uspRadio.radioFirstStart -> startupManager.loraFirstStart | ||
|
|
||
| modeManager.runSequence -> safeModeSeq.seqRunIn | ||
| safeModeSeq.seqDone -> modeManager.completeSequence | ||
| modeManager.sequenceDoneNotify -> startupManager.safeModeCompleteSequence | ||
|
|
||
| # RTC time change cancels running sequences | ||
| rtcManager.cancelSequences[0] -> cmdSeq.seqCancelIn | ||
| rtcManager.cancelSequences[1] -> payloadSeq.seqCancelIn | ||
| rtcManager.cancelSequences[2] -> safeModeSeq.seqCancelIn | ||
| } | ||
|
|
||
|
|
||
| connections RadioRateGroup { | ||
| # 1 Hz tick for the revert deadline and telemetry flush. Slot 20 is the first unused rate-group slot. | ||
| rateGroup1Hz.RateGroupMemberOut[20] -> uspRadio.run | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Synchronize existing submodule checkouts with the new URLs.
Changing
.gitmodulesdoes not update URLs already stored in existing clones’.git/config. SinceMakefile:10-13runsgit submodule updatewithoutgit submodule sync, developers with an existing checkout may continue fetching the old upstream repositories instead of the OSSF forks.Add
git submodule sync --recursivebefore the update, or explicitly document that migration step.🤖 Prompt for AI Agents