In my previous post I talked about the FEC used by the SMOG-P and ATL-1. In there, I reverse-engineered the long frames transmitted by SMOG-P and found that they use the AO-40 FEC protocol.
After publishing that post I started reverse-engineering the short frames. Meanwhile, Peter Horvathpointed me to a Github repository containing an implementation of the FEC used for short frames and long frames. I hadn’t seen that repository before (it’s not easy to search for SMOG-P or ATL-1 in Google, as many unrelated results come up). Indeed this repository contains the source of a FEC decoder for the short frames, so there is no need to reverse-engineer it.
Timur Kristóf, the author of that repository, says that the team plans to release the source for the decoder, but that they are currently very busy with the early operations of the satellites. This is very good news.
I have studied the code in the Github repository and included a decoder for the short FEC frames in gr-satellites.
They transmit in the 70cm Amateur satellite band, and although they have beeen successfully coordinated with IARU (see here and here), documentation about the protocols they use has not been published. There is some groundstation software available here, but the interesting part is implemented in the atlgnd_x86_64 and smogpgnd_x86_64 binary executables, for which source code is not available. As far as I know both satellites transmit using the same (or very similar) protocols.
In this post I describe my first attempts at reverse-engineering the transmissions of SMOG-P, with successful results. Preliminary support for decoding SMOG-P and ATL-1 has been added to gr-satellites in the maint-3.8 branch.
The AO-40 FEC protocol used a concatenated code with a (160, 128) Reed-Solomon code and an r=1/2, k=7 convolutional code, together with scrambling and interleaving to achieve very good performance. The same protocol has then been used in the FUNcube satellites, so I have an AO-40 FEC decoder in gr-satellites since I added support for AO-73.
It is quite easy to notice that the QO-100 beacon transmits both uncoded and FEC messages. Indeed, using my gr-satellites decoder, I see that an uncoded message is transmitted every 23 seconds approximately. Since an uncoded message comprises 514 bytes, it takes 10.28 seconds to transmit it at 400baud, so something else must be sent between uncoded messages.
A FEC message is formed by 5200 symbols (after applying FEC), so it takes 13 seconds to transmit at 400baud. This gives us the total 23.28 seconds that I had observed between uncoded messages. Note that the contents of the uncoded and FEC blocks are different. An uncoded block contains 8 lines of 64 characters plus 2 bytes of CRC. A FEC block only contains 4 lines of 64 characters, and no CRC.
I have added a FEC decoder to the QO-100 decoder in gr-satellites, so that it now decodes both FEC and uncoded messages.
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.
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.