Decoding packets from GOMX-3: modulation and coding

Recently, Mike DK3WN pointed me to some decoder software for the satellite GOMX-3. This satellite is a 3U cubesat from GomSpace and transmits in the 70cm Amateur band. It has an ADS-B receiver on board, as well as an L-band SDR. As far as I know, no Amateur has decoded packets from this satellite previously, and Mike had some problems running the decoder software. I have taken a look at the software and tried my best to decode some packets from GOMX-3. So far, I have been able to do Reed-Solomon decoding and get CSP packets. However, I don’t have the precise details for the beacon format yet. Here, I describe all of my findings.

In my system, the GNUradio decoder from GomSpace builds and runs without problems. The only special thing I see about this OOT-module is that it uses ZeroMQ. I don’t know if GNUradio comes with ZeroMQ support built by default. In Gentoo, this is just a USE option. Presumably, the dependency on ZeroMQ could easily be removed from the decoder, because it is only used to pass the packets to some telemetry decoding software that I’ve been unable to find.

The data I’ve been using for my experiments is an IQ recording that I made during this month’s V-UHF contest. The antenna I used was just a 50cm whip on top of my car. Despite this, some packets are up to 14dB over the noise floor and I get several decodes with 0 byte errors.

The modulation used by GOMX-3 is GFSK at 19200 baud. It seems that it has used lower baudrates in the past, but now it is running at 19k2. The satellite transmits CSP packets. These are Reed-Solomon encoded. The Reed-Solomon code used is the recommended by the CCSDS in their TM Synchronization and Channel Coding book. In fact, GomSpace’s decoder uses the implementation by Phil KA9Q of CCSDS Reed-Solomon.

On top of the Reed-Solomon coding, a scrambler is used. After reading the code a bit, it turns out that this scrambler is the very same one that is used in G3RUH 9k6 AX.25 packet radio (this is the standard for Amateur packet radio at 9600 baud). This is just a multiplicative scrambler with polynomial $$1 + x^{12} + x^{17}$$. Although the decoder from GomSpace has its own descrambler block, one can also use GNUradio’s Descrambler block with Mask=0x21 and Length=16 (more on this in a future post).

The interesting thing about GOMX-3 scrambling is that the preamble is not scrambled, in contrast to G3RUH 9k6 packet radio. In AX.25 packet radio, the preamble is a sequence of HDLC flag bytes (the bits 01111110). In G3RUH 9k6 these bytes are scrambled, so at first sight they just look random. However, GOMX-3 transmits a sequence of the bits 01 which is not scrambled. After that, the scrambled syncword begins. You can see this perfectly in the picture below, which shows the baseband (FM demodulated) data. It is also possible to see this effect in the waterfall picture on top of this post. Since the preamble is periodic, it essentially generates just 3 frequencies when it is FM modulated. Thus, the preamble looks different from the scrambled data, which appears as a block of white noise. In contrast, G3RUH 9k6 packets just look like a block of noise. Not scrambling the preamble is probably a good idea, as it may help to do clock recovery, because the start of the packet is a very simple signal.

It is important to note that, even though the transmission changes from unscrambled to scrambled at the start of the syncword, no special measures should be taken while descrambling. Applying the descrambler to the whole stream of bits will transform the preamble into garbage, but it will descramble correctly the syncword and data. This is because the switch from unscrambled transmission to scrambled transmission is entirely handled by the transmitter (this can be accomplished, for instance, by loading the correct seed in the LFSR when scrambling starts).

Another difference between G3RUH 9k6 packets and GOMX-3 packets is that G3RUH uses NRZI coding, while GOMX-3 uses plain NRZ coding (a 1 is transmitted as a positive frequency shift and a 0 is transmitted as a negative frequency shift). Thus, it is important to preserve the polarity of the baseband FM-demodulated signal. For some reason, Linrad inverts the polarity, so I have to compensate for this by inverting the signal again in GNUradio.

The syncword used is 0x930B51DE (in big-endian format). Keep in mind that it is sent scrambled, so it is impossible to see it just by looking at the figure above. The next byte after the syncword contains the length of the Reed-Solomon coded data plus 1 (to include this byte in the length count), as an 8-bit unsigned integer. The Reed-Solomon coded data comes after this length byte. I think this length byte is potentially a bad idea, since a bit error in this byte will most likely make the packet much harder to decode.

The data encoded with Reed-Solomon is organized as follows. The first byte is the total length of this data (also counting this byte). The next 4 bytes are the CSP header. For some strange reason, the CSP header is in big-endian format (it should be little-endian). The decoder from GomSpace takes care of this by swapping the bytes around. The remaining bytes are the palyoad of the CSP packet.

The code I’m using can be found in my fork of gr-ax100. In the next post, I’ll talk about the contents of the CSP packets. For now, I’m just leaving you a very small packet from GOMX-3. Next time, I’ll tell you what this packet is.

------------ FRAME INFO -------------
Length: 29
Bytes corrected: 0
Dest: 10

* MESSAGE DEBUG PRINT PDU VERBOSE *
()
pdu_length = 28
contents =
0000: 01 01 af 8a 00 01 02 03 04 05 06 07 08 09 0a 0b
0010: 0c 0d 0e 0f 10 11 12 13 cc 79 eb e6
***********************************