## DSLWP-B first JT4G test

Yesterday, between 9:00 and 11:00, DSLWP-B made its first JT4G 70cm transmissions from lunar orbit. Several stations such as Cees Bassa and the rest of the PI9CAM team at Dwingeloo, the Netherlands, Fer IW1DTU in Italy, Tetsu JA0CAW and Yasuo JA5BLZ in Japan, Mike DK3WN in Germany, Jiang Lei BG6LQV in China, Dave G4RGK in the UK, and others exchanged reception reports on Twitter. Some of them have also shared their recordings of the signals.

Last week I presented a JT4G detection algorithm intended to detect very weak signals from DSLWP-B, down to -25dB SNR in 2500Hz. I have now processed the recordings of yesterday’s transmissions with this algorithm and here I look at the results. I have also made a Python script with the algorithm so that people can process their recordings easily. Instructions are included in this post.

## First results of DSLWP-B Amateur VLBI

In March this year I spoke about the Amateur VLBI with LilacSat-2 experiment. This experiment consisted of a GPS-synchronized recording of LilacSat-2 at groundstations in Harbin and Chongqing, China, which are 2500km apart. The experiment was a preparation for the Amateur VLBI project with the DSLWP lunar orbiting satellites, and I contributed with some signal processing techniques for VLBI.

As you may know, the DSLWP-B satellite is now orbiting the Moon since May 25 and the first Amateur VLBI session was performed last Sunday. The groundstations at Shahe in Beijing, China, and Dwingeloo in the Netherlands performed a GPS-synchronized recording of the 70cm signals from DSLWP-B from 04:20 to 5:40 UTC on 2018-06-10. I have adapted my VLBI correlation algorithms and processed these recordings. Here are my first results.

## 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.

## Update on DSLWP-B orbit determination

Last Sunday, I used Scott Tilley VE7TIL’s Doppler measurements of the DSLWP-B S-band beacon to perform orbit determination using GMAT. Yesterday Scott sent me the Doppler data he has been collecting during this week. I have re-run my orbit determination process to include this new data.

Below I show the Keplerian state that was determined on 2018-06-03, in comparison with the new state determined on 2018-06-10 (both are referenced to the same epoch of 2018-05-26 00:00:00 UTC).

% 20180603
%DSLWP_B.SMA = 8761.0758581
%DSLWP_B.ECC = 0.768016853537
%DSLWP_B.INC = 16.9728174682
%DSLWP_B.RAAN = 295.670653562
%DSLWP_B.AOP = 130.427472407
%DSLWP_B.TA = 178.126596496

% 20180610
DSLWP_B.SMA = 8762.40279943
DSLWP_B.ECC = 0.764697135746
DSLWP_B.INC = 18.6101083906
DSLWP_B.RAAN = 297.248156986
DSLWP_B.AOP = 130.40460851
DSLWP_B.TA = 178.09494681


It seems that there is still an indetermination of a few degrees in the inclination and right-ascension of the ascending node and a few kilometres in the semi-major axis.

The graph below shows the Doppler fit.

The Jupyter notebook where these calculations are performed can be found here.

## 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.

## DSLWP-B’s journey to the Moon: part III

This is a follow-up on the series about DSLWP-B’s orbital dynamics (see part I and part II). In part I we looked at the tracking files published by Wei Mingchuan BG2BHC, which list the position and velocity of the satellite in ECEF coordinates, and presented basic orbit propagation with GMAT. In part II we explored GMAT’s capabilities to plan and perform manoeuvres, making a tentative simulation of DSLWP-B’s mid-course correction and lunar orbit injection. Now we turn to the study of DSLWP-B’s elliptical lunar orbit.

In this post we will examine the Keplerian elements of the orbits described by each of the tracking files published so far. We will also use Scott Tilley VE7TIL’s Doppler measurements of the S-band beacon of DSLWP-B to validate and determine the orbit.

## DSLWP-B’s journey to the Moon: part II

This forms parts of a series of posts showing how to use GMAT to track the DSLWP-B Chinese lunar satellite. In part I we looked at how to examine and validate the tracking files published by BG2BHC using GMAT. It is an easy exercise to use GMAT to perform orbit propagation and produce new tracking files. However, note that the available tracking files come from orbit planning and simulation, not from actual measurements. It seems that the elliptical lunar orbit achieved by DSWLP-B is at least slightly different from the published data. We are already working on using Doppler measurements to perform orbit determination (stay tuned for more information).

Recall that there are three published tracking files that can be taken as a rough guideline of DSLWP-B’s actual trajectory. Each file covers 48 hours. The first file starts just after trans-lunar injection, and the second and third files already show the lunar orbit. Therefore, there is a gap in the story: how DSLWP-B reached the Moon.

There are at least two manoeuvres (or burns) needed to get from trans-lunar injection into lunar orbit. The first is a mid-course correction, whose goal is to correct slightly the path of the spacecraft to make it reach the desired point for lunar orbit injection, which is usually the lunar orbit periapsis (the periapsis is the lowest part of the elliptical orbit). The second is the lunar orbit injection, a braking manoeuvre to get the spacecraft into the desired lunar orbit and adjust the orbit apoapsis (the highest part of the orbit). Without a lunar orbit injection, the satellite simply swings by the Moon and doesn’t enter lunar orbit.

In this post we will see how to use GMAT to calculate and simulate these two burns, so as to obtain a full trajectory that is consistent with the published tracking files. The final trajectory can be seen in the figure below.

## DSLWP-B’s journey to the Moon: part I

As you may well know, on May 20 a CZ-4C rocket launched from Xichang, China, to deliver Queqiao, the Chang’e 4 relay satellite, to the Moon. Queqiao is a communications relay satellite designed to orbit the L2 point of the Earth-Moon system, supporting the future Chang’e 4 rover that will land on the far side of the Moon. From the L2 point, Queqiao has a good view of both the Earth and the far side of the Moon.

This launch was shared by the DSLWP-A and -B microsatellites, also called Longjiang 1 and 2. These two satellites are designed to be put on a 200 x 9000km lunar orbit and their main scientific mission is a proof of concept of the Discovering the Sky at Longest Wavelengths experiment, a radioastronomy HF interferometer that uses the Moon as a shield from Earth’s interferences.

The DSLWP satellites carry an Amateur radio payload which consists of a 250 baud (or 500 baud) GMSK transmitter which uses $$r=1/2$$ or $$r=1/4$$ turbo codes, a JT4G beacon, and a camera allowing open telecommand (such as the camera on BY70-1 and LilacSat-1). A year ago, while the radio system was being designed, I wrote a post about DSLWP’s SSDV downlink, which transmits the images taken by the camera.

Wei Mingchuan BG2BHC, who is part of the DSLWP team, has been posting updates on Twitter about the status of the mission. If you’ve been following these closely, you’ll already know that unfortunately radio contact with DSLWP-A was lost on the UTC afternoon of May 22. Since then, all tries to contact the spacecraft have failed (the team will publicly release more information about its fate soon). On the other hand, DSLWP-B has been successfully injected into lunar orbit and is now orbiting the Moon since the UTC afternoon of May 25.

More posts will follow about the radio communications of DSLWP, but this series of posts will deal with the orbital dynamics part of the mission. In this first post, I will look at the tracking files released so far by Wei, which can be used to compute the spacecraft’s position and Doppler.

## 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