Ultima attività 1 month ago

LRIT Packet Decoder

Revisione 836d534c8c92ac4417c3851d77025768c3d0c7a9

decoder.c Raw
1#include <stdio.h>
2#include <stdint.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <time.h>
6#include <math.h>
7#include <memory.h>
8#include <limits.h>
9#include <sys/time.h>
10#include <sys/resource.h>
11#include <fec.h>
12#include "random/pn.h"
13
14// WORK IN PROGRESS
15
16static const unsigned char BitsSetTable256[256] = {
17# define B2(n) n, n+1, n+1, n+2
18# define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2)
19# define B6(n) B4(n), B4(n+1), B4(n+1), B4(n+2)
20 B6(0), B6(1), B6(1), B6(2)
21};
22
23// Header, because I don't want an extra file
24
25#define FRAMESIZE 1024
26#define SYNCWORDSIZE 32
27#define MINCORRELATIONBITS 46
28#define FRAMEBITS (FRAMESIZE * 8)
29
30#define VITPOLYA 0x4F
31#define VITPOLYB 0x6D
32
33#define CHECK_VITERBI_CORRECTIONS
34
35#define CODEDFRAMESIZE (FRAMEBITS * 2)
36#define SYNCWORDSIZEDOUBLE (SYNCWORDSIZE * 2)
37#define PARITY_OFFSET 892
38
39const uint64_t UW0 = 0xfca2b63db00d9794;
40const uint64_t UW2 = 0x035d49c24ff2686b;
41const uint64_t REVUW0 = 0xfc51793e700e6b68;
42const uint64_t REVUW2 = 0x03ae86c18ff19497;
43
44typedef struct {
45 uint32_t uw0mc;
46 uint32_t uw0p;
47 uint32_t uw2mc;
48 uint32_t uw2p;
49 uint32_t ruw0mc;
50 uint32_t ruw0p;
51 uint32_t ruw2mc;
52 uint32_t ruw2p;
53} correlation_t ;
54
55uint8_t UW0b[SYNCWORDSIZE * 2];
56uint8_t UW2b[SYNCWORDSIZE * 2];
57uint8_t REVUW0b[SYNCWORDSIZE * 2];
58uint8_t REVUW2b[SYNCWORDSIZE * 2];
59
60uint8_t codedData[CODEDFRAMESIZE];
61uint8_t decodedData[FRAMESIZE];
62uint8_t correctedData[CODEDFRAMESIZE];
63uint8_t rsCorrectedData[FRAMESIZE];
64uint8_t rsWorkBuffer[255];
65
66uint8_t M_PDU[886];
67
68int viterbiPolynomial[2] = {VITPOLYA, VITPOLYB};
69
70
71void initUW();
72void checkCorrelation(uint8_t *buffer, int buffLength, correlation_t *corr);
73void resetCorrelation(correlation_t * corr);
74uint32_t hardCorrelate(uint8_t dataByte, uint8_t wordByte);
75void fixPacket(uint8_t *buffer, int buffLength, uint8_t n);
76void convEncode(uint8_t *data, int dataLength, uint8_t *output, int outputLen);
77uint32_t calculateError(uint8_t *original, uint8_t *corrected, int length);
78void deinterleaveRS(uint8_t *data, uint8_t *rsbuff, uint8_t pos, uint8_t I);
79void interleaveRS(uint8_t *idata, uint8_t *outbuff, uint8_t pos, uint8_t I);
80
81// Code
82
83uint32_t swapEndianess(uint32_t num) {
84 return ((num>>24)&0xff) | ((num<<8)&0xff0000) | ((num>>8)&0xff00) | ((num<<24)&0xff000000);
85}
86
87uint32_t maxCorrelation(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
88 uint32_t f = (a > b ? a : b);
89 uint32_t g = (c > d ? c : d);
90 return f > g ? f : g;
91}
92
93
94void initUW() {
95 printf("Converting Sync Words to Soft Data\n");
96 for (int i = 0; i < SYNCWORDSIZEDOUBLE; i++) {
97 UW0b[i] = (UW0 >> (SYNCWORDSIZEDOUBLE-i-1)) & 1 ? 0xFF : 0x00;
98 UW2b[i] = (UW2 >> (SYNCWORDSIZEDOUBLE-i-1)) & 1 ? 0xFF : 0x00;
99 REVUW0b[i] = (REVUW0 >> (SYNCWORDSIZEDOUBLE-i-1)) & 1 ? 0xFF : 0x00;
100 REVUW2b[i] = (REVUW2 >> (SYNCWORDSIZEDOUBLE-i-1)) & 1 ? 0xFF : 0x00;
101 }
102}
103
104uint32_t hardCorrelate(uint8_t dataByte, uint8_t wordByte) {
105 //1 if (a > 127 and b == 255) or (a < 127 and b == 0) else 0
106 return (dataByte >= 127 & wordByte == 0) | (dataByte < 127 & wordByte == 255);
107}
108
109void checkCorrelation(uint8_t *buffer, int buffLength, correlation_t *corr) {
110 resetCorrelation(corr);
111 for (int i = 0; i < buffLength - SYNCWORDSIZEDOUBLE; i++) {
112 uint32_t uw0c = 0;
113 uint32_t uw2c = 0;
114 uint32_t ruw0c = 0;
115 uint32_t ruw2c = 0;
116
117 for (int k = 0; k < SYNCWORDSIZEDOUBLE; k++) {
118 uw0c += hardCorrelate(buffer[i+k], UW0b[k]);
119 uw2c += hardCorrelate(buffer[i+k], UW2b[k]);
120 ruw0c += hardCorrelate(buffer[i+k], REVUW0b[k]);
121 ruw2c += hardCorrelate(buffer[i+k], REVUW2b[k]);
122 }
123
124 corr->uw0p = uw0c > corr->uw0mc ? i : corr->uw0p;
125 corr->uw2p = uw2c > corr->uw2mc ? i : corr->uw2p;
126 corr->ruw0p = ruw0c > corr->ruw0mc ? i : corr->ruw0p;
127 corr->ruw2p = ruw2c > corr->ruw2mc ? i : corr->ruw2p;
128
129 corr->uw0mc = uw0c > corr->uw0mc ? uw0c : corr->uw0mc;
130 corr->uw2mc = uw2c > corr->uw2mc ? uw2c : corr->uw2mc;
131 corr->ruw0mc = ruw0c > corr->ruw0mc ? ruw0c : corr->ruw0mc;
132 corr->ruw2mc = ruw2c > corr->ruw2mc ? ruw2c : corr->ruw2mc;
133 }
134}
135
136void resetCorrelation(correlation_t * corr) {
137 memset(corr, 0x00, sizeof(correlation_t));
138}
139
140void fixPacket(uint8_t *buffer, int buffLength, uint8_t n) {
141 if (n != 0) {
142 for (int i=0; i < buffLength; i+=2) {
143 if (n % 2) { // Process IQ Inversion
144 char a = buffer[i];
145 buffer[i] = buffer[i+1];
146 buffer[i+1] = a;
147 }
148
149 if (n >= 4) { // Process 180 phase shift, aka inverted bits
150 buffer[i] ^= 0xFF;
151 buffer[i+1] ^= 0xFF;
152 }
153 }
154 }
155}
156
157uint32_t calculateError(uint8_t *original, uint8_t *corrected, int length) {
158 uint32_t errors = 0;
159 for (int i=0; i<length; i++) {
160 errors += hardCorrelate(original[i], ~corrected[i]);
161 }
162
163 return errors;
164}
165
166void convEncode(uint8_t *data, int dataLength, uint8_t *output, int outputLen) {
167 unsigned int encstate = 0;
168 uint8_t c;
169 uint32_t pos = 0;
170 uint32_t opos = 0;
171
172 memset(output, 0x00, outputLen);
173 while (pos < dataLength && (pos * 16) < outputLen) {
174 c = data[pos];
175 for(int i=7;i>=0;i--){
176 encstate = (encstate << 1) | ((c >> 7) & 1);
177 c <<= 1;
178 output[opos] = ~(0 - parity(encstate & viterbiPolynomial[0]));
179 output[opos+1] = ~(0 - parity(encstate & viterbiPolynomial[1]));
180
181 opos += 2;
182 }
183 pos++;
184 }
185}
186
187void printBuff(uint8_t *buff, int length) {
188 int countlen = (length > 40 ? 40 : length);
189 for (int i=0; i<countlen; i++) {
190 if (i % 8 == 0 && i != 0) {
191 printf("\n");
192 }
193 printf("%d ", buff[i]);
194 }
195 printf("\n");
196}
197
198void deinterleaveRS(uint8_t *data, uint8_t *rsbuff, uint8_t pos, uint8_t I) {
199 // Copy data
200 for (int i=0; i<223; i++) {
201 rsbuff[i] = data[i*I + pos];
202 }
203 // Copy parity
204 for (int i=0; i<32; i++) {
205 rsbuff[i+223] = data[PARITY_OFFSET + i*I + pos];
206 }
207}
208
209void interleaveRS(uint8_t *idata, uint8_t *outbuff, uint8_t pos, uint8_t I) {
210 // Copy data
211 for (int i=0; i<223; i++) {
212 outbuff[i*I + pos] = idata[i];
213 }
214 // Copy parity - Not needed here, but I do.
215 for (int i=0; i<32; i++) {
216 //outbuff[PARITY_OFFSET + i*I + pos] = idata[i+223];
217 outbuff[PARITY_OFFSET + i*I + pos] = 0x00;
218 }
219}
220
221int main(int argc,char *argv[]) {
222
223 if (argc < 3) {
224 printf("Usage: ./decoder inputfile outputfile");
225 return 1;
226 }
227
228 char *inputfile = argv[1];
229 char *outputfile = argv[2];
230 void *viterbi;
231
232 correlation_t corr;
233
234 printf("Opening files\n");
235 FILE *input = fopen(inputfile, "r");
236 FILE *output = fopen(outputfile, "w");
237
238 initUW();
239
240 printf("Initializing Viterbi\n");
241 set_viterbi27_polynomial(viterbiPolynomial);
242 if((viterbi = create_viterbi27(FRAMEBITS)) == NULL){
243 printf("create_viterbi27 failed\n");
244 exit(1);
245 }
246
247 fseek(input, 0L, SEEK_END);
248 uint64_t sz = ftell(input);
249 fseek(input, 0L, SEEK_SET);
250 printf("Input size is %lu\n", sz);
251
252 uint64_t readsize = 0;
253 uint64_t frameCount = 1;
254
255 while (readsize < sz) {
256 // Read Data
257 uint32_t chunkSize = sz - readsize > CODEDFRAMESIZE ? CODEDFRAMESIZE : sz - readsize;
258 memset(codedData, 0x00, CODEDFRAMESIZE);
259 fread(codedData, chunkSize, 1, input);
260
261 //printBuff(codedData, chunkSize);
262 // Check Correlation
263 checkCorrelation(codedData, chunkSize, &corr);
264 // Get Max Correlation
265 uint32_t maxCorr = maxCorrelation(corr.uw0mc, corr.uw2mc, corr.ruw0mc, corr.ruw2mc);
266
267 if (maxCorr < MINCORRELATIONBITS) {
268 printf(" Skipping read. Correlation %d less than required %d.\n", maxCorr, MINCORRELATIONBITS);
269 } else {
270 // Check Phase Shifting and Position
271 uint8_t n;
272 uint32_t p;
273
274 if (maxCorr == corr.uw0mc) {
275 n = 0;
276 p = corr.uw0p;
277 } else if (maxCorr == corr.uw2mc) {
278 n = 4;
279 p = corr.uw2p;
280 } else if (maxCorr == corr.ruw0mc) {
281 n = 1;
282 p = corr.ruw0p;
283 } else if (maxCorr == corr.ruw2mc) {
284 n = 5;
285 p = corr.ruw2p;
286 }
287
288 if (p != 0) {
289 // Shift position
290 char *shiftedPosition = codedData + p;
291 //printf(" Missing bytes for frame: %d\n", p);
292 memcpy(codedData, shiftedPosition, CODEDFRAMESIZE - p); // Copy from p to chunk size to start of codedData
293
294 readsize += chunkSize; // Add what we processed to readsize.
295
296 uint32_t oldChunkSize = chunkSize;
297 chunkSize = (sz - readsize) > p ? p : (sz - readsize); // Read needed bytes to fill a frame.
298 //printf(" Reading for frame missing bytes: %d\n", chunkSize);
299 fread(codedData + CODEDFRAMESIZE - p, chunkSize, 1, input);
300 }
301
302 // Correct Frame Phase
303 //printf(" Fixing packet.\n");
304 fixPacket(codedData, CODEDFRAMESIZE, n);
305
306 // Viterbi
307 //printf(" Decoding using viterbi.\n");
308 init_viterbi27(viterbi, 0);
309 update_viterbi27_blk(viterbi, codedData, FRAMEBITS + 6);
310 chainback_viterbi27(viterbi, decodedData, FRAMEBITS, 0);
311
312 #ifdef CHECK_VITERBI_CORRECTIONS
313 //printf(" Re-encoding.\n");
314 // Calculate Errors
315 convEncode(decodedData, FRAMESIZE, correctedData, CODEDFRAMESIZE);
316 //printf(" Calculating errors.\n");
317 uint32_t errors = calculateError(codedData, correctedData, CODEDFRAMESIZE) / 2;
318 uint32_t signalQuality = 100 - (100 * errors) / FRAMEBITS;
319 #endif
320
321 // De-randomization
322 //printf(" De-randomizing data.\n");
323 uint8_t skipsize = (SYNCWORDSIZE/8);
324 memcpy(decodedData, decodedData + skipsize, FRAMESIZE-skipsize);
325 for (int i=0; i<FRAMESIZE-skipsize; i++) {
326 decodedData[i] ^= pn[i];
327 }
328
329 // Reed-solomon
330 int derrlocs[255];
331 int derrors[4] = { 0, 0, 0, 0 };
332
333 for (int i=0; i<4; i++) {
334 deinterleaveRS(decodedData, rsWorkBuffer, i, 4);
335 derrors[i] = decode_rs_ccsds(rsWorkBuffer, derrlocs, 0, 0);
336 interleaveRS(rsWorkBuffer, rsCorrectedData, i, 4);
337 }
338
339 // Packet Header Filtering
340 uint8_t versionNumber = (*rsCorrectedData) & 0xC0 >> 6;
341 uint8_t scid = ((*rsCorrectedData) & 0x3F) << 2 | (*(rsCorrectedData+1) & 0xC0) >> 6;
342 uint8_t vcid = (*(rsCorrectedData+1)) & 0x3F;
343
344 // Packet Counter from Packet
345 uint32_t counter = *((uint32_t *) (rsCorrectedData+2));
346 counter = swapEndianess(counter);
347 counter &= 0xFFFFFF00;
348 counter = counter >> 8;
349
350 if (vcid == 63) {
351 //printf("Empty Frame. Discarding.\n");
352 } else { //if (vcid == 42) {
353 fwrite(rsCorrectedData, FRAMESIZE - skipsize, 1, output);
354 printf("Frame %lu.\n", frameCount);
355 printf(" Version Number: %u\n", versionNumber);
356 printf(" S/C ID: %u\n", scid);
357 printf(" VC ID: %u\n", vcid);
358 printf(" Packet Number: %u\n", counter);
359 #ifdef CHECK_VITERBI_CORRECTIONS
360 printf(" Viterbi Errors: %u/%u bits\n", errors, FRAMEBITS);
361 printf(" Signal Quality: %u%%\n", signalQuality);
362 #endif
363 printf(" RS Errors: %d %d %d %d\n", derrors[0], derrors[1], derrors[2], derrors[3]);
364 printf(" Sync Correlation: %d\n", maxCorr);
365 switch(n) {
366 case 0: printf(" Max Correlation with 0 degrees Word at %u\n", p); break;
367 case 4: printf(" Max Correlation with 180 degrees Word at %u\n", p); break;
368 case 1: printf(" Max Correlation with 0 degrees Word at %u\n with IQ Reversal", p); break;
369 case 5: printf(" Max Correlation with 180 degrees Word at %u\n with IQ Reversal", p); break;
370 }
371 // Separate M_PDU
372 memcpy(M_PDU, rsCorrectedData + 6, 886);
373
374 uint16_t fhp = (((*M_PDU) & 3) << 8) | *(M_PDU + 1);
375
376 printf(" First Header Pointer: %d\n", fhp);
377
378 memcpy(M_PDU, M_PDU + 2, 884); // Copy CP_PDU to M_PDU start, so its easier to manipulate.
379 //memcpy(M_PDU, M_PDU + fhp, 884 - fhp);
380
381 int packetVersion = ((*M_PDU) & 0xE0) >> 5;
382 int type = (*M_PDU & 0x10) >> 4;
383 int apid = ((*M_PDU & 3) << 8) | *(M_PDU+1);
384
385 int sequenceFlag = *(M_PDU + 2) & 0xC0;
386 int packetSequenceCounter = ((*(M_PDU + 2) & 0x3F) << 8) | *(M_PDU + 3);
387 uint16_t packetLength = *((uint16_t *)(M_PDU + 4));
388
389 printf(" Packet Version: %d - Type: %d - APID: %d\n", packetVersion, type, apid);
390 printf(" Sequence Flag: %d packetSequenceCounter: %d\n", sequenceFlag, packetSequenceCounter);
391 printf(" Packet Length: %d\n", packetLength);
392 }
393
394 frameCount++;
395 }
396
397 readsize += chunkSize;
398 }
399
400 fclose(input);
401 fclose(output);
402 return 0;
403}
pn.h Raw
1char pn[1020] = {
2 0xff, 0x48, 0x0e, 0xc0, 0x9a, 0x0d, 0x70, 0xbc,
3 0x8e, 0x2c, 0x93, 0xad, 0xa7, 0xb7, 0x46, 0xce,
4 0x5a, 0x97, 0x7d, 0xcc, 0x32, 0xa2, 0xbf, 0x3e,
5 0x0a, 0x10, 0xf1, 0x88, 0x94, 0xcd, 0xea, 0xb1,
6 0xfe, 0x90, 0x1d, 0x81, 0x34, 0x1a, 0xe1, 0x79,
7 0x1c, 0x59, 0x27, 0x5b, 0x4f, 0x6e, 0x8d, 0x9c,
8 0xb5, 0x2e, 0xfb, 0x98, 0x65, 0x45, 0x7e, 0x7c,
9 0x14, 0x21, 0xe3, 0x11, 0x29, 0x9b, 0xd5, 0x63,
10 0xfd, 0x20, 0x3b, 0x02, 0x68, 0x35, 0xc2, 0xf2,
11 0x38, 0xb2, 0x4e, 0xb6, 0x9e, 0xdd, 0x1b, 0x39,
12 0x6a, 0x5d, 0xf7, 0x30, 0xca, 0x8a, 0xfc, 0xf8,
13 0x28, 0x43, 0xc6, 0x22, 0x53, 0x37, 0xaa, 0xc7,
14 0xfa, 0x40, 0x76, 0x04, 0xd0, 0x6b, 0x85, 0xe4,
15 0x71, 0x64, 0x9d, 0x6d, 0x3d, 0xba, 0x36, 0x72,
16 0xd4, 0xbb, 0xee, 0x61, 0x95, 0x15, 0xf9, 0xf0,
17 0x50, 0x87, 0x8c, 0x44, 0xa6, 0x6f, 0x55, 0x8f,
18 0xf4, 0x80, 0xec, 0x09, 0xa0, 0xd7, 0x0b, 0xc8,
19 0xe2, 0xc9, 0x3a, 0xda, 0x7b, 0x74, 0x6c, 0xe5,
20 0xa9, 0x77, 0xdc, 0xc3, 0x2a, 0x2b, 0xf3, 0xe0,
21 0xa1, 0x0f, 0x18, 0x89, 0x4c, 0xde, 0xab, 0x1f,
22 0xe9, 0x01, 0xd8, 0x13, 0x41, 0xae, 0x17, 0x91,
23 0xc5, 0x92, 0x75, 0xb4, 0xf6, 0xe8, 0xd9, 0xcb,
24 0x52, 0xef, 0xb9, 0x86, 0x54, 0x57, 0xe7, 0xc1,
25 0x42, 0x1e, 0x31, 0x12, 0x99, 0xbd, 0x56, 0x3f,
26 0xd2, 0x03, 0xb0, 0x26, 0x83, 0x5c, 0x2f, 0x23,
27 0x8b, 0x24, 0xeb, 0x69, 0xed, 0xd1, 0xb3, 0x96,
28 0xa5, 0xdf, 0x73, 0x0c, 0xa8, 0xaf, 0xcf, 0x82,
29 0x84, 0x3c, 0x62, 0x25, 0x33, 0x7a, 0xac, 0x7f,
30 0xa4, 0x07, 0x60, 0x4d, 0x06, 0xb8, 0x5e, 0x47,
31 0x16, 0x49, 0xd6, 0xd3, 0xdb, 0xa3, 0x67, 0x2d,
32 0x4b, 0xbe, 0xe6, 0x19, 0x51, 0x5f, 0x9f, 0x05,
33 0x08, 0x78, 0xc4, 0x4a, 0x66, 0xf5, 0x58, 0xff,
34 0x48, 0x0e, 0xc0, 0x9a, 0x0d, 0x70, 0xbc, 0x8e,
35 0x2c, 0x93, 0xad, 0xa7, 0xb7, 0x46, 0xce, 0x5a,
36 0x97, 0x7d, 0xcc, 0x32, 0xa2, 0xbf, 0x3e, 0x0a,
37 0x10, 0xf1, 0x88, 0x94, 0xcd, 0xea, 0xb1, 0xfe,
38 0x90, 0x1d, 0x81, 0x34, 0x1a, 0xe1, 0x79, 0x1c,
39 0x59, 0x27, 0x5b, 0x4f, 0x6e, 0x8d, 0x9c, 0xb5,
40 0x2e, 0xfb, 0x98, 0x65, 0x45, 0x7e, 0x7c, 0x14,
41 0x21, 0xe3, 0x11, 0x29, 0x9b, 0xd5, 0x63, 0xfd,
42 0x20, 0x3b, 0x02, 0x68, 0x35, 0xc2, 0xf2, 0x38,
43 0xb2, 0x4e, 0xb6, 0x9e, 0xdd, 0x1b, 0x39, 0x6a,
44 0x5d, 0xf7, 0x30, 0xca, 0x8a, 0xfc, 0xf8, 0x28,
45 0x43, 0xc6, 0x22, 0x53, 0x37, 0xaa, 0xc7, 0xfa,
46 0x40, 0x76, 0x04, 0xd0, 0x6b, 0x85, 0xe4, 0x71,
47 0x64, 0x9d, 0x6d, 0x3d, 0xba, 0x36, 0x72, 0xd4,
48 0xbb, 0xee, 0x61, 0x95, 0x15, 0xf9, 0xf0, 0x50,
49 0x87, 0x8c, 0x44, 0xa6, 0x6f, 0x55, 0x8f, 0xf4,
50 0x80, 0xec, 0x09, 0xa0, 0xd7, 0x0b, 0xc8, 0xe2,
51 0xc9, 0x3a, 0xda, 0x7b, 0x74, 0x6c, 0xe5, 0xa9,
52 0x77, 0xdc, 0xc3, 0x2a, 0x2b, 0xf3, 0xe0, 0xa1,
53 0x0f, 0x18, 0x89, 0x4c, 0xde, 0xab, 0x1f, 0xe9,
54 0x01, 0xd8, 0x13, 0x41, 0xae, 0x17, 0x91, 0xc5,
55 0x92, 0x75, 0xb4, 0xf6, 0xe8, 0xd9, 0xcb, 0x52,
56 0xef, 0xb9, 0x86, 0x54, 0x57, 0xe7, 0xc1, 0x42,
57 0x1e, 0x31, 0x12, 0x99, 0xbd, 0x56, 0x3f, 0xd2,
58 0x03, 0xb0, 0x26, 0x83, 0x5c, 0x2f, 0x23, 0x8b,
59 0x24, 0xeb, 0x69, 0xed, 0xd1, 0xb3, 0x96, 0xa5,
60 0xdf, 0x73, 0x0c, 0xa8, 0xaf, 0xcf, 0x82, 0x84,
61 0x3c, 0x62, 0x25, 0x33, 0x7a, 0xac, 0x7f, 0xa4,
62 0x07, 0x60, 0x4d, 0x06, 0xb8, 0x5e, 0x47, 0x16,
63 0x49, 0xd6, 0xd3, 0xdb, 0xa3, 0x67, 0x2d, 0x4b,
64 0xbe, 0xe6, 0x19, 0x51, 0x5f, 0x9f, 0x05, 0x08,
65 0x78, 0xc4, 0x4a, 0x66, 0xf5, 0x58, 0xff, 0x48,
66 0x0e, 0xc0, 0x9a, 0x0d, 0x70, 0xbc, 0x8e, 0x2c,
67 0x93, 0xad, 0xa7, 0xb7, 0x46, 0xce, 0x5a, 0x97,
68 0x7d, 0xcc, 0x32, 0xa2, 0xbf, 0x3e, 0x0a, 0x10,
69 0xf1, 0x88, 0x94, 0xcd, 0xea, 0xb1, 0xfe, 0x90,
70 0x1d, 0x81, 0x34, 0x1a, 0xe1, 0x79, 0x1c, 0x59,
71 0x27, 0x5b, 0x4f, 0x6e, 0x8d, 0x9c, 0xb5, 0x2e,
72 0xfb, 0x98, 0x65, 0x45, 0x7e, 0x7c, 0x14, 0x21,
73 0xe3, 0x11, 0x29, 0x9b, 0xd5, 0x63, 0xfd, 0x20,
74 0x3b, 0x02, 0x68, 0x35, 0xc2, 0xf2, 0x38, 0xb2,
75 0x4e, 0xb6, 0x9e, 0xdd, 0x1b, 0x39, 0x6a, 0x5d,
76 0xf7, 0x30, 0xca, 0x8a, 0xfc, 0xf8, 0x28, 0x43,
77 0xc6, 0x22, 0x53, 0x37, 0xaa, 0xc7, 0xfa, 0x40,
78 0x76, 0x04, 0xd0, 0x6b, 0x85, 0xe4, 0x71, 0x64,
79 0x9d, 0x6d, 0x3d, 0xba, 0x36, 0x72, 0xd4, 0xbb,
80 0xee, 0x61, 0x95, 0x15, 0xf9, 0xf0, 0x50, 0x87,
81 0x8c, 0x44, 0xa6, 0x6f, 0x55, 0x8f, 0xf4, 0x80,
82 0xec, 0x09, 0xa0, 0xd7, 0x0b, 0xc8, 0xe2, 0xc9,
83 0x3a, 0xda, 0x7b, 0x74, 0x6c, 0xe5, 0xa9, 0x77,
84 0xdc, 0xc3, 0x2a, 0x2b, 0xf3, 0xe0, 0xa1, 0x0f,
85 0x18, 0x89, 0x4c, 0xde, 0xab, 0x1f, 0xe9, 0x01,
86 0xd8, 0x13, 0x41, 0xae, 0x17, 0x91, 0xc5, 0x92,
87 0x75, 0xb4, 0xf6, 0xe8, 0xd9, 0xcb, 0x52, 0xef,
88 0xb9, 0x86, 0x54, 0x57, 0xe7, 0xc1, 0x42, 0x1e,
89 0x31, 0x12, 0x99, 0xbd, 0x56, 0x3f, 0xd2, 0x03,
90 0xb0, 0x26, 0x83, 0x5c, 0x2f, 0x23, 0x8b, 0x24,
91 0xeb, 0x69, 0xed, 0xd1, 0xb3, 0x96, 0xa5, 0xdf,
92 0x73, 0x0c, 0xa8, 0xaf, 0xcf, 0x82, 0x84, 0x3c,
93 0x62, 0x25, 0x33, 0x7a, 0xac, 0x7f, 0xa4, 0x07,
94 0x60, 0x4d, 0x06, 0xb8, 0x5e, 0x47, 0x16, 0x49,
95 0xd6, 0xd3, 0xdb, 0xa3, 0x67, 0x2d, 0x4b, 0xbe,
96 0xe6, 0x19, 0x51, 0x5f, 0x9f, 0x05, 0x08, 0x78,
97 0xc4, 0x4a, 0x66, 0xf5, 0x58, 0xff, 0x48, 0x0e,
98 0xc0, 0x9a, 0x0d, 0x70, 0xbc, 0x8e, 0x2c, 0x93,
99 0xad, 0xa7, 0xb7, 0x46, 0xce, 0x5a, 0x97, 0x7d,
100 0xcc, 0x32, 0xa2, 0xbf, 0x3e, 0x0a, 0x10, 0xf1,
101 0x88, 0x94, 0xcd, 0xea, 0xb1, 0xfe, 0x90, 0x1d,
102 0x81, 0x34, 0x1a, 0xe1, 0x79, 0x1c, 0x59, 0x27,
103 0x5b, 0x4f, 0x6e, 0x8d, 0x9c, 0xb5, 0x2e, 0xfb,
104 0x98, 0x65, 0x45, 0x7e, 0x7c, 0x14, 0x21, 0xe3,
105 0x11, 0x29, 0x9b, 0xd5, 0x63, 0xfd, 0x20, 0x3b,
106 0x02, 0x68, 0x35, 0xc2, 0xf2, 0x38, 0xb2, 0x4e,
107 0xb6, 0x9e, 0xdd, 0x1b, 0x39, 0x6a, 0x5d, 0xf7,
108 0x30, 0xca, 0x8a, 0xfc, 0xf8, 0x28, 0x43, 0xc6,
109 0x22, 0x53, 0x37, 0xaa, 0xc7, 0xfa, 0x40, 0x76,
110 0x04, 0xd0, 0x6b, 0x85, 0xe4, 0x71, 0x64, 0x9d,
111 0x6d, 0x3d, 0xba, 0x36, 0x72, 0xd4, 0xbb, 0xee,
112 0x61, 0x95, 0x15, 0xf9, 0xf0, 0x50, 0x87, 0x8c,
113 0x44, 0xa6, 0x6f, 0x55, 0x8f, 0xf4, 0x80, 0xec,
114 0x09, 0xa0, 0xd7, 0x0b, 0xc8, 0xe2, 0xc9, 0x3a,
115 0xda, 0x7b, 0x74, 0x6c, 0xe5, 0xa9, 0x77, 0xdc,
116 0xc3, 0x2a, 0x2b, 0xf3, 0xe0, 0xa1, 0x0f, 0x18,
117 0x89, 0x4c, 0xde, 0xab, 0x1f, 0xe9, 0x01, 0xd8,
118 0x13, 0x41, 0xae, 0x17, 0x91, 0xc5, 0x92, 0x75,
119 0xb4, 0xf6, 0xe8, 0xd9, 0xcb, 0x52, 0xef, 0xb9,
120 0x86, 0x54, 0x57, 0xe7, 0xc1, 0x42, 0x1e, 0x31,
121 0x12, 0x99, 0xbd, 0x56, 0x3f, 0xd2, 0x03, 0xb0,
122 0x26, 0x83, 0x5c, 0x2f, 0x23, 0x8b, 0x24, 0xeb,
123 0x69, 0xed, 0xd1, 0xb3, 0x96, 0xa5, 0xdf, 0x73,
124 0x0c, 0xa8, 0xaf, 0xcf, 0x82, 0x84, 0x3c, 0x62,
125 0x25, 0x33, 0x7a, 0xac, 0x7f, 0xa4, 0x07, 0x60,
126 0x4d, 0x06, 0xb8, 0x5e, 0x47, 0x16, 0x49, 0xd6,
127 0xd3, 0xdb, 0xa3, 0x67, 0x2d, 0x4b, 0xbe, 0xe6,
128 0x19, 0x51, 0x5f, 0x9f, 0x05, 0x08, 0x78, 0xc4,
129 0x4a, 0x66, 0xf5, 0x58
130};