Decoding the BlueWalker 3 S-band downlink

BlueWalker 3 is a satellite built by AST SpaceMobile that was launched in 2022-09-11. It is as a prototype mission that will try to communicate from low Earth orbit with unmodified cellphones on ground using a large 64 m² unfoldable phased array antenna. It has received some criticism because of concerns of the satellite being too bright due to the large antenna (impacting astronomy observations) and potentially causing RF interference to radioastronomy and other services, since the cellular bands it will use are normally used only in terrestrial applications.

It also received criticism when shortly after launch, amateur radio operators noticed that the satellite was transmitting packets on 437.500 MHz, in the UHF amateur satellite band. The mission of this satellite is not compatible with the amateur radio service and it hasn’t received IARU coordination. There were some arguments on Twitter about whether BlueWalker 3 actually had the proper experimental license from the FCC to do this or not, and people posted ITU SNL filings and FCC applications. I didn’t track all of this in detail, so I don’t have a well informed opinion about whether BlueWalker 3 is following the regulations correctly.

A month ago, I looked at the UHF packets and checked that BlueWalker 3 used exactly the same modulation and coding as Light-1, which is a 3U cubesat from United Arab Emirates (this was first discovered by Tetsurou Satou JA0CAW). The framing contains the typical elements of the built-in packet handler of low cost FSK chips such as the Texas Instruments CC11xx family. Scott Tilley noticed some details that seem to explain this connection: Light-1 was built by NanoAvionics, which apparently has collaborated with AST SpaceMobile in the BlueWalker 3 mission. Therefore, it seems that the satellite bus used by BlueWalker 3 is that of a typical cubesat.

BlueWalker 3 also transmits in S-band, at a frequency of 2245 MHz. Scott Tilley has been doing some observations of this signal and sharing some recordings. Aang254 has been analysing the signal and remarks that it’s mostly idle data. In this post I’ll do an analysis of the BlueWalker 3 S-band signal using two recordings made by Scott.

The modulation used by BlueWalker 3 in S-band is GMSK. The two recordings that I’ve looked at use different baudrates: 128 kbaud, and 512 kbaud. The first recording I’ll use hasn’t been shared publicly, as far as I know. It was made on 2022-09-25 05:19:12 UTC. It is ~6.8 seconds long and the transmitter is on during all the recording. There is some fading on the signal. The modulation is 128 kbaud GMSK.

Waterfall of the BlueWalker 3 128 kbaud S-band signal

The second recording was shared in this tweet. It was made on 2022-10-05 19:24:59 UTC. It is ~30.2 seconds long, and contains three bursts of ~9.6 seconds each. There is also some fading, and the modulation is 512 kbaud GMSK. The figure below shows the start of one of the bursts.

Waterfall of the BlueWalker 3 512 kbaud S-band signal

The coding in both recordings is convolutionally encoded CCSDS frames following the TM Synchronization and Channel Coding Blue Book. The frame size is 355 bytes in the 128 kbaud recording and 1219 bytes in the 512 kbaud recording. The frames are scrambled with the CCSDS synchronous scrambler, marked with the 32-bit ASM, and the whole stream of bits, including the ASM, is convolutionally encoded with the r=1/2 k=7 CCSDS code.

So far all of this seems straightforward, but the contents of the frames are somewhat strange. Almost all the frames contain exactly the same data, which consists of a mostly zeros and some non-zero bytes at the end of the frame. I will call these frames “idle frames”. A few exceptional non-idle frames contain different data, but I haven’t found any obvious structure in this data.

The contents of idle frames in the 128 kbaud recording are the following. Note that there are 286 zero bytes followed by 69 non-zero bytes. The non-zero bytes look random and their autocorrelation doesn’t show any peaks, except at lag zero.

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 15 20
c4 a4 86 c3 6f e5 0e 17 5b 1d 56 a3 3f 10 63 69
4b 3c e1 5f fd 7c 2b c0 24 da b5 68 cc 47 8f 05
12 15 68 29 c6 a1 90 4b c6 73 32 5b b7 d7 5e 49
7f 56 e5 42 b0 05 e8 59 48 60 96 16 b5 9d 6f 60
ad 71 04

There is only one non-idle frame in the first recording. These are its contents.

