Skip to content

Commit

Permalink
Write some low level FEC tests.
Browse files Browse the repository at this point in the history
These currently fail - there are some bugs in libfec.
  • Loading branch information
mutability committed Dec 8, 2020
1 parent fc8362f commit e4cefb7
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
dump978-fa
skyview978
faup978
fec_tests
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ faup978: faup978_main.o socket_input.o uat_message.o track.o faup978_reporter.o
skyaware978: skyaware978_main.o socket_input.o uat_message.o track.o skyaware_writer.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)

fec_tests: fec_tests.o libs/fec/init_rs_char.o libs/fec/decode_rs_char.o libs/fec/encode_rs_char.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@

format:
clang-format -style=file -i *.cc *.h

Expand Down
105 changes: 105 additions & 0 deletions fec_tests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "uat_protocol.h"

#include <cstdlib>
#include <iostream>
#include <vector>

extern "C" {
#include "fec/rs.h"
}

void test_rs_decode(unsigned seed, int trials, int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) {
srand(seed);

void *rs = ::init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad);

int NN = (1 << symsize) - 1;
int blocklen = NN - pad;
int datalen = blocklen - nroots;

std::vector<unsigned char> test_block(blocklen, 0);
std::vector<unsigned char> working_block(blocklen, 0);

for (int trial = 0; trial < trials; ++trial) {
/* build random test data, encode it */
for (int i = 0; i < datalen; ++i)
test_block[i] = std::rand() & NN;

::encode_rs_char(rs, test_block.data(), test_block.data() + datalen);

/* test errors */
for (int n_errors = 0; n_errors <= nroots; ++n_errors) {
working_block = test_block;

std::vector<int> error_val(blocklen, 0);

/* generate errors */
for (int i = 0; i < n_errors; ++i) {
int loc;
do {
loc = std::rand() % blocklen;
} while (error_val[loc]);

int bits;
do {
bits = std::rand() & NN;
} while (!bits);

error_val[loc] = bits;
working_block[loc] ^= bits;
}

/* try to decode */
int n_corrected = ::decode_rs_char(rs, working_block.data(), NULL, 0);

if (n_errors > nroots / 2) {
/* exceeded error correction capacity */
if (n_corrected >= 0) {
std::cerr << "RS(" << blocklen << "," << datalen << ") (seed: " << seed << " trial: " << trial << " errors: " << n_errors << ")"
<< " returned success, but should have failed" << std::endl;
}
} else {
if (n_corrected != n_errors) {
std::cerr << "RS(" << blocklen << "," << datalen << ") (seed: " << seed << " trial: " << trial << " errors: " << n_errors << ")"
<< " claimed to correct " << n_corrected << " errors" << std::endl;
}
if (working_block != test_block) {
std::cerr << "RS(" << blocklen << "," << datalen << ") (seed: " << seed << " trial: " << trial << " errors: " << n_errors << ")"
<< " data wasn't corrected correctly" << std::endl;
}
}
}
}

::free_rs_char(rs);
}

int main(int argc, char **argv) {

test_rs_decode(/* seed */ 1,
/* trials */ 10000,
/* symsize */ 8,
/* gfpoly */ flightaware::uat::fec::DOWNLINK_SHORT_POLY,
/* fcr */ 120,
/* prim */ 1,
/* nroots */ flightaware::uat::fec::DOWNLINK_SHORT_ROOTS,
/* pad */ flightaware::uat::fec::DOWNLINK_SHORT_PAD);

test_rs_decode(/* seed */ 1,
/* trials */ 10000,
/* symsize */ 8,
/* gfpoly */ flightaware::uat::fec::DOWNLINK_LONG_POLY,
/* fcr */ 120,
/* prim */ 1,
/* nroots */ flightaware::uat::fec::DOWNLINK_LONG_ROOTS,
/* pad */ flightaware::uat::fec::DOWNLINK_LONG_PAD);

test_rs_decode(/* seed */ 1,
/* trials */ 10000,
/* symsize */ 8,
/* gfpoly */ flightaware::uat::fec::UPLINK_BLOCK_POLY,
/* fcr */ 120,
/* prim */ 1,
/* nroots */ flightaware::uat::fec::UPLINK_BLOCK_ROOTS,
/* pad */ flightaware::uat::fec::UPLINK_BLOCK_PAD);
}
52 changes: 52 additions & 0 deletions libs/fec/encode_rs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* Reed-Solomon encoder
* Copyright 2002, Phil Karn, KA9Q
* May be used under the terms of the GNU Lesser General Public License (LGPL)
*/
#include <string.h>

