Trying to make the DSLWP-B GMSK decoder more robust

If you’ve being following my latest posts, probably you’ve seen that I’m taking great care to decode as much as possible from the SSDV transmissions by DSLWP-B using the recordings made at the Dwingeloo radiotelescope. Since Dwingeloo sees a very high SNR, the reception should be error free, even without any bit error before Turbo decoding.

However, there are some occasional glitches that corrupt a packet, thus losing an SSDV frame. Some of these glitches have been attributed to a frequency jump in the DSLWP-B transmitter. This jump has to do with the onboard TCXO, which compensates frequency digitally, in discrete steps. When the frequency jump happens, the decoder’s PLL loses lock and this corrupts the packet that is being received (note that a carrier phase slip will render the packet undecodable unless it happens very near the end of the packet).

There are other glitches where the gr-dslwp decoder is at fault. The ones that I’ve identify deal in one way or another with the detection of the ASM (attached sync marker). Here I describe some of these problems and my proposed solutions.

Report for today’s DSLWP-B SSDV session

Today an SSDV transmission session from DSLWP-B was programmed between 7:00 and 9:00 UTC. The main receiving groundstation was the Dwingeloo radiotelescope. Cees Bassa retransmitted the reception progress live on Twitter. Since the start of the recording, it seemed that some of the SSDV packets were being lost. As Dwingeloo gets a very high SNR and essentially no bit errors, any lost packets indicate a problem either with the transmitter at DSLWP-B or with the receiving software at Dwingeloo.

My analysis of last week’s SSDV transmissions spotted some problems in the transmitter. Namely, some packets were being cut short. Therefore, I have been closely watching out the live reports from Cees Bassa and Wei Mingchuan BG2BHC and then spent most of the day analysing in detail the recordings done at Dwingeloo, which have been already published here. This is my report.

First SSDV transmission from DSLWP-B

As some of you may know, DSLWP-B, the Chinese lunar-orbiting Amateur satellite carries a camera which is able to take pictures of the Moon and stars. The pictures can be downlinked through the 70cm 250bps GMSK telemetry channel using the SSDV protocol. Since an r=1/2 turbo code is used, this gives a net rate of 125bps, without taking into account overhead due to headers. Thus, even small 640×480 images can take many minutes to transfer, but that is the price one must pay for sending pictures over a distance of 400000km.

On Saturday August 3, at 01:27 UTC, the first SSDV downlink in the history of DSLWP-B was attempted. According to Wei Mingchuan BG2BHC, the groundstation at Harbin managed to command the picture download at 436.400MHz a few minutes before the GMSK transmitter went off at 01:30 UTC. A few SSDV frames were received by the PI9CAM radiotelescope at Dwingeloo.

The partial image that was received was quickly shared on Twitter and on the DSLWP-B camera webpage. The PI9CAM team has now published the IQ recording of this event in their recording repository. Here I analyze that recording and perform my own decoding of the image.

Trying to decode EQUiSat

EQUiSat is a cubesat from Brown University that was launched to the ISS on May 21 with the Cygnus CRS-9 supply ship. It was released from the ISS on July 13. The payload of EQUiSat is rather interesting: an optical beacon, formed by an array of 4 high power LEDs designed to flash and be visible with the naked eye.

The EQUiSat radio system is also quite interesting and unusual. It uses the PacificCrest XDL Micro transmitter in 4FSK mode. This UHF transmitter is normally used to transmit data between survey GNSS receivers. Unfortunately, there is very little documentation about the radio protocol used by this transmitter.

I am in communication with the satellite team, since they are interested in producing a GNU Radio decoder. However, they don’t know much about the radio protocol either. Here is my first try at trying to decode transmissions from EQUiSat.

K2SAT S-band image receiver

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.

DSLWP-B GMSK detector

Following the success of my JT4G detector, which I used to detect very weak signals from DSWLP-B and was also tested by other people, I have made a similar detector for the 250baud GMSK telemetry transmissions.

The coding used by the DSLWP-B GMSK telemetry follows the CCSDS standards for turbo-encoded GMSK/OQPSK. The relevant documentation can be found in the TM Synchronization and Channel Coding and Radio Frequency and Modulation Systems–Part 1: Earth Stations and Spacecraft blue books.

The CCSDS standards specify that a 64bit ASM shall be attached to each \(r=1/2\) turbo codeword. The idea of this algorithm is to correlate against the ASM (adequately precoded and modulated in GMSK). The ASM spans 256ms and the correlation is done as a single coherent integration. As a rule of thumb, this should achieve a reliable detection of signals down to around 12dB C/N0, which is equivalent to -12dB Eb/N0 or -22dB SNR in 2500Hz. Note that the decoding threshold for the \(r=1/2\) turbo code is around 1.5dB Eb/N0, so it is much easier to detect the GMSK beacon using this algorithm than to decode it. The difficulty of GMSK detection is comparable to the difficulty of JT4G decoding, which has a decoding threshold of around -23dB SNR in 2500Hz.

