A year ago, I made a decoder for the AO-40 FEC. While AO-40 has been dead for many years, the same FEC system is used in AO-73 and the rest of the FUNcube satellites. This decoder was later included in gr-satellites and it is currently used in the decoders for AO-73, UKube-1 and Nayif-1.
When I implemented this FEC decoder, for simplicity I used a hard decision Viterbi decoder, since my main concern was to get all the system working. I always intended to replace this by a soft decision Viterbi decoder, but it seems that I forgot completely about it.
Now, while thinking about integrating gr-aausat (my AAUSAT-4 decoder OOT module) into gr-satellites and adding a soft Viterbi decoder for AAUSAT-4, I have remembered about this. While the decoder for AAUSAT-4 will have to wait, since I have found a bug in the GNU Radio Viterbi decoder that makes it segfault, I have already added a soft Viterbi AO-40 FEC decoder to the FUNcube decoders in gr-satellites.
Recall that the AO-40 FEC decoder works as described by the figure below.
My implementation of the hard decision decoder was as follows (click to view the figure in larger size):
Hard symbols come into the "Synchronize frame" block, that searches the distributed syncword and forms a PDU when it finds it. The PDU elements are also hard symbols. The "Deinterleaver" block implements a matrix deinterleaving with the hard symbols and then transforms them to soft symbols (just -1.0 and 1.0) before passing the PDU to the "FEC Async Decoder", since the Viterbi decoder always expects soft symbols.
With this in mind, doing soft Viterbi decoding is just a matter of sending soft symbols instead of hard symbols into the synchronizer, and also working with soft symbols in the deinterleaver. The new soft decoder is shown below.
The deinterleaver is the same as before, but working with floats instead of bytes. Since the synchronizer has access to soft symbols, it could use them to perform the correlation of the soft symbol stream against the syncword and detect the syncword by the correlation peak. However, I have decided to make it work as the previous version: it only looks at the sign of the soft symbols to detect the syncword. I don't think that this difference is very important, since the main task of the synchronizer is to avoid sending too much PDUs into the decoder by reducing the number of false positives.
Looking only at the sign of the soft symbols in the synchronizer makes it easier to choose the threshold, since it can be specified as the maximum number of bit errors to tolerate in the syncword.