All docsStellar LinkRF bench · by Stellar Systems v0.1.0

Signal Processing

PL Register Map

The catalogued PL registers by name, address and access; the shell control bits; reading and writing registers safely from the CLI, the API and scenarios.

The PL exposes one 1 MiB AXI-Lite window at 0x4000_0000, split into seven 64 KiB windows; each modem block has a 256-byte sub-window inside its window. satlinkd addresses registers through a catalogue of names (ps/crates/satlink-pl-driver/src/catalog.rs) whose addresses are the same constants the daemon itself uses, so a name in the CLI and a name in the firmware cannot mean different things.

Reading and writing by name#

Shell
satlinkctl reg list deframer                       # filter by substring
satlinkctl reg get rx_demod.deframer.frame_cnt
satlinkctl reg set tx.scrambler.ctrl 0xFF01        # write, then read back
satlinkctl pl                                      # shell, IRQ and sequencer snapshot
RoutePurpose
GET /api/v1/pl/regs?filter=<substr>&values=trueList catalogued registers, optionally with their values
GET /api/v1/pl/regs/{name}Read one: {"name", "addr", "access", "value"}
POST /api/v1/pl/regs/{name}Write one: {"value": 65281}; returns the value read back
GET /api/v1/pl/registers/{addr}Read by address (only catalogued addresses are safe)
GET /api/v1/pl/status, /pl/profile-sequencer, /pl/interruptsDecoded snapshots
ws://<board>:8080/ws/pl/registersEvery register write, as it happens

A manual write marks the active profile dirty. In scenarios, use a reg: step; to follow a register over a run, add it to [telemetry] watch_registers.

Remember the two traps of reading back:

  • Shadow registers (most configuration registers of the modem and the channel emulator) return the active value: a write reads back as the old value until the profile sequencer commits.
  • Pulse bits (clear bits, monitor.power_meter.ctrl[1]) read 0 by design.

Shell control bits#

shell.axi_ctrl.global_ctrl (0x4000_0000):

BitMeaning
0PL loopback mux: 1 routes TX through the channel emulator into RX. Written by every profile apply from radio.loopback
4, 5Drive the AD9361 ENABLE and TXNRX pins (pin-control ENSM modes; the daemon uses SPI control instead)
8ADC capture tap gate (IQ captures and spectrum). Lowering it clears the capture overflow flag

Other shell registers:

RegisterMeaning
shell.axi_ctrl.versionShell version, 0x00010000
shell.axi_ctrl.build_idBitstream build identifier (0xDEADBEEF by default; also the value of an unimplemented offset, so it does not distinguish builds today)
shell.axi_ctrl.cfg_epochIncremented by each committed profile
shell.axi_ctrl.rf_status[4] ADC capture overflow (sticky), [3:2] ADC enables, [1:0] DAC enables
shell.irq.statusLatched events, write 1 to clear: [0] profile applied, [1] profile error, [2] frame received, [3] IQ record done, [4] timing lock lost, [5] carrier lock lost, [6] FIFO overflow, [7] DMA event, [8] RSSI threshold

The profile sequencer#

RegisterMeaning
common.seq.seq_ctrl[0] apply, [1] abort, [2] timed, [3] partial RX, [4] partial TX, [8] validation OK
common.seq.seq_state0 IDLE, 1 STAGED, 2 VALIDATING, 3 WAIT_SAFE, 4 COMMIT, 5 REARM (7 after a manual pulse)
common.seq.seq_status, seq_err_codeStatus and error code (1 = validation refused)
common.seq.seq_timeout, seq_profile_idTimeout and the id of the last committed profile (0xC0DE for a channel-only commit)

To commit staged writes by hand, write 0x101 (apply and validation OK) to common.seq.seq_ctrl; 0x1 alone is refused with error 1. After a manual pulse the sequencer sits in state 7 and ignores the next commit until something re-arms it (a profile apply does). SEQ_STATE = 3 that does not clear means some stream never goes idle: the datapath is jammed.

Catalogue#

Every register the daemon knows, with its absolute address and access (RW read/write, RO read only, W1C write 1 to clear). Descriptive or inert registers are flagged in the Transmitter Chain and Receiver Chain pages.

Shell (0x4000_0000)#

NameAddressAccess
shell.axi_ctrl.global_ctrl0x4000_0000RW
shell.axi_ctrl.version0x4000_0004RO
shell.axi_ctrl.build_id0x4000_0008RO
shell.axi_ctrl.cfg_epoch0x4000_000cRO
shell.axi_ctrl.rf_status0x4000_0010RO
shell.irq.status0x4000_0100W1C
shell.irq.enable0x4000_0104RW
shell.irq.force0x4000_0108RW
shell.coeff_mem.ctrl0x4000_0300RW
shell.coeff_mem.addr0x4000_0304RW
shell.coeff_mem.data0x4000_0308RW
shell.coeff_mem.bank_sel0x4000_030cRW
shell.coeff_mem.status0x4000_0310W1C

