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.