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.
Since Cees begun receiving the SSDV data, he was getting lost packets, as his first tweet shows:
Back at @radiotelescoop to download the #DSLWP image from the lunar surface. The image download has started, and the image is being filled in as we speak! @bg2bhc @tammojan @ea4gpz pic.twitter.com/rqk4qamKb3
— Cees Bassa (@cgbassa) August 12, 2018
After transmission, the picture Cees obtained looked like this:
Image download done. Looks like the B1 demod flowchart either stopped or crashed just before or when the download ended. GMSK signals should still be present in the IQ recording. pic.twitter.com/nV5DV5nnag
— Cees Bassa (@cgbassa) August 12, 2018
Seeing some lost packets, I quickly turned to the analysis of the IQ recording made at Dwingeloo in search of corrupted packets or anything else that could prevent all packets from decoding correctly. The corresponding recording is 2018-08-12T06:58:02_436.4MHz.
The Jupyter notebook where the analysis of the recording is done is here. As I did for last week’s transmissions, I have analysed the location of the ASMs (attached sync markers) to identify Turbo codewords, and payed attention to the distance between these in case any Turbo codeword got cut short.
The SSDV transmission is done in a single GMSK burst and there are a few bursts of telemetry before the SSDV starts. A total of 130 Turbo codewords where found. Of these, 117 mark SSDV packets, 5 correspond to telemetry packets transmitted before the SSDV transmission, and the remaining 8 are telemetry packets interleaved with the SSDV transmission.
Decoding the recording with the GNU Radio flowgraph replay_ssdv.grc using a frequency offset of 1500Hz shows no problems whatsoever. The SSDV decoder runs correctly and there are no missing packets.
$ ssdv -d -D dslwp_ssdv.bin mare_nubium.jpg Callsign: DSLWP Image ID: 1E Resolution: 640x480 MCU blocks: 2400 Sampling factor: 2x1 Quality level: 5 Read 117 packets
The SSDV decoder produces a complete image, as shown below.
I do not know why Cees got missing packets when decoding the image in real time.
While I was analyzing the first recording, Cees already had decoded the next image and published two new recordings. The image he decoded is shown in the tweet below. Again, there are several missing packets.
Lots of lost packets because of the flowchart crashing, but here is a #DSLWP image of the Sun with lots of lens flare! pic.twitter.com/716UqKTu7F
— Cees Bassa (@cgbassa) August 12, 2018
The two recordings Cees shared are 2018-08-12T07:41:24_436.4MHz and 2018-08-12T08:32:25_436.4MHz. A quick analysis of these with the GNU Radio decoder shows problems.
The first of these two recordings contains a retransmission of the Mare Nubium image shown above. The SSDV decoder shows that the decoding starts at packet 61, so we’ve missed the beginning of the image. Then there is a gap between packets 89 and 107. After the image has ended, we see out-of-order packets, which the SSDV doesn’t like. Besides packets 5, 7 and 24, which are odd, what happens is that the image starts again and we get most of the packets from 0 to 80. Some preprocessing could be done to order the packets before sending them into the SSDV decoder, but still there are some missing packets.
$ ssdv -d -D dslwp_ssdv.bin mare_nubium_again.jpg Callsign: DSLWP Image ID: 1E Resolution: 640x480 MCU blocks: 2400 Sampling factor: 2x1 Quality level: 5 Gap detected between packets -1 and 61 Gap detected between packets 89 and 107 Packets are not in order. 115 > 5 Packets are not in order. 115 > 7 Packets are not in order. 115 > 24 Packets are not in order. 115 > 0 Packets are not in order. 115 > 1 Packets are not in order. 115 > 2 Packets are not in order. 115 > 3 Packets are not in order. 115 > 4 Packets are not in order. 115 > 5 Packets are not in order. 115 > 6 Packets are not in order. 115 > 7 Packets are not in order. 115 > 8 Packets are not in order. 115 > 9 Packets are not in order. 115 > 10 Packets are not in order. 115 > 11 Packets are not in order. 115 > 12 Packets are not in order. 115 > 13 Packets are not in order. 115 > 14 Packets are not in order. 115 > 15 Packets are not in order. 115 > 16 Packets are not in order. 115 > 17 Packets are not in order. 115 > 22 Packets are not in order. 115 > 23 Packets are not in order. 115 > 24 Packets are not in order. 115 > 25 Packets are not in order. 115 > 26 Packets are not in order. 115 > 27 Packets are not in order. 115 > 28 Packets are not in order. 115 > 29 Packets are not in order. 115 > 30 Packets are not in order. 115 > 31 Packets are not in order. 115 > 32 Packets are not in order. 115 > 33 Packets are not in order. 115 > 34 Packets are not in order. 115 > 35 Packets are not in order. 115 > 36 Packets are not in order. 115 > 37 Packets are not in order. 115 > 38 Packets are not in order. 115 > 39 Packets are not in order. 115 > 40 Packets are not in order. 115 > 41 Packets are not in order. 115 > 42 Packets are not in order. 115 > 43 Packets are not in order. 115 > 44 Packets are not in order. 115 > 45 Packets are not in order. 115 > 46 Packets are not in order. 115 > 47 Packets are not in order. 115 > 48 Packets are not in order. 115 > 49 Packets are not in order. 115 > 50 Packets are not in order. 115 > 51 Packets are not in order. 115 > 52 Packets are not in order. 115 > 53 Packets are not in order. 115 > 54 Packets are not in order. 115 > 55 Packets are not in order. 115 > 56 Packets are not in order. 115 > 57 Packets are not in order. 115 > 58 Packets are not in order. 115 > 59 Packets are not in order. 115 > 60 Packets are not in order. 115 > 61 Packets are not in order. 115 > 62 Packets are not in order. 115 > 63 Packets are not in order. 115 > 64 Packets are not in order. 115 > 65 Packets are not in order. 115 > 66 Packets are not in order. 115 > 67 Packets are not in order. 115 > 68 Packets are not in order. 115 > 69 Packets are not in order. 115 > 70 Packets are not in order. 115 > 71 Packets are not in order. 115 > 72 Packets are not in order. 115 > 73 Packets are not in order. 115 > 74 Packets are not in order. 115 > 75 Packets are not in order. 115 > 76 Packets are not in order. 115 > 77 Packets are not in order. 115 > 78 Packets are not in order. 115 > 79 Packets are not in order. 115 > 80 Read 119 packets
Below we see the image produced by the SSDV decoder. Note it has ignored all the beginning of the image, since it is retransmitted out-of-order.
The last recording corresponds to the purple Sun image. Decoding starts by packet 3, then packets 4 and 5 are missing, and there is a large gap between packets 41 and 70. Also, after the end of the image, packets 70 through 80 are transmitted again.
$ ssdv -d -D dslwp_ssdv.bin purple_thing.jpg Callsign: DSLWP Image ID: 2B Resolution: 640x480 MCU blocks: 2400 Sampling factor: 2x1 Quality level: 5 Gap detected between packets -1 and 3 Gap detected between packets 3 and 6 Gap detected between packets 41 and 70 Packets are not in order. 79 > 70 Packets are not in order. 79 > 71 Packets are not in order. 79 > 72 Packets are not in order. 79 > 73 Packets are not in order. 79 > 74 Packets are not in order. 79 > 75 Packets are not in order. 79 > 76 Packets are not in order. 79 > 77 Packets are not in order. 79 > 78 Packets are not in order. 79 > 79 Unexpected MCU ID in packet 80. Read 59 packets
The image produced by the SSDV decoder is show below. Note the large gap and packets 4 and 5, which are missing.
What I find very puzzling is that the gaps in Cees image are completely different from mine. He doesn’t have the large gap, but he has more smaller gaps. Thus I have spent the rest of the day investigating this recording, setting aside for the moment the recording of the retransmission of the Mare Nubium image.
The Jupyter notebook with the analysis of the recording is here.
After some investigation I have found that there is a frequency jump in the DSLWP-B transmitter, which is something that Wei already suspected (see here). Apparently, it has something to do with the DSLWP-B onboard TCXO. This frequency jump upsets the coherent OQPSK decoder and makes it lose a couple of packets. The effects in the GNU Radio decoder can be seen in the figure below.
In detail, when the frequency jump happens, the PLL loses sync and the tail of one packet gets corrupted. The ASM frequency estimator for the next packet fails completely, so the next packet is garbage. After this, decoding resumes normally. This corresponds to SSDV packets 4 and 5 and explains why they where lost.
Even though the frequency jump prevents coherent decoding, non-coherent decoding is possible given the large SNR of the signal. I have done this by hand in the Jupyter notebook to spot any other problems. The idea is to demodulate the GMSK signal as an FSK signal in the manner I’ve being doing before. However, then the GMSK symbols must be transformed into QPSK symbols. This is a bit tricky. It involves integrating the GMSK symbols and considering phase ambiguities. See the Jupyter notebook for more details.
The Jupyter notebook saves all Turbo codewords to a file. This file is then loaded into the GNU Radio flowgraph replay_ssdv_postproc.grc, which performs descrambling, Turbo decoding, and extraction of the SSDV frames.
A total of 67 ASMs where found in the Jupyter notebook and the GNU Radio flowgraph decodes correctly 67 TM master frames. These have sequence numbers 9 through 75, which indicates that there are no lost packets. Of these frames, 61 are SSDV packets, which belong to virtual channel 1 and have virtual sequence numbers 240 through 255 and 0 through 44. The remaining 6 frames are transmitted through virtual channel 0.
As one can see in the Jupyter notebook, the SSDV packets are transmitted in three different GMSK bursts.
The SSDV decoder produces the following output. Note that packets 70 through 80 have been transmitted twice.
$ ssdv -d -D dslwp_ssdv.bin purple_sun.jpg Callsign: DSLWP Image ID: 2B Resolution: 640x480 MCU blocks: 2400 Sampling factor: 2x1 Quality level: 5 Gap detected between packets -1 and 3 Gap detected between packets 41 and 70 Packets are not in order. 79 > 70 Packets are not in order. 79 > 71 Packets are not in order. 79 > 72 Packets are not in order. 79 > 73 Packets are not in order. 79 > 74 Packets are not in order. 79 > 75 Packets are not in order. 79 > 76 Packets are not in order. 79 > 77 Packets are not in order. 79 > 78 Packets are not in order. 79 > 79 Unexpected MCU ID in packet 80. Read 61 packets
The JPEG image produced by the decoder is shown below. It is the same as the image shown before, except for the fact that packets 4 and 5 are no longer missing. The large gap is still present.
Therefore the conclusion is that a frequency jump in the DSLWP-B transmitter causes the coherent OQPSK demodulation to fail and corrupts SSDV packets 4 and 5. This can be fixed by using a non-coherent demodulator. However, there is a large gap: packets 42 through 69 where not transmitted. The master and virtual channel sequence numbers are consistent and indicate that all the transmitted packets where received correctly. The problem is with the transmitter software, which has skipped several SSDV packets from transmission.
Note that there is no evidence that samples were lost in the recording by Dwingeloo. The phase of the GMSK signal is continuous, all the ASMs identified carry a valid packet, and there are no gaps in the TM sequence numbers.
At this point I am quite puzzled. Remember that the image shown by Cees Bassa of the purple Sun didn’t have a large gap as mine does. I have no clue of where the packets to fill this large gap have come from, since they were not transmitted during the recording made at Dwingeloo.
Update 2018-08-12: Shortly after publishing this post and talking with Cees Bassa about the different recordings, I have noted that I missidentified all the SSDV packets in the second recording (the one containing a partial picture of Mare Nubium) as belonging to the same image. This is an oversight on my part. The image IDs in the SSDV packets clearly show two different images. The fist one is the picture of Mare Nubium. The second one, comprised by the packets 0 through 80 that I though were a repetition is the first transmission of the picture of the purple Sun.
The SSDV decoder assumes that all the SSDV packets form part of the same image. After separating the packets of each image, I get the following JPEG image.
Thus, we see that the purple Sun image was transmitted completely during the second recording and retransmitted leaving a large gap during the third recording. There are a few missing packets in the image above, but this is probably caused by a frequency jump in the transmitter. The missing packets can be completed with the retransmission of the image in the third recording.
To aid in recovering SSDV files, I have made the script ssdv_sort.py, which gets a file containing several SSDV packets, separates them according to the image ID, sorts them, and calls the SSDV decoder for each image. This script can be called as
$ ./ssdv_sort.py /tmp/ssdv /tmp/ssdv_out
Here /tmp/ssdv
is a file containing all the SSDV packets extracted from the second and third recording (it has been obtained by concatenating the outputs of the GNU Radio decoder on each file using cat
). This produces the files /tmp/ssdv_out_30.jpg
and /tmp/ssdv_out_43.jpg
, shown below.
Thus, finally the image of the purple Sun is complete and the mistery of where the pieces in Cees’ tweet came from is solved.
6 comments