kopia lustrzana https://github.com/projecthorus/horus-gui
7N1 support, detect valid sample rates.
rodzic
cf9e67691b
commit
2e77ed056b
41
README.md
41
README.md
|
@ -2,11 +2,24 @@
|
|||
|
||||
Telemetry demodulator for the following modems in use by Project Horus
|
||||
* Horus Binary Modes (4FSK)
|
||||
* v1 - Legacy 22 byte mode, Golay FEC
|
||||
* v2 - 16/32-byte modes, LDPC FEC (Still in development)
|
||||
* RTTY (7N2 and 8N2, standard UKHAS sentences with CRC16 only)
|
||||
* v1 - Legacy 22 byte mode, Golay(23,12) FEC
|
||||
* v2 - 16/32-byte modes, LDPC FEC (Under development)
|
||||
* RTTY (7N1, 7N2 and 8N2, standard [UKHAS sentences](https://ukhas.org.uk/communication:protocol) with CRC16 only)
|
||||
|
||||
This project serves as a graphical front-end to [horusdemodlib](https://github.com/projecthorus/horusdemodlib) a Python/C library of telemetry demodulators based off the [codec2](https://github.com/drowe67/codec2) FSK modem. The core modem used in this library is very well tested, and performs in line with incoherent FSK demodulator theory. The RTTY decoder is approximately [2dB better](http://www.rowetel.com/?p=5906) than dl-fldigi, and the Horus Binary v1 modem approximately 7 dB better again. Once finished, the Horus Binary v2 modes should provide an additional few dB more performance yet again.
|
||||
This project serves as a graphical front-end to [horusdemodlib](https://github.com/projecthorus/horusdemodlib) a Python/C library of telemetry demodulators based off the [codec2](https://github.com/drowe67/codec2) FSK modem. The core modem used in this library is very well tested, and performs in line with incoherent FSK demodulator theory. The RTTY decoder is approximately [2dB better](http://www.rowetel.com/?p=5906) than dl-fldigi, and the Horus Binary v1 modem approximately 7 dB better again. Once finished, the Horus Binary v2 modes should provide more flexibility over the v1 mode, and provide further performance improvements.
|
||||
|
||||
### Important Performance Notes
|
||||
The FSK demodulator at the core of this application expects the transmitter to behave like a modem. That is, it should:
|
||||
* Have a symbol rate which is close to the desired symbol rate (within +/- 1000 ppm).
|
||||
* Maintain that symbol rate throughout a transmission (i.e. not drift in symbol rate across a transmission)
|
||||
* Not have gaps between transmitted bytes.
|
||||
* Not drift a lot in frequency during a transmission (a few Hz/sec is probably OK - this needs to be tested further)
|
||||
|
||||
All of the above are achievable from a small microcontroller such as an Arduino. The use of [interrupts](https://ukhas.org.uk/guides:interrupt_driven_rtty) (instead of sleep statements) to control symbol timing is recommended. Raspberry Pi UARTs (in particular the 'mini-UART') are known to have gaps between transmitter bytes, so be warned!
|
||||
|
||||
If you are having issues decoding telemetry from your payload, then carefully investigate the above points. If you are still having issues, then please contact me with a recording via the e-mail address below.
|
||||
|
||||
### Authors
|
||||
|
||||
Written by:
|
||||
* GUI & Glue Code - Mark Jessop <vk5qi@rfhead.net>
|
||||
|
@ -14,21 +27,18 @@ Written by:
|
|||
* FSK Modem Wrapper - XSSFox
|
||||
* LDPC Codes - Bill Cowley
|
||||
|
||||
**Note: This is very much a work in progress!**
|
||||
|
||||
![Screenshot](doc/horusgui_screenshot.png)
|
||||
|
||||
|
||||
### Known Issues
|
||||
* Occasional crash when processing is stopped just as a packet is being processed by horus_api.
|
||||
* Queue events not processed on OSX when the application is running in the background.
|
||||
|
||||
### TODO LIST - Important Stuff
|
||||
* Better build system via Travis (@xssfox)
|
||||
|
||||
### TODO LIST - Extras
|
||||
* Waterfall Display (? Need something GPU accelerated if possible...)
|
||||
* rotctld rotator control?
|
||||
### TODO LIST
|
||||
* Important Things
|
||||
* Better build system via Travis (@xssfox)
|
||||
* Extras
|
||||
* Waterfall Display (? Need something GPU accelerated if possible...)
|
||||
* rotctld rotator control?
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -96,9 +106,8 @@ Or run the helper startup script:
|
|||
$ python horus-gui.py
|
||||
```
|
||||
|
||||
## Updating
|
||||
As this repository is under regular development, you will likely need to update frequently.
|
||||
This means updating both this repository, and horusdemodlib, on which it depends.
|
||||
### Updating
|
||||
As this repository is under regular development, you will likely need to update frequently. For those using the binary builds, this just means downloading a new file and running it. If you're running from source, this means updating both this repository, and horusdemodlib, on which it depends.
|
||||
|
||||
```console
|
||||
$ cd ~/horusdemodlib
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__ = "0.1.8"
|
||||
__version__ = "0.1.9"
|
||||
|
|
|
@ -48,7 +48,7 @@ def init_audio(widgets):
|
|||
|
||||
def populate_sample_rates(widgets):
|
||||
""" Populate the sample rate ComboBox with the sample rates of the currently selected audio device """
|
||||
global audioDevices
|
||||
global audioDevices, pyAudio
|
||||
|
||||
# Clear list of sample rates.
|
||||
widgets["audioSampleRateSelector"].clear()
|
||||
|
@ -56,18 +56,29 @@ def populate_sample_rates(widgets):
|
|||
# Get information on current audio device
|
||||
_dev_name = widgets["audioDeviceSelector"].currentText()
|
||||
|
||||
# Add in fixed sample rate for GQRX input.
|
||||
|
||||
if _dev_name == 'GQRX UDP':
|
||||
# Add in fixed sample rate for GQRX input, which only outputs at 48 kHz.
|
||||
widgets["audioSampleRateSelector"].addItem(str(48000))
|
||||
widgets["audioSampleRateSelector"].setCurrentIndex(0)
|
||||
|
||||
if _dev_name in audioDevices:
|
||||
# TODO: Determine valid samples rates. For now, just use the default.
|
||||
# TODO: Add support for resampling.
|
||||
#_samp_rate = 48000 #
|
||||
_samp_rate = int(audioDevices[_dev_name]["defaultSampleRate"])
|
||||
widgets["audioSampleRateSelector"].addItem(str(_samp_rate))
|
||||
widgets["audioSampleRateSelector"].setCurrentIndex(0)
|
||||
# Determine which sample rates from a common list are valid for this device.
|
||||
_possible_rates = [8000.0, 22050.0, 44100.0, 48000.0, 96000.0]
|
||||
for _rate in _possible_rates:
|
||||
_dev_info = audioDevices[_dev_name]
|
||||
_valid = pyAudio.is_format_supported(
|
||||
_rate,
|
||||
input_device=_dev_info['index'],
|
||||
input_channels=1,
|
||||
input_format=pyaudio.paInt16
|
||||
)
|
||||
if _valid:
|
||||
widgets["audioSampleRateSelector"].addItem(str(int(_rate)))
|
||||
|
||||
# Pick the default one.
|
||||
_default_samp_rate = int(audioDevices[_dev_name]["defaultSampleRate"])
|
||||
widgets["audioSampleRateSelector"].setCurrentText(str(_default_samp_rate))
|
||||
else:
|
||||
logging.error("Audio - Unknown Audio Device")
|
||||
|
||||
|
|
|
@ -11,12 +11,14 @@ from pyqtgraph.Qt import QtCore
|
|||
from ruamel.yaml import YAML
|
||||
from . import __version__
|
||||
from .modem import populate_modem_settings
|
||||
from .audio import populate_sample_rates
|
||||
from horusdemodlib.payloads import download_latest_payload_id_list, download_latest_custom_field_list
|
||||
import horusdemodlib.payloads
|
||||
|
||||
default_config = {
|
||||
"version": __version__,
|
||||
"audio_device": "None",
|
||||
"audio_sample_rate": "48000",
|
||||
"modem": "Horus Binary v1 (Legacy)",
|
||||
"baud_rate": -1,
|
||||
"habitat_upload_enabled": True,
|
||||
|
@ -89,6 +91,11 @@ def read_config(widgets):
|
|||
# Try and set the audio device.
|
||||
# If the audio device is not in the available list of devices, this will fail silently.
|
||||
widgets["audioDeviceSelector"].setCurrentText(default_config["audio_device"])
|
||||
# Populate the list of valid sample rates
|
||||
populate_sample_rates(widgets)
|
||||
# Attempt to set the configured sample rate. This will fail silently if it does not exist.
|
||||
widgets["audioSampleRateSelector"].setCurrentText(str(default_config["audio_sample_rate"]))
|
||||
|
||||
# Try and set the modem. If the modem is not valid, this will fail silently.
|
||||
widgets["horusModemSelector"].setCurrentText(default_config["modem"])
|
||||
# Populate the default settings.
|
||||
|
@ -127,6 +134,7 @@ def save_config(widgets):
|
|||
default_config["horus_udp_enabled"] = widgets["horusUploadSelector"].isChecked()
|
||||
default_config["horus_udp_port"] = int(widgets["horusUDPEntry"].text())
|
||||
default_config["audio_device"] = widgets["audioDeviceSelector"].currentText()
|
||||
default_config["audio_sample_rate"] = widgets["audioSampleRateSelector"].currentText()
|
||||
default_config["modem"] = widgets["horusModemSelector"].currentText()
|
||||
default_config["baud_rate"] = int(widgets["horusModemRateSelector"].currentText())
|
||||
|
||||
|
|
|
@ -12,6 +12,13 @@ HORUS_MODEM_LIST = {
|
|||
"default_tone_spacing": 270,
|
||||
"use_mask_estimator": False,
|
||||
},
|
||||
"RTTY (7N1)": {
|
||||
"id": Mode.RTTY_7N1,
|
||||
"baud_rates": [50, 75, 100, 300, 600, 1000],
|
||||
"default_baud_rate": 100,
|
||||
"default_tone_spacing": 425,
|
||||
"use_mask_estimator": False,
|
||||
},
|
||||
"RTTY (7N2)": {
|
||||
"id": Mode.RTTY_7N2,
|
||||
"baud_rates": [50, 75, 100, 300, 600, 1000],
|
||||
|
|
Ładowanie…
Reference in New Issue