K2SAT is a cubesat developed by the Aeroespace Systems and Control Lab in KAIST, a university in Daejeon, South Korea. It will be launched later this year, between September and October. The main mission of the satellite is to test the transmission of images taken with its onboard camera using an S-band QPSK transmitter that supports up to 2Mbps data rate. This will use the 2.4GHz Amateur satellite band, and the satellite has already coordinated a downlink frequency of 2404MHz. The K2SAT team at KAIST is the same one that built the QB50 KR01 (LINK) cubesat.
Since February, I have been collaborating with Pilwon Kwak and the rest of the K2SAT team to produce a GNU Radio receiver for the S-band image downlink and add it to my gr-satellites project. This receiver has now been publicly released. Here I explain the main details of the transmitter and protocol used by K2SAT and the implementation of the receiver.
The transmitter used by K2SAT is the STX from Clyde Space. This is a 2.4GHz transmitter that transmits either QPSK or OQPSK at a bitrate of up to 2Mbps (symbol rate up to 1Msps). The coding of the user bitstream in the STX transmitter goes as follows.
The bitstream is first scrambled using the V.35 Intelsat scrambler. This scrambler is also known as the IESS-308 scrambler and I have already spoken about it in my Outernet reverse engineering posts. The implementation for the descrambler in the K2SAT receiver is thus taken directly from gr-outernet.
After scrambling, the data is sent to a differential encoder. The output of the differential encoder goes to a convolutional encoder with \(k=7\), \(r=1/2\), and CCSDS polynomials. The output of the
POLYB polynomial is encoded as the I of the QPSK symbol and the output of the
POLYA polynomial is encoded as the Q of the QPSK symbol. The QPSK symbol is then transmitted over the air using an optional \(\alpha = 0.35\) RRC filter. Viterbi decoding is done in GNU Radio using the FECAPI CC decoder blocks.
When receiving a QPSK constellation, we have a phase ambiguity which is an integer multiple of 90º. A 180º phase shift corresponds to an inversion of the signal (multiplication by -1). For an inverted input, the Viterbi decoder gives an inverted output, since the polynomials have an odd number of non-zero coefficients. This inverted output is then handled by the differential decoder, which gives the correct output. Thus, we only need to care about a phase shift of 90º. This is handled by running two branches of the receiver in parallel: one on the received constellation, another on the received constellation rotated 90º (or -90º). Only one of the branches will succeed.
The full GNU Radio decoder flowgraph can be seen in the image below (click on the image to view it in full size).
The 2Mbps data rate includes FEC, so the maximum user data rate is 1Mbps. The STX supports the full data rate of 2Mbps and also reduced data rates of 1Mbps, 500kbps and 250kbps.
Regarding framing, the STX doesn’t implement any particular form of framing, so it is up to the user to implement their own. When transmitting data, the STX has two transmission modes: the synchronization mode and the data mode. In synchronization mode the transmitter will send repeatedly the CCSDS 32bit syncword
0x1ACFFC1D. This can be used to achieve byte synchronization in the receiver. In the data mode, the transmitter will send and consume the user data available in the TX FIFO, or the dummy data byte
0x55 whenever the TX FIFO is empty. When changing from synchronization mode to data mode, the STX also transmits a
0x55 byte before starting to send data from the TX FIFO. The change from synchronization mode to data mode may happen after any byte in the 32bit syncword, not only after a complete repetition of the whole 32bit pattern.
Therefore, to transmit packetized data, the user should put the transceiver in synchronization mode and start filling the TX FIFO with the beginning of the packet. When the TX FIFO is full and some time has passed so that the syncword has been repeated enough, the user should switch the STX to data mode and keep feeding the TX FIFO with the packet data. When all the packet has been fed to the TX FIFO and the TX FIFO empties, the user can switch off the STX. Depending on how fast this is done, additional
0x55 bytes may be transmitted at the end of the packet.
The framing for K2SAT is based on the AX.25 Telemetry and Telecommand Transfer Frames Format document originally prepared by the Swiss Space Centre for SwissCube, which was then used for the QB50 project. An older (but still valid to understand K2SAT framing) version of this document may be found here.
The Telemetry and Telecommand Transfer Frame format uses AX.25 UI (unnumbered) frames and includes a secondary header to provide additional functionality. The figure below shows the usual AX.25 packet, which is fully described in the AX.25 2.2 spec.
The secondary header and the payload are stored inside the information field, formatted as shown in the figure below.
The current version number is
00. The virtual channel ID enables up to 8 simultaneous channels. The master frame counter and virtual channel frame counter are counters which count the number of packets sent (modulo 256) for this physical channel and for this virtual channel. They are used to detect packet loss. The first header pointer is used to handle fragmentation inside the data field (see the document for more details). The time flag indicates whether the optional time field is present (and its size). The TC count indicates the number of telecommands received, and is used to detect packet loss in the uplink.
Note that the secondary header losely resembles the CCSDS TM Space Data Link Protocol.
K2SAT uses the Telemetry and Telecommand Transfer Frame Format as indicated in the figure below.
The JPEG image is fragmented in chunks of up to 2023 bytes and transmitted in the data field. The first header pointer field is repurposed as follows:
0x00 indicates that this is the first chunk of the image;
0xFF indicates that this is the last chunk of the image; and
0xEE indicates any other situation (a chunk which is neither the first nor the last). The optional time field is not sent by K2SAT.
K2SAT has a few deviations from the AX.25 standard that it is worth mentioning. The first is that NRZI or bit stuffing is not used. This makes the detection of packet boundaries a bit difficult. In standard AX.25, bit stuffing ensures that the
0x7e HDLC flag cannot happen inside the packet. In the case of K2SAT nothing prevents the byte
0x7e from appearing inside the packet data.
Second, the CRC16 that is used is not the same as in standard AX.25. Using the notation from this website, standard AX.25 uses CRC16_X_25, while K2SAT uses CRC16_CCIT_FALSE. The difference is that in AX.25 the input and output are reflected and the output is XORed against
0xFFFF, while K2SAT doesn’t do this. Another difference is that in standard AX.25 the CRC covers the whole AX.25 packet, starting by the beginning of the destination address and ending with the last bit of the information field. In K2SAT the CRC also covers the initial
0x7e flag that comes before the destination address.
The framing used by K2SAT relates to the STX synchronization system as follows. A JPEG image is sent using several AX.25 frames without stopping the transmitter. At the beginning of the transmission, the STX is in synchronization mode so the repeating sync vector is sent. At some point, the transmitter is changed to data mode, so a
0x55 byte is sent. This byte is immediately followed by the
0x7e flag marking the packet start and then the first frame of the image is transmitted. After the final
0x7e flag of this packet, the STX continues in data mode. Therefore, several
0x55 bytes are sent until the next packet starts, first sending its
0x7e flag. This process continues until the last packet of the image is sent. After that, more
0x55 bytes are sent and then the transmitter turns off.
Knowledge of this interaction between the K2SAT framing and the STX enables us to detect packet boundaries more reliable (without this knowledge it would be rather difficult or inefficient). The K2SAT deframer in the GNU Radio receiver uses
0x557e to detect the beginning of the packet, using my “Sync and create packed PDU” block. When the sequence
0x557e is found, the 2200 bytes following this sequence are extracted into a PDU. This ensures that the full packet fits into the PDU.
The end of the packet is detected in the following manner. The PDU is scanned for the sequence
0x7e555555. When this sequence is found, it is assumed to mark the packet end and the CRC is checked. If the CRC check is successful, then the packet is passed along to the image re-assembler. If the CRC check is not successful, it is assumed that this is not the packet end and the PDU is scanned further in case another
0x7e555555 appears later. This packet boundary detection scheme is very reliable and more or less efficient.
The image re-assembler receives the PDUs and assembles the chunks to form the JPEG file. Packet lost is detected by looking at the virtual channel counter. In case a packet is lost, the reception of the image fails, since in general this is not a recoverable error because the size of the lost chunk is not known (in practise, K2SAT always uses the maximum chunk size except for the last chunk). The GNU Radio receiver uses feh to show the image in real time as it is being received. This is something I have already done for other image receivers such as those for BY70-1, D-SAT and 1KUNS-PF.
The image receiver for K2SAT is included as
k2sat_image.grc in the
apps/ folder of gr-satellites. To run, it needs the following example IQ file (206MB), which is a recording of the engineering model transmitter done by the K2SAT team. This file is a 2Msps IQ file containing a JPEG image transmitted at 500kbaud (250kbps taking FEC into account). The image can be seen in the figure below.
Its resolution is 2048×1536 and its size is 178024 bytes, so it should take 5.7 seconds to transmit without taking packet overhead into account. The QPSK transmission takes a total of 7 seconds.
It will be quite interesting to try to receive K2SAT when it gets launched. As far as I know, this is the first Amateur satellite that has a fast data mode (where fast means anything higher than 50kbaud) with a publicly available decoder. Other Amateur satellites have used fast transmitters in the S-band, but only their team had access the decoder.