Skip to content

PureSignal on Protocol 2

Brian Keating edited this page May 3, 2026 · 3 revisions

PureSignal (Adaptive Predistortion) on Protocol 2

This page has moved. PureSignal is now wired for both Protocol 1 (Hermes Lite 2 — using the radio's internal coupler) and Protocol 2 (ANAN G2, G2 MkII, Saturn / Saturn-XDMA — external coupler). The dashboard UI was redesigned around a live calibration cockpit shared across all boards. See PureSignal for the current page.

The notes below describe the legacy P2-only checkbox-style UI and predate the redesign. They're kept here for reference and so older issue / PR links still resolve.


PureSignal is an adaptive predistortion engine that measures the actual RF coming out of your linear amplifier, compares it to what the radio's TX-DAC sent in, and continuously adjusts the transmit waveform so the on-air signal stays clean. The result is meaningfully lower IMD, less splatter, and better third- and fifth-order products on SSB and digital modes — usually equivalent to running a much more conservative drive level on an unlinearized amp.

The math and the WDSP calcc engine that drives all this is Warren Pratt's work. OpenHPSDR Zeus wires it up for Protocol 2 boards (ANAN G2, G2 MkII, Saturn / Saturn-XDMA). Protocol-1 (Hermes / HL2) PureSignal is not yet wired in OpenHPSDR Zeus and the UI gates the controls off when you connect to a P1 board.

Availability. PureSignal arrived on develop via PR #103 (TX panadapter + PureSignal foundation + AutoAttenuate convergence) and the follow-up PR #104 (reconnect-state-resync). Rack-verified on a G2 MkII at 80 m / 1300 W external amp / firmware 2.7b41.

What you need

Three things on the hardware side:

  1. A Protocol 2 radio — ANAN G2, G2 MkII, Saturn, or Saturn-XDMA. The OpenHPSDR Zeus connect dialog will report protocolSupported=43 (or higher) for these boards.
  2. An external amplifier with a directional coupler — typically the coupler is a small board with a forward and reverse port; you want the forward port (a sample of the amp's output, attenuated by 30–40 dB).
  3. A coax run from the coupler back to the radio's "Bypass" / "EXT 1" RX port — this is what OpenHPSDR Zeus calls "External" feedback. You can also use the radio's internal feedback path (no external amp), but the practical case is an external linear and an external coupler.

Without the coupler-to-Bypass coax, PureSignal has nothing to measure — there's no way for calcc to compare amp-output to amp-input.

The PureSignal panel

PureSignal lives in the PS Settings panel. The controls map closely to Thetis's Linearity menu, which OpenHPSDR Zeus uses as the canonical reference.

Master enable

  • PS — master toggle. When on, OpenHPSDR Zeus tells the radio to enable the paired-DDC feedback stream (DDC0 carries the post-PA coupler sample, DDC1 carries the TX-DAC reference loopback) and arms the WDSP calcc state machine. When off, no feedback streams flow and the engine sits idle.
  • Disabled when not connected, or when connected to a Protocol-1 board.

Run mode

Two buttons — pick one:

  • Autocalcc runs continuously while keyed, retraining the predistortion correction whenever it can. This is the everyday-operating mode and what you want for normal SSB / digital work. After calibration converges the engine keeps refining as your envelope statistics drift.
  • Single — run one calibration pass, then hold the resulting correction without retraining. Useful when you want a known-stable correction on the air (e.g. for a short test transmission on a band you have a saved correction for).

Auto-Attenuate

Checkbox. When on, OpenHPSDR Zeus continuously adjusts the radio's TX step attenuator (ADC0 path, byte 59 of the CmdTx packet) to keep the post-PA feedback level inside the WDSP target window of info[4] ∈ [128, 181]. This is the recovery loop: if your amp's coupler is delivering too hot a sample, AutoAttenuate increases the step attenuator until calcc sees a clean envelope it can fit. If the sample is too quiet, AutoAttenuate backs off — but if it's already at 0 dB and still too quiet, you need to raise drive at the radio.

The threshold logic, ramp behaviour, and 152.293 anchor point all match Thetis's timer2code. The step is gated on calcc actually completing a calibration attempt (info[5] increment) so the loop doesn't fight the engine mid-fit.

Default: ON. Turn it off only if you want to drive the TX step attenuator manually for some reason.

Feedback Source

Two-position selector — pick the antenna port the feedback ADC samples from:

  • Internal — the radio's internal feedback path. No external amp.
  • External — the radio's Bypass / EXT 1 port (where you've run the coupler coax). This is what you want with an external linear.

This setting flips the ALEX_RX_ANTENNA_BYPASS bit on the wire (alex0, byte 1432-1435 of the high-priority packet) so the radio routes the right ADC to DDC0.

Advanced

Several less-frequently-touched parameters, defaults match Thetis / pihpsdr canonical values:

  • PIN — pin one end of the polynomial fit (default ON).
  • MAP — apply the resulting map to the TX path (default ON).
  • STBL — stabiliser (default OFF; ON enables aggressive convergence guards).
  • Relax Tolerance — relaxes calcc's polynomial-tolerance check from 0.8 to 0.4 (default OFF for strict).
  • MOX Wait — settle delay between MOX-on and the first calibration sample (default 0.2 s).
  • CAL Wait — settle between calibration passes (default 0.0 s — back-to-back).
  • AMP Delay — the analog delay through your amp from input to coupler tap, in nanoseconds (default 150 ns). Most LDMOS bricks land in 100–250 ns; only worth measuring if you suspect time-alignment problems.
  • TINT — internal calcc integration / SPI preset (default 16/256).

You generally don't need to touch any of these. The non-default values are documented in Warren Pratt's PureSignal paper and in Thetis's PSForm.cs.

Using it

First-time calibration

  1. Wire it up. Coupler forward port → coax → radio Bypass / EXT 1 port. Power the amp.
  2. Connect to the radio in OpenHPSDR Zeus.
  3. Tune to a band where you have actual operating drive (most operators dial in PureSignal on the band they use most).
  4. Open the PS panel. Set:
    • PS = on
    • Auto mode (not Single)
    • Auto-Attenuate ticked
    • Feedback Source = External
  5. Key MOX with mic for ~10 seconds. Speak normally — calcc needs real envelope content (a constant carrier doesn't carry the modulation statistics it fits to).

You should see:

  • The PureSignal feedback bar in the panel light up and stop pegged at zero.
  • The cal-state badge transitioning through SETUP → COLLECT → CALC → STAYON.
  • The PureSignal "correcting" indicator turning green.
  • On an external receiver (KiwiSDR, second rig), distinctly cleaner IMD product levels.

If you watch the backend log you'll see AutoAttenuate ramp the TX step attenuator up from 0 dB until the feedback peak settles in the target window. On a typical 80 m setup at 1 kW the convergence point lands somewhere around 18–25 dB of step attenuation; YMMV.

Routine operation

Once it's working, leave PS = on, Auto mode, AutoAttenuate ticked. PureSignal retrains continuously while you operate. Mode and band changes don't disturb it (the WDSP engine just resets its state on the next key-up). If you tune outside the band where you originally calibrated, it'll re-converge during the first long key-down on the new band.

The engine settings are persisted to LiteDB, so they survive an OpenHPSDR Zeus restart. Your Auto/Single choice, AutoAttenuate state, Feedback Source, and the advanced timing values all come back the way you left them.

What "good" looks like

If you have a backend log open, healthy PureSignal looks like this during an SSB transmission:

psAutoAttn.armed reset attn=0
psAutoAttn.step feedback=440 info5=1 ddB=9.2 attn 0->1 dB
psAutoAttn.step feedback=435 info5=2 ddB=9.1 attn 1->2 dB
…
psAutoAttn.step feedback=182 info5=21 ddB=1.5 attn 20->21 dB
wdsp.psState 4->5 info4=162 info6=0x0000 info13=1 info14=1
wdsp.psState 5->6 info4=162 info6=0x0000 info13=0 info14=1
wdsp.psState 6->4 info4=162 info6=0x0000 info13=0 info14=1

Key indicators:

  • info4 in [128, 181] — the feedback envelope is in the WDSP target window.
  • info14=1 — corrections are actively being applied to the TX path.
  • info6=0x0000 mostly — scheck accepting the polynomial fits. Occasional 0x0040 (cm-changed-too-much) is normal envelope jitter and the engine recovers.
  • State machine cycling through 4 (LCOLLECT) ↔ 5 (LMOXCHECK) ↔ 6 (LCALC) ↔ 7 (LDELAY) ↔ 8 (LSTAYON) — calcc happily running its retrain loop.

On the air you should hear (or the KiwiSDR should show) IMD product levels several dB lower than the un-PureSignal'd transmission of the same audio.

Troubleshooting

"PS is armed but feedback bar shows nothing"

Most common cause: you reconnected to the radio mid-session and the first key-down landed before the engine state resynced. After PR #104 this should self-heal on the next key-down — the dirty-flag fix re-pushes the canonical PS state to the fresh engine instance on every reconnect. If you're on a build that predates PR #104, the workaround is to toggle any PS advanced field (e.g. Relax Tolerance off then on) which forces a full state push.

"AutoAttenuate ramps to 31 dB and feedback is still too high"

Your coupler tap is delivering more signal than 31 dB of step attenuation can knock down. Either:

  • Add an external attenuator (a 10 dB or 20 dB pad) inline between the coupler and the radio's Bypass port, or
  • Use a coupler with more isolation (40 dB minimum is a reasonable target).

"Feedback bar bounces but never settles, IMD on the air doesn't improve"

Time alignment is off. Check AMP Delay — measuring this properly takes a scope, but a sensible first guess by amp class:

  • Solid-state LDMOS (modern, 600 W–2 kW): 100–200 ns
  • Older bipolar (mid-1990s designs): 200–400 ns
  • Tube amps: 50–150 ns (the inherent transit time is short, but the input matching network can add some)

"Spurs visible on KiwiSDR even when info14=1"

Confirm the feedback path is actually carrying RF: tune your amp into a dummy load, key MOX briefly, and verify the feedback bar moves. If it doesn't, the coax run from coupler to Bypass is the place to look — open coax, wrong port, dead coupler.

"PS works in USB but not in LSB" / "Two-tone tones land on the wrong sideband in LSB"

This is a known TwoTone-only issue tracked separately, fixed in a follow-up PR (see project_twotone_lsb_pending.md — TwoTone follow-up). Mic-driven SSB PureSignal works correctly in both modes regardless.

"PS broke after I clicked Disconnect / Connect or hard-reloaded the OpenHPSDR Zeus tab"

This was a real bug; fixed in PR #104. If you're on a build that doesn't yet include #104 and you hit this, the workaround is to toggle one of the PS advanced settings (Relax Tolerance is the easiest) which forces the engine to re-pick-up the canonical state.

Hardware peak — what's the right value for your radio?

The "hardware peak" parameter (SetPSHWPeak) tells calcc the peak normalised amplitude your radio's PA can produce. It's used to compute the feedback target window, so getting it right matters. OpenHPSDR Zeus picks the right value automatically based on your board class:

Board Hardware peak
ANAN G2, G2 MkII, Saturn / Saturn-XDMA 0.6121
ANAN-7000, ANAN-8000, Orion 0.2899
HermesLite-2 (P1, not yet wired) 0.2400
StemLab (P1) 0.4160
Other Protocol-1 (Hermes, Atlas) 0.4067

These come from pihpsdr (transmitter.c:1166-1179) which is the project's authority for MkII-specific behaviour. Thetis's table differs slightly for ANAN_G2 (0.2899 vs pihpsdr's 0.6121); OpenHPSDR Zeus follows pihpsdr because that's the value that converges on rack tests.

Further reading

  • Warren Pratt's PureSignal paperPureSignal Adaptive Pre-Distortion (Public), Friedrichshafen 2014. The original conceptual document. Covers the operator workflow in plain language.
  • Thetis sourceSource/Console/PSForm.cs (UI + timer2code AutoAttenuate), Source/Console/cmaster.cs (wire-side PS), Source/Console/clsHardwareSpecific.cs (per-board defaults).
  • pihpsdr sourcesrc/transmitter.c (engine arm + ps_setpk per board), src/new_protocol.c (wire format), src/ps_menu.c (UI + ps_calibration_timer).
  • WDSP sourcenative/wdsp/calcc.c is the canonical state machine.

See also

  • TX Controls — MOX / TUNE / drive controls that pair with PureSignal.
  • Meters — TX stage meters where PureSignal feedback shows.
  • Bandwidth and Filters — TX filter, which determines the bandwidth calcc is fitting to.

Clone this wiki locally