80 bb 5d 82 0e 47 96 1b fb 60 dc 1d f5 77 0e 39
85 ed 25 86 b0 85 60 1e a9 b3 e8 ae 0a c5 bf 62
44 35 a3 49 b0 6b 7a f9 ab 79 8f 97 39 95 f4 f1
5d 63 e5 00 0b 89 c4 29 1f d4 99 bf b2 79 5c fb
2f 7c d9 17 d3 cc 66 b5 33 ea 43 20 9a 88 c9 0d
09 ed b2 08 4a ac 14 a2 2c f4 34 6d 11 79 4c 5e
db c3 66 2a 4b 5c 9b ba 04 9f d0 d1 60 35 ce ea
d9 ab 3e aa 7f 22 5c 0c fa 5c 32 bb b9 28 4f 4c
00 64 5e d4 49 2f bf c4 66 27 bd 22 44 0d 0f db
5c 94 b2 d4 e5 12 de 43 14 ed d8 a7 73 88 b3 bc
86 be 73 aa 15 50 c6 4f 43 d1 6e ec a5 db 69 67
b9 ec 37 f3 b8 ed 51 ab 3d 57 52 89 59 76 77 d5
ce ca 00 6d 63 e9 66 5c 84 29 40 d2 3b 0e 79 ef
17 56 be 37 9f a3 72 fb 25 9c 20 f8 31 1c 81 f2
79 cd af 32 24 b2 7e 37 ec b9 e5 4e a0 35 1e e6
25 bf 61 76 b7 15 68 1e a7 ac 75 96 4e ed 49 e1
6e 2b 74 be 93 c7 c8 d0 39 7d dd 48 5d 50 01 d9
c9 87 a7 b6 dc 3a 49 d2 ea 97 09 dd 87 73 cd 09
09 d6 74 14 b8 00 47 a4 8e 0f 3d d3 76 e3 9d 49
05 46 94 21 97 fd 1a 62 ba 98 13 20 df a1 da 84
11 1c 97 0a f7 2f 87 97 9c d8 13 26 09 16 b8 eb
38 71 43 e3 9c 09 02 c6 ee eb 77 a5 d6 51 29 59
78 be 04

It is even possible to see the frame structure on the waterfall, because the zeros of the idle frames, when scrambled and convolutionally encoded, create a periodic sequence of length 510 symbols, which produces many spectral lines. Looking at the texture of the signal in the waterfall, we can identify the areas full of zeros, followed by the random-like data at the end of each frame. Additionally, in the waterfall below we can see the non-idle frame close to the centre.

Waterfall showing the frame structure of the 128 kbaud signal

In the 512 kbaud recording, the idle frames contain the following data. Note that the first 1054 bytes are zeros, and the last 165 bytes contain non-zero data. In contrast to the 128 kbaud frames, in the 512 kbaud frames this last part seems to be formed mostly by blocks of 4 non-zero bytes separated by a zero byte.

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 46 b5
70 16 8f 26 a4 00 57 7b 40 ec 00 2f 8d b2 fc 00
e3 1f 3f 81 00 3c b1 58 a6 00 2e 02 94 58 00 b4
e7 21 19 00 fd ca 18 4a 00 01 20 32 4b 00 d6 55
9e 2f 00 f4 5a 01 6f 00 6a f2 da a0 00 a4 8d b2
fc 00 e3 8e 55 6c 00 c4 16 1c 29 00 7e d5 27 cb
00 3d 16 1c 29 00 7e 8e 55 6c 00 c4 8d b2 fc 00
e3 f2 da a0 00 a4 5a 01 6f 00 6a 55 9e 2f 00 f4
20 32 4b 00 d6 ca 18 4a 00 01 e7 21 19 00 fd 02
94 58 00 b4 b1 58 a6 00 2e 1f 3f 81 00 3c 8d b2
fc 00 e3 7b 40 ec 00 2f 8f 26 a4 00 57 b5 70 16
00 46 2f

Each burst in the 512 kbaud recording starts with approximately 80 symbols that contain a repeating 101010 sequence (not convolutionally encoded), followed by a non-idle frame, and then 250 idle frames. We can see this quite well in the waterfall. The red blip in the carrier frequency at the beginning of the burst corresponds to the 101010 sequence.

Waterfall showing the frame structure of the 512 kbaud signal

In this recording we have 3 non-idle frames in total; one at the beginning of each burst. The 3 frames have completely different random-like contents.

In find that all this is a little bit strange. The non-idle frames could very well contain encrypted or high entropy data, which is reasonable. However, the non-zero bytes at the end of idle-frames are quite unusual. Also, the fact that in a burst transmission only one frame of useful data followed by many idle frames is sent is perhaps a bit odd. The frame sizes are also somewhat unusual.

