All docsStellar LinkRF bench · by Stellar Systems v0.1.0

Control & Automation

Chain Conditioning

The prerequisites of an emission, read back from the board; the one order that establishes them; chain targets; recovery without a reboot.

Before the modem can put a sample where you want it, a dozen independent things must be right: the AD9361 calibrated and tuned at the right rate, a profile applied after that tuning, the DAC fed from the modem, the transceiver in an emitting state, the loopback switches on the right side, the TX egress open and the datapath claimed. Getting any of them wrong produces a chain that looks healthy and transmits nothing.

The chain layer enumerates these prerequisites, reads them back from the board on every request, and establishes the missing ones in the only order that works.

Checking the chain#

Shell
satlinkctl chain status                    # judged against the target the board is wired for
satlinkctl chain status --target air       # "what would it take to go on air?"

GET /api/v1/chain returns the same, with one entry per condition:

FieldMeaning
keyThe condition's name (below)
stageThe group it belongs to
sourceboard (read from a register or IIO attribute now) or session (held by the daemon since boot)
required, observedWhat the target needs, and what was read
verdictmet, unmet or unknown
breaksWhat goes wrong when it is not met

An unreadable fact is unknown, and unknown counts as not met: the chain refuses to build a plan on a register it could not read.

The conditions#

KeyStageApplies toRequired
calibratedunconditioneddevice loopback, airThe AD9361's analog calibrations have run since boot
rateunconditioneddevice loopback, airThe AD9361 sample rate is exactly what the active profile's symbol rate needs (at most 13 MSa/s without a profile)
tuningunconditioneddevice loopback, airThe LVDS digital interface was tuned, and not lost to a later calibration
profileunprofiledallA profile is applied (the named one, when you name one)
profile-orderunprofileddevice loopback, airThe profile was applied after the last tuning (a tuning overwrites part of what a profile sets)
modulatormisroutedallThe selected modulator is the enabled one
dac-sourcemisrouteddevice loopback, airdac_data_sel = 2 (DMA): the DAC takes the modem's samples
ensmmisrouteddevice loopback, airThe AD9361 ENSM is in fdd
pl-muxmisroutedallGLOBAL_CTRL[0] is 1 for the PL loopback, 0 otherwise
device-loopbackmisrouteddevice loopback, airThe AD9361's internal digital loopback is closed (device loopback) or open (air)
tx-egressnot-armedallThe modem's TX egress is open
datapathnot-armedallsatlinkd holds the modem's DMA devices

The overall stage is the stage of the first unmet condition: unconditioned, unprofiled, misrouted, not-armed, or ready.

Bringing the chain up#

Shell
satlinkctl chain up --target air --profile rf_loopback
satlinkctl chain up --target pl  --profile pl_loopback

POST /api/v1/chain/condition with {"target": "air", "profile": "rf_loopback"} does the same. With no profile named, the currently applied one is used; with none applied, the request is refused rather than guessing, because the profile decides the frame length, the coding and the frequency.

Only the missing steps run, always in this order:

StepRuns whenWhy here
calibratedevice loopback or air, not calibrated since bootIt resets the AD9361, so everything else must come after it
set-ensmafter a calibration, or when the ENSM is not fddThe tuning needs a clocked data port; this is also what undoes the RF kill switch
tuneafter a calibration, or when the rate, tuning or ENSM is wrongSets the AD9361 rate (the profile's, or --rate) and sweeps the LVDS delays at that rate. It drives the DAC to a test pattern during the sweep
apply-profileafter any tune, or when the profile is missing, wrong or older than the tuningA tuning invalidates the profile
set-modeafter any earlier step, or when a switch is wrongA profile apply rewrites the loopback mux and the LOs, so the mode is set last
start-txwhen the TX egress is closed
enable-datapathwhen the datapath is not held

The result lists the steps run and the chain state re-read afterwards. For the air target the verdict states all three doors explicitly: pl-mux 0, device-loopback open, dac-source 2 (DMA), reaches_the_connector: true.

Manual steps#

The individual steps are available when you need them, but taking them out of order undoes the earlier ones:

Shell
satlinkctl rf calibrate          # resets the part: FIRST, before anything else
satlinkctl rf tune --rate 2500000
satlinkctl profile apply rf_loopback
satlinkctl rf air                # or: rf rf (device loopback), rf pl (PL loopback)
satlinkctl radio start-tx
satlinkctl datapath enable

rf air and rf rf refuse when the interface was never tuned or when the profile was applied before the last tuning; --force overrides the refusal.

Chain targets#

--targetScenario chain.targetMeaning
pl-loopback or plplTX → channel emulator → RX inside the FPGA. The AD9361 is not used
device-loopbackdevice-loopbackThrough the AD9361's internal digital loopback, before the mixers. Nothing leaves the board; LOs, gains and attenuation have no effect
airairOut through the mixers to TX1

rf is accepted by the CLI as an alias of the device loopback, but scenarios deliberately refuse it: an "RF" mode that emits nothing is exactly the confusion that makes an analyser on the connector show nothing.

Recovering the receiver without a reboot#

The receiver's loops can get stuck: symbols flow, the lock flags read true, and the deframer never finds its marker. A clear flushes the AGC, the timing loop and the carrier loop in signal-flow order, preserving every other bit of their control registers:

Shell
satlinkctl chain recover         # POST /api/v1/chain/recover

It says what it pulsed; it does not say the link is healed. Check that with a byte-exact loopback or with frame counters that move, never with the lock flags.

Scenario runs on the air path do this automatically: after the profile apply, the engine pulses the clear 500 ms after its traffic feed starts, so the loops re-acquire on a live signal. A clear issued before traffic flows does not help. A profile apply also clears the loops.

Scenarios and the chain#

Every scenario run conditions the chain first, for a target derived from its profile (radio.loopback: true → pl, otherwise air) unless the scenario declares one, and refuses to start when the target cannot be reached: no run record, no report. See Scenarios.

Stellar Link · v0.1.0

↑↓ to moveEnter to open