Here I explain the details of this GMSK ASM detector. The Python script for the detector is dslwp_gmsk.py.

JT4G detection algorithm for DSLWP-B

Now that DSLWP-B has already been for 17 days in lunar orbit, there have been several tests of the 70cm Amateur Radio payload, using 250bps GMSK with an r=1/2 turbo code. Several stations have received and decoded these transmissions successfully, ranging from the 25m radiotelescope at PI9CAM in Dwingeloo, the Netherlands (see recordings here) and the old 12m Inmarsat C-band dish in Shahe, Beijing, to much more modest stations such as DK3WN‘s, with a 15.4dBic 20-element crossed yagi in RHCP. The notices for future tests are published in Wei Mingchuan BG2BHC’s twitter account.

As far as I know, there have been no tests using JT4G yet. According to the documentation of WSJT-X 1.9.0, JT4G can be decoded down to -17dB SNR measured in 2.5kHz bandwidth. However, if we don’t insist on decoding the data, but only detecting the signal, much weaker signals can be detected. The algorithm presented here achieves reliable detections down to about -25dB SNR, or 9dB C/N0.

This possibility is very interesting, because it enables very modest stations to detect signals from DSLWP-B. In comparison, the r=1/2 turbo code can achieve decodes down to 1dB Eb/N0, or 25dB C/N0. In theory, this makes detection of JT4G signals 16dB easier than decoding the GMSK telemetry. Thus, very small stations should be able to detect JT4G signals from DSLWP-B.

Flashing a Vaisala RS41 radiosonde

The Vaisala RS41 radiosonde is a weather radiosonde that is currently being launched in Madrid Barajas and other sounding sites in Spain, Europe and Australia. I have already spoken about how to decode it. One of the most interesting aspects of this model is that the RS41 contains a STM32F1 ARM Cortex-M3 microcontroller, a SiLabs FSK transmitter, and a uBlox GPS receiver, whereas the older RS92 contained custom ASICs to perform these functions. Thus, it is easy to reflash this radiosonde and write custom firmware for it, giving a lot of possibilities for experimentation.

In STARcon 2018, Julián Santamaría from AEMET (the Spanish meteorological office) gave me an RS41. While I have some long-term ideas about how to use it as a propagation sounder, I have just started playing with it. In this brief note, I explain how to flash the radiosonde with custom firmware.

1KUNS-PF image decoder

A week ago, Mike Rupprecht DK3WN told me that he had discovered JPEG images in the packets transmitted by 1KUNS-PF. I’ve had some time now to take a look at the information he sent me (including KISS dumps of the packets) and add an image decoder to gr-satellites.

JPEG images are not so difficult to spot amongst binary data, since they contain JFIF in ASCII in their header (4a 46 49 46 in hex). Another telltale sign of JPEG is the ff d8 ff that marks the start of the file. Presumably this is how Mike first noticed the images.

Mike has published some information about the image packets transmitted by 1KUNS-PF and he has been posting some of the images he receives.

Below there is the hex dump of the first and second packet CSP packet of a JPEG image (note the JFIF and ff d8 ff inside the packet payload).

pdu_length = 138
contents = 
0000: 00 e2 92 42 00 00 ff d8 ff e0 00 10 4a 46 49 46 
0010: 00 01 01 01 00 00 00 00 00 00 ff db 00 43 00 0c 
0020: 08 09 0b 09 08 0c 0b 0a 0b 0e 0d 0c 0e 12 1e 14
0030: 12 11 11 12 25 1a 1c 16 1e 2c 26 2e 2d 2b 26 2a
0040: 29 30 36 45 3b 30 33 41 34 29 2a 3c 52 3d 41 47
0050: 4a 4d 4e 4d 2f 3a 55 5b 54 4b 5a 45 4c 4d 4a ff
0060: db 00 43 01 0d 0e 0e 12 10 12 23 14 14 23 4a 32
0070: 2a 32 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a
0080: 4a 4a 4a 4a 4a 4a fa 14 dc 9e

pdu_length = 138
contents = 
0000: 00 e2 92 42 00 01 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 
0010: 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 
0020: 4a 4a 4a 4a ff c4 00 1f 00 00 01 05 01 01 01 01 
0030: 01 01 00 00 00 00 00 00 00 00 01 02 03 04 05 06 
0040: 07 08 09 0a 0b ff c4 00 b5 10 00 02 01 03 03 02 
0050: 04 03 05 05 04 04 00 00 01 7d 01 02 03 00 04 11 
0060: 05 12 21 31 41 06 13 51 61 07 22 71 14 32 81 91 
0070: a1 08 23 42 b1 c1 15 52 d1 f0 24 33 62 72 82 09 
0080: 0a 16 17 18 19 1a 95 64 b7 7e

It seems that all the image packets are 138 bytes long. The first four bytes are the CSP header. Then we have 16bit big-endian field which counts the number of chunk, starting by 00. The last four bytes of the packet are most likely a checksum, and the remaining bytes are the corresponding chunk of the JPEG file.