I have looked at the signal in more detail to check that there are no weird non-obvious things, such as part of the symbol stream not being convolutionally encoded, or pieces of data not preceded by the CCSDS ASM. After all, in my analysis I have obtained the frame length from the distance between consecutive ASMs, and assumed that everything between two ASMs forms part of a frame. What follows is a summary of the checks I’ve done.

I am using the following GNU Radio flowgraph. The signal is FM demodulated with a Quadrature Demod block. Then we do a rectangular pulse shape filter followed by the Symbol Sync block using the Gardner TED. Since there is an ambiguity in how to pair the input symbols for the Viterbi decoder, we run two branches in parallel. In each branch we perform Viterbi decoding and then extract the frames based on the ASM detection and fixed length. The frames are descrambled and saved to a file. Some of the intermediate signals are also saved to files for analysis.

BlueWalker 3 S-band GNU Radio decoder flowgraph

We start with the demodulated soft symbols of the 128 kbaud recording. These have a reasonable SNR, so we can assume that the Viterbi decoder will correct all the bit errors.

In order to check that all the data is convolutionally encoded, we take the output of each of the two Viterbi decoders and re-encode it. Then we multiply the soft symbols by the result of this re-encoding. If the data is in fact convolutionally encoded and the Viterbi decoder is working correctly, we will only get 1’s. Otherwise, we will get 1’s and -1’s. The figure below shows the results obtained by applying this procedure to each of the two Viterbi decoder outputs. We see that it is the second Viterbi decoder the one that is working correctly in this case, and that all the data is convolutionally encoded.

Next we compute the correlation between the output of the second Viterbi decoder and the CCSDS 32-bit ASM. We check that all the correlation peaks are exactly 2872 bits apart.

We align the bits to the location of the first ASM and plot a raster map with one frame per line. We see that all the frames are equal (idle frames) except for a single non-idle frame halfway through. Note that these frames are still scrambled. Since here we are plotting the Viterbi decoder output, which can’t skip any data, we see that there are really no weird gaps between ASMs.

Here is the raster map of the frames produced by the GNU Radio flowgraph. These are descrambled, so we can see that most of the contents of idle frames are zeros. Note that the GNU Radio flowgraph only outputs frames when it detects an ASM, so it would skip data that is not marked by an ASM.

The same procedure is done with the 512 kbaud recording. In this case there are three bursts of signal, with gaps containing only noise between them. In each of the bursts, the Viterbi decoder that works correctly can change. We see that it’s the second decoder for bursts 1 and 2, and the first decoder for burst 3.

We check that the separation between ASMs is exactly 9784 bits except when there is a gap between bursts.

We examine the symbols at the beginning of each burst to check that the first data being transmitted is in fact part of a convolutionally encoded CCSDS frame. The plots below shows the ~80 symbols of 101010 symbols followed by the start of the data. A vertical line marks the location of the first ASM in the burst (since we measure the location of the ASM in bits at the Viterbi decoder output, but here we are plotting symbols, the location is multiplied by 2). It seems that the start of the burst is done by pushing zeros through the convolutional encoder, which causes the convolutional encoder to output the 101010 sequence, and then the ASM is pushed into the encoder, causing the start of the non-101010 data.

I have only done this analysis for the first two bursts. I assume that at the beginning of the third burst the same will happen.

Here is the raster map corresponding to the 512 kbaud frames output by the GNU Radio flowgraph. We can see the non-idle frames at the beginning of the second and third bursts. The non-idle frame at the beginning of the third burst doesn’t show up because the resolution of the plot is limited, but we can zoom in on the plot and check that it’s there.

Only frames 0, 251, and 502 are non-idle. The rest are idle frames and have the same contents. This means that a burst consists of a non-idle frame followed by 250 idle frames. In fact, we can measure in Inspectrum the duration of each burst as 9.594 s. This corresponds to 251 frames, since each frame takes 38.22 ms to transmit.

The code and intermediate data products used in this post can be found in this repository. The analysis and plots have been done in this Jupyter notebook.

3 comments

  1. I have no knowledge or expertise in this area but from my understanding the u.s. dept. of defense is supposedly piggy backing some project off this satellite as well. Would that explain any anomalies?

  2. Hello Daniel, I would like to record the data and decode a S-band satellite. I tried tracking them using N2YO website but i couldn’t find the satellites. May I please know how I can track these satellites for recording.

Leave a Reply to destevez Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.