mirror of
https://github.com/smittix/intercept.git
synced 2026-06-22 03:58:52 -07:00
Add fine tune offset for digital voice
This commit is contained in:
+4
-1
@@ -490,6 +490,7 @@ def start_dmr() -> Response:
|
|||||||
device = validate_device_index(data.get('device', 0))
|
device = validate_device_index(data.get('device', 0))
|
||||||
protocol = str(data.get('protocol', 'auto')).lower()
|
protocol = str(data.get('protocol', 'auto')).lower()
|
||||||
ppm = validate_ppm(data.get('ppm', 0))
|
ppm = validate_ppm(data.get('ppm', 0))
|
||||||
|
fine_tune = int(data.get('fineTune', 0) or 0)
|
||||||
demod = str(data.get('demod', 'nfm')).lower()
|
demod = str(data.get('demod', 'nfm')).lower()
|
||||||
except (ValueError, TypeError) as e:
|
except (ValueError, TypeError) as e:
|
||||||
return jsonify({'status': 'error', 'message': f'Invalid parameter: {e}'}), 400
|
return jsonify({'status': 'error', 'message': f'Invalid parameter: {e}'}), 400
|
||||||
@@ -500,6 +501,8 @@ def start_dmr() -> Response:
|
|||||||
return jsonify({'status': 'error', 'message': f'Invalid demod. Use: {", ".join(VALID_DEMODS)}'}), 400
|
return jsonify({'status': 'error', 'message': f'Invalid demod. Use: {", ".join(VALID_DEMODS)}'}), 400
|
||||||
if protocol == 'p25p2' and not is_fme:
|
if protocol == 'p25p2' and not is_fme:
|
||||||
return jsonify({'status': 'error', 'message': 'P25 Phase 2 requires dsd-fme.'}), 400
|
return jsonify({'status': 'error', 'message': 'P25 Phase 2 requires dsd-fme.'}), 400
|
||||||
|
if abs(fine_tune) > 20000:
|
||||||
|
return jsonify({'status': 'error', 'message': 'Fine tune offset too large (max +/- 20000 Hz).'}), 400
|
||||||
|
|
||||||
# Clear stale queue
|
# Clear stale queue
|
||||||
try:
|
try:
|
||||||
@@ -517,7 +520,7 @@ def start_dmr() -> Response:
|
|||||||
|
|
||||||
dmr_active_device = device
|
dmr_active_device = device
|
||||||
|
|
||||||
freq_hz = int(frequency * 1e6)
|
freq_hz = int((frequency * 1e6) + fine_tune)
|
||||||
|
|
||||||
# Build rtl_fm command (48kHz sample rate for DSD).
|
# Build rtl_fm command (48kHz sample rate for DSD).
|
||||||
# Squelch disabled (-l 0): rtl_fm's squelch chops the bitstream
|
# Squelch disabled (-l 0): rtl_fm's squelch chops the bitstream
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ function startDmr() {
|
|||||||
const protocol = document.getElementById('dmrProtocol')?.value || 'auto';
|
const protocol = document.getElementById('dmrProtocol')?.value || 'auto';
|
||||||
const gain = parseInt(document.getElementById('dmrGain')?.value || 40);
|
const gain = parseInt(document.getElementById('dmrGain')?.value || 40);
|
||||||
const ppm = parseInt(document.getElementById('dmrPPM')?.value || 0);
|
const ppm = parseInt(document.getElementById('dmrPPM')?.value || 0);
|
||||||
|
const fineTune = parseInt(document.getElementById('dmrFineTune')?.value || 0);
|
||||||
const relaxCrc = document.getElementById('dmrRelaxCrc')?.checked || false;
|
const relaxCrc = document.getElementById('dmrRelaxCrc')?.checked || false;
|
||||||
const demod = document.getElementById('dmrDemod')?.value || 'nfm';
|
const demod = document.getElementById('dmrDemod')?.value || 'nfm';
|
||||||
const device = typeof getSelectedDevice === 'function' ? getSelectedDevice() : 0;
|
const device = typeof getSelectedDevice === 'function' ? getSelectedDevice() : 0;
|
||||||
@@ -84,14 +85,14 @@ function startDmr() {
|
|||||||
// Save settings to localStorage for persistence
|
// Save settings to localStorage for persistence
|
||||||
try {
|
try {
|
||||||
localStorage.setItem(DMR_SETTINGS_KEY, JSON.stringify({
|
localStorage.setItem(DMR_SETTINGS_KEY, JSON.stringify({
|
||||||
frequency, protocol, gain, ppm, relaxCrc, demod
|
frequency, protocol, gain, ppm, fineTune, relaxCrc, demod
|
||||||
}));
|
}));
|
||||||
} catch (e) { /* localStorage unavailable */ }
|
} catch (e) { /* localStorage unavailable */ }
|
||||||
|
|
||||||
fetch('/dmr/start', {
|
fetch('/dmr/start', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ frequency, protocol, gain, device, ppm, relaxCrc, demod })
|
body: JSON.stringify({ frequency, protocol, gain, device, ppm, fineTune, relaxCrc, demod })
|
||||||
})
|
})
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
@@ -617,12 +618,14 @@ function restoreDmrSettings() {
|
|||||||
const protoEl = document.getElementById('dmrProtocol');
|
const protoEl = document.getElementById('dmrProtocol');
|
||||||
const gainEl = document.getElementById('dmrGain');
|
const gainEl = document.getElementById('dmrGain');
|
||||||
const ppmEl = document.getElementById('dmrPPM');
|
const ppmEl = document.getElementById('dmrPPM');
|
||||||
|
const fineTuneEl = document.getElementById('dmrFineTune');
|
||||||
const crcEl = document.getElementById('dmrRelaxCrc');
|
const crcEl = document.getElementById('dmrRelaxCrc');
|
||||||
const demodEl = document.getElementById('dmrDemod');
|
const demodEl = document.getElementById('dmrDemod');
|
||||||
if (freqEl && s.frequency != null) freqEl.value = s.frequency;
|
if (freqEl && s.frequency != null) freqEl.value = s.frequency;
|
||||||
if (protoEl && s.protocol) protoEl.value = s.protocol;
|
if (protoEl && s.protocol) protoEl.value = s.protocol;
|
||||||
if (gainEl && s.gain != null) gainEl.value = s.gain;
|
if (gainEl && s.gain != null) gainEl.value = s.gain;
|
||||||
if (ppmEl && s.ppm != null) ppmEl.value = s.ppm;
|
if (ppmEl && s.ppm != null) ppmEl.value = s.ppm;
|
||||||
|
if (fineTuneEl && s.fineTune != null) fineTuneEl.value = s.fineTune;
|
||||||
if (crcEl && s.relaxCrc != null) crcEl.checked = s.relaxCrc;
|
if (crcEl && s.relaxCrc != null) crcEl.checked = s.relaxCrc;
|
||||||
if (demodEl && s.demod) demodEl.value = s.demod;
|
if (demodEl && s.demod) demodEl.value = s.demod;
|
||||||
} catch (e) { /* localStorage unavailable */ }
|
} catch (e) { /* localStorage unavailable */ }
|
||||||
|
|||||||
@@ -51,6 +51,15 @@
|
|||||||
title="Frequency error correction for your RTL-SDR dongle. Digital voice is very sensitive to frequency offset.">
|
title="Frequency error correction for your RTL-SDR dongle. Digital voice is very sensitive to frequency offset.">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Fine Tune (Hz)</label>
|
||||||
|
<input type="number" id="dmrFineTune" value="0" min="-5000" max="5000" step="100" style="width: 100%;"
|
||||||
|
title="Offset the tuned frequency by a small amount without changing PPM.">
|
||||||
|
<span style="font-size: 0.75em; color: var(--text-muted); display: block; margin-top: 2px;">
|
||||||
|
Adjust in 100 Hz steps; small offsets can dramatically improve P25 decode.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-top: 4px;">
|
<div class="form-group" style="margin-top: 4px;">
|
||||||
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">
|
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">
|
||||||
<input type="checkbox" id="dmrRelaxCrc" style="width: auto; accent-color: var(--accent-cyan);">
|
<input type="checkbox" id="dmrRelaxCrc" style="width: auto; accent-color: var(--accent-cyan);">
|
||||||
|
|||||||
Reference in New Issue
Block a user