Lucas Teske revised this gist 9 years ago. Go to revision
1 file changed, 32 insertions, 30 deletions
decoder.c
| @@ -25,6 +25,10 @@ static const unsigned char BitsSetTable256[256] = { | |||
| 25 | 25 | #define MINCORRELATIONBITS 46 | |
| 26 | 26 | #define FRAMEBITS (FRAMESIZE * 8) | |
| 27 | 27 | ||
| 28 | + | #define RSBLOCKS 4 | |
| 29 | + | #define RSPARITYSIZE 32 | |
| 30 | + | #define RSPARITYBLOCK (RSPARITYSIZE * RSBLOCKS) | |
| 31 | + | ||
| 28 | 32 | #define VITPOLYA 0x4F | |
| 29 | 33 | #define VITPOLYB 0x6D | |
| 30 | 34 | ||
| @@ -211,8 +215,7 @@ void interleaveRS(uint8_t *idata, uint8_t *outbuff, uint8_t pos, uint8_t I) { | |||
| 211 | 215 | } | |
| 212 | 216 | // Copy parity - Not needed here, but I do. | |
| 213 | 217 | for (int i=0; i<32; i++) { | |
| 214 | - | //outbuff[PARITY_OFFSET + i*I + pos] = idata[i+223]; | |
| 215 | - | outbuff[PARITY_OFFSET + i*I + pos] = 0x00; | |
| 218 | + | outbuff[PARITY_OFFSET + i*I + pos] = idata[i+223]; | |
| 216 | 219 | } | |
| 217 | 220 | } | |
| 218 | 221 | ||
| @@ -234,7 +237,8 @@ int main(int argc,char *argv[]) { | |||
| 234 | 237 | char *inputfile = argv[1]; | |
| 235 | 238 | char *outputfile = argv[2]; | |
| 236 | 239 | void *viterbi; | |
| 237 | - | ||
| 240 | + | uint32_t averageVitCorrections = 0; | |
| 241 | + | uint32_t averageRSCorrections = 0; | |
| 238 | 242 | correlation_t corr; | |
| 239 | 243 | ||
| 240 | 244 | printf("Opening files\n"); | |
| @@ -321,7 +325,9 @@ int main(int argc,char *argv[]) { | |||
| 321 | 325 | convEncode(decodedData, FRAMESIZE, correctedData, CODEDFRAMESIZE); | |
| 322 | 326 | //printf(" Calculating errors.\n"); | |
| 323 | 327 | uint32_t errors = calculateError(codedData, correctedData, CODEDFRAMESIZE) / 2; | |
| 324 | - | uint32_t signalQuality = 100 - (100 * errors) / FRAMEBITS; | |
| 328 | + | float signalErrors = (100.f * errors) / FRAMEBITS; // 0 to 16 | |
| 329 | + | signalErrors = 100 - (signalErrors * 10); | |
| 330 | + | uint32_t signalQuality = signalErrors < 0 ? 0 : signalErrors; | |
| 325 | 331 | #endif | |
| 326 | 332 | ||
| 327 | 333 | // De-randomization | |
| @@ -336,16 +342,26 @@ int main(int argc,char *argv[]) { | |||
| 336 | 342 | int derrlocs[255]; | |
| 337 | 343 | int derrors[4] = { 0, 0, 0, 0 }; | |
| 338 | 344 | ||
| 339 | - | for (int i=0; i<4; i++) { | |
| 340 | - | deinterleaveRS(decodedData, rsWorkBuffer, i, 4); | |
| 345 | + | for (int i=0; i<RSBLOCKS; i++) { | |
| 346 | + | deinterleaveRS(decodedData, rsWorkBuffer, i, RSBLOCKS); | |
| 341 | 347 | derrors[i] = decode_rs_ccsds(rsWorkBuffer, derrlocs, 0, 0); | |
| 342 | - | interleaveRS(rsWorkBuffer, rsCorrectedData, i, 4); | |
| 348 | + | interleaveRS(rsWorkBuffer, rsCorrectedData, i, RSBLOCKS); | |
| 343 | 349 | } | |
| 344 | 350 | ||
| 345 | 351 | // If RS returns -1 for all 4 RS Blocks, | |
| 346 | 352 | if (derrors[0] == -1 && derrors[1] == -1 && derrors[2] == -1 && derrors[3] == -1) { | |
| 347 | - | printf("Corrupted packet, RS Cannot correct.\n"); | |
| 353 | + | #ifdef CHECK_VITERBI_CORRECTIONS | |
| 354 | + | printf(" Viterbi Errors: %u/%u bits\n", errors, FRAMEBITS); | |
| 355 | + | printf(" Signal Quality: %u%%\n", signalQuality); | |
| 356 | + | printf(" Sync Correlation: %d\n", maxCorr); | |
| 357 | + | #endif | |
| 358 | + | printf(" Corrupted packet, RS Cannot correct. Dropping.\n"); | |
| 348 | 359 | goto packet_process_end; | |
| 360 | + | } else { | |
| 361 | + | averageRSCorrections += derrors[0] != -1 ? derrors[0] : 0; | |
| 362 | + | averageRSCorrections += derrors[1] != -1 ? derrors[1] : 0; | |
| 363 | + | averageRSCorrections += derrors[2] != -1 ? derrors[2] : 0; | |
| 364 | + | averageRSCorrections += derrors[3] != -1 ? derrors[3] : 0; | |
| 349 | 365 | } | |
| 350 | 366 | ||
| 351 | 367 | // Packet Header Filtering | |
| @@ -358,7 +374,7 @@ int main(int argc,char *argv[]) { | |||
| 358 | 374 | counter = swapEndianess(counter); | |
| 359 | 375 | counter &= 0xFFFFFF00; | |
| 360 | 376 | counter = counter >> 8; | |
| 361 | - | writeChannel(rsCorrectedData, FRAMESIZE, vcid); | |
| 377 | + | writeChannel(rsCorrectedData, FRAMESIZE - RSPARITYBLOCK - (SYNCWORDSIZE/8), vcid); | |
| 362 | 378 | ||
| 363 | 379 | if (vcid == 63) { | |
| 364 | 380 | //printf("Empty Frame. Discarding.\n"); | |
| @@ -382,35 +398,21 @@ int main(int argc,char *argv[]) { | |||
| 382 | 398 | case 1: printf(" Max Correlation with 0 degrees Word at %u\n with IQ Reversal", p); break; | |
| 383 | 399 | case 5: printf(" Max Correlation with 180 degrees Word at %u\n with IQ Reversal", p); break; | |
| 384 | 400 | } | |
| 385 | - | // Separate M_PDU | |
| 386 | - | memcpy(M_PDU, rsCorrectedData + 6, 886); | |
| 387 | - | ||
| 388 | - | uint16_t fhp = (((*M_PDU) & 3) << 8) | *(M_PDU + 1); | |
| 389 | - | ||
| 390 | - | printf(" First Header Pointer: %d\n", fhp); | |
| 391 | - | ||
| 392 | - | memcpy(M_PDU, M_PDU + 2, 884); // Copy CP_PDU to M_PDU start, so its easier to manipulate. | |
| 393 | - | //memcpy(M_PDU, M_PDU + fhp, 884 - fhp); | |
| 394 | - | ||
| 395 | - | int packetVersion = ((*M_PDU) & 0xE0) >> 5; | |
| 396 | - | int type = (*M_PDU & 0x10) >> 4; | |
| 397 | - | int apid = ((*M_PDU & 3) << 8) | *(M_PDU+1); | |
| 398 | - | ||
| 399 | - | int sequenceFlag = *(M_PDU + 2) & 0xC0; | |
| 400 | - | int packetSequenceCounter = ((*(M_PDU + 2) & 0x3F) << 8) | *(M_PDU + 3); | |
| 401 | - | uint16_t packetLength = *((uint16_t *)(M_PDU + 4)); | |
| 402 | - | ||
| 403 | - | printf(" Packet Version: %d - Type: %d - APID: %d\n", packetVersion, type, apid); | |
| 404 | - | printf(" Sequence Flag: %d packetSequenceCounter: %d\n", sequenceFlag, packetSequenceCounter); | |
| 405 | - | printf(" Packet Length: %d\n", packetLength); | |
| 406 | 401 | } | |
| 407 | 402 | packet_process_end: | |
| 403 | + | averageVitCorrections += errors; | |
| 408 | 404 | frameCount++; | |
| 409 | 405 | } | |
| 410 | 406 | ||
| 411 | 407 | readsize += chunkSize; | |
| 412 | 408 | } | |
| 413 | 409 | ||
| 410 | + | averageVitCorrections /= frameCount; | |
| 411 | + | averageRSCorrections /= frameCount * 4; | |
| 412 | + | ||
| 413 | + | printf("Average Viterbi Correction: %u\n", averageVitCorrections); | |
| 414 | + | printf("Average ReedSolomon Correction: %u\n", averageRSCorrections); | |
| 415 | + | ||
| 414 | 416 | fclose(input); | |
| 415 | 417 | fclose(output); | |
| 416 | 418 | return 0; | |
Lucas Teske revised this gist 9 years ago. Go to revision
1 file changed, 18 insertions, 4 deletions
decoder.c
| @@ -11,8 +11,6 @@ | |||
| 11 | 11 | #include <fec.h> | |
| 12 | 12 | #include "random/pn.h" | |
| 13 | 13 | ||
| 14 | - | // WORK IN PROGRESS | |
| 15 | - | ||
| 16 | 14 | static const unsigned char BitsSetTable256[256] = { | |
| 17 | 15 | # define B2(n) n, n+1, n+1, n+2 | |
| 18 | 16 | # define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2) | |
| @@ -77,7 +75,7 @@ void convEncode(uint8_t *data, int dataLength, uint8_t *output, int outputLen); | |||
| 77 | 75 | uint32_t calculateError(uint8_t *original, uint8_t *corrected, int length); | |
| 78 | 76 | void deinterleaveRS(uint8_t *data, uint8_t *rsbuff, uint8_t pos, uint8_t I); | |
| 79 | 77 | void interleaveRS(uint8_t *idata, uint8_t *outbuff, uint8_t pos, uint8_t I); | |
| 80 | - | ||
| 78 | + | void writeChannel(uint8_t *data, int size, uint16_t vcid); | |
| 81 | 79 | // Code | |
| 82 | 80 | ||
| 83 | 81 | uint32_t swapEndianess(uint32_t num) { | |
| @@ -218,6 +216,14 @@ void interleaveRS(uint8_t *idata, uint8_t *outbuff, uint8_t pos, uint8_t I) { | |||
| 218 | 216 | } | |
| 219 | 217 | } | |
| 220 | 218 | ||
| 219 | + | void writeChannel(uint8_t *data, int size, uint16_t vcid) { | |
| 220 | + | char filename[256]; | |
| 221 | + | sprintf(filename, "channels/channel_%d.bin", vcid); | |
| 222 | + | FILE *f = fopen(filename, "a+"); | |
| 223 | + | fwrite(data, size, 1, f); | |
| 224 | + | fclose(f); | |
| 225 | + | } | |
| 226 | + | ||
| 221 | 227 | int main(int argc,char *argv[]) { | |
| 222 | 228 | ||
| 223 | 229 | if (argc < 3) { | |
| @@ -336,6 +342,12 @@ int main(int argc,char *argv[]) { | |||
| 336 | 342 | interleaveRS(rsWorkBuffer, rsCorrectedData, i, 4); | |
| 337 | 343 | } | |
| 338 | 344 | ||
| 345 | + | // If RS returns -1 for all 4 RS Blocks, | |
| 346 | + | if (derrors[0] == -1 && derrors[1] == -1 && derrors[2] == -1 && derrors[3] == -1) { | |
| 347 | + | printf("Corrupted packet, RS Cannot correct.\n"); | |
| 348 | + | goto packet_process_end; | |
| 349 | + | } | |
| 350 | + | ||
| 339 | 351 | // Packet Header Filtering | |
| 340 | 352 | uint8_t versionNumber = (*rsCorrectedData) & 0xC0 >> 6; | |
| 341 | 353 | uint8_t scid = ((*rsCorrectedData) & 0x3F) << 2 | (*(rsCorrectedData+1) & 0xC0) >> 6; | |
| @@ -346,9 +358,11 @@ int main(int argc,char *argv[]) { | |||
| 346 | 358 | counter = swapEndianess(counter); | |
| 347 | 359 | counter &= 0xFFFFFF00; | |
| 348 | 360 | counter = counter >> 8; | |
| 361 | + | writeChannel(rsCorrectedData, FRAMESIZE, vcid); | |
| 349 | 362 | ||
| 350 | 363 | if (vcid == 63) { | |
| 351 | 364 | //printf("Empty Frame. Discarding.\n"); | |
| 365 | + | //fwrite(rsCorrectedData, FRAMESIZE - skipsize, 1, fill); | |
| 352 | 366 | } else { //if (vcid == 42) { | |
| 353 | 367 | fwrite(rsCorrectedData, FRAMESIZE - skipsize, 1, output); | |
| 354 | 368 | printf("Frame %lu.\n", frameCount); | |
| @@ -390,7 +404,7 @@ int main(int argc,char *argv[]) { | |||
| 390 | 404 | printf(" Sequence Flag: %d packetSequenceCounter: %d\n", sequenceFlag, packetSequenceCounter); | |
| 391 | 405 | printf(" Packet Length: %d\n", packetLength); | |
| 392 | 406 | } | |
| 393 | - | ||
| 407 | + | packet_process_end: | |
| 394 | 408 | frameCount++; | |
| 395 | 409 | } | |
| 396 | 410 | ||
Lucas Teske revised this gist 9 years ago. Go to revision
2 files changed, 533 insertions
decoder.c(file created)
| @@ -0,0 +1,403 @@ | |||
| 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 | + | ||
| 16 | + | static 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 | + | ||
| 39 | + | const uint64_t UW0 = 0xfca2b63db00d9794; | |
| 40 | + | const uint64_t UW2 = 0x035d49c24ff2686b; | |
| 41 | + | const uint64_t REVUW0 = 0xfc51793e700e6b68; | |
| 42 | + | const uint64_t REVUW2 = 0x03ae86c18ff19497; | |
| 43 | + | ||
| 44 | + | typedef 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 | + | ||
| 55 | + | uint8_t UW0b[SYNCWORDSIZE * 2]; | |
| 56 | + | uint8_t UW2b[SYNCWORDSIZE * 2]; | |
| 57 | + | uint8_t REVUW0b[SYNCWORDSIZE * 2]; | |
| 58 | + | uint8_t REVUW2b[SYNCWORDSIZE * 2]; | |
| 59 | + | ||
| 60 | + | uint8_t codedData[CODEDFRAMESIZE]; | |
| 61 | + | uint8_t decodedData[FRAMESIZE]; | |
| 62 | + | uint8_t correctedData[CODEDFRAMESIZE]; | |
| 63 | + | uint8_t rsCorrectedData[FRAMESIZE]; | |
| 64 | + | uint8_t rsWorkBuffer[255]; | |
| 65 | + | ||
| 66 | + | uint8_t M_PDU[886]; | |
| 67 | + | ||
| 68 | + | int viterbiPolynomial[2] = {VITPOLYA, VITPOLYB}; | |
| 69 | + | ||
| 70 | + | ||
| 71 | + | void initUW(); | |
| 72 | + | void checkCorrelation(uint8_t *buffer, int buffLength, correlation_t *corr); | |
| 73 | + | void resetCorrelation(correlation_t * corr); | |
| 74 | + | uint32_t hardCorrelate(uint8_t dataByte, uint8_t wordByte); | |
| 75 | + | void fixPacket(uint8_t *buffer, int buffLength, uint8_t n); | |
| 76 | + | void convEncode(uint8_t *data, int dataLength, uint8_t *output, int outputLen); | |
| 77 | + | uint32_t calculateError(uint8_t *original, uint8_t *corrected, int length); | |
| 78 | + | void deinterleaveRS(uint8_t *data, uint8_t *rsbuff, uint8_t pos, uint8_t I); | |
| 79 | + | void interleaveRS(uint8_t *idata, uint8_t *outbuff, uint8_t pos, uint8_t I); | |
| 80 | + | ||
| 81 | + | // Code | |
| 82 | + | ||
| 83 | + | uint32_t swapEndianess(uint32_t num) { | |
| 84 | + | return ((num>>24)&0xff) | ((num<<8)&0xff0000) | ((num>>8)&0xff00) | ((num<<24)&0xff000000); | |
| 85 | + | } | |
| 86 | + | ||
| 87 | + | uint32_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 | + | ||
| 94 | + | void 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 | + | ||
| 104 | + | uint32_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 | + | ||
| 109 | + | void 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 | + | ||
| 136 | + | void resetCorrelation(correlation_t * corr) { | |
| 137 | + | memset(corr, 0x00, sizeof(correlation_t)); | |
| 138 | + | } | |
| 139 | + | ||
| 140 | + | void 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 | + | ||
| 157 | + | uint32_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 | + | ||
| 166 | + | void 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 | + | ||
| 187 | + | void 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 | + | ||
| 198 | + | void 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 | + | ||
| 209 | + | void 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 | + | ||
| 221 | + | int 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(file created)
| @@ -0,0 +1,130 @@ | |||
| 1 | + | char 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 | + | }; | |