CW decoder in gr-satnogs 1.3.0

With the upgrade to gr-satnogs version 1.3.0 we can now decode Morse in CW signals. Unfortunately, the current decoder has a few problems.

  • A fixed decimation factor of 5 is used for the Xlating FIR filter. Given that different SDRs sample at different sample rates, this factor should be something like int(samp_rate_rx/100e3) to get 100kHz output
  • @DL4PD noted that the coarse Doppler correction happens at a too slow rate
  • The new flowchart no longer mixes the audio signal to a 1kHz offset from the Doppler corrected value, hence the Morse code is near 0Hz in the ogg files and barely audible
  • The absence of an AGC before the CW to symbols block means that decoding only works if the signal levels happen to be right for the threshold

@DL4PD and I run an adapted flowchart that fixes the first three problems. We’re planning a merge request. Any suggestions to fix problem 4, or other issues with the flowchart would be appreciated.


I have made a merge request marked as WIP (work in progress). You can find it here:

Any help is really appreciated!

1 Like

I am trying to reduce the resampling ovehead… Hope in a couple of hours to be ready!


Can someone test in order to proceed with the merging?

1 Like

I’ll do immediately when I’m back home from work tomorrow morning!


I would like to help you test the cw decoder.
Can someone help me to implement the git request locally?
I cloned gr-satnogs but I don’t know, how to get the changes.

I’m trying to understand git, but it’s not that simple. :slight_smile:

Hi Alex,

I can try to give you some hints, but I am also just a beginner in git.
If you have the current release of satnogs-client and gr-satnogs running, the easiest way would be to simply replace the decoder script in /usr/bin after you built it on your own. You could also run a complete gr-satnogs git build, but that takes some more steps. I am using the replace method for my #37 station in prod to get the current results.

I assume you have the current release running on a remote accessible RasPi, cloned the gr-satnogs repository from librespace to your PC and you have installed that in your environment. You have a working GNURADIO installation.

“cd” into your gr-satnogs directory and do a:

$ git status

Current branch should then be “master”.
Add a remote repository with the name “surligas”:

$ git remote add surligas

Now you have to pull the work of surligas into your local repository:

$ git pull surligas

You will receive all the branches @surligas is working on.
Now checkout the “fix-cw-decoder” branch:

$ git checkout surligas/fix-cw-decoder

Compile the flowgraph:

$ cd apps/flowgraphs
$ grcc cw_decoder.grc -d .

Read carefully: there’s a dot (".") at the end!
Now how to get that newly compiled decoder script on your Pi?

$ scp <piuser@yourrasppi_ip>:/home/<pi_user>/

SSH login to your RasPi and copy the from the user’s home-directory into the installation directory of gr-satnogs:

$ sudo cp /usr/bin/ ./ # <- backup before overwriting!
$ sudo cp /usr/bin/

You should be advised this is not the usual way to try out softwarechanges, but it is the easiest to do for a single script. If you re-install gr-satnogs all changes will be lost.

If you have any questions: feel free to ask.

If someone finds any errors: pse jump in :wink:


Many thanks for updating the flowchart. I ran it on a test observation (explained below), and it seems to work pretty well. The audio sounds a lot better, and the CW decoding works reasonably well. As far as I’m concerned it can be merged and put into operation. Here’s a test observation on simulated data. Check the audio signal and the decoded data packets. The encoded string consists of 20 repetitions of the quick brown fox jumps over the lazy dog 0123456789 of which the decoder decoded quite a few.

I think there may be scope for the development of software to simulate IQ data with modulated signals to test the SatNOGS flowcharts. For the CW decoder I wrote some python code to generate exactly this, and use it as input for @surligas’ CW decoder. It simulates Morse code on a CW signal whose frequency is affected by the Doppler effect, and whose strength changes with the range between the satellite and the station. The output is IQ data that can be fed into the decoder. I’ve not found out a way to fake the rigctl commands as input for the coarse Doppler correction, so instead I’ve fed the IQ data with the CW at 300Hz directly into the Polyphase Arbitrary Resampler. Hence, this simulation does not really test the refresh rate of the Doppler correction.

My plan is to try to adapt some of the simulation functions (Doppler frequency and signal strength) such that they can be used as input to GRC flowcharts and that the majority of the simulation can be done in GRC itself with functions that exist there (generation of noise, use of already existing BPSK, FSK, GMSK modulators).

I’d be interested what people think of this.

1 Like

@cgbsat that’s great!

FYI I have already a CW generator integrated in the gr-satnogs. You have to enable the debug blocks during the cmake in order to be part of the installation.

So I would suggest to proceed with the merging and then fine tune the AGC for better decoding.

I just set up fix-cw-decoder on my station and have not had the same good luck as @cgbsat

compare mine:

to his:


That true Corey,

the CW decoder prior converting the signal to audio has a low pass filter with a passband of ±2KHz. From the waterfall I can see that the CW tone is at the limit.

I didn’t have such good luck, too!
Really good observations with even better audio didn’t decode even a dit.

I think there’s a bit more work to do.

I think some of the CW beacon frequencies just need fine-tuning…

1 Like

This is also possible - there are some “baudrates” missing in db, too.

If you watch the XW-2* observations on my #37 station you can see what I mean with “good observations” :wink:

I know the decoder I use for manual decoding has a feature to automatically use the “loudest” peak to center on. And as the peak moves it follows.

Could try to implement something like that.

Can you provide the links of these observations? Is the signal inside the pass-band of the filter?

In general, some IQ captures by enabling the corresponding argument on the flowgraph would be very helpful.

1 Like

It is a bit difficult on my Smartphone, but here’s a start:

I will provide an IQ recording as soon as possible tomorrow morning!

Great to see some progress on decoders :slight_smile:

Hi Corey,

I’m pretty sure I was running a @dl4pd CW flowchart, not yet the one by @surligas. Unfortunately I can’t find the GRC file for that flow chart, but it must be the one that @dl4pd’s MR

1 Like

First one here:

I have to manually copy the files from out of the /tmp folder because I am not running a post-observation script. If someone has sth to automate this:pse meep me :wink:


Another one:

1 Like


Thank you very much for the detailed description!
This is exactly, what I need to know and to continue.


1 Like