Skip to content

Mixing Morse code and error control coding for extreme weak-signal, noise-free QSOs. In active development, studying error control coding, digital signal processing, rust.

License

Notifications You must be signed in to change notification settings

devzendo/digimorse

Repository files navigation

digimorse

What is this?

Morse code was the first means by which messages were sent by Marconi, as he performed his experiments in the 1890's. This was achieved using a crude spark gap transmitter. In 1913, Edwin Armstrong and Alexander Meissner used thermionic valves to build a continuous wave oscillator which refined the transmission mechanism. This form of transmission, known by the acronym CW, was widely used for military, maritime and commercial telegraphy, gradually being replaced by more modern systems of communication. Its last maritime use was in 1999.

It is still, however, used widely by amateur radio operators, such as myself. Although the electronic circuits used have been refined as far as they can be, the essential continuous wave transmission mechanism has remained unchanged.

This project is an attempt to modernise that.

Project Status

Project started September 2020. Currently in its early development / feasibility study phase.

Currently in May 2024, I'm working on the receiver, taking audio input and running it through a Fast Fourier Transform to obtain the incoming frequency spectrum. I've completed the last part of the transmit chain of major system components, specifically the modulation of channel symbols using Gaussian Frequency Shift Keying. The transmit chain from the Arduino-based Morse key interface, keyer protocol decoder, sidetone generator, source encoder and channel encoder (using a CRC and low-density parity-check (LDPC) code) are all done.

After this, I'll need to modify the transmitter to permit output to a .WAV file, for use in testing the receiver chain.

There's no graphical user interface at the moment - the system is configured and used via a command line interface. After the transmitter is complete, and can be used from the command line, I'll make a start on the GUI and receiver chain.

I'm also porting it from its original macOS development system to run on Ubuntu. It should also run on Windows.

Overview

This is an EXPERIMENT in taking Morse code, in real-time, encoding it, wrapping it in modern error-detection/correction codes, and modulating it out to a connected amateur radio transceiver as a narrow-bandwidth signal.

The intention is to take our historic mode of communication, and be able to receive it and decode it (with your brain) whilst removing the effects of natural or man-made interference and fading. The operator will be able to visualise all the transmissions in a waterfall display, making it easy to see and select transmissions of interest. There will be the facility to filter out some or all stations so you can hone in on the one you want - and reply to it in digitally encoded Morse. By adding error correction, and carefully designing the encoding and modulation, it is hoped that the weak signal characteristic enjoyed by users of FT8, JT9 etc. can be added to Morse.

What digimorse is not:

  • Computer-generated or computer-decoded Morse. It doesn't decode the Morse for you. That's cheating! It is a beautiful skill to master, like a language or musical instrument; mastering Morse is a fine human achievement. digimorse seeks to add another dimension to it!
  • The death of CW or Amateur Radio As We Know It(tm). You don't have to use it!
  • Completely automated, just macro-key-pressing. No, you use your normal Morse key or paddle. Macros will come later perhaps.
  • Quantized. If you have a unique rhythm to your keying, digimorse won't correct it. The timing of your keying goes out verbatim. You can use our keyer with a paddle which will give good timing (later).

There are arguments that adding a keyboard entry facility (instead of key/paddle) and an auto-decoder (instead of human decode) might be warranted: in the case of disabilities. I'm happy to discuss these and maybe implement them; they're not my current priority.

What you'll find different to usual CW:

  • No noise! QRN, QRM, QSB, gone!
  • When you start keying, digimorse encodes your callsign and locator automatically, digitally. Receiving stations will see who and where you are on the waterfall display. Your encoded Morse is sent along with this - so receivers won't hear your keying as soon as you start. There are short delays.
  • When you stop keying, digimorse may not have finished encoding and transmitting. The screen will show you how much longer your transmission will actually take.
  • So there's not a rapid-fire switching of conversation.

