The family of BEESAT satellites from the TU Berlin transmit telemetry on the Amateur bands using the Mobitex-NX protocol. Some of the BEESAT satellites also include a digipeater using this same protocol. There is a GNUradio implementation from TU Berlin of a software TNC for these satellites. This software has some shortcomings (for instance, FEC decoding wasn’t working properly). I’ve made my own fork where I’ve fixed some of the problems. Here I’ll talk about various aspects of the Mobitex-NX protocol and the GNUradio implementation.
The details about how the Mobitex protocol works can be read in the MX909A datasheet. Many thanks to Andy UZ7HO for pointing me to this document. The only difference between the standard Mobitex protocol and the Mobitex-NX protocol is that a callsign is included after the frame header and before the data blocks. The callsign is transmited as 6 bytes in ASCII followed by a 2 byte CRC-16CCITT (this is the same CRC that is used in AX.25). Therefore, the contents of a Mobitex-NX frame are as follows:
- Bit sync. The pattern
0xccrepeated several times.
- Frame sync:
- Control. 2 bytes (see below for the contents)
- FEC of control (1 byte, containing 4 parity bits for each control byte)
- Callsign. 6 bytes in ASCII
- CRC-16CCITT of Callsign. 2 bytes
- Several data blocks. Each data block is 20 bytes long
The contents of the control bytes are:
- 1st byte, bits 0 through 4. Number of data blocks minus one. The number of data blocks in the frame is one plus the value of this field, so any number of blocks between 1 and 32 is possible. This field can also mean “number of errors”, but I’m not sure about when and how this is used (perhaps in an ACK message to indicate how many blocks where received erroneously).
- 1st byte, bits 5 through 7. Message type. See below.
- 2nd byte, bit 0. Baud bit. If this bit is set, the packet is transmitted in double baudrate (9600bps) mode. The beginning of the packet is always transmitted at 4800bps. A double baudrate packets uses some more fields to accommodate for the baudrate change. This won’t be described in this post.
- 2nd byte, bit 1. ACK bit. If this bit is set, the packet is requesting an ACK.
- 2nd byte, bits 2 and 3. Sub-address. The sub-address of the ground station is 0 and the broadcast sub-address is 3.
- 2nd byte, bits 4 through 7. Address. The address of the ground station is 0 and the broadcast address is 0xf.
The telemetry messages of BEESAT-4 are addressed to the ground station (both in the address and sub-address fields).
The message types and corresponding values of the message type field are:
- 0. ACK
- 1. REG. This is a regular packet, and it is how telemetry is transmitted.
- 2. DIGI. Probably a digipeated packet. I still have to check how this is used.
- 3. ECHO. Presumably a ping packet.
- 4. BAUD. Something related to baudrate change perhaps?
The FEC used is a (12,8,3) linear code. This means that 4 parity bits are added to each byte and that the FEC decoder is able to correct up to one bit error in each of the resulting 12 bit blocks (and detect up to 2 errors). Each data block is made up of 18 data bytes (each one augmented with its 4 parity bits). The CRC-16CCITT of these 18 data bytes (not including the FEC parity bits) is also included in the data block, together with its corresponding two 4-bit parity fields. The whole data block is scrambled and interleaved. Upon reception, after descrambling and deinterleaving, each of the bytes in the block (including the 2 CRC bytes) is checked for errors using the corresponding 4 parity bits, and errors are corrected when possible. After this is done, the CRC of the block is checked, and the block is deemed invalid if it fails. This is different from many other protocols in which a whole packet is either good or not. Here a packet can have several invalid blocks while the rest of the packet is good.
An “errorcode” is used to indicate which blocks are invalid. This is a 32-bit bit-field that indicates which blocks are invalid. The bits that are set indicate an invalid block. The errorcode is in little-endian format, so the bit number 0 of the fist byte of the error code corresponds to the first data block and so on.
The “NX Decoder” block in the GNUradio implementation appends the following 6 bytes to the packet
0xaa E1 E2 E3 E4 0xbb. The bytes E1, E2, E3, E4 are the 4 errorcode bytes. The bytes
0xbb are placeholders for some values that are supposed to be reported by the receiver. The first of these bytes is referred to in the TU Berlin code as “TEMP” (temperature, perhaps?) and the second of these bytes is the signal quality. These are not used in the current version of the software.
The “TNC NX” block in the GNUradio implementation also prepends an 8 byte header to the packet. The fields of this header are not very useful and some of them are not even populated (NORAD ID, for instance). It seems to be a header for some internal ground station control protocol that they use in TU Berlin. You can see more details about this header in gscf_com.cc
Something about the Mobitex-NX protocol that I don’t like is the way that the callsign is transmitted. The rest of the frame uses a (12,8,3) linear code that works quite well and manages to correct many errors. However, the callsign doesn’t use any FEC and is only protected by a CRC-16CCITT. The CRC is just used to check if the callsign is correct, but not to correct for errors. This has the effect that most of the time the callsign has some bit errors and it doesn’t pass the CRC check. This is only slightly annoying, because the callsign is not used for anything other than documentation. The receiver will print an error message if the callsign CRC doesn’t match, but it will process the packet anyway.
Using a CRC-16 just for 6 bytes of data is a bit ridiculous. It would have been much better to use the same linear code that the rest of the message, including 3 bytes of parity instead of 2 bytes of CRC-16. In any case, this is how things are done in the protocol and the receiver has no control about it.
Nevertheless, the CRC-16 can be used as a linear (affine, technically) error correcting code. Formally it is such a thing, although it is rarely used in that manner. A CRC-16 applied to 6 bytes of data makes a (64, 48, 4) affine code, since according to this listing the minimum Hamming distance of the code is 4. This means that a single bit error can be corrected reliably. Also, if we try to correct double bit errors we can do so correctly most of the time. This is sometimes done for AX.25 packets, which are much longer than 6 bytes. Thus, in my fork of the GNUradio code I have included an algorithm that tries to corrects single and double bit errors by flipping bits until the CRC matches. This will correct all the single bit errors and most of the double bit errors. The improvement obtained by using this error correction scheme is very noticeable.