Decoding AO-40 uncoded telemetry

AO-40 is an Amateur satellite that was active between 2000 and 2004. It had several transponders and beacons covering many bands from HF to microwave and its position on a HEO orbit provided several consecutive hours of coverage each day and allowed long distance contacts. Since then, many interesting things have happened with Amateur satellites, particularly the high increase of the number of cubesats that is happening over the last few years, but even so, we haven’t seen again any other satellite with the characteristics of AO-40 nor it is to be expected in the near future.

I was quite young when AO-40 was operational, so for me this is all history. However, Pieter N4IP has posted recently on Twitter some IQ recordings of AO-40 that he made back in 2003. I have been playing with these recordings to see how AO-40 was like. One of the things I’ve dong is to write my own telemetry decoder using GNU Radio.

AO-40 transmitted telemetry using 400bps BPSK. There were two modes: an uncoded mode which used no forward error correction and an experimental FEC mode proposed by Phil Karn KA9Q. The FEC mode was used later in the FUNcube satellites, and I’ve already talked about it in a previous post. The beacon in Pieter’s recordings is in uncoded mode. Here I describe this mode in detail and how my decoder works. The decoder and a small sample taken from Pieter’s recordings have already been included in gr-satellites.

Low latency decoder for LilacSat-1

LilacSat-1 is one of the QB50 project cubesats. It will be released tomorrow from the ISS. The most interesting aspect of this satellite is that it has an Amateur Radio transponder with an FM uplink on the 2m band and a Codec2 1300bps digital voice downlink on the 70cm band. It is the first time that an Amateur satellite really uses digital voice, as previous tests have only used an analog FM repeater to relay D-STAR and similar digital voice modes. LilacSat-1 however implements a Codec2 encoder in software using its ARM processor. I have talked about LilacSat-1 Codec2 downlink already in this blog. Here I present a low latency decoder for the digital voice downlink that I have recently included in gr-satellites.

gr-satellites refactored

In August last year I started my gr-satellites project as a way to make my experiments in decoding Amateur Satellite telemetry easier to use for other people. Since then, gr-satellites has become a stable project which supports 17 satellites using several different protocols. However, as time has gone by, I have been adding functionality in new GNU Radio OOT modules. Eventually, the core of gr-satellites depended on 5 OOT modules and another 7 OOT modules were used for each of the satellite families. This makes gr-satellites cumbersome to install from scratch and it also makes it difficult to track when each of the OOT modules is updated.

I have now refactored gr-satellites and included most of the OOT modules into gr-satellites, so that it is much easier to install and update. The only OOT modules I have kept separate are the following:

  • gr-aausat, because it doesn’t use libfec for FEC decoding, and includes its own implementation of a Viterbi and RS decoder. Eventually I would like to modify gr-aausat to make it use libfec and include it into gr-satellites.
  • beesat-sdr, because it is actively developed by TU Berlin and I have collaborated some code with them. Also, the implementation of the decoder is quite different from everything else in gr-satellites.
  • gr-lilacsat, because it is actively developed by Harbin Institute of Technology and I have collaborated some code with them. However, as I explained in a previous post, the FEC decoding for these satellites is now done very differently in gr-satellites in comparison to gr-lilacsat, as I have replaced many custom blocks by stock GNU Radio blocks. I will have to examine carefully how much code from gr-lilacsat is actually needed in gr-satellites.

The refactored version is already available in the Github repository for gr-satellites. Users updating from older versions should note that gr-satellites is now a complete GNU Radio OOT module instead of a collection of GRC flowgraphs, so it should be built and installed with cmake as usual (see the README). The GRC flowgraphs are in the apps/ folder.

The OOT modules that have been included into gr-satellites will be deprecated and no longer developed independently. I will leave their Github repositories up with a note pointing to gr-satellites.

This is not the end of the story. There are some more things I want to do with gr-satellites in the next few weeks:

  • Use cmake to build and install hierarchical flowgraphs, saving the user from this cumbersome step.
  • Use cmake to build the python scripts associated to the decoders.
  • Collect in a Git submodule the sample WAV files that are scattered across the different OOT modules. Add WAV samples for missing satellites. Use these WAVs to test decoders, perhaps even with some automation by a script.