What do I need to try it?

  • A fairly modern computer running Windows 10, macOS 10.15ish (High Sierra to Big Sur), or Ubuntu 16.xx LTS, 18.xx LTS, 20.xx LTS.
  • Sorry no Raspberry Pi yet - definitely considering a build for this.
  • An interface between the computer sound system and your amateur radio transceiver, e.g. Tigertronics SignaLink USB.
  • Monitor, keyboard, mouse.
  • An interface between your Morse key or paddle and USB. See the https://github.com/devzendo/digimorse-arduino-keyer project for a simple Arduino Nano-based Morse key/paddle <-> USB Serial interface and simple keyer.

Downloads

There aren't any yet. There will be for the first release, but that won't be any time soon. You'd have to install build tools and build it yourself...

Roadmap

First release:

  • Reads keyer output, measures timings, source-encodes these, and mixes with callsign and locator information, adds error detection/correction with a low-density parity check code, modulates using ??? and Gaussian Frequency Shift Keying to prevent hard phase transitions resulting in splatter.
  • Can choose your transmit offset within the 2500Hz bandwidth shown.
  • Waterfall shows all signals in received bandwidth, and their decoded callsign/locator information.
  • Select a signal, or click-drag-release over a portion of the display to apply a filter so that only the chosen signals are played.

Second release:

  • Who knows?

Release Notes

0.0.1 First Release (work in progress)

  • Created repository! Wrote the above... made notes... learning about information theory, error control coding, modulation/demodulation, the Fourier transform, the Rust programming language, the FLTK and PortAudio frameworks for GUI and audio, built the Arduino keyer.

Configuring and running Digimorse

The GUI is not present yet; all configuration needs to be done via the command line. To run Digimorse, use the terminal or Command Prompt, and run the 'digimorse' program. There are several options and modes in which you can run the software. Add the '--help' option to the command line to show the full details.

Before Digimorse can be used, several devices need setting in its configuration.

You will need to configure your audio output device (for speakers or headphone) so you can hear the decoded Morse, and your sidetone when keying.

You will need to configure your transceiver audio output and input devices so Digimorse can receive and transmit encoded Morse.

To discover the names of the audio devices currently available on your system, use the ListAudioDevices mode:

$ digimorse ListAudioDevices
[2021-09-17T07:49:11Z INFO  digimorse] Number of audio devices = 4
[2021-09-17T07:49:11Z INFO  digimorse] 0: "Built-in Microphone" / IN:2 OUT:0 @ 96000Hz default; 48000Hz supported
[2021-09-17T07:49:11Z INFO  digimorse] 1: "Built-in Output" / IN:0 OUT:2 @ 44100Hz default; 48000Hz supported
[2021-09-17T07:49:11Z INFO  digimorse] 2: "USB AUDIO  CODEC" / IN:0 OUT:2 @ 48000Hz default; 48000Hz supported
[2021-09-17T07:49:11Z INFO  digimorse] 3: "USB AUDIO  CODEC" / IN:2 OUT:0 @ 48000Hz default; 48000Hz supported

Please take care with the device names. Note in the above output, my transceiver is shown as "USB AUDIO CODEC" - and has two spaces between AUDIO and CODEC. You must copy-and-paste these names precisely when setting the devices, as shown below...

Now, set the appropriate devices. This is a one-off operation, you don't need to do it every time Digimorse runs - the settings you make here are saved in the software's configuration file. The following command should be given on one line; it is split for display in this guide:

$ digimorse --audioout "Built-in Output" --rigaudioout "USB AUDIO  CODEC" --rigaudioin "USB AUDIO  CODEC"
  --keyer /dev/tty.usbserial-1420
