In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import binascii

In [2]:
def hexprint(x):
    print(' '.join([('0'+j[2:])[-2:] for j in map(hex, np.packbits(x))]))

An example packet from ESEO.


In [3]:
bits = np.array([0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\
                dtype = 'uint8')

In [4]:
hexprint(bits)


7e 7e d3 f8 0e a2 ea c4 8e 2c 4b 0e 28 fa 90 20 4f 4c b1 23 ab 18 63 1a f5 ce 57 97 2f 05 87 d0 ac c6 99 bb 20 d6 89 9b 01 84 e9 3a d7 ac c9 69 a5 4f 14 51 33 5f be 9c 9c 5a ba ba 75 84 06 ca 07 84 0a a0 15 da 57 38 d0 da db 75 49 08 16 f3 28 72 37 ec 93 98 2f c5 88 ad 6b 4a c3 0b 38 3c 39 e8 5a d4 5a af ea d6 ed 25 20 3d c7 5c 67 9a 3d 48 8c 01 55 86 03 48 d2 61 8d 96 d8 0e f6 ad 73 30 b5 66 54 de 18 64 25 cb 50 cf 7c f1 71 53 3a 35 28 b1 c0 2c f6 9b a2 8a 3e 3d fb 48 df 97 e3 fc 9d 7e 7e 44 44 7f 80

Trim the data between the 0x7e7e flags. We skip Reed-Solomon decoding, since we are confident that there are no bit errors. We remove the 16 Reed-Solomon parity check bytes.


In [27]:
data = bits[16:16+161*8-16*8]
hexprint(data)


d3 f8 0e a2 ea c4 8e 2c 4b 0e 28 fa 90 20 4f 4c b1 23 ab 18 63 1a f5 ce 57 97 2f 05 87 d0 ac c6 99 bb 20 d6 89 9b 01 84 e9 3a d7 ac c9 69 a5 4f 14 51 33 5f be 9c 9c 5a ba ba 75 84 06 ca 07 84 0a a0 15 da 57 38 d0 da db 75 49 08 16 f3 28 72 37 ec 93 98 2f c5 88 ad 6b 4a c3 0b 38 3c 39 e8 5a d4 5a af ea d6 ed 25 20 3d c7 5c 67 9a 3d 48 8c 01 55 86 03 48 d2 61 8d 96 d8 0e f6 ad 73 30 b5 66 54 de 18 64 25 cb 50 cf 7c f1 71 53 3a 35 28

Reverse the bytes in the data.


In [6]:
def reflect_bytes(x):
    return np.fliplr(x[:x.size//8*8].reshape((-1,8))).ravel()

In [7]:
data_rev = reflect_bytes(data)
hexprint(data_rev)


cb 1f 70 45 57 23 71 34 d2 70 14 5f 09 04 f2 32 8d c4 d5 18 c6 58 af 73 ea e9 f4 a0 e1 0b 35 63 99 dd 04 6b 91 d9 80 21 97 5c eb 35 93 96 a5 f2 28 8a cc fa 7d 39 39 5a 5d 5d ae 21 60 53 e0 21 50 05 a8 5b ea 1c 0b 5b db ae 92 10 68 cf 14 4e ec 37 c9 19 f4 a3 11 b5 d6 52 c3 d0 1c 3c 9c 17 5a 2b 5a f5 57 6b b7 a4 04 bc e3 3a e6 59 bc 12 31 80 aa 61 c0 12 4b 86 b1 69 1b 70 6f b5 ce 0c ad 66 2a 7b 18 26 a4 d3 0a f3 3e 8f 8e ca 5c ac 14

Perform bit de-stuffing.


In [8]:
def destuff(x):
    y = list()
    run = 0
    for i, bit in enumerate(x):
        if run == 5:
            if bit == 1:
                print('Long run found at bit', i)
                break
            else:
                run = 0
        elif bit == 0:
            run = 0
            y.append(bit)
        elif bit == 1:
            run += 1
            y.append(bit)
    return np.array(y, dtype = 'uint8')

In [9]:
data_rev_destuff = destuff(data_rev)

That it interesting, we have found a run of ones longer than 5 inside the data. We wouln't expect such a run due to byte stuffing. This happens during byte of a total of 161 data bytes.


In [10]:
1193/8


Out[10]:
149.125

In [11]:
hexprint(data_rev_destuff)


cb 1f e0 8a ae 46 e2 69 a4 e0 28 be 24 13 c8 ca 37 13 54 63 19 62 bd cf d7 4f ca 0e 10 b3 56 39 9d d0 46 b9 1d 98 02 19 75 ce b3 59 39 6a 5f 45 11 59 9f 9f 9c 9c ad 2e ae d7 10 b0 29 f0 21 50 05 a8 5b f4 38 16 b7 b7 5d 24 20 d1 9e 28 9d d8 6f a4 67 e5 18 8d ae b2 96 1e 80 e1 e4 e0 ba d1 5a d7 aa bb 5d bd 20 25 e7 19 d7 32 cd e0 91 8c 05 53 0e 00 92 5c 35 8b 48 db 83 7f 5c e0 ca d6 62 a7 b1 82 6a 4d 30 af 33 f1 f3 b2 97 2b 05 00

Perform G3RUH descrambling.


In [12]:
def descramble(x):
    y = np.concatenate((np.zeros(17, dtype='uint8'), x))
    z = y[:-17] ^ y[5:-12] ^ y[17:]
    return z

def nrzi_decode(x):
    return x ^ np.concatenate((np.zeros(1, dtype = 'uint8'), x[:-1])) ^ 1

In [13]:
data_descrambled = descramble(data_rev_destuff)
hexprint(data_descrambled)


cb 13 34 fb 56 a9 51 24 f3 4e b4 cc bb ae 9b ff 5f d5 3e df f5 62 a7 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 ca aa 02 aa aa aa aa aa 2a aa aa aa aa aa aa aa 00 00 03 a5 aa af 2a d7 7d 8a 5c 01 83 59 b0 45 fc ce aa 71 55 2e aa 2e aa 6e aa 06 aa 8e 06 aa aa aa aa aa 23 55 55 29 75 55 55 23 55 55 29 75 55 55 59 99 f5 55 59 66 0a aa aa aa aa aa aa aa aa aa aa aa aa aa a1 5a a1 55 55 55 55 db 3c 00

Perform NRZ-I decoding.


In [14]:
data_nrz = nrzi_decode(data_descrambled)
hexprint(data_nrz)


51 65 51 79 02 02 06 49 75 16 11 55 19 86 29 ff 0f c0 5e 4f f0 2c 0b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d0 00 fc 00 00 00 00 00 c0 00 00 00 00 00 00 00 ff ff fd 88 80 07 40 43 3c b0 8d fe bd 0a 97 98 fd 56 00 b6 00 46 00 c6 00 a6 00 fa 00 36 fa 00 00 00 00 00 cd 00 00 42 30 00 00 4d 00 00 42 30 00 00 0a aa f0 00 0a 2a f0 00 00 00 00 00 00 00 00 00 00 00 00 00 0e 08 0e 00 00 00 00 c9 5d c0

The long sequences of zeros are a good indicator, but still we don't have the expected 8A A6 8A 9E 40 40 60 92 AE 68 88 AA 98 61 AX.25 header.

Reflect the bytes again.


In [15]:
data_nrz_rev = reflect_bytes(data_nrz)
hexprint(data_nrz_rev)


8a a6 8a 9e 40 40 60 92 ae 68 88 aa 98 61 94 ff f0 03 7a f2 0f 34 d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 00 3f 00 00 00 00 00 03 00 00 00 00 00 00 00 ff ff bf 11 01 e0 02 c2 3c 0d b1 7f bd 50 e9 19 bf 6a 00 6d 00 62 00 63 00 65 00 5f 00 6c 5f 00 00 00 00 00 b3 00 00 42 0c 00 00 b2 00 00 42 0c 00 00 50 55 0f 00 50 54 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 70 10 70 00 00 00 00 93 ba

The CRC is CRC16_CCITT_ZERO following the notation of this online calculator.

Data from SITAEL


In [16]:
raw_input_bits = np.array([1,1,0,1,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,1,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,1,0,0,0,1,0,1,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,1,0,0,0,1,0,1,0,0,0,1,1,1,1,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,1,0,1,1,0,1,0,1,0,0,1,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0,1,0,0,0,1,1,0,0,0,1,1,1,0,0,0,1,0,1,1,1,0,1,0,0,0,0,1,1,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,1,1,1,1,1,0,1,1,1,0,1,0,0,0,1,0,1,1,0,1,0,1,0,1,0,0,0,1,1,0,1,1,0,0,1,1,0,0,0,1,0,1,0,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0,1,0,1,0,0,0,1,1,0,0,1,1,0,1,1,1,1,1,0,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,1,1,0,1,1,0,0,1,1,0,0,1,0,1,0,0,1,1,1,0,1,1,0,1,0,1,1,0,0,0,0,1,1,0,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1,0,1,0,0,0,1,0,0,1,1,0,0,0,1,1,1,1,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,1,0,1,0,0,1,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,1,1,1,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,1,1,0,0,1,1,0,1,0,1,0,0,0,0,0,1,0,1,0,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,0,0,1,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,0,1,1,1,0,0,1,0,1,0,1,1,0,1,0,0,1,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,1,0,1,1,1,1,0,1,0,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,0,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,0,1,0,1,1,1,1,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,1,1,0,0,0,0,1,0,1,1,1,1,0,0,1,0,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,1,1,1,0,0,1,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,0,1,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,0,1,0,0,0,1,1,1,1,1,0,0,1,0,1,1,1,1,1,1,0,1,1,0,1,1,1,0,1,1,1,0,0,1,1,0,1,1,1,1,1,0,1,0,0,1,1,0,1,0,1,1,1,0,1,1,1,1,1,1,0,0,1,1,0,1,0,1,1,1,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,1,1,1,0,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,1,1,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,0,1,0,1,1,0,1,0,0,0,0,1,0,0,0,1,1,0,1,1,0,1,0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,1,0,1,1,0,1,0,0,1,1,0,0,0,1,1,0,1,1,0,0,1,0,0,0,1,0,1,0,1,1,0,0,0,0,1,1,0,1,0,0,0,1,0,1,0,0,1,0,0,1,1,1,1,1,0,0,1,1,0,1,1,1,0,1,0,1,0,0,1,1,1,1,0,1,1,1,0,0], dtype = 'uint8')
hexprint(raw_input_bits)


d3 f8 0e a2 ea c4 8e 2c 4b 0e 28 fa 90 20 c7 33 a6 58 cb 52 ef 01 94 16 14 29 18 e2 e8 7c 77 3e e8 b5 46 cc 50 d0 cd ca 33 7d 1b 83 37 26 44 3b 32 9d ac 34 1c 72 72 d7 51 31 e9 78 26 5b a4 31 98 22 19 c9 08 6c d4 14 ea 40 89 3b 0b 66 c8 13 f9 c6 31 39 5a 7b ab eb 46 13 13 bd 5d 8b b3 44 96 c7 d7 b3 0c 06 2a f9 86 de 17 96 0f 01 2d 79 a2 81 2f 5d b7 65 1f 2f db b9 be 9a ef cd 74 82 9b e9 f3 e1 b4 dc e7 43 96 3e 21 87 9c 1c 9f e5 cb 0c 5a 11 b5 78 09 32 ad 31 b2 2b 0d 14 9f 37 53 dc

In [17]:
raw_input_bits.size//8


Out[17]:
162

In [18]:
raw_input_stream = 'D3F8 0EA2 EAC4 8E2C 4B0E 28FA 9020 C733 A658 CB52 EF01 9416 1429 18E2 E87C 773E E8B5 46CC 50D0 CDCA 337D 1B83 3726 443B 329D AC34'

In [19]:
#input_stream = np.unpackbits(np.frombuffer(binascii.a2b_hex(raw_input_stream.replace(' ','')), dtype='uint8'))
input_stream = raw_input_bits
input_stream_reflected = reflect_bytes(input_stream)
hexprint(input_stream_reflected)


cb 1f 70 45 57 23 71 34 d2 70 14 5f 09 04 e3 cc 65 1a d3 4a f7 80 29 68 28 94 18 47 17 3e ee 7c 17 ad 62 33 0a 0b b3 53 cc be d8 c1 ec 64 22 dc 4c b9 35 2c 38 4e 4e eb 8a 8c 97 1e 64 da 25 8c 19 44 98 93 10 36 2b 28 57 02 91 dc d0 66 13 c8 9f 63 8c 9c 5a de d5 d7 62 c8 c8 bd ba d1 cd 22 69 e3 eb cd 30 60 54 9f 61 7b e8 69 f0 80 b4 9e 45 81 f4 ba ed a6 f8 f4 db 9d 7d 59 f7 b3 2e 41 d9 97 cf 87 2d 3b e7 c2 69 7c 84 e1 39 38 f9 a7 d3 30 5a 88 ad 1e 90 4c b5 8c 4d d4 b0 28 f9 ec ca 3b

They have CC64 rather than ec 64 near the end. Why?

We drop the Reed-Solomon parity check bytes (last 16 bytes).


In [20]:
input_stream_reflected_no_rs = input_stream_reflected[:-16*8]
input_stream_reflected_no_rs.size//8


Out[20]:
146

In [21]:
after_unstuffing = destuff(input_stream_reflected_no_rs)
hexprint(after_unstuffing)


cb 1f e0 8a ae 46 e2 69 a4 e0 28 be 24 13 8f 31 94 6b 4d 2b de 00 a5 a0 a2 50 61 1c 5c ff 73 e1 7a d6 23 30 a0 bb 35 3c cb fb 18 3d 8c 84 5b 89 97 26 a5 87 09 c9 dd 71 51 92 e3 cc 9b 44 b1 83 28 93 12 62 06 c5 65 0a e0 52 3b 9a 0c c2 79 13 f8 e3 27 16 b7 b5 75 d8 b2 32 2f 6e b4 73 48 9a 78 fd e6 98 30 2a 4f e1 7b f0 d3 e2 02 d2 79 16 07 e5 d7 6d 37 cf 4d b9 d7 eb 3f ec cb 90 76 65 f7 c7 2d 3b ef 89 a5 f4 27 09 c9 c7 da 7e 66 00

Here we have 18 3d instead of 1839 near the end.


In [22]:
after_unstuffing.size/8


Out[22]:
143.375

In [23]:
after_derandom = nrzi_decode(descramble(after_unstuffing))
hexprint(reflect_bytes(after_derandom))


8a a6 8a 9e 40 40 60 92 ae 68 88 aa 98 61 b2 ff f0 06 7a 01 00 c3 00 00 00 0c 07 2a 3d 89 24 45 3f 6a aa 5a 3d 43 64 22 3f 40 3b 6d bd 38 01 6d 3f 9d b6 7d bf 1c 1a ce c5 fb 20 83 43 85 c8 05 c5 f5 ef 16 40 83 0f 7b 3f 5d 68 e4 c0 e0 a9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 e2 00 c5 00 c6 00 da 00 16 00 e0 30 c7 63 c6 00 be 00 d0 00 6f 00 3a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 68 01 f2 31 f6 a3

In [24]:
after_derandom.size


Out[24]:
1147

For some reason we have needed to do something funny with the start of the descrambler (changing byte align) and reflect the bytes again to get something as in their example.


In [25]:
reflect_bytes(after_derandom).size/8


Out[25]:
143.0