OmniSDR — User manual

How to use OmniSDR: the panes, the click, the right-click menu, Follow-me, Sync, smoothing, layouts, and the common gotchas.

Contents

OmniSDR is a fullscreen multi-band HF spectrum companion. It shows you the activity across many ham bands at once, in real time, so you can spot something interesting and click it to tune your own UberSDR tab (or a rigctld-connected radio) onto that signal. It is not a radio — it never plays audio or demodulates anything itself. Think of it as a pointer that sits next to your UberSDR.

The live instance is at https://omnisdr.on8st.be.

Quick start (60 seconds)

  1. Open https://omnisdr.on8st.be.
  2. You should see a row of bands (160m, 80m, 40m, 20m, 15m, 10m by default), each with a small spectrum trace on top and a scrolling waterfall underneath.
  3. Hover over a band — a vertical crosshair follows your cursor, and the frequency under the cursor appears at the bottom of the pane (along with the power level in dBm).
  4. Click anywhere on a band. A new tab opens to UberSDR pre-tuned to exactly that frequency. From the second click onwards OmniSDR re-tunes the existing UberSDR tab in place — no reload, no audio re-prompt.
  5. As you tune UberSDR around (in its own UI), a coloured marker line tracks UberSDR's current frequency on OmniSDR, with the freq label at the bottom of the relevant pane.

That's the whole basic flow. Everything below is detail.

What you see on screen

Panes

Each band is rendered as one pane:

┌────────────────────────────────────────────────────┐
│ 20m                                                │  ← band label
│ ╱╲   ╱╲     ╱╲                                     │
│╱  ╲ ╱  ╲╱╲ ╱  ╲╱╲   spectrum  (top 25%)            │
│    ╲    ╱  ╲    ╲                                  │
├─14.0──14.1──14.2──14.3 MHz ────────────────────────┤  ← frequency axis
│▓▓▓▓░░░▓▓▓░░▓▓░░░░░░░▓▓▓░░▓▓░░░░▓▓░░▓░░▓▓░░░░░░░░░░│
│▓▓░░▓░▓▓░░░░▓▓▓░░░▓▓░▓░░▓▓░░░░░░▓░░░░░░▓░░░░░░░░░░░│  waterfall (75%, scrolls down)
│░▓░▓░░▓▓▓░░▓░░░░░░▓▓▓░░░░▓▓░░░░░░░░▓▓▓░░░▓▓░░░░░░░░│
│ 14.250 USB · -82 dBm                               │  ← cursor + marker readouts
└────────────────────────────────────────────────────┘

Layout

Bands are packed into rows. By default the bands are sorted left-to-right by start frequency and fill rows top-to-bottom. The packer keeps each band the same width per Hz across the whole screen (so a wide band like MW is much wider than a narrow band like 30m). That equal-Hz/pixel invariant gives an honest "where on HF you are" feel, but it leaves trailing whitespace when bands don't add up exactly to the screen.

If you'd rather have every row stretch all the way to the right edge, turn on Options ▸ Fill window — each row will then stretch independently and the whole canvas is filled. Different rows will have different Hz/pixel.

Colours

The waterfall and spectrum line share one colormap. Whether the colours are scaled per-band (each band lit independently) or all together (single scale across all bands) is Options ▸ Per-band scaling. The default is per-band, because the shipped presets mix MW (loud) with high HF (quiet) and a single shared scale would crush the weaker bands to black.

Cursor, clicks, and markers

Hovering

When your cursor is over a pane:

Clicking

Click on a pane to tune.

Markers

Every ticked target has its own marker — a vertical coloured line at the target's current frequency:

Each marker carries a small label at the bottom of the pane in the same colour (e.g. UberSDR 14.250). If the target's link is down, the marker is dashed to remind you the displayed frequency may not reflect the actual VFO.

If a marker's frequency falls outside every visible pane (e.g. UberSDR jumped to 6 MHz while you're only showing 20m), the marker is rendered as a small edge-indicator on the closest pane, pointing outward, with the freq next to it. So you always know roughly where each target is, even if you can't see the exact band right now.

The right-click menu

Right-click anywhere on the canvas to open the main context menu. It has four entries:

Layouts ▸
Options ▸
Targets ▸
About…

The submenus auto-open on hover, so you can browse them by just moving the cursor; clicking opens the same way. The menu auto-dismisses if you move the cursor away and don't come back within ~250 ms.