RX DDC (0x4001_0000)#

NameAddressAccess
rx_ddc.chan_cfg.freq_hz0x4001_0000RW
rx_ddc.chan_cfg.baudrate0x4001_0004RW
rx_ddc.chan_cfg.mod_sel0x4001_0008RW
rx_ddc.chan_cfg.sps0x4001_000cRW
rx_ddc.ingress.ctrl0x4001_0100RW
rx_ddc.ingress.gain0x4001_0104RW
rx_ddc.ingress.status0x4001_0108RO
rx_ddc.ingress.smpl_cnt0x4001_010cRO
rx_ddc.ddc.ctrl0x4001_0200RW
rx_ddc.ddc.nco_freq0x4001_0204RW
rx_ddc.ddc.decim0x4001_0208RW
rx_ddc.ddc.filter_sel0x4001_020cRW
rx_ddc.ddc.gain0x4001_0210RO
rx_ddc.ddc.status0x4001_0214RO
rx_ddc.rx_switch.ctrl0x4001_0300RW
rx_ddc.rx_switch.route_sel0x4001_0304RW
rx_ddc.rx_switch.monitor_tap0x4001_0308RW

RX demodulator (0x4002_0000)#

NameAddressAccess
rx_demod.agc.ctrl0x4002_0000RW
rx_demod.agc.target0x4002_0004RW
rx_demod.agc.attack0x4002_0008RW
rx_demod.agc.decay0x4002_000cRW
rx_demod.agc.gain0x4002_0010RO
rx_demod.agc.status0x4002_0014RO
rx_demod.matched_filter.ctrl0x4002_0100RW
rx_demod.matched_filter.coeff_bank0x4002_0104RW
rx_demod.matched_filter.sps0x4002_0108RW
rx_demod.matched_filter.status0x4002_010cRO
rx_demod.timing_recovery.ctrl0x4002_0200RW
rx_demod.timing_recovery.loop_bw0x4002_0204RW
rx_demod.timing_recovery.status0x4002_0208RO
rx_demod.timing_recovery.phase_err0x4002_020cRO
rx_demod.timing_recovery.lock_cnt0x4002_0210RO
rx_demod.carrier_recovery.ctrl0x4002_0300RW
rx_demod.carrier_recovery.loop_bw0x4002_0304RW
rx_demod.carrier_recovery.status0x4002_0308RO
rx_demod.carrier_recovery.cfo0x4002_030cRO
rx_demod.carrier_recovery.phase_err0x4002_0310RO
rx_demod.carrier_recovery.sweep_range0x4002_0314RW
rx_demod.carrier_recovery.sweep_step0x4002_0318RW
rx_demod.carrier_recovery.fll0x4002_031cRW
rx_demod.carrier_recovery.fdet_cfg0x4002_0320RW
rx_demod.carrier_recovery.fdet_thresh0x4002_0324RW
rx_demod.carrier_recovery.fdet_freq0x4002_0328RO
rx_demod.carrier_recovery.fdet_status0x4002_032cRO
rx_demod.slicer.ctrl0x4002_0400RW
rx_demod.slicer.status0x4002_0404RO
rx_demod.slicer.sym_cnt0x4002_0408RO
rx_demod.demod_bpsk.ctrl0x4002_0500RW
rx_demod.demod_bpsk.status0x4002_0504RO
rx_demod.demod_bpsk.evm0x4002_0508RO
rx_demod.demod_qpsk.ctrl0x4002_0600RW
rx_demod.demod_qpsk.status0x4002_0604RO
rx_demod.demod_qpsk.evm0x4002_0608RO
rx_demod.demod_qpsk.sig_pwr0x4002_060cRO
rx_demod.demod_qpsk.err_pwr0x4002_0610RO
rx_demod.demod_qpsk.win_cnt0x4002_0614RO
rx_demod.demod_gmsk.ctrl0x4002_0700RW
rx_demod.demod_gmsk.bt0x4002_0704RW
rx_demod.demod_gmsk.status0x4002_0708RO
rx_demod.deframer.ctrl0x4002_0800RW
rx_demod.deframer.sync_word0x4002_0804RW
rx_demod.deframer.frame_len0x4002_0808RW
rx_demod.deframer.scramble0x4002_080cRW
rx_demod.deframer.status0x4002_0810RO
rx_demod.deframer.frame_cnt0x4002_0814RO
rx_demod.deframer.err_cnt0x4002_0818RO
rx_demod.fec_rx.ctrl0x4002_0900RW
rx_demod.fec_rx.rate0x4002_0904RW
rx_demod.fec_rx.status0x4002_0908RO
rx_demod.fec_rx.corr_cnt0x4002_090cRO
rx_demod.fec_rx.fail_cnt0x4002_0910RO

TX (0x4003_0000)#

