In a previous post, I talked about the satellite CAS-2T on a recent Chinese launch. CAS-2T was designed to remain attached to the upper stage of the rocket and decay in a few days. However, due to an error in the launch, the upper stage of the rocket and CAS-2T where put on a long-term 1000km x 500km elliptical orbit. A few days after launch we learned that another satellite, called KS-1Q was also attached to the same upper stage of the rocket. This satellite transmits telemetry on the 70cm Amateur Satellite band.
I haven’t been able to completely decode telemetry from KS-1Q yet, mostly because the satellite team hasn’t given many technical details about the telemetry format. There is a technical brochure in Chinese, but it is not publicly available. I have asked the team if they could send me a copy, but they haven’t replied. Here I report my findings so far in case someone finds them useful.
The modulation is 20kbaud FSK. I have used Michael Ossmann’s whole packet clock recovery to extract the bits from some packets recorded by Scott K4KDR. You can see the result of whole packet clock recovery on one of these packets in this gist. There is a preamble and postamble of alternating 0’s and 1’s.
The satellite team have announced that the FEC used is an r=1/2, k=7 convolutional code with CCSDS polynomials and a (255,223) Reed-Solomon code. We also know that the frames have 223 bytes worth of data, indicating that no padding is used for Reed-Solomon. No scrambler is used. Mingchuan BG2BHC has been in contact with the KS-1Q team and he has provided us some of this information.
The main problem is that I don’t know how long is the syncword or what should the contents of the data look like. Therefore, I don’t know where the FEC encoded data starts inside the packet. I have made a small python script that tries to perform FEC decoding starting at all possible offsets within the packet. The problem with this approach is that, due to the nature of the FEC used, decoding also succeeds when the offset is the correct one plus or minus a small multiple of 16 symbols. Therefore, it can’t be used to find the correct offset.
The python script is in this gist. Through trial and error I’ve learnt that the Reed-Solomon code used is CCSDS with dual basis, which corresponds to
decode_rs_ccsds() in Phil Karn’s KA9Q libfec. Many other satellites use the conventional representation instead, which corresponds to
decode_rs_8(). When running this python script, I get decodes with a low number of bit and byte errors, indicating that my understanding of the FEC is correct. However, as remarked above, this is not enough to determine where the FEC data starts within the packet.
Summary of the technical details:
- FEC: Concatenated code with CCSDS r=1/2, k=7 convolutional code and CCSDS (255,223) Reed-Solomon with dual basis representation
- Payload length: 223 bytes
- Syncword length: unknown
- Presence of some data between syncword and FEC encoded payload: unknown
- Convolutional code tail-ending: unknown
KS-1Q use ccsds standard tlm syncword ‘1acffc1d’ 0001 1010….
No, it doesn’t. Take a look at the sample packet:
The sequence 1acffc1d doesn’t appear anywhere (nor its bitwise inversion).
seems the sample packet is not correct. i build KS-1Q and i cannot recovery this baseband bitstream with factory tlm debug tools.
The sample packet was recoded from KS-1Q when it launched. It may have a few bit errors, but I’ve been able to do Viterbi and RS decoding on it, so I wouldn’t say it’s not correct.
I’ll have to look at it again more carefully to see if there is any trace of the syncword “1acffc1d”, even if it is corrupted by bit errors or inverted.
from nov 11 to nov 19 we can receive KS-1Q telemetry twice a day, after nov 20 our antenna rotator is dead, so we stopped operating KS-1Q.
telecommand is successful in day 13 to day 19, it will reply a 0x0e in csp packet to after gcs command is executed.
KS-1Q use two polynomial in convolutional encoder, these outputs marked as c1 and c2. transmitted bitstream is c1, ~c2, c1, ~c2 which ‘~’ is logical not. if c1 and ~c2 is interchanged the viterbi decoder cannot get correct result. you can insert a zero before putting raw samples into viterbi decoder