I don’t know how to detect the end of one image other than by taking note of the beginning of the next image. In fact, this is the last packet of this image:

pdu_length = 138
contents = 
0000: 00 e2 92 42 00 47 8a 00 5a 28 00 a2 81 05 14 00 
0010: 51 40 05 14 00 51 40 05 14 00 51 40 05 14 00 51 
0020: 40 c2 8a 00 28 a0 02 8a 00 28 a0 04 a2 80 0a 28 
0030: 18 51 40 05 14 00 51 40 05 14 00 51 40 05 14 c6 
0040: 14 50 01 45 00 14 50 01 45 00 14 50 01 45 00 14 
0050: 50 01 45 00 14 50 01 45 00 7f ff d9 00 00 00 00 
0060: 00 00 00 00 00 11 41 42 00 48 00 00 04 58 00 00 
0070: 00 10 00 00 00 51 d0 38 c9 54 05 ac 8f d7 00 00 
0080: bc 24 00 00 bc 24 dc bd 44 b0 

The ff d9 that occurs mid-packet is the end-of-file of the JPEG file. I don’t know what to make of the rest of the data following it. Since not all of it is zero, it doesn’t look as deliberate padding. It might be the case that the satellite is sending information left over in a buffer.

The image below is the whole JPEG file contained in the packets received by Mike. It was sent using 72 chunks, for a total of 9216 bytes (at 128 bytes per chunk) and its resolution is 640×480. Most of the other images sent by 1KUNS-PF are smaller.

JPEG image downlinked by 1KUNS-PF

1KUNS-PF decoded

A few days ago, I spoke about my tries to decode telemetry from 1KUNS-PF. Since then, Mike Rupprecht DK3WN has managed to get in contact with Lorenzo Frezza, from the satellite team in La Sapienza, who has given us very valuable and detailed information regarding the telemetry. This has allowed me to include a fully working decoder for 1KUNS-PF in gr-satellites. Many thanks to Lorenzo for his collaboration.

Just after reading Lorenzo’s description of the coding, where he mentions Golay and Reed Solomon, I noticed that 1KUNS-PF was using the NanoCom AX100 transceiver in ASM+Golay mode. This is the same mode that the Chinese TY-2 and TY-6 satellites use, and I’ve already spoken about ASM+Golay mode in a post about TY-2. The only difference between these Chinese satellites and 1KUNS-PF is that 1KUNS-PF is currently using 1k2 (but perhaps might change to 9k6 in the future), whereas the Chinese satellites use 9k6. With this in mind, it is very easy to adapt the decoder for TY-2 to obtain a decoder for 1KUNS-PF.

Regarding my previous tries, note that I had tried to identify the syncword as 11011001111010010101110001000011, whereas the correct syncword is 10010011000010110101000111011110. My syncword candidate was inverted (this might be a problem with sideband inversion in the recording by Mike that I used) and off by one bit (due to the difficulty of deciding where the preamble ends).

After reading Lorenzo’s email, it has been a very easy and fast task to add a fully working decoder to gr-satellites, while before I wasn’t optimistic at all about the difficulty of decoding this satellite. This makes me think about two things:

  • We should really check the usual suspects (i.e., popular modems) when trying to reverse-engineer some new satellite. I could have found this out by myself just by trying the AX100 ASM+Golay decoder.
  • Some advice IARU Satcoord: if a satellite uses some popular hardware (for instance the U482C or the AX100) or some popular standard (CCSDS), please list that in the frequency coordination sheet. Lorenzo’s email could have been well summarised in the sentence “1KUNS-PF uses a NanoCom AX100 in the ASM+Golay mode”, and then we would have been able to decode this satellite without any effort.

Lorenzo has also sent us the telemetry format, which is rather simple. Using that, I’ve been able to add a telemetry decoder also. The new decoder for 1KUNS-PF can be found as sat_1kuns_pf.grc in gr-satellites. I have also added a sample recording to satellite-recordings. The telemetry in one of the packets in the sample recording is as follows:

CSP header:
        Priority:		2
        Source:			1
        Destination:		9
        Destination port:	10
        Source port:		37
        Reserved field:		0
        HMAC:			0
        XTEA:			0
        RDP:			0
        CRC:			0
Container: 
    beacon_counter = 4274
    solar_panel_voltage = ListContainer: 
        2448.0
        2448.0
        2432.0
    eps_temp = ListContainer: 
        1.0
        3.0
        2.0
        2.0
    eps_boot_cause = 7
    eps_batt_mode = 3
    solar_panel_current = 0.0
    system_input_current = 80.0
    battery_voltage = 8262.0
    radio_PA_temp = 4.0
    tx_count = 45584
    rx_count = 0
    obc_temp = ListContainer: 
        1.0
        1.0
    ang_velocity_mag = 10
    magnetometer = ListContainer: 
        288.0
        0.0
        0.0
    main_axis_of_rot = 89