add Q65 mode integration
This commit is contained in:
parent
e66be7c12d
commit
d6d6d97a13
@ -1,7 +1,8 @@
|
||||
**unreleased**
|
||||
- Introduced `squelch_auto_margin` config option that allows configuring the auto squelch level
|
||||
- Removed `port` configuration option; `rtltcp_compat` takes the port number with the new connectors
|
||||
- Added support for new WSJT-X modes FST4 and FST4W (only available with WSJT-X 2.3)
|
||||
- Added support for new WSJT-X modes FST4, FST4W (only available with WSJT-X 2.3) and Q65 (only avilable with
|
||||
WSJT-X 2.4)
|
||||
- Added support for demodulating M17 digital voice signals using m17-cxx-demod
|
||||
- New reporting infrastructure, allowing WSPR and FST4W spots to be sent to wsprnet.org
|
||||
- Add some basic filtering capabilities to the map
|
||||
|
@ -318,6 +318,10 @@ fst4_enabled_intervals = [15, 30]
|
||||
# available values (in seconds): 120, 300, 900, 1800
|
||||
fst4w_enabled_intervals = [120, 300]
|
||||
|
||||
# Q65 allows many combinations of intervals and submodes. This setting determines which combinations will be decoded.
|
||||
# Please use python tuples of (interval: int, mode: str) to specify the combinations. For example:
|
||||
q65_enabled_combinations = [(30, "A"), (120, "E"), (60, "C")]
|
||||
|
||||
# JS8 comes in different speeds: normal, slow, fast, turbo. This setting controls which ones are enabled.
|
||||
js8_enabled_profiles = ["normal", "slow"]
|
||||
# JS8 decoding depth; higher value will get more results, but will also consume more cpu
|
||||
|
@ -29,7 +29,7 @@ import math
|
||||
from functools import partial
|
||||
|
||||
from owrx.kiss import KissClient, DirewolfConfig
|
||||
from owrx.wsjt import Ft8Profile, WsprProfile, Jt9Profile, Jt65Profile, Ft4Profile, Fst4Profile, Fst4wProfile
|
||||
from owrx.wsjt import Ft8Profile, WsprProfile, Jt9Profile, Jt65Profile, Ft4Profile, Fst4Profile, Fst4wProfile, Q65Profile
|
||||
from owrx.js8 import Js8Profiles
|
||||
from owrx.audio import AudioChopper
|
||||
|
||||
@ -433,6 +433,8 @@ class dsp(object):
|
||||
chopper_profiles = Fst4Profile.getEnabledProfiles()
|
||||
elif smd == "fst4w":
|
||||
chopper_profiles = Fst4wProfile.getEnabledProfiles()
|
||||
elif smd == "q65":
|
||||
chopper_profiles = Q65Profile.getEnabledProfiles()
|
||||
if chopper_profiles is not None and len(chopper_profiles):
|
||||
chopper = AudioChopper(self, self.secondary_process_demod.stdout, *chopper_profiles)
|
||||
chopper.start()
|
||||
@ -573,7 +575,7 @@ class dsp(object):
|
||||
def isWsjtMode(self, demodulator=None):
|
||||
if demodulator is None:
|
||||
demodulator = self.get_secondary_demodulator()
|
||||
return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w"]
|
||||
return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"]
|
||||
|
||||
def isJs8(self, demodulator=None):
|
||||
if demodulator is None:
|
||||
|
4
debian/changelog
vendored
4
debian/changelog
vendored
@ -3,8 +3,8 @@ openwebrx (0.21.0) UNRELEASED; urgency=low
|
||||
auto squelch level
|
||||
* Removed `port` configuration option; `rtltcp_compat` takes the port number
|
||||
with the new connectors
|
||||
* Added support for new WSJT-X modes FST4 and FST4W (only available with
|
||||
WSJT-X 2.3)
|
||||
* Added support for new WSJT-X modes FST4, FST4W (only available with WSJT-X
|
||||
2.3) and Q65 (only available with WSJT-X 2.4)
|
||||
* Added support for demodulating M17 digital voice signals using
|
||||
m17-cxx-demod
|
||||
* New reporting infrastructure, allowing WSPR and FST4W spots to be sent to
|
||||
|
@ -1192,6 +1192,7 @@ img.openwebrx-mirror-img
|
||||
#openwebrx-panel-digimodes[data-mode="js8"] #openwebrx-digimode-content-container,
|
||||
#openwebrx-panel-digimodes[data-mode="fst4"] #openwebrx-digimode-content-container,
|
||||
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-content-container,
|
||||
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-content-container,
|
||||
#openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-select-channel,
|
||||
#openwebrx-panel-digimodes[data-mode="wspr"] #openwebrx-digimode-select-channel,
|
||||
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-select-channel,
|
||||
@ -1201,7 +1202,8 @@ img.openwebrx-mirror-img
|
||||
#openwebrx-panel-digimodes[data-mode="pocsag"] #openwebrx-digimode-select-channel,
|
||||
#openwebrx-panel-digimodes[data-mode="js8"] #openwebrx-digimode-select-channel,
|
||||
#openwebrx-panel-digimodes[data-mode="fst4"] #openwebrx-digimode-select-channel,
|
||||
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-select-channel
|
||||
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-select-channel,
|
||||
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-select-channel
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
@ -1215,7 +1217,8 @@ img.openwebrx-mirror-img
|
||||
#openwebrx-panel-digimodes[data-mode="pocsag"] #openwebrx-digimode-canvas-container,
|
||||
#openwebrx-panel-digimodes[data-mode="js8"] #openwebrx-digimode-canvas-container,
|
||||
#openwebrx-panel-digimodes[data-mode="fst4"] #openwebrx-digimode-canvas-container,
|
||||
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-canvas-container
|
||||
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-canvas-container,
|
||||
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-canvas-container
|
||||
{
|
||||
height: 200px;
|
||||
margin: -10px;
|
||||
|
@ -158,7 +158,7 @@ DemodulatorPanel.prototype.updatePanels = function() {
|
||||
var modulation = this.getDemodulator().get_secondary_demod();
|
||||
$('#openwebrx-panel-digimodes').attr('data-mode', modulation);
|
||||
toggle_panel("openwebrx-panel-digimodes", !!modulation);
|
||||
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4', 'fst4', 'fst4w'].indexOf(modulation) >= 0);
|
||||
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4', 'fst4', 'fst4w', "q65"].indexOf(modulation) >= 0);
|
||||
toggle_panel("openwebrx-panel-js8-message", modulation == "js8");
|
||||
toggle_panel("openwebrx-panel-packet-message", modulation === "packet");
|
||||
toggle_panel("openwebrx-panel-pocsag-message", modulation === "pocsag");
|
||||
|
@ -78,7 +78,7 @@ WsjtMessagePanel.prototype.pushMessage = function(msg) {
|
||||
return $('<div/>').text(input).html()
|
||||
};
|
||||
|
||||
if (['FT8', 'JT65', 'JT9', 'FT4', 'FST4'].indexOf(msg['mode']) >= 0) {
|
||||
if (['FT8', 'JT65', 'JT9', 'FT4', 'FST4', 'Q65'].indexOf(msg['mode']) >= 0) {
|
||||
matches = linkedmsg.match(/(.*\s[A-Z0-9]+\s)([A-R]{2}[0-9]{2})$/);
|
||||
if (matches && matches[2] !== 'RR73') {
|
||||
linkedmsg = html_escape(matches[1]) + '<a href="map?locator=' + matches[2] + '" target="openwebrx-map">' + matches[2] + '</a>';
|
||||
|
@ -98,6 +98,9 @@ class Modes(object):
|
||||
requirements=["wsjt-x-2-3"],
|
||||
service=True,
|
||||
),
|
||||
DigitalMode(
|
||||
"q65", "Q65", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x-2-4"], service=True
|
||||
),
|
||||
DigitalMode(
|
||||
"js8", "JS8Call", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["js8call"], service=True
|
||||
),
|
||||
|
@ -18,7 +18,7 @@ class PskReporter(Reporter):
|
||||
interval = 300
|
||||
|
||||
def getSupportedModes(self):
|
||||
return ["FT8", "FT4", "JT9", "JT65", "FST4", "JS8"]
|
||||
return ["FT8", "FT4", "JT9", "JT65", "FST4", "JS8", "Q65"]
|
||||
|
||||
def stop(self):
|
||||
self.cancelTimer()
|
||||
|
32
owrx/wsjt.py
32
owrx/wsjt.py
@ -7,6 +7,7 @@ from owrx.parser import Parser
|
||||
from owrx.audio import AudioChopperProfile
|
||||
from abc import ABC, ABCMeta, abstractmethod
|
||||
from owrx.config import Config
|
||||
from enum import Enum
|
||||
|
||||
import logging
|
||||
|
||||
@ -142,6 +143,37 @@ class Fst4wProfile(WsjtProfile):
|
||||
return [Fst4wProfile(i) for i in profiles if i in Fst4wProfile.availableIntervals]
|
||||
|
||||
|
||||
class Q65Mode(Enum):
|
||||
A = 1
|
||||
B = 2
|
||||
C = 3
|
||||
D = 4
|
||||
E = 5
|
||||
|
||||
|
||||
class Q65Profile(WsjtProfile):
|
||||
availableIntervals = [15, 30, 60, 120, 300]
|
||||
|
||||
def __init__(self, interval, mode: Q65Mode):
|
||||
self.interval = interval
|
||||
self.mode = mode
|
||||
|
||||
def getMode(self):
|
||||
return "Q65"
|
||||
|
||||
def getInterval(self):
|
||||
return self.interval
|
||||
|
||||
def decoder_commandline(self, file):
|
||||
return ["jt9", "--q65", "-p", str(self.interval), "-b", self.mode.name, "-d", str(self.decoding_depth()), file]
|
||||
|
||||
@staticmethod
|
||||
def getEnabledProfiles():
|
||||
config = Config.get()
|
||||
profiles = config["q65_enabled_combinations"] if "q65_enabled_combinations" in config else []
|
||||
return [Q65Profile(i, Q65Mode[m]) for i, m in profiles if i in Fst4wProfile.availableIntervals]
|
||||
|
||||
|
||||
class WsjtParser(Parser):
|
||||
def parse(self, messages):
|
||||
for data in messages:
|
||||
|
Loading…
Reference in New Issue
Block a user