-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Short message decoder implementation
- Loading branch information
Showing
8 changed files
with
2,199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
CC = gcc | ||
CFLAGS = -Wall -Wextra -O3 -std=c99 | ||
LDFLAGS = -L. -ldecshortmsg | ||
RM = rm | ||
AR = ar | ||
|
||
.PHONY: all | ||
all: libdecshortmsg usage | ||
|
||
usage: libdecshortmsg dec_short_usage.c | ||
$(CC) dec_short_usage.c $(LDFLAGS) -o dec_usage | ||
|
||
libdecshortmsg: dec_short_msg.o rs/decode_rs.o viterbi_short/spiral-vit_scalar_1280.o | ||
$(AR) rcs libdecshortmsg.a dec_short_msg.o rs/decode_rs.o viterbi_short/spiral-vit_scalar_1280.o | ||
|
||
dec_short_msg.o: dec_short_msg.c | ||
$(CC) $(CFLAGS) -c -fPIC dec_short_msg.c -o dec_short_msg.o | ||
|
||
rs/decode_rs.o: rs/decode_rs.c | ||
$(CC) $(CFLAGS) -c -fPIC rs/decode_rs.c -o rs/decode_rs.o | ||
|
||
viterbi/spiral-vit_scalar.o: viterbi_short/spiral-vit_scalar_1280.c | ||
$(CC) $(CFLAGS) -c -fPIC viterbi_short/spiral-vit_scalar_1280.c -o viterbi_short/spiral-vit_scalar_1280.o | ||
|
||
clean: clean-debug | ||
-$(RM) libdecshortmsg.a dec_short_msg.o rs/decode_rs.o viterbi_short/spiral-vit_scalar_1280.o | ||
-$(RM) usage | ||
|
||
clean-debug: | ||
-$(RM) debug_* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
* Viterbi encoder based on SPIRAL (http://spiral.ece.cmu.edu/vitgen/) decoder | ||
* Reed-Solonom decoder is Phil Karn's work | ||
*/ | ||
|
||
/* | ||
* Revised and modified by szabolor | ||
* 2015, 2016 | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include "dec_short_msg.h" | ||
|
||
const uint8_t Scrambler[320] = { | ||
0xff, 0x48, 0x0e, 0xc0, 0x9a, 0x0d, 0x70, 0xbc, 0x8e, 0x2c, 0x93, 0xad, 0xa7, 0xb7, 0x46, 0xce, | ||
0x5a, 0x97, 0x7d, 0xcc, 0x32, 0xa2, 0xbf, 0x3e, 0x0a, 0x10, 0xf1, 0x88, 0x94, 0xcd, 0xea, 0xb1, | ||
0xfe, 0x90, 0x1d, 0x81, 0x34, 0x1a, 0xe1, 0x79, 0x1c, 0x59, 0x27, 0x5b, 0x4f, 0x6e, 0x8d, 0x9c, | ||
0xb5, 0x2e, 0xfb, 0x98, 0x65, 0x45, 0x7e, 0x7c, 0x14, 0x21, 0xe3, 0x11, 0x29, 0x9b, 0xd5, 0x63, | ||
0xfd, 0x20, 0x3b, 0x02, 0x68, 0x35, 0xc2, 0xf2, 0x38, 0xb2, 0x4e, 0xb6, 0x9e, 0xdd, 0x1b, 0x39, | ||
0x6a, 0x5d, 0xf7, 0x30, 0xca, 0x8a, 0xfc, 0xf8, 0x28, 0x43, 0xc6, 0x22, 0x53, 0x37, 0xaa, 0xc7, | ||
0xfa, 0x40, 0x76, 0x04, 0xd0, 0x6b, 0x85, 0xe4, 0x71, 0x64, 0x9d, 0x6d, 0x3d, 0xba, 0x36, 0x72, | ||
0xd4, 0xbb, 0xee, 0x61, 0x95, 0x15, 0xf9, 0xf0, 0x50, 0x87, 0x8c, 0x44, 0xa6, 0x6f, 0x55, 0x8f, | ||
0xf4, 0x80, 0xec, 0x09, 0xa0, 0xd7, 0x0b, 0xc8, 0xe2, 0xc9, 0x3a, 0xda, 0x7b, 0x74, 0x6c, 0xe5, | ||
0xa9, 0x77, 0xdc, 0xc3, 0x2a, 0x2b, 0xf3, 0xe0, 0xa1, 0x0f, 0x18, 0x89, 0x4c, 0xde, 0xab, 0x1f, | ||
0xe9, 0x01, 0xd8, 0x13, 0x41, 0xae, 0x17, 0x91, 0xc5, 0x92, 0x75, 0xb4, 0xf6, 0xe8, 0xd9, 0xcb, | ||
0x52, 0xef, 0xb9, 0x86, 0x54, 0x57, 0xe7, 0xc1, 0x42, 0x1e, 0x31, 0x12, 0x99, 0xbd, 0x56, 0x3f, | ||
0xd2, 0x03, 0xb0, 0x26, 0x83, 0x5c, 0x2f, 0x23, 0x8b, 0x24, 0xeb, 0x69, 0xed, 0xd1, 0xb3, 0x96, | ||
0xa5, 0xdf, 0x73, 0x0c, 0xa8, 0xaf, 0xcf, 0x82, 0x84, 0x3c, 0x62, 0x25, 0x33, 0x7a, 0xac, 0x7f, | ||
0xa4, 0x07, 0x60, 0x4d, 0x06, 0xb8, 0x5e, 0x47, 0x16, 0x49, 0xd6, 0xd3, 0xdb, 0xa3, 0x67, 0x2d, | ||
0x4b, 0xbe, 0xe6, 0x19, 0x51, 0x5f, 0x9f, 0x05, 0x08, 0x78, 0xc4, 0x4a, 0x66, 0xf5, 0x58, 0xff, | ||
0x48, 0x0e, 0xc0, 0x9a, 0x0d, 0x70, 0xbc, 0x8e, 0x2c, 0x93, 0xad, 0xa7, 0xb7, 0x46, 0xce, 0x5a, | ||
0x97, 0x7d, 0xcc, 0x32, 0xa2, 0xbf, 0x3e, 0x0a, 0x10, 0xf1, 0x88, 0x94, 0xcd, 0xea, 0xb1, 0xfe, | ||
0x90, 0x1d, 0x81, 0x34, 0x1a, 0xe1, 0x79, 0x1c, 0x59, 0x27, 0x5b, 0x4f, 0x6e, 0x8d, 0x9c, 0xb5, | ||
0x2e, 0xfb, 0x98, 0x65, 0x45, 0x7e, 0x7c, 0x14, 0x21, 0xe3, 0x11, 0x29, 0x9b, 0xd5, 0x63, 0xfd, | ||
}; | ||
|
||
/* Deinterleave data: | ||
* | ||
* - The bits of every interleaved byte is spread with 80 bit distance of each | ||
* other. This function reorder these bits to be neighboring again. | ||
* - The first interleaved column (65 byte) is the SYNC_POLY (0x48), ommit it (thus i=1). | ||
* - The CCSDS standard using CONV_POLY_B (0x6d) in inverted format, but | ||
* viterbi decoder assumes non-inverted bits, so invert every second bit | ||
* by hand. | ||
*/ | ||
void deinterleave(uint8_t raw[RAW_SIZE], uint8_t conv[CONV_SIZE]) { | ||
uint16_t i = 0; | ||
uint16_t j = 0; | ||
uint16_t counter = 0; | ||
|
||
while (counter < RAW_SIZE) { | ||
if (i >= RAW_SIZE) { | ||
i -= (RAW_SIZE - 1); | ||
} | ||
if (++counter > INTERLEAVER_PILOT_BITS) { | ||
conv[j++] = raw[i]; | ||
// printf("%4d: %4d -> %02x [INTER]\n", counter, j, conv[j-1]); | ||
} else { | ||
// printf("%4d: %4d -> %02x [PILOT]\n", counter, i, raw[i]); | ||
} | ||
i += INTERLEAVER_STEP_SIZE; | ||
} | ||
} | ||
|
||
/* Viterbi decoder: | ||
* It uses the one generated from http://www.spiral.net/ | ||
*/ | ||
void viterbi(uint8_t conv[CONV_SIZE], uint8_t dec_data[RS_SIZE]) { | ||
struct v *vp; | ||
COMPUTETYPE conv_compute[CONV_SIZE]; | ||
int i; | ||
|
||
if((vp = create_viterbi(FRAMEBITS)) == NULL){ | ||
printf("create_viterbi failed\n"); | ||
exit(1); | ||
} | ||
|
||
init_viterbi(vp, 0); | ||
|
||
// COMPUTETYPE is set to uint32, so convert uint8 to uint32 | ||
// but the softbit value should be between 0 and 255 (!) | ||
i = CONV_SIZE; | ||
while (i--) { | ||
conv_compute[i] = conv[i]; | ||
} | ||
|
||
update_viterbi_blk(vp, conv_compute, FRAMEBITS+(K-1)); | ||
chainback_viterbi(vp, dec_data, FRAMEBITS, 0); | ||
|
||
delete_viterbi(vp); | ||
} | ||
|
||
void descramble(uint8_t dec_data[RS_SIZE], uint8_t rs[RS_BLOCK_SIZE]) { | ||
uint16_t i; | ||
|
||
for (i = 0; i < RS_BLOCK_SIZE; ++i) { | ||
rs[i] = dec_data[i] ^ Scrambler[i]; | ||
} | ||
} | ||
|
||
void rs_decode(uint8_t rs[RS_BLOCK_SIZE], uint8_t data[DATA_SIZE], int8_t *error) { | ||
uint16_t i; | ||
|
||
*error = decode_rs_8(rs, NULL, 0); | ||
|
||
// use 'memcpy' instead! | ||
for (i = 0; i < DATA_SIZE; ++i) { | ||
data[i] = rs[i]; | ||
} | ||
} | ||
|
||
void decode_data(uint8_t raw[RAW_SIZE], uint8_t data[DATA_SIZE], int8_t *error) { | ||
uint8_t conv[CONV_SIZE]; | ||
uint8_t dec_data[RS_SIZE]; | ||
uint8_t rs[RS_BLOCK_SIZE]; | ||
|
||
deinterleave(raw, conv); | ||
viterbi(conv, dec_data); | ||
descramble(dec_data, rs); | ||
rs_decode(rs, data, error); | ||
} | ||
|
||
void decode_data_debug( | ||
uint8_t raw[RAW_SIZE], // Data to be decoded | ||
uint8_t data[DATA_SIZE], // Decoded data | ||
int8_t *error, // RS decoder modules corrected errors or -1 if unrecoverable error happened | ||
uint8_t conv[CONV_SIZE], // Deinterleaved data with SYNC removed | ||
uint8_t dec_data[RS_SIZE], // Viterbi decoder output | ||
uint8_t rs[RS_BLOCK_SIZE] // RS codeblocks without the leading padding 95 zeros | ||
) { | ||
deinterleave(raw, conv); | ||
viterbi(conv, dec_data); | ||
descramble(dec_data, rs); | ||
rs_decode(rs, data, error); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#ifndef DEC_REF_H | ||
#define DEC_REF_H | ||
|
||
#include <stdint.h> | ||
#include "viterbi_short/spiral-vit_scalar_1280.h" | ||
#include "rs/decode_rs.h" | ||
|
||
#define DEBUG | ||
|
||
#define INTERLEAVER_STEP_SIZE 51 | ||
#define INTERLEAVER_PILOT_BITS 80 | ||
|
||
#define RAW_SIZE 2652 // 51*52 | ||
#define CONV_SIZE 2572 | ||
|
||
#define RS_SIZE 160 | ||
#define DATA_SIZE 128 | ||
#define FRAME_BITS 1280 | ||
#define RS_BLOCK_SIZE 160 | ||
|
||
extern const uint8_t Scrambler[320]; | ||
|
||
void decode_data(uint8_t raw[RAW_SIZE], uint8_t data[DATA_SIZE], int8_t *error); | ||
|
||
#ifdef DEBUG | ||
void decode_data_debug(uint8_t raw[RAW_SIZE], uint8_t data[DATA_SIZE], int8_t *error, uint8_t conv[CONV_SIZE], uint8_t dec_data[RS_SIZE], uint8_t rs[RS_BLOCK_SIZE]); | ||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include "dec_short_msg.h" | ||
|
||
void test_decode_data(char const *filename) { | ||
FILE *fp; | ||
uint8_t raw[RAW_SIZE]; | ||
uint8_t data[DATA_SIZE]; | ||
int8_t error; | ||
|
||
fp = fopen(filename, "rb"); | ||
fread(raw, 1, sizeof(raw), fp); | ||
fclose(fp); | ||
|
||
decode_data(raw, data, &error); | ||
|
||
printf("Errors: RS = %d\n", error); | ||
fp = fopen("dec_data", "wb"); | ||
fwrite(data, 1, sizeof(data), fp); | ||
fclose(fp); | ||
} | ||
|
||
void test_decode_data_debug(char const *filename) { | ||
FILE *fp; | ||
uint8_t raw[RAW_SIZE] = {0}; // Raw data to be decoded | ||
uint8_t conv[CONV_SIZE] = {0}; // Deinterleaved raw block with SYNC removed | ||
uint8_t dec_data[RS_SIZE] = {0}; // Viterbi output: RS blocks interleaved and scrambled | ||
uint8_t rs[RS_BLOCK_SIZE] = {0}; // RS blocks without leading padding zeros | ||
uint8_t data[DATA_SIZE] = {0}; // Decoded data | ||
int8_t error = 0; // RS block decoded and corrected errors (or -1 if unrecoverable error occured) | ||
|
||
int i; | ||
|
||
fp = fopen(filename, "rb"); | ||
fread(raw, 1, RAW_SIZE, fp); | ||
fclose(fp); | ||
|
||
decode_data_debug(raw, data, &error, conv, dec_data, rs); | ||
|
||
printf("Errors: RS = %d\n", error); | ||
|
||
fp = fopen("out/data", "wb"); | ||
fwrite(data, 1, DATA_SIZE, fp); | ||
fclose(fp); | ||
|
||
fp = fopen("out/conv", "wb"); | ||
fwrite(conv, 1, CONV_SIZE, fp); | ||
fclose(fp); | ||
|
||
fp = fopen("out/dec_data", "wb"); | ||
fwrite(dec_data, 1, RS_SIZE, fp); | ||
fclose(fp); | ||
|
||
fp = fopen("out/rs", "wb"); | ||
fwrite(rs, 1, RS_BLOCK_SIZE, fp); | ||
fclose(fp); | ||
} | ||
|
||
int main(int argc, char const *argv[]) { | ||
// test_decode_data(argv[1]); | ||
test_decode_data_debug(argv[1]); | ||
|
||
return 0; | ||
} |
Oops, something went wrong.