NameAddressAccess
tx.chan_cfg.freq_hz0x4003_0000RW
tx.chan_cfg.baudrate0x4003_0004RW
tx.chan_cfg.mod_sel0x4003_0008RW
tx.chan_cfg.sps0x4003_000cRW
tx.framer.ctrl0x4003_0100RW
tx.framer.frame_len0x4003_0108RW
tx.framer.pad0x4003_010cRW
tx.framer.status0x4003_0110RO
tx.framer.frame_cnt0x4003_0114RO
tx.fec_tx.ctrl0x4003_0200RW
tx.fec_tx.rate0x4003_0204RW
tx.fec_tx.status0x4003_0208RO
tx.mod_bpsk.ctrl0x4003_0300RW
tx.mod_bpsk.sps0x4003_0304RW
tx.mod_bpsk.coeff0x4003_0308RW
tx.mod_bpsk.status0x4003_030cRO
tx.mod_qpsk.ctrl0x4003_0400RW
tx.mod_qpsk.sps0x4003_0404RW
tx.mod_qpsk.coeff0x4003_0408RW
tx.mod_qpsk.status0x4003_040cRO
tx.mod_gmsk.ctrl0x4003_0500RW
tx.mod_gmsk.bt0x4003_0504RW
tx.mod_gmsk.sps0x4003_0508RW
tx.mod_gmsk.coeff0x4003_050cRW
tx.mod_gmsk.status0x4003_0510RO
tx.duc.ctrl0x4003_0600RW
tx.duc.nco_freq0x4003_0604RW
tx.duc.interp0x4003_0608RW
tx.duc.filter_sel0x4003_060cRW
tx.duc.gain0x4003_0610RW
tx.duc.status0x4003_0614RO
tx.egress.ctrl0x4003_0700RW
tx.egress.status0x4003_0704RO
tx.egress.cnt0x4003_0708RW
tx.asm_insert.ctrl0x4003_0800RW
tx.asm_insert.sync_word0x4003_0804RW
tx.asm_insert.status0x4003_0808RO
tx.asm_insert.asm_cnt0x4003_080cRO
tx.scrambler.ctrl0x4003_0900RW
tx.scrambler.status0x4003_0904RO
tx.scrambler.frame_cnt0x4003_0908RO
tx.fill.ctrl0x4003_0a00RW
tx.fill.pre_len0x4003_0a04RW
tx.fill.post_len0x4003_0a08RW
tx.fill.pat_hi0x4003_0a0cRW
tx.fill.pat_lo0x4003_0a10RW
tx.fill.status0x4003_0a14RO
tx.fill.fill_cnt0x4003_0a18RO
tx.fill.pre_cnt0x4003_0a1cRO

Monitor (0x4004_0000)#

NameAddressAccess
monitor.rssi.ctrl0x4004_0000RW
monitor.rssi.avg0x4004_0004RW
monitor.rssi.inst0x4004_0008RW
monitor.rssi.threshold0x4004_000cRW
monitor.rssi.status0x4004_0010RO
monitor.power_meter.ctrl0x4004_0100RW
monitor.power_meter.tap_sel0x4004_0104RW
monitor.power_meter.result0x4004_0108RW
monitor.power_meter.status0x4004_010cRO
monitor.power_meter.rms0x4004_0110RO
monitor.power_meter.tap_sel_b0x4004_0114RW
monitor.power_meter.rms_b0x4004_0118RO
monitor.fft.ctrl0x4004_0200RW
monitor.fft.size0x4004_0204RW
monitor.fft.src_sel0x4004_0208RW
monitor.fft.status0x4004_020cRO
monitor.fft.dma_addr0x4004_0210RW
monitor.iq_recorder.ctrl0x4004_0300RW
monitor.iq_recorder.src_sel0x4004_0304RW
monitor.iq_recorder.depth0x4004_0308RW
monitor.iq_recorder.pretrig0x4004_030cRW
monitor.iq_recorder.dma_addr0x4004_0310RW
monitor.iq_recorder.status0x4004_0314RO
monitor.iq_recorder.smpl_cnt0x4004_0318RO

Common (profile sequencer) (0x4005_0000)#

NameAddressAccess
common.seq.seq_ctrl0x4005_0000RW
common.seq.seq_state0x4005_0004RO
common.seq.seq_status0x4005_0008RO
common.seq.seq_err_code0x4005_000cRO
common.seq.seq_timeout0x4005_0010RW
common.seq.seq_profile_id0x4005_0014RW

Channel emulator (0x4006_0000)#

NameAddressAccess
channel.chan_nco_freq0x4006_0000RW
channel.chan_atten0x4006_0004RW
channel.chan_awgn_amp0x4006_0008RW
channel.chan_burst_rate0x4006_000cRW
channel.chan_ctrl0x4006_0010RW

The DAC core of the AD9361 interface (dac_data_sel, the DDS tones) lies outside this window. The daemon reaches it through the cf-ad9361-dds-core IIO driver; see Chain Conditioning.

Stellar Link · v0.1.0

↑↓ to moveEnter to open