And of course, there are many QB50 project satellites being launched starting next week. I’ll try to keep up and add decoders for them, especially for the ones using not so standard modes. I already have a working decoder for Duchifat-2, since I have been collaborating with their team at Herzliya Space Laboratory. I will also adapt the LilacSat-1 decoder from gr-lilacsat. This decoder has already been featured in this blog.

Calibrating the Hermes-Lite 2.0 beta2 in Linrad

Lately, I have been trying to make an amplitude and phase calibration of my Hermes-Lite 2 beta2 in order to use Linrad’s smart noise blanker. This is quite a task because Linrad doesn’t support the Hermes-Lite 2 directly. Today I’ve finally managed to do it. Here I describe all my setup and calibration results.

Sending data from GNU Radio into Linrad using the network

During the last few days I’ve been experimenting with feeding signals from GNU Radio into Linrad using Linrad’s network protocol. Linrad has several network protocols designed to share data between different instances of Linrad, but generally these protocols are only supported by Linrad itself. The only other example I know of is MAP65, which can receive noise-blanked data from Linrad using the timf2 format.

The result of these experiments is a GNU Radio out-of-tree module called gr-linrad which allows to send data from GNU Radio and receive the data in Linrad. Currently, gr-linrad only supports sending a one-channel complex IQ signal using the raw 24 bit format, but I’ll probably add more options in the future. The intended application of gr-linrad is to easily add support for SDR hardware to Linrad. Usually GNU Radio has support for most SDR hardware in the market, perhaps through osmocom or other libraries. Linrad has support for a good amount of SDR hardware, but there are some notable exceptions of unsupported hardware, such as the HackRF One. I also want to use my Hermes-Lite 2.0 beta2 in Linrad, and this seems the easiest way to do it.

Another possible use of gr-linrad is as an instrumentation for any kind of GNU Radio flowgraph. It is very easy to stream data into Linrad, so it can be used as a very nice waterfall display or to do any sort of signal processing, such as noise blanking or adaptive polarization. Here I describe how to get the test flowgraph in gr-linrad working and some aspects of the network protocol.

GNU Radio decoder for AO-73

During the last few days, I have been talking with Edson PY2SDR about using GNU Radio to decode digital telemetry from AO-73 (FUNcube-1) and other FUNcube satellites. I hear that in Virginia Tech Groundstation they have a working GNU Radio decoder, but it seems they never published it.

The modulation that the FUNcube satellites use is DBPSK at 1200baud. The coding is based on a CCSDS concatenated code with a convolutional code and Reed-Solomon, but it makes extensive use of interleaving to combat the fading caused by the spin of the spacecraft. This system was originally designed by Phil Karn KA9Q for AO-40. Phil has a description of the AO-40 FEC system in his web and there is another nice description by James Miller G3RUH.

I took a glance at this documents and noted that it would be a nice and easy exercise to implement a decoder in GNU Radio, as I have most of the building blocks that are needed already working as part of gr-satellites. Today, I have implemented an out-of-tree module with a decoder for the AO-40 FEC in gr-ao40. There is another gr-ao40 project out there, but it seems incomplete. For instance, it doesn’t have any code to search for the syncword. I have also added decoders for AO-73 and UKube-1 to gr-satellites.

The signal processing in gr-ao40 is as described in the following diagram taken from G3RUH’s paper.

AO-40 FEC decoding (borrowed from G3RUH’s paper)

First, the distributed syncword is searched using a C++ custom block. It is possible to set a threshold in this block to account for several bit errors in the syncword. De-interleaving is done using another C++ custom block. For Viterbi decoding, I have used the “FEC Async Decoder” block from GNU Radio, since I like to use stock blocks when possible. Then, CCSDS descrambling is done with a hierarchical block from gr-satellites. Finally, the interleaved Reed-Solomon decoders are implemented in a C++ custom blocks that uses Phil Karn’s libfec.

The complete FEC decoder is implemented as a hierarchical block as show in the figure below.

GNU Radio AO-40 FEC decoder

Coding for HIT satellites (and other CCSDS satellites)