#ifdef FIXED
#include "fixed.h"
#elif defined(BIGSYM)
#include "int.h"
#else
#include "char.h"
#endif

void ENCODE_RS(
#ifdef FIXED
data_t *data, data_t *bb,int pad){
#else
void *p,data_t *data, data_t *bb){
struct rs *rs = (struct rs *)p;
#endif
int i, j;
data_t feedback;

#ifdef FIXED
/* Check pad parameter for validity */
if(pad < 0 || pad >= NN)
return;
#endif

memset(bb,0,NROOTS*sizeof(data_t));

for(i=0;i<NN-NROOTS-PAD;i++){
feedback = INDEX_OF[data[i] ^ bb[0]];
if(feedback != A0){ /* feedback term is non-zero */
#ifdef UNNORMALIZED
/* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
* always be for the polynomials constructed by init_rs()
*/
feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
#endif
for(j=1;j<NROOTS;j++)
bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
}
/* Shift */
memmove(&bb[0],&bb[1],sizeof(data_t)*(NROOTS-1));
if(feedback != A0)
bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
else
bb[NROOTS-1] = 0;
}
}
58 changes: 58 additions & 0 deletions libs/fec/encode_rs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* The guts of the Reed-Solomon encoder, meant to be #included
* into a function body with the following typedefs, macros and variables supplied
* according to the code parameters:
* data_t - a typedef for the data symbol
* data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded
* data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols
* NROOTS - the number of roots in the RS code generator polynomial,
* which is the same as the number of parity symbols in a block.
Integer variable or literal.
*
* NN - the total number of symbols in a RS block. Integer variable or literal.
* PAD - the number of pad symbols in a block. Integer variable or literal.
* ALPHA_TO - The address of an array of NN elements to convert Galois field
* elements in index (log) form to polynomial form. Read only.
* INDEX_OF - The address of an array of NN elements to convert Galois field
* elements in polynomial form to index (log) form. Read only.
* MODNN - a function to reduce its argument modulo NN. May be inline or a macro.
* GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form
* The memset() and memmove() functions are used. The appropriate header
* file declaring these functions (usually <string.h>) must be included by the calling
* program.
* Copyright 2004, Phil Karn, KA9Q
* May be used under the terms of the GNU Lesser General Public License (LGPL)
*/


#undef A0
#define A0 (NN) /* Special reserved value encoding zero in index form */

{
int i, j;
data_t feedback;

memset(parity,0,NROOTS*sizeof(data_t));

for(i=0;i<NN-NROOTS-PAD;i++){
feedback = INDEX_OF[data[i] ^ parity[0]];
if(feedback != A0){ /* feedback term is non-zero */
#ifdef UNNORMALIZED
/* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
* always be for the polynomials constructed by init_rs()
*/
feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
#endif
for(j=1;j<NROOTS;j++)
parity[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
}
/* Shift */
memmove(&parity[0],&parity[1],sizeof(data_t)*(NROOTS-1));
if(feedback != A0)
parity[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
else
parity[NROOTS-1] = 0;
}
}
15 changes: 15 additions & 0 deletions libs/fec/encode_rs_char.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* Reed-Solomon encoder
* Copyright 2002, Phil Karn, KA9Q
* May be used under the terms of the GNU Lesser General Public License (LGPL)
*/
#include <string.h>

#include "char.h"
#include "rs-common.h"

void encode_rs_char(void *p,data_t *data, data_t *parity){
struct rs *rs = (struct rs *)p;

#include "encode_rs.h"

}
1 change: 1 addition & 0 deletions libs/fec/rs.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define _FEC_RS_H_

/* General purpose RS codec, 8-bit symbols */
void encode_rs_char(void *rs,unsigned char *data,unsigned char *parity);
int decode_rs_char(void *rs,unsigned char *data,int *eras_pos,
int no_eras);
void *init_rs_char(int symsize,int gfpoly,
Expand Down

0 comments on commit e4cefb7

Please sign in to comment.