Τρίτη 3 Σεπτεμβρίου 2024

TCI Morse code decoder for SUNSDR

Morse Code Decoding Pipeline with SUNSDR, SOX, and Multimon-NG

This command line one-liner demonstrates how to receive, process, and decode Morse code signals using a combination of Python, SOX, and Multimon-NG. Below is a breakdown of the process and the software tools involved:

1. SUNSDR Transceiver and eesdr-tci Python Library

  • SUNSDR Transceiver: The SUNSDR transceiver is a software-defined radio (SDR) device that allows users to transmit and receive radio signals. It can handle a wide range of frequencies and modulations.
  • eesdr-tci: The eesdr-tci library is a Python interface for controlling Expert Electronics SDRs, like the SUNSDR, via the TCI (Transceiver Control Interface) protocol. This library allows interaction with the SDR, managing its settings, and receiving audio samples directly into a Python script.

The command used to receive audio samples is:

python3 ~/eesdr-tci/example/receive_audio.py

This command runs a Python script that connects to the SUNSDR transceiver and receives raw audio samples, typically in a high-fidelity format suitable for further processing.

2. SOX (Sound eXchange)

  • SOX: SOX is a versatile command-line utility that can convert and manipulate audio data in various formats. It's widely used for resampling, converting between audio formats, and applying effects.
  • Resampling with SOX: In this one-liner, SOX is used to resample the audio from the SUNSDR. The original audio is in a 48 kHz sample rate with 16-bit signed integer format and stereo channels. This audio is downsampled to a 22.05 kHz sample rate with mono channel output, which is more suitable for processing by the Morse code decoder.

The SOX command is:

sox -V -t raw -b 16 -e signed-integer -c 2 -r 48k - -t raw -b 16 -e signed-integer -c 1 -r 22050 -

Here’s what the options mean:

  • -V: Enables verbosity, allowing you to see what SOX is doing.
  • -t raw: Specifies that the input and output are raw audio streams.
  • -b 16 -e signed-integer: Specifies 16-bit signed integer encoding.
  • -c 2 -r 48k: Indicates that the input audio has 2 channels and a sample rate of 48 kHz.
  • -c 1 -r 22050: Specifies that the output should have 1 channel (mono) and a sample rate of 22.05 kHz.

3. Multimon-NG

  • Multimon-NG: This is a popular multi-channel decoder for various digital transmission formats, including Morse code (CW), POCSAG, FLEX, and others. Multimon-NG takes the resampled audio and decodes the Morse code signals into readable text.

The Multimon-NG command is:

multimon-ng -c -a MORSE_CW -

Here’s what the options mean:

  • -c: removes all other demodulators except for what is specified with -a.
  • -a MORSE_CW: Tells Multimon-NG to use the Morse code (CW) decoder.
  • -: Specifies that the input will be taken from the standard input (piped from the SOX command).

Summary

This one-liner integrates multiple tools to achieve a seamless workflow for decoding Morse code. The Python script communicates with the SUNSDR transceiver to receive raw audio samples, which are then resampled by SOX to a suitable format for Morse code decoding. Finally, Multimon-NG decodes the resampled audio and extracts the Morse code, outputting the decoded text to the console. This pipeline is efficient for real-time signal processing and decoding in a streamlined manner.

  • python3 ~/eesdr-tci/example/receive_audio.py |sox -V -t raw -b 16 -e signed-integer -c 2 -r 48k - -t raw -b 16 -e signed-integer -c 1 -r 22050 - | multimon-ng -c -a MORSE_CW -
  • Τρίτη 10 Σεπτεμβρίου 2019

    Decoding FT8 in with any SDR like USRP, LimeSDR, PlutoSDR, rtlsdr

    It's been a while since the devastating release of those new controversial digital modes on Ham radio, but not many ways to actually decode them.

    Since the early days of JT65 I was trying to find a way to decode 6M spots with my RTL-SDR stick. Of course that was not easy at all, because it had to be synced in each transmission beginning and end, the clock had to be accurate and not drifting. So I had to upgrade my stick from RTL-SDR.com, then I managed to use rtl-fm to decode SSB and save it into a wav file. WSJT-X module jt9 had to be run from command line, compiled in an ARM board and then decode the signal. That was partially a success, but I only had a bunch of lines with the decoded signals and nothing to do with them. Of course the purpose was to publish to pskreporter.info and "upgrade" my double quad band CW-skimmer.

    A few years have passed since then, FT8 is here, JT65 is dead, and there are only a few CW spots there. So most of the traffic and propagation indications come from FT8. I've been running multiple instances of WSJT-X software with 2 USRP1 SDR's connected via USB to a single host for more than 2 years now, but then came the Red Pitaya...

    I was always wondering why we have to convert IQ data to audio and then feed the FT8 decoder with an audio file, since the it's more straight forward and needs fewer conversions, and of course a more effective way!
    But, WSJT-X only supported decoding wav files and there was no other similar software to implement an FT8 decoder.

    Of course having read more than 100 comments on the wonderful Red Pitaya github post I knew that there was hope. The main reason a whole year passed since I first read it and the day I finally made it, is that I had not understand that c2 files were just a 32bit floating point complex signal.
    The first and only issue of Red Pitaya FT8 decoder on github was answering that question. Then it was a mater of time to construct the csdr command sequence and make a C2 file!!

    For start we get IQ data from USB and stream them to a UDP port in order to be accessible from many hosts and many apps.
    The easiest way to do that is follow the openwebrx way and run something like the "rx_samples_to_file" command and pipe output to ncat. Another solution would be to run OpenwebRx itself that provides the data. In the USRP1 case the start command would be:

    start_rtl_command="/usr/lib/uhd/examples/rx_samples_to_file --file /dev/stdout --rate  {samp_rate} --freq {center_freq} --gain  {rf_gain} --wirefmt sc16 --bw 1000000 --type short".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate)

    In my case sampling rate was 1MS/s and frequency was 14.074MHz on 20M band, so I had to do some downsampling later on.

    The first part of the receiver command is to get samples from UDP port.
    We do that using nc

    nc -v 127.0.0.1 4951 

    Then we convert sc16 format that USRP outputs to 32bit floating point format using csdr:

    csdr convert_i16_f

    then of course we have to downsample, or decimate. Since the input of the decoder has to be 4000 samples/s we have to decimate by 250 times:

    csdr fir_decimate_cc 250 0.00166665 HAMMING

    Now we use the bandpass_fir_fft command to get the Upper sideband of SSB and do some filtering:

    csdr bandpass_fir_fft_cc 0 0.8 0.05 
    *actually bandpass filtering is not required because ft8 decoder needs as input complex signals

    combining them all together results in the following command:

    nc -v 127.0.0.1 4951 | csdr convert_i16_f |csdr fir_decimate_cc 250 0.00166665 HAMMING | csdr bandpass_fir_fft_cc 0 0.8 0.05 >  FT8.c2

    And the result: 

    Don't be biased by the small amount of decodes, the SDR actually runs without any pre-amplification on a hardware modified LFRX card with just a wire antenna.

    Now the only thing that has to be done is run the scripts provided by Red Pitaya team, and you can report FT8 to pskreporter site using any SDR that can output raw I/Q data!

    next target is to do multi channel (band) decoding using a single USRP.