Esc closes any open menu, and f toggles fullscreen.

Layouts ▸

Lists every saved preset. The currently-active preset (the one whose band selection matches your live selection) is highlighted. Click a preset to swap to it — both the bands shown and the row layout switch.

Manage Layouts… opens the band palette.

Default presets shipped with OmniSDR:

HF Ham        — the six main HF ham bands
Lower HF      — 160 / 80 / 40 / 30 / 20 / 17 m
Upper HF      — 15 / 12 / 10 / 6 m
Contest       — bands that see contest activity
FT8 HF        — the 10 FT8 watering holes (3 kHz each)
WSPR Tour     — the 10 WSPR watering holes (~2 kHz each)
Digital 20m   — JS8 / RTTY / PSK31 / Olivia / FT8 on 20m, side by side
SWBC Tour     — shortwave broadcast bands (LW / MW / 49m / 31m / 19m / 16m)
AM Broadcast  — LW + MW + 60m + 49m
LF/MF         — 2200m / 630m / NDB beacons

Options ▸

Display-only toggles. Saved per session.

Targets ▸

Where you control who receives your tunes.

Follow targets    [ ]    ← toggle, visible to all
Sync targets      [ ]    ← toggle, LAN clients only
─────────────────────
· UberSDR         ✓      ← per-target tick list
· rigctld@host    ✓
Manage Targets…          ← LAN only

The two toggles change behaviour; the per-target tick list controls which targets are part of the action.

A target's row shows:

Click anywhere on a target's row to tick/untick it.

Manage Targets… (LAN only) opens the panel that configures rigctld subnet scanning and per-target friendly names.

About…

Static info panel — name, version stamp, links.

Follow targets (Follow-me mode)

When ON, OmniSDR shows the bands your ticked targets are currently on, instead of your manual selection. As a target retunes, the panes swap to follow.

How it works

For each ticked target with a known frequency, OmniSDR picks the widest catalog band that contains that frequency (so a target on 14.074 MHz lands on 20m, not 20m FT8, because 20m is broader and gives more context). The result is de-duplicated and sorted left to right.

Off-band targets

If a target's frequency doesn't fit any catalog band (e.g. a shortwave broadcast freq), it doesn't add a pane — but its marker still appears as an edge-indicator on whichever visible pane is closest. So you keep seeing roughly where each target is, without losing your layout.

Sticky bands (no dead-end empty state)

If you're already showing some panes via Follow-me and every ticked target then roams off-band at once, OmniSDR keeps the last shown layout on screen instead of going blank. Edge-indicators on those panes still tell you where the targets are.

The cache is cleared:

So if you really do want a blank canvas, just untick or toggle off.

Empty states

In a few cases Follow-me does show a hint screen. Each one tells you how to escape:

In every empty state you can right-click to bring up the menu and turn Follow-me off — the hint text has pointer-events: none so the canvas underneath always receives the right-click.

Auto-off when you touch the bands manually

If Follow-me is on and you do anything that mutates your band selection (click a band chip in the palette, apply a preset, etc.), Follow-me turns itself off. Without that guard a manual change would be immediately overridden by the next derivation pass. Toggle Follow-me back on when you want the live tracking back.

UberSDR bridge bootstrap

The UberSDR bridge only delivers frequency events to its window.opener. On a freshly loaded OmniSDR (or after closing and reopening the UberSDR tab) we need to call window.open() to become the opener; until then no frequency events flow.

Two paths bootstrap that link, both safe inside a real user gesture:

After the tab is reopened, OmniSDR pings the bridge every 500 ms for up to 10 seconds. The bridge replies ready plus the current VFO, at which point Follow-me has a marker to derive a band from and a pane appears.

Sync targets

When ON, every target frequency change fans out to the other ticked targets. So if you turn the rig knob on rigctld, UberSDR follows; if you click a freq in UberSDR's own UI, rigctld follows; if you click on OmniSDR, everything moves together.

LAN-only. Public clients don't see the toggle and the server rejects the option for them — a public viewer can't move a LAN operator's rig.

Loop protection

When a sync fan-out drives a target, the server stamps that target with a "I just synced this one" timestamp. The bridge / poll echo that follows (a marker event reporting "I'm now on freq X") is suppressed if it arrives within 300 ms of the stamp. Otherwise sync would bounce the same frequency around forever.