[2021-09-17T07:50:13Z INFO  digimorse] Setting audio output device to 'Built-in Output'
[2021-09-17T07:50:13Z INFO  digimorse] Setting rig output device to 'USB AUDIO  CODEC'
[2021-09-17T07:50:13Z INFO  digimorse] Setting audio input device to 'USB AUDIO  CODEC'
[2021-09-17T07:50:13Z INFO  digimorse] Audio output device is 'Built-in Output'
[2021-09-17T07:50:13Z INFO  digimorse] Rig output device is 'USB AUDIO  CODEC'
[2021-09-17T07:50:13Z INFO  digimorse] Rig input device is 'USB AUDIO  CODEC'
[2021-09-17T07:50:13Z WARN  digimorse] No keyer serial port device has been configured; use the -k or --keyer options

Ok, now we have the audio devices set, we need to tell Digimorse which device the keyer is connected to. Currently there's no easy way to show which device this is. Basically, plug it in, and:

  • On Windows, look in Device Manager under COM and LPT ports, to see what's new.
  • On macOS, in a terminal, ls -l /dev/tty.usbserial* and choose the device file you see there.

Configuration File

  • macOS: /Users//Library/ApplicationData/digimorse/digimorse.toml
  • Linux: /home//.digimorse/digimorse.toml
  • Windows: C:\Users<your username>\AppData\Roaming\digimorse.toml

Development

Current activities

For information on current development activities, please see the TODO file file.

Technology

All development is in Rust, which is a new, difficult, but interesting language. It would be easier in C++, and quicker - but probably less provably correct, and portability would be painful.

Source directory structure

The source is split into the following directories:

src/lib.rs - main body of code split into various modules.

src/digimorse.bin/main.rs - the main application.

docs - documentation, rough notes, references.

Building

You need Rust 1.64.0 or greater.

  • cargo test
  • cargo build --release

Building on macOS

Since digimorse uses fltk-sys, which compiles its C++ during build, and this requires the macOS SDK, you may find you need to create a symbolic link to fix this build issue:

 fatal: not a git repository (or any of the parent directories): .git
  CMake Warning at /opt/local/share/cmake-3.22/Modules/Platform/Darwin-Initialize.cmake:303 (message):
    Ignoring CMAKE_OSX_SYSROOT value:

     /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk

    because the directory does not exist.

In /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/, there's a directory called MacOSX.sdk. After upgrading XCode, I had to create a link in the SDKs directory pointing to it:

bash-3.2# ls -l
total 0
drwxr-xr-x  7 root  wheel  224 Nov 19 22:25 MacOSX.sdk
lrwxr-xr-x  1 root  wheel   10 Mar  8 07:44 MacOSX12.0.sdk -> MacOSX.sdk
lrwxr-xr-x  1 root  wheel   10 Mar  7 10:03 MacOSX12.1.sdk -> MacOSX.sdk

You also need portaudio (which needs pkg-config). Install from macports. There are brew variants, but I don't know brew.

Building on Windows

This requires PortAudio, which I've built using CMake, and Visual Studio 2017 command line tools. I used the pa_stable_v190700_20210406.tgz file from http://files.portaudio.com/download.html and the build instructions from http://www.portaudio.com/docs/v19-doxydocs/compile_cmake.html . So from a Visual Studio 'x64 Native Tools Command Prompt for VS 2017', which also contains CMake 3.10.3 on the PATH:

(the .tgz file has been extracted into the 'portaudio' directory, which I am above)
C:\Users\Matt Gumbley\Downloads> mkdir portaudio-cmake
C:\Users\Matt Gumbley\Downloads> cd portaudio-cmake
C:\Users\Matt Gumbley\Downloads\portaudio-cmake> cmake ..\portaudio -G "NMake Makefiles"
 ... the system is investigated ...
-- Generating done
-- Build files have been written to: C:/Users/Matt Gumbley/Downloads/portaudio-cmake
C:\Users\Matt Gumbley\Downloads\portaudio-cmake> cmake --build . --config Release --target portaudio_static
Scanning dependencies of target portaudio
[  4%] Building C object CMakeFiles/portaudio.dir/src/common/pa_allocation.c.obj
pa_allocation.c
 ... building happens ...
