All docsStellar LinkRF bench · by Stellar Systems v0.1.0

Radio Concepts

RF Fundamentals

Sample rates and the symbol-rate ladder, bandwidths, the LO and NCO offset scheme, gains and attenuation, and what the level indicators mean.

This page explains the radio quantities an operator sets and reads on SatLink, and how they are constrained by the hardware. The modem's internals are covered in Signal Processing.

Sample rate, samples per symbol and symbol rate#

The symbol rate on the air is not a free number. It is a division:

text
symbol_rate = ad9361_sample_rate / (sps × interp)
TermRangeWhy
sps4, fixedEvery pulse-shaping kernel in the PL (the RRC matched filter, the BPSK, QPSK and GMSK modulators) is built for 4 samples per symbol when the bitstream is synthesised. A profile with any other samples_per_symbol is refused
interp1 to 32The range the DUC decodes (the DDC decimates by the same factor)
AD9361 sample rate2 083 333 to 61 440 000 Sa/sThe part's own limits
Modem sample rateup to 13 MSa/sAbove that the chain cannot fill every DAC beat and the DAC is fed zeros

So only a fixed ladder of symbol rates can be produced. phy.symbol_rate_baud in a profile must be one of the available rungs; GET /api/v1/system/capabilities lists them all.

Symbol rate (baud)AD9361 rateinterpAvailable
5 000 00020 MSa/s1No — above the 13 MSa/s the modem sustains
2 500 00010 MSa/s1Yes
1 250 0005 MSa/s1Yes
625 0002.5 MSa/s1Yes
312 5002.5 MSa/s2Yes
156 2502.5 MSa/s4Yes
78 1252.5 MSa/s8Yes
39 062.52.5 MSa/s16Yes
19 531.252.5 MSa/s32Yes
9 765.625—64No — needs interp 64, or a part rate below its floor

The bottom six rungs all run the AD9361 at 2.5 MSa/s, so moving between them changes only the DUC/DDC factor and does not retune the part (retuning invalidates the digital interface calibration, see Chain Conditioning).

A profile apply writes interp into the DUC and DDC. It does not set the AD9361's sample rate: that belongs to the tuning step of the chain conditioning, and the chain's rate condition catches the two disagreeing.

Bandwidth#

The transmit pulse and the receive matched filter are root-raised-cosine filters with roll-off α = 0.35, so the occupied bandwidth is about Rs × 1.35: 26 kHz at 19 531.25 baud, 53 kHz at 39 062.5 baud, 3.4 MHz at 2.5 Mbaud.

The AD9361's analog filters are sized on every profile apply from the symbol rate: Rs × 1.35 × 1.2, clamped to the part's 200 kHz floor and 40 MHz ceiling. Below about 127 kbaud the 200 kHz floor decides. The applied values are readable in /api/v1/radio/status (rx_bandwidth_hz, tx_bandwidth_hz).

Tuning: LO plus NCO#

The AD9361 leaks a little of its local oscillator at the LO frequency. If the LO sat exactly on the channel centre, that leakage would land in the middle of the signal. SatLink therefore tunes in two stages:

  1. the LO (coarse, analog) is placed below the requested centre by an offset;
  2. the NCO (fine, digital, in the DUC and DDC) shifts the signal back up by the same offset.

The offset is 1.25 × Rs × 1.35 / 2, a quarter past the band edge, so the leakage falls just outside the occupied band. For a 437.2 MHz profile at 19 531.25 baud this places the LOs about 16.5 kHz below 437.2 MHz with a +16.5 kHz NCO offset. If the signal is too wide for the sampled band to fit the offset, the tuning refuses rather than picking a bad value.

A profile apply performs this tuning and reports it in one sentence, including the centre actually reached (the LO synthesiser has a finite step, typically a few hertz off).

You can also move the NCO by hand, per side, within ±fs/2:

Shell
satlinkctl radio nco --rx-hz=-2500 --tx-hz=0     # attached form for negative values
satlinkctl radio freq 437200000 --channel both    # the LOs (rx, tx or both)

A manual change of frequency, gain or register after a profile apply marks the active profile dirty: GET /api/v1/profiles/active then reports dirty: true and what made it so.

Gains and attenuation#

There are two kinds of gain knob, and they must not be confused:

DomainKnobUnitWhere
rf (default)AD9361 RX gaindB of amplificationradio.rx_gain_db, satlinkctl radio gain --rx-db
rf (default)AD9361 TX gaindB of attenuation, 0 to −89.75radio.tx_power_dbm (negative values), satlinkctl radio gain --tx-db
digitalRX ingress scalarQ8.8 fixed pointsatlinkctl radio gain --domain digital
digitalTX DUC gainQ15 fixed point (0x7FFF = unity)satlinkctl radio gain --domain digital

On this part the TX gain is an attenuation: 0 dB is full drive and values go negative. A profile's tx_power_dbm is therefore applied only when it is zero or negative; a positive value (a power at an antenna, behind an external amplifier) is refused with an explanation. When a profile sets rx_gain_db, the AD9361's own AGC is switched to manual, because the part refuses gain writes while its AGC owns the setting.

/api/v1/radio/status carries both families: rx_gain_db/tx_gain_db are the PL's digital scalars; rx_rf_gain_db/tx_rf_gain_db are the part's gains in dB. Read the one you set.

Output level#

On the reference bench the board's output at the TX1 connector was calibrated as:

text
P_board ≈ att + 15.8 dBm        (att = TX attenuation, −30 ≤ att ≤ −10 dB measured)

This is a calibration of one board at 437 MHz, not a datasheet value. Linearity below −30 dB of attenuation has not been measured.

Reading the receive level#

Several indicators describe the received signal. They measure different things:

IndicatorWhat it isHow to read it
part_rssi_dbThe AD9361's own RSSI (in_voltage0_rssi), dB below full scale, referred to the input (the receive gain is already compensated)Smaller is stronger. On the reference bench, ~75 means no signal
rssi_dbmThe PL's RSSI meter, downstream of the ADC and the DDCTracks the analog gain 1 dB per dB until it saturates. Its absolute offset is not calibrated (off by about 13 dB)
agc_gainThe PL AGC's linear gain (Q4.12, maximum just under 16.0)Near 16.0 while traffic flows means the receiver is starved: raise rx_gain_db. Near 16.0 with nothing transmitted is normal
part_rx_gain_dbThe AD9361's RX gain, read back from the partThe independent variable of a gain sweep

Duplex and the ENSM#

The AD9361's Enable State Machine (ENSM) must be in an emitting state for the transmitter to put anything on the connector. On-air conditioning sets it to fdd (frequency-division duplex: transmit and receive at once). The RF kill switch sets it to alert. The profile field radio.duplex is descriptive and does not drive the ENSM.

Time on the board#

The board has no real-time clock and reads 1970 at power-on. Every timestamp it emits (ts_ms on the link, frame times on /api/v1/frames, the run clock) counts from boot or from daemon start, and says so in a field beside it. Stamp arrival on your own host when you need to correlate with anything else.

Stellar Link · v0.1.0

↑↓ to moveEnter to open