More than a year ago, I spoke about my efforts to decode ÑuSat-1 and -2. I got as far as reverse-engineering the syncword and packet length, and I conjectured that the last 4 bytes of the packet were a CRC, but without the scrambler algorithm I couldn’t do much. Recently I’ve been exchanging some emails with Gerardo Richarte from Satellogic, which is the company behind the ÑuSat satellites. He has been able to provide me the details of the protocol that I wasn’t able to reverse engineer. The result of this exchange is that a complete decoder for ÑuSat-1 and -2 is now included in gr-satellites, together with an example recording. The beacon format is still unknown, but there is some ASCII data in the beacon. Here I summarise the technical details of the protocol used by ÑuSat. Thanks to Gerardo for his help and to Mike DK3WN for insisting into getting this job eventually done.

The first thing to admit is that I got the syncword wrong: I thought that the syncword was `0x00F2D566`

, but the correct syncword is `0x01E5AACC`

. Note that the correct syncword is just `0x00F2D566`

shifted to the left by one bit. The reason for this error is that when the preamble is an alternating sequence of 0’s and 1’s, it is difficult to guess if the preamble ends as …0101 or as …1010. An error in this guess will shift the reverse-engineered syncword by one bit. Of course, after guessing the syncword incorrectly, all my packets were shifted one bit. It took us several days to realise this.

ÑuSat packets are 64 bytes long, as I correctly guessed, and they are scrambled. However, a (64, 60) Reed-Solomon code is applied after scrambling, so the first step in the decoding process is to decode the Reed-Solomon code. The RS code used by ÑuSat is compatible with the implementation in the rscode library, so I have just included the relevant files from this library into gr-satellites. Note that the 4 last bytes of the packet are not a CRC, as I expected, but rather the Reed-Solomon check bytes.

After doing Reed-Solomon decoding and stripping these 4 last bytes, we are left with a 60 byte packet. The first two bytes are a header, and the remaining 58 bytes are the beacon. The first byte of the header is the length of the beacon, so its content is always 58. The second byte of the header is a CRC-8 of the 58 bytes comprising the beacon. However, the beacon is scrambled, so it must be descrambled before checking the CRC-8. Note that 2 byte header is not scrambled.

The scrambler is just an additive scrambler with the following sequence:

0x1D, 0x8B, 0x06, 0x0C, 0x54, 0xDF, 0x21, 0xCB, 0x5C, 0x74, 0xE3, 0x15, 0x68, 0x04, 0x41, 0x91, 0x7A, 0x3D, 0x7A, 0x81, 0x30, 0x57, 0x1A, 0x0A, 0x09, 0xDB, 0x33, 0x57, 0x1F, 0x86, 0xEF, 0x58, 0xE0, 0x16, 0xBD, 0x9B, 0xA6, 0x42, 0xFB, 0x09, 0xD6, 0xCB, 0xE1, 0x27, 0x8E, 0xE7, 0x95, 0x1B, 0x46, 0x4C, 0xEE, 0xC3, 0x75, 0x7D, 0xA6, 0x1C, 0xF2, 0x45, 0x01, 0x00, 0xFE, 0xAF, 0xFD, 0x03

Of course, only the first 58 bytes of this sequence are used. I think that this sequence comes from an LFSR. I don’t know the polynomial for this LFSR, but I think that obtaining the polynomial from the LFSR output sequence is a treatable mathematical problem.

After descrambling the beacon by doing an XOR with the sequence above, we do the CRC-8 check. The CRC-8 code used is the standard CRC-8 code in this online CRC calculator (polynomial 0x7, initial and final value 0x0, no inversions).

The hexdump of the KISS file containing the beacons decoded from the ÑuSat-2 sample recording included in satellite-recordings is in this gist.

As a bonus, it turns out that the (64, 48) Reed-Solomon code used in the TT-64 protocol, which is employed by the QB50 cubesat AT03 Pegasus, is also compatible with the rscode library. I have included a general Reed-Solomon decoder block using rscode in gr-satellites, and this is now used in the at03 decoder, which now is a complete FEC decoder with Reed-Solomon decoding and CRC checking.

… finally 🙂 Great thanks to you and Gera for this work. Never give up 😉

73 Mike