mirror of
https://github.com/jketterl/openwebrx.git
synced 2026-01-19 15:10:21 +01:00
JT4 enablement
This commit is contained in:
parent
10c642e102
commit
c16ec8ef0d
|
|
@ -3,6 +3,7 @@
|
|||
- Added support for the MSK144 digimode
|
||||
- Added support for decoding ADS-B with dump1090
|
||||
- Added support for decoding HFDL and VDL2 aircraft communications
|
||||
- Added support for JT4 modes
|
||||
- Added decoding of ISM band transmissions using rtl_433
|
||||
- Added support for decoding RDS data on WFM broadcasts using redsea decoder
|
||||
- Added decoding for DAB broadcast stations using csdr-eti and dablin
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ It has the following features:
|
|||
- Multiple SDR devices can be used simultaneously
|
||||
- [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag, D-Star, NXDN)
|
||||
- [wsjt-x](https://wsjt.sourceforge.io/) based demodulators (FT8, FT4, WSPR, JT65, JT9, FST4,
|
||||
FST4W)
|
||||
FST4W, JT4)
|
||||
- [direwolf](https://github.com/wb2osz/direwolf) based demodulation of APRS packets
|
||||
- [JS8Call](http://js8call.com/) support
|
||||
- [DRM](https://github.com/jketterl/openwebrx/wiki/DRM-demodulator-notes) support
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ DemodulatorPanel.prototype.updatePanels = function() {
|
|||
var mode = Modes.findByModulation(modulation);
|
||||
toggle_panel("openwebrx-panel-digimodes", modulation && (!mode || mode.secondaryFft));
|
||||
// WSJT-X modes share the same panel
|
||||
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4', 'fst4', 'fst4w', "q65", "msk144"].indexOf(modulation) >= 0);
|
||||
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'jt4', 'ft4', 'fst4', 'fst4w', "q65", "msk144"].indexOf(modulation) >= 0);
|
||||
// these modes come with their own
|
||||
['js8', 'packet', 'pocsag', 'adsb', 'ism', 'hfdl', 'vdl2'].forEach(function(m) {
|
||||
toggle_panel('openwebrx-panel-' + m + '-message', modulation === m);
|
||||
|
|
@ -382,4 +382,4 @@ $.fn.demodulatorPanel = function(){
|
|||
this.data('panel', new DemodulatorPanel(this));
|
||||
}
|
||||
return this.data('panel');
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ MessagePanel.prototype.scrollToBottom = function() {
|
|||
function WsjtMessagePanel(el) {
|
||||
MessagePanel.call(this, el);
|
||||
this.initClearTimer();
|
||||
this.qsoModes = ['FT8', 'JT65', 'JT9', 'FT4', 'FST4', 'Q65', 'MSK144'];
|
||||
this.qsoModes = ['FT8', 'JT65', 'JT9', 'JT4', 'FT4', 'FST4', 'Q65', 'MSK144'];
|
||||
this.beaconModes = ['WSPR', 'FST4W'];
|
||||
this.modes = [].concat(this.qsoModes, this.beaconModes);
|
||||
}
|
||||
|
|
@ -809,4 +809,4 @@ $.fn.vdl2MessagePanel = function() {
|
|||
this.data('panel', new Vdl2MessagePanel(this));
|
||||
}
|
||||
return this.data('panel');
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ defaultConfig = PropertyLayer(
|
|||
wsjt_decoding_depths=PropertyLayer(jt65=1),
|
||||
fst4_enabled_intervals=[15, 30],
|
||||
fst4w_enabled_intervals=[120, 300],
|
||||
jt4_enabled_submodes=["F", "G"],
|
||||
q65_enabled_combinations=["A30", "E120", "C60"],
|
||||
js8_enabled_profiles=["normal", "slow"],
|
||||
js8_decoding_depth=3,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from owrx.form.input import CheckboxInput, NumberInput, DropdownInput, Js8Profil
|
|||
from owrx.form.input.wfm import WfmTauValues
|
||||
from owrx.form.input.wsjt import Q65ModeMatrix, WsjtDecodingDepthsInput
|
||||
from owrx.form.input.converter import OptionalConverter
|
||||
from owrx.wsjt import Fst4Profile, Fst4wProfile
|
||||
from owrx.wsjt import Fst4Profile, Fst4wProfile, JT4Profile
|
||||
from owrx.breadcrumb import Breadcrumb, BreadcrumbItem
|
||||
|
||||
|
||||
|
|
@ -90,6 +90,11 @@ class DecodingSettingsController(SettingsFormController):
|
|||
"Enabled FST4W intervals",
|
||||
[Option(v, "{}s".format(v)) for v in Fst4wProfile.availableIntervals],
|
||||
),
|
||||
MultiCheckboxInput(
|
||||
"jt4_enabled_submodes",
|
||||
"Enabled JT4 Submodes",
|
||||
[Option(v, "{}".format(v)) for v in JT4Profile.availableSubmodes],
|
||||
),
|
||||
Q65ModeMatrix("q65_enabled_combinations", "Enabled Q65 Mode combinations"),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -611,7 +611,7 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
|
|||
def _getSecondaryDemodulator(self, mod) -> Optional[SecondaryDemodulator]:
|
||||
if isinstance(mod, SecondaryDemodulator):
|
||||
return mod
|
||||
if mod in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"]:
|
||||
if mod in ["ft8", "wspr", "jt65", "jt9", "jt4", "ft4", "fst4", "fst4w", "q65"]:
|
||||
from csdr.chain.digimodes import AudioChopperDemodulator
|
||||
from owrx.wsjt import WsjtParser
|
||||
return AudioChopperDemodulator(mod, WsjtParser())
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ class Modes(object):
|
|||
WsjtMode("wspr", "WSPR", bandpass=Bandpass(1350, 1650)),
|
||||
WsjtMode("fst4", "FST4", requirements=["wsjt-x-2-3"]),
|
||||
WsjtMode("fst4w", "FST4W", bandpass=Bandpass(1350, 1650), requirements=["wsjt-x-2-3"]),
|
||||
WsjtMode("jt4", "JT4", requirements=["wsjt-x-2-4"]),
|
||||
WsjtMode("q65", "Q65", requirements=["wsjt-x-2-4"]),
|
||||
DigitalMode("msk144", "MSK144", requirements=["msk144"], underlying=["usb"], service=True),
|
||||
Js8Mode("js8", "JS8Call"),
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class PskReporter(FilteredReporter):
|
|||
Current version at the time of the last change:
|
||||
https://www.adif.org/314/ADIF_314.htm#Mode_Enumeration
|
||||
"""
|
||||
return ["FT8", "FT4", "JT9", "JT65", "FST4", "JS8", "Q65", "WSPR", "FST4W", "MSK144"]
|
||||
return ["FT8", "FT4", "JT9", "JT4", "JT65", "FST4", "JS8", "Q65", "WSPR", "FST4W", "MSK144"]
|
||||
|
||||
def stop(self):
|
||||
self.cancelTimer()
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ class ServiceHandler(SdrSourceEventClient):
|
|||
def _getSecondaryDemodulator(self, mod) -> Optional[ServiceDemodulator]:
|
||||
if isinstance(mod, ServiceDemodulatorChain):
|
||||
return mod
|
||||
if mod in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"]:
|
||||
if mod in ["ft8", "wspr", "jt65", "jt9", "jt4", "ft4", "fst4", "fst4w", "q65"]:
|
||||
from csdr.chain.digimodes import AudioChopperDemodulator
|
||||
from owrx.wsjt import WsjtParser
|
||||
return AudioChopperDemodulator(mod, WsjtParser())
|
||||
|
|
|
|||
31
owrx/wsjt.py
31
owrx/wsjt.py
|
|
@ -62,6 +62,16 @@ class Fst4wProfileSource(ConfigWiredProfileSource):
|
|||
return [Fst4wProfile(i) for i in profiles if i in Fst4wProfile.availableIntervals]
|
||||
|
||||
|
||||
class JT4ProfileSource(ConfigWiredProfileSource):
|
||||
def getPropertiesToWire(self) -> List[str]:
|
||||
return ["jt4_enabled_submodes"]
|
||||
|
||||
def getProfiles(self) -> List[AudioChopperProfile]:
|
||||
config = Config.get()
|
||||
profiles = config["jt4_enabled_submodes"] if "jt4_enabled_submodes" in config else []
|
||||
return [JT4Profile(i) for i in profiles if i in JT4Profile.availableSubmodes]
|
||||
|
||||
|
||||
class Q65ProfileSource(ConfigWiredProfileSource):
|
||||
def getPropertiesToWire(self) -> List[str]:
|
||||
return ["q65_enabled_combinations"]
|
||||
|
|
@ -102,6 +112,8 @@ class WsjtProfiles(object):
|
|||
return Fst4ProfileSource()
|
||||
elif mode == "fst4w":
|
||||
return Fst4wProfileSource()
|
||||
elif mode == "jt4":
|
||||
return JT4ProfileSource()
|
||||
elif mode == "q65":
|
||||
return Q65ProfileSource()
|
||||
|
||||
|
|
@ -197,6 +209,25 @@ class Fst4wProfile(WsjtProfile):
|
|||
return "FST4W"
|
||||
|
||||
|
||||
class JT4Profile(WsjtProfile):
|
||||
availableSubmodes = ["A", "B", "C", "D", "E", "F", "G"]
|
||||
|
||||
def __init__(self, submode):
|
||||
self.submode = submode
|
||||
|
||||
def getInterval(self):
|
||||
return 60
|
||||
|
||||
def getSubmode(self):
|
||||
return self.submode
|
||||
|
||||
def decoder_commandline(self, file):
|
||||
return ["jt9", "-4", "-b", str(self.submode), "-F", "1000" , "-d", str(self.decoding_depth()), file]
|
||||
|
||||
def getMode(self):
|
||||
return "JT4"
|
||||
|
||||
|
||||
class Q65Mode(Enum):
|
||||
# value is the bandwidth multiplier according to https://physics.princeton.edu/pulsar/k1jt/Q65_Quick_Start.pdf
|
||||
A = 1
|
||||
|
|
|
|||
Loading…
Reference in a new issue