The Harbin Institute of Technology satellites LilacSat-2, BY70-1 and the upcoming LilacSat-1 all use a concatenated code with an \(r=1/2, k=7\) convolutional code and a (255,223) Reed-Solomon code according to the CCSDS TM Synchronization and Channel Coding blue book specifications. The GNU Radio decoder gr-lilacsat by Wei BG2BHC includes a custom implementation of the relevant part of the CCSDS stack, probably ported into GNU Radio from some other software.

Recently, I have been working on decoding KS-1Q and I’ve seen that it uses the same CCSDS coding as the HIT satellites. This has made me realise that most of this CCSDS coding can be processed using stock GNU Radio blocks, without the need for custom blocks. The only exception is Reed-Solomon decoding. This can be done easily with gr-libfec, which provides an easy interface from GNU Radio to Phil Karn’s libfec. Here I look at the details of the CCSDS coding and how to process it with GNU Radio. I’ve updated the decoders in gr-satellites to use this kind of processing. I’ll also talk about the small advantages of doing it in this way versus using the custom implementation in gr-lilacsat.

KS-1Q decoded

In a previous post, I talked about my attempts to decode KS-1Q. Lately, WarMonkey, who is part of the satellite team, has been giving me some extra information and finally I have been able to decode the packets from the satellite. The decoder is in gr-ks1q, together with a sample recording contributed by Scott K4KDR. I’ve also added support for KS-1Q in gr-satellites. Here I look at the coding of the packets in more detail.

Looking at BY70-1 image downlink

BY70-1 is a Chinese Amateur satellite that will launch on Monday 26 December. It has a V/U FM repeater, a camera and a 9k6 BPSK downlink on 70cm that transmits telemetry and the JPEG images taken by the camera. The BPSK downlink uses the same modulation and coding as LilacSat-2, of which I have spoken several times. Recently, Wei MingChuan BG2BHC has added support for the image downlink of BY70-1 to gr-lilacsat and a bit stream recording to test the image receiver.

Unfortunately, the image decoder is closed-source, as it contains some certification methods used to avoid fake packets over the internet. However, Wei gave me a brief description of how the image downlink protocol works. After seeing the closed-source decoder running, I had enough to figure out how the protocol works. I have implemented an open-source image decoder as a python GNU Radio block. It is in my gr-lilacsat fork, and it will soon be included in the upstream gr-lilacsat repository. Here I look at the protocol used for the image downlink.

Improving signal processing in my OTH radar receiver

This is a follow up post to my experiments studying OTH radar. I have found that the signal processing I did there to obtain the cross-correlation was far from optimal. This produced the strange side-bands below the main reflection. The keen reader might have noticed that I was doing the cross-correlation with a template pulse that lasted the whole pulse repetition cycle. However, the pulses from the radar are shorter. Therefore, it is a better idea to use a shorter template pulse. Ideally, the template pulse should have the same length as the transmitted pulse. However, I don’t know this length precisely, because multipath propagation makes the received pulses a bit longer. However, I think that 6.5ms is a good estimate.

I have also changed the window for the pulse. I’m now using a Dolph-Chebyshev window. I use scipy to compute this window, because it is not included in GNU Radio. This window has the property that the side-bands have constant attenuation. Indeed, it minimizes the \(L^\infty\) norm of the side-bands. There is a parameter that tunes the side-bands attenuation. For higher attenuations, you have a wider main lobe, while if you want a narrower main love you get less side-band attenuation. These properties make this window useful in radar applications.

Below I’m doing the cross-correlation in GNU Radio with a shorter template pulse shaped with a Dolph-Chebyshev window set for 55dB attenuation.

Cross-correlation with shorter pulse

The good thing about the settable attenuation of the Dolph-Chebyshev window is that it can be used to trade-off performance between different features. First, we use an attenuation of 100dB. The side-bands are below the noise floor in this case, so we have no “false responses” in our cross-correlation. The drawback is that the main lobe is wide so the resolution of the features of the ionosphere in the image below is not very good.

Dolph-Chebyshev window with 100dB attenuation

Next we try with 55dB attenuation. This narrows the main lobe, improving the resolution and crispness of the features of the ionosphere in the image below. However, side-bands start being visible above the noise floor, producing “false responses”. However, comparing with the image above, we now know where the false responses are.

Dolph-Chebyshev window with 55dB attenuation

I have updated the gist with the GNU Radio flowgraph and python script used to produce the images.