[fix](trx-frontend-http): move passband overlay to resolved DIG sideband
The spectrum passband overlay is drawn one-sided per mode, but DIG was hardcoded to upper sideband — so switching the DIG sideband (or tuning DIG/Auto across 10 MHz) left the overlay on the wrong side of the carrier even though the backend had flipped the demodulator. Resolve the DIG overlay direction from the current sideband policy and dial frequency, mirroring the backend: usb → upper, lsb → lower, auto → upper at or above 10 MHz and lower below. The overlay repaints immediately on a policy change (optimistically on the selector, and on confirmed filter state) and tracks frequency as it already did. Non-SDR backends keep the historical upper-sideband overlay. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UiK871ht2uPFBHtMbxy3wD Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -3729,10 +3729,19 @@ function visibleBandwidthSpecs(freqHz = lastFreqHz, mode = modeEl ? modeEl.value
|
|||||||
}
|
}
|
||||||
return [{ centerHz: freqHz, widthHz: currentBandwidthHz }];
|
return [{ centerHz: freqHz, widthHz: currentBandwidthHz }];
|
||||||
}
|
}
|
||||||
|
function digSidebandDirection() {
|
||||||
|
if (sdrDigSidebandPolicy === "usb") return 1;
|
||||||
|
if (sdrDigSidebandPolicy === "lsb") return -1;
|
||||||
|
if (typeof lastFreqHz === "number" && isFiniteNumber(lastFreqHz)) {
|
||||||
|
return lastFreqHz >= DIG_AUTO_SIDEBAND_THRESHOLD_HZ ? 1 : -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
function sidebandDirectionForMode(mode = modeEl ? modeEl.value : "") {
|
function sidebandDirectionForMode(mode = modeEl ? modeEl.value : "") {
|
||||||
const modeUpper = String(mode || "").toUpperCase();
|
const modeUpper = String(mode || "").toUpperCase();
|
||||||
if (modeUpper === "LSB" || modeUpper === "CWR") return -1;
|
if (modeUpper === "LSB" || modeUpper === "CWR") return -1;
|
||||||
if (modeUpper === "USB" || modeUpper === "CW" || modeUpper === "DIG") return 1;
|
if (modeUpper === "DIG") return sdrDigSidebandSupported ? digSidebandDirection() : 1;
|
||||||
|
if (modeUpper === "USB" || modeUpper === "CW") return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
function displaySpanForBandwidthSpec(spec, mode = modeEl ? modeEl.value : "") {
|
function displaySpanForBandwidthSpec(spec, mode = modeEl ? modeEl.value : "") {
|
||||||
@@ -4760,10 +4769,15 @@ function render(update) {
|
|||||||
}
|
}
|
||||||
if (typeof update.filter.sdr_dig_sideband === "string") {
|
if (typeof update.filter.sdr_dig_sideband === "string") {
|
||||||
sdrDigSidebandSupported = true;
|
sdrDigSidebandSupported = true;
|
||||||
|
const prevPolicy = sdrDigSidebandPolicy;
|
||||||
|
sdrDigSidebandPolicy = update.filter.sdr_dig_sideband;
|
||||||
if (sdrDigSidebandEl && document.activeElement !== sdrDigSidebandEl) {
|
if (sdrDigSidebandEl && document.activeElement !== sdrDigSidebandEl) {
|
||||||
sdrDigSidebandEl.value = update.filter.sdr_dig_sideband;
|
sdrDigSidebandEl.value = update.filter.sdr_dig_sideband;
|
||||||
}
|
}
|
||||||
updateWfmControls();
|
updateWfmControls();
|
||||||
|
if (prevPolicy !== sdrDigSidebandPolicy && lastSpectrumData) {
|
||||||
|
scheduleSpectrumDraw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof update.show_sdr_gain_control === "boolean") {
|
if (typeof update.show_sdr_gain_control === "boolean") {
|
||||||
@@ -6634,6 +6648,8 @@ var sdrNbSupported = false;
|
|||||||
var sdrDigSidebandWrapEl = document.getElementById("sdr-dig-sideband-wrap");
|
var sdrDigSidebandWrapEl = document.getElementById("sdr-dig-sideband-wrap");
|
||||||
var sdrDigSidebandEl = document.getElementById("sdr-dig-sideband");
|
var sdrDigSidebandEl = document.getElementById("sdr-dig-sideband");
|
||||||
var sdrDigSidebandSupported = false;
|
var sdrDigSidebandSupported = false;
|
||||||
|
var sdrDigSidebandPolicy = "auto";
|
||||||
|
var DIG_AUTO_SIDEBAND_THRESHOLD_HZ = 1e7;
|
||||||
fetch("/audio", { method: "GET" }).then((r) => {
|
fetch("/audio", { method: "GET" }).then((r) => {
|
||||||
if (r.status === 404) audioRow.style.display = "none";
|
if (r.status === 404) audioRow.style.display = "none";
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@@ -7033,6 +7049,8 @@ function submitSdrDigSideband() {
|
|||||||
if (!sdrDigSidebandSupported || !sdrDigSidebandEl) return;
|
if (!sdrDigSidebandSupported || !sdrDigSidebandEl) return;
|
||||||
const policy = sdrDigSidebandEl.value || "auto";
|
const policy = sdrDigSidebandEl.value || "auto";
|
||||||
if (policy !== "auto" && policy !== "usb" && policy !== "lsb") return;
|
if (policy !== "auto" && policy !== "usb" && policy !== "lsb") return;
|
||||||
|
sdrDigSidebandPolicy = policy;
|
||||||
|
if (lastSpectrumData) scheduleSpectrumDraw();
|
||||||
postPath(`/set_sdr_dig_sideband?policy=${encodeURIComponent(policy)}`).catch(() => {
|
postPath(`/set_sdr_dig_sideband?policy=${encodeURIComponent(policy)}`).catch(() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2450,10 +2450,26 @@ function visibleBandwidthSpecs(freqHz: number | null = lastFreqHz, mode = modeEl
|
|||||||
return [{ centerHz: freqHz, widthHz: currentBandwidthHz }];
|
return [{ centerHz: freqHz, widthHz: currentBandwidthHz }];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve the DIG passband direction from the current policy and dial
|
||||||
|
// frequency, mirroring the backend's demodulator resolution so the spectrum
|
||||||
|
// overlay lands on the same sideband that is actually being demodulated.
|
||||||
|
function digSidebandDirection() {
|
||||||
|
if (sdrDigSidebandPolicy === "usb") return 1;
|
||||||
|
if (sdrDigSidebandPolicy === "lsb") return -1;
|
||||||
|
// "auto": USB at/above the threshold, LSB below.
|
||||||
|
if (typeof lastFreqHz === "number" && isFiniteNumber(lastFreqHz)) {
|
||||||
|
return lastFreqHz >= DIG_AUTO_SIDEBAND_THRESHOLD_HZ ? 1 : -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
function sidebandDirectionForMode(mode = modeEl ? modeEl.value : "") {
|
function sidebandDirectionForMode(mode = modeEl ? modeEl.value : "") {
|
||||||
const modeUpper = String(mode || "").toUpperCase();
|
const modeUpper = String(mode || "").toUpperCase();
|
||||||
if (modeUpper === "LSB" || modeUpper === "CWR") return -1;
|
if (modeUpper === "LSB" || modeUpper === "CWR") return -1;
|
||||||
if (modeUpper === "USB" || modeUpper === "CW" || modeUpper === "DIG") return 1;
|
// On SDR the DIG sideband is configurable; resolve it. On other backends
|
||||||
|
// keep the historical upper-sideband overlay.
|
||||||
|
if (modeUpper === "DIG") return sdrDigSidebandSupported ? digSidebandDirection() : 1;
|
||||||
|
if (modeUpper === "USB" || modeUpper === "CW") return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3683,10 +3699,16 @@ function render(update: AppUpdate) {
|
|||||||
}
|
}
|
||||||
if (typeof update.filter.sdr_dig_sideband === "string") {
|
if (typeof update.filter.sdr_dig_sideband === "string") {
|
||||||
sdrDigSidebandSupported = true;
|
sdrDigSidebandSupported = true;
|
||||||
|
const prevPolicy = sdrDigSidebandPolicy;
|
||||||
|
sdrDigSidebandPolicy = update.filter.sdr_dig_sideband;
|
||||||
if (sdrDigSidebandEl && document.activeElement !== sdrDigSidebandEl) {
|
if (sdrDigSidebandEl && document.activeElement !== sdrDigSidebandEl) {
|
||||||
sdrDigSidebandEl.value = update.filter.sdr_dig_sideband;
|
sdrDigSidebandEl.value = update.filter.sdr_dig_sideband;
|
||||||
}
|
}
|
||||||
updateWfmControls();
|
updateWfmControls();
|
||||||
|
// Repaint the passband overlay if the DIG sideband just changed.
|
||||||
|
if (prevPolicy !== sdrDigSidebandPolicy && lastSpectrumData) {
|
||||||
|
scheduleSpectrumDraw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof update.show_sdr_gain_control === "boolean") {
|
if (typeof update.show_sdr_gain_control === "boolean") {
|
||||||
@@ -5621,6 +5643,11 @@ let sdrNbSupported = false;
|
|||||||
const sdrDigSidebandWrapEl = document.getElementById("sdr-dig-sideband-wrap");
|
const sdrDigSidebandWrapEl = document.getElementById("sdr-dig-sideband-wrap");
|
||||||
const sdrDigSidebandEl = document.getElementById("sdr-dig-sideband") as HTMLSelectElement | null;
|
const sdrDigSidebandEl = document.getElementById("sdr-dig-sideband") as HTMLSelectElement | null;
|
||||||
let sdrDigSidebandSupported = false;
|
let sdrDigSidebandSupported = false;
|
||||||
|
// Current DIG sideband policy ("auto" | "usb" | "lsb"), mirrored from server
|
||||||
|
// filter state. Drives the spectrum passband overlay direction for DIG.
|
||||||
|
let sdrDigSidebandPolicy = "auto";
|
||||||
|
// Matches DigSidebandPolicy::AUTO_THRESHOLD_HZ on the backend.
|
||||||
|
const DIG_AUTO_SIDEBAND_THRESHOLD_HZ = 10_000_000;
|
||||||
|
|
||||||
// Hide audio row if audio is not configured on the server
|
// Hide audio row if audio is not configured on the server
|
||||||
fetch("/audio", { method: "GET" }).then((r) => {
|
fetch("/audio", { method: "GET" }).then((r) => {
|
||||||
@@ -6076,6 +6103,10 @@ function submitSdrDigSideband() {
|
|||||||
if (!sdrDigSidebandSupported || !sdrDigSidebandEl) return;
|
if (!sdrDigSidebandSupported || !sdrDigSidebandEl) return;
|
||||||
const policy = sdrDigSidebandEl.value || "auto";
|
const policy = sdrDigSidebandEl.value || "auto";
|
||||||
if (policy !== "auto" && policy !== "usb" && policy !== "lsb") return;
|
if (policy !== "auto" && policy !== "usb" && policy !== "lsb") return;
|
||||||
|
// Optimistically move the passband overlay to the chosen sideband so the
|
||||||
|
// display responds instantly, before the server round-trip confirms it.
|
||||||
|
sdrDigSidebandPolicy = policy;
|
||||||
|
if (lastSpectrumData) scheduleSpectrumDraw();
|
||||||
postPath(`/set_sdr_dig_sideband?policy=${encodeURIComponent(policy)}`).catch(() => {});
|
postPath(`/set_sdr_dig_sideband?policy=${encodeURIComponent(policy)}`).catch(() => {});
|
||||||
}
|
}
|
||||||
if (sdrDigSidebandEl) {
|
if (sdrDigSidebandEl) {
|
||||||
|
|||||||
Reference in New Issue
Block a user