[100%] Linking C static library portaudio_static_x64.lib
[100%] Built target portaudio_static

The resulting portaudio_static_x86.lib file is committed to this repository under lib\windows, renamed to portaudio.lib. The build.rs control file for digimorse

Building on Linux

e.g. on Ubuntu (I'm using Ubuntu 22.04 Budgie) apt install build-essential cmake apt install libudev1 libudev0 libudev-dev librust-libudev-dev apt install libportaudio2 apt install libxft-dev libxext-dev libxinerama-dev libxcursor-dev libpango1.0-dev

apt install libfltk1.1 libfltk1.1-dev

apt install libfltk1.3 libfltk1.3-dev apt install libasound2-dev libjack-dev libjack0 libportaudiocpp0 portaudio19-dev Install rustup.

Documentation

Please see the 'docs' directory. The main document is 'The digimorse Communications Protocol'.

There are various other rough notes in ASCII, RTF and OmmWriter format.

The documentation is built using LaTeX. I use MacPorts, with the texlive and texlive-latex-extra packages. The main styles used are from the Tufte-LaTeX package, which may be found at https://github.com/Tufte-LaTeX/tufte-latex. I use the tufte-handout class.

To build the documentation, a simple 'make' should suffice - this produces the relevant PDFs.

Acknowledgements

Bart Massey's PortAudio examples at https://github.com/BartMassey/portaudio-rs-demos

Shepmaster's panic_after test helper routine at rust-lang/rfcs#2798

The authors of the Tufte-LaTeX package, from https://github.com/Tufte-LaTeX/tufte-latex

Wim Looman provided the initial LaTeX Makefile, from https://gist.github.com/Nemo157/539229

Martin Nawrath for the Direct Digital Synthesis sine wave generator ported to Rust in ToneGenerator.rs. See http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-dds-sinewave-generator/ Used in earlier keying generation code in ToneGenerator.rs.

Prof. Sarah J. Johnson for writing "Iterative Error Correction: Turbo, Low-Density Parity-Check and Repeat- Accumulate Codes".

Adam Greig for his labrador-ldpc LDPC encoder/decoder at https://github.com/adamgreig/labrador-ldpc Used in the digimorse channel codec. Thanks also to Ed W8EMV for suggesting it on the mastodon.radio instance.

Radford M. Neal for his LDPC-Codes LDPC parity check matrix generation code at https://github.com/radfordneal/LDPC-codes Used in early experiments in generating the LDPC parity check and generator matrices.

Maxime Tremblay for the LDPC and Sparse Binary Matrix crates at https://github.com/maxtremblay/ldpc and https://github.com/maxtremblay/sparse-binary-matrix Used in early experiments encoding and decoding in the digimorse channel codec.

Daniel Estévez's LDPC Toolbox crate at https://github.com/daniestevez/ldpc-toolbox Used in initial experiments encoding and decoding in the digimorse channel codec.

Kārlis Goba YL3JG's ft8_lib at https://github.com/kgoba/ft8_lib. In particular, the Gaussian Frequency Shift Keying code at https://github.com/kgoba/ft8_lib/blob/master/gen_ft8.c which is adapted to the slightly wider bandwidth modulation used by digimorse in the transmitter.

Minoru Tomobe's RustFT8 at https://github.com/w-ockham/RustFT8 for a conversion of the above GFSK code to Rust, which helped with the transmitter, and also for the graph plotting code used to visualise and tune the GFSK code.

Bibliography

TBC

License, Copyright & Contact info

This code is released under the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0.html.

(C) 2020-2023 Matt J. Gumbley

matt.gumbley@devzendo.org

Mastodon: @M0CUV@mastodon.radio

Twitter: (abandoned) @mattgumbley @devzendo

http://devzendo.github.io/digimorse

About

Mixing Morse code and error control coding for extreme weak-signal, noise-free QSOs. In active development, studying error control coding, digital signal processing, rust.

Topics

Resources

License

Stars

Watchers

Forks

Languages