300 ms is well over the round-trip-plus-radio-respond time and well under any human "I'm still turning the knob" cadence, so genuine operator activity is never dropped.

Tick scope

Sync only fans out to targets that are ticked by at least one session with sync ON — the union across sessions. Unticking a target opts it out, even if a sibling session would have included it. This way you can e.g. leave UberSDR ticked on one browser, untick it on another, turn sync on, and the unticked browser's rigctld will follow UberSDR without the unticked browser itself moving UberSDR.

Sync + Follow-me together

Both on:

Sync on, Follow-me off:

Sync off, Follow-me on:

Smoothing

Each level bundles two kinds of smoothing under one knob so you don't have to think about them separately:

LevelTemporalFrequency
Offnonenone
Lightmildnone
Mediummedium1.5 kHz
Strongheavy3 kHz

The frequency-axis window is hard-capped at 3 kHz — the bandwidth of an SSB signal — regardless of strength. A wider window would average weak SSB voice signals back into the noise floor, which we never want.

On bands narrower than 3 kHz (FT8/WSPR watering holes) the cap is larger than the band itself. Strong smoothing on those will flatten everything; pick a lower level there.

Smoothing is applied client-side (in your browser). The server just stores your choice. Every tab can have its own subjective level.

The band palette (Manage Layouts)

Layouts ▸ Manage Layouts… opens the palette: every band in the catalog shown as a small chip with its own mini spectrum preview, grouped by type (ham bands, broadcast, digital, etc).

Edits here flow into the live view immediately — no apply step.

Manage Targets (LAN only)

Opens a panel that controls the rigctld subnet scanner and per-target friendly names.

Subnet config is per session but is gated behind the LAN scope, so a public viewer cannot reach this panel even if they craft a request manually.

URL session and browser-local settings

OmniSDR's URL carries a session token in the hash: https://omnisdr.on8st.be/#s=<token>. Every session has its own server-side state file, so you can have multiple parallel sessions on the same browser by pinning different #s=... URLs.

Settings — your selection, presets, layout, options (Fill window / Per-band / Smoothing / Follow / Sync), target ticks, target labels, UberSDR override URL — are also mirrored to localStorage.omnisdr.settings in your browser. When you open a fresh URL (no #s= hash) on the same browser, OmniSDR generates a new session token but immediately primes it with your localStorage so you land on your previous view, not on defaults.

Multi-device

Open the same browser bookmark on a second device: the second device has its own localStorage, so its first connect will overwrite the server-side session with its own settings. The rule is last-device-wins. This is the deliberate trade-off in favour of single-browser consistency: it means "follow my preferences" works predictably on one browser, at the cost of multi-device users having to consciously share state.

Keyboard shortcuts

KeyWhat it does
fToggle fullscreen
EscClose any open menu / exit fullscreen

Common scenarios

"I just loaded the page and the canvas is empty"

If Follow-me is on, the hint will tell you what's missing:

If Follow-me is off, the hint reads right-click to choose bands. Right-click and pick a preset under Layouts.

"I tuned UberSDR but OmniSDR didn't follow"

Check:

  1. Follow targets is on (right-click ▸ Targets).
  2. UberSDR is ticked in the per-target list.
  3. The bridge is connected. If you reloaded OmniSDR since the UberSDR tab was opened, the bridge has no opener and isn't sending events. Click anywhere on the canvas to bootstrap it (or toggle Follow targets off and on again).

"Follow-me turned itself off when I clicked a band"

That's intentional. Any manual change to the band selection auto-disables Follow-me — otherwise the next derivation pass would override your choice. Just toggle Follow-me back on when you want the live tracking again.

"Sync sent my rig somewhere weird"

Probably a sibling session is also driving it. Sync uses the union of ticks across every sync-enabled session. If two browsers both have sync on but tick different sets, the union of those sets gets driven by every retune anywhere. Either untick the unwanted target in every sync-enabled session, or turn sync off in the offending session.

"I want to start completely fresh"

Public vs LAN

OmniSDR classifies your connection based on the source IP (the operator runs from 192.168.36.0/24). LAN clients see one extra menu (Manage Targets) and one extra toggle (Sync). Public clients see the rest of the UI normally — they just can't configure the LAN-side scanner or move a LAN rig.

Source: docs/user-guide.md in the on8st/omnisdr repo on the Pi 5.