From 700e1b3b95116ee156d3af9dc7c09f8347eafbe4 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sun, 11 Sep 2016 21:51:39 +0000 Subject: [PATCH] initial checkin of C side of LDPC FSK decoder git-svn-id: https://svn.code.sf.net/p/freetel/code@2852 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/src/ldpc_dec.c | 253 +++++++++++++++ codec2-dev/src/mpdecode_core.c | 561 +++++++++++++++++++++++++++++++++ codec2-dev/src/mpdecode_core.h | 74 +++++ 3 files changed, 888 insertions(+) create mode 100644 codec2-dev/src/ldpc_dec.c create mode 100644 codec2-dev/src/mpdecode_core.c create mode 100644 codec2-dev/src/mpdecode_core.h diff --git a/codec2-dev/src/ldpc_dec.c b/codec2-dev/src/ldpc_dec.c new file mode 100644 index 00000000..805b4794 --- /dev/null +++ b/codec2-dev/src/ldpc_dec.c @@ -0,0 +1,253 @@ +/* + FILE...: ldpc_dec.c + AUTHOR.: Matthew C. Valenti, Rohit Iyer Seshadri, David Rowe + CREATED: Sep 2016 + + Command line C LDPC decoder derived from MpDecode.c in the CML + library. Allows us to run the same decoder in Octave and C. The + code is defined by the parameters and array stored in the include + file below, which can be machine generated from the Octave function + ldpc_fsk_lib.m:ldpc_decode() + + The include file also contains test input/output vectors for the LDPC + decoder for testing this program. + + Build: + + $ gcc -o ldpc_dec ldpc_dec.c mpdecode_core.c -Wall -lm -g + + TODO: + [ ] C cmd line encoder + [ ] SD output option + [ ] Es/No option for testing + [ ] decoder + [X] test mode or file I/O (incl stdin/stdout) + [X] Octave code to generate include file + + MAX_ITER as well + [ ] check into SVN + [ ] enc/dec running on cmd line + [ ] fsk_demod modified for soft decisions + [ ] drs232 modified for SD + + use UW syn cin this program to check BER with coding + [ ] revisit CML support, maybe blog post +*/ + +#include +#include +#include +#include +#include +#include +#include "mpdecode_core.h" + +/* Machine generated consts, H_rows, H_cols, test input/output data to + change LDPC code regenerate this file. */ + +#include "ldpc_code.h" + +void run_ldpc_decoder(int DecodedBits[], int ParityCheckCount[], double input[]); + +int main(int argc, char *argv[]) +{ + int CodeLength, NumberParityBits, max_iter; + int i, j, r, num_ok, num_runs; + + /* derive some parameters */ + + max_iter = MAX_ITER; + CodeLength = CODELENGTH; /* length of entire codeword */ + NumberParityBits = NUMBERPARITYBITS; + + if (argc < 2) { + fprintf(stderr, "usage: %s --test\n", argv[0]); + fprintf(stderr, "usage: %s InOneSDSymbolPerDouble OutOneBitPerInt\n", argv[0]); + exit(0); + } + + int *DecodedBits = calloc( max_iter*CodeLength, sizeof( int ) ); + int *ParityCheckCount = calloc( max_iter, sizeof(int) ); + + if (!strcmp(argv[1],"--test")) { + + /* test mode --------------------------------------------------------*/ + + fprintf(stderr, "Starting test using pre-compiled test data .....\n"); + fprintf(stderr, "Codeword length: %d\n", CodeLength); + fprintf(stderr, "Parity Bits....: %d\n", NumberParityBits); + + num_runs = 100; num_ok = 0; + + for(r=0; r +#include +#include "mpdecode_core.h" + +/* Phi function */ +static float phi0( + float x ) +{ + float z; + + if (x>10) + return( 0 ); + else if (x< 9.08e-5 ) + return( 10 ); + else if (x > 9) + return( 1.6881e-4 ); + /* return( 1.4970e-004 ); */ + else if (x > 8) + return( 4.5887e-4 ); + /* return( 4.0694e-004 ); */ + else if (x > 7) + return( 1.2473e-3 ); + /* return( 1.1062e-003 ); */ + else if (x > 6) + return( 3.3906e-3 ); + /* return( 3.0069e-003 ); */ + else if (x > 5) + return( 9.2168e-3 ); + /* return( 8.1736e-003 ); */ + else { + z = (float) exp(x); + return( (float) log( (z+1)/(z-1) ) ); + } +} + +static float correction( + float xinput ) +{ + if (xinput > 2.625 ) + return( 0 ); + else if (xinput < 1 ) + return( -0.375*xinput + 0.6825 ); + else + return( -0.1875*xinput + 0.5 ); + +} + +static float LambdaAPPstar( float mag1, + float mag2 ) +{ + if (mag1 > mag2) + return( fabs( mag2 + correction( mag1 + mag2 ) - correction( mag1 - mag2 ) ) ); + else + return( fabs( mag1 + correction( mag1 + mag2 ) - correction( mag2 - mag1 ) ) ); +} + +void init_c_v_nodes(struct c_node *c_nodes, + int shift, + int NumberParityBits, + int max_row_weight, + double *H_rows, + int H1, + int CodeLength, + struct v_node *v_nodes, + int NumberRowsHcols, + double *H_cols, + int max_col_weight, + int dec_type, + double *input) +{ + int i, j, k, count, cnt, c_index, v_index; + + /* first determine the degree of each c-node */ + + if (shift ==0){ + for (i=0;i 0 ) { + count++; + } + } + c_nodes[i].degree = count; + if (H1){ + if (i==0){ + c_nodes[i].degree=count+1; + } + else{ + c_nodes[i].degree=count+2; + } + } + } + } + else{ + cnt=0; + for (i=0;i<(NumberParityBits/shift);i++) { + for (k=0;k 0 ) { + count++; + } + } + c_nodes[cnt].degree = count; + if ((i==0)||(i==(NumberParityBits/shift)-1)){ + c_nodes[cnt].degree=count+1; + } + else{ + c_nodes[cnt].degree=count+2; + } + cnt++; + } + } + } + + if (H1){ + + if (shift ==0){ + for (i=0;i0){ + cnt=0; + for (i=0;i<(NumberParityBits/shift);i++){ + + for (k =0;k 0 ) { + count++; + } + } + v_nodes[i].degree = count; + } + + for(i=CodeLength-NumberParityBits+shift;i 0 ) { + count++; + } + } + v_nodes[i].degree = count; + } + } + + if (shift>0){ + v_nodes[CodeLength-1].degree =v_nodes[CodeLength-1].degree+1; + } + + + /* set up v_nodes */ + + for (i=0;i=CodeLength-NumberParityBits+shift)){ + v_nodes[i].index[j]=i-(CodeLength-NumberParityBits+shift)+count; + if (shift ==0){ + count=count+1; + } + else{ + count=count+shift; + } + } else { + v_nodes[i].index[j] = (int) (H_cols[i+j*NumberRowsHcols] - 1); + } + + /* search the connected c-node for the proper message value */ + for (c_index=0;c_index 0) + v_nodes[i].sign[j] = 0; + else + v_nodes[i].sign[j] = 1; + } + } + + /* detect errors */ + if (BitErrors[iter] == 0) + break; + } +} + + +/* function for doing the MP decoding */ +void MinSum( int BitErrors[], + int DecodedBits[], + struct c_node c_nodes[], + struct v_node v_nodes[], + int CodeLength, + int NumberParityBits, + int max_iter, + float r_scale_factor, + float q_scale_factor, + int data[] ) +{ + int i,j, iter, i_prime; + float min_beta; + int sign; + float temp_sum; + float Qi; + + for (iter=0;iter 0) + v_nodes[i].sign[j] = 0; + else + v_nodes[i].sign[j] = 1; + } + } + + /* count data bit errors, assuming that it is systematic */ + for (i=0;i 0) + v_nodes[i].sign[j] = 0; + else + v_nodes[i].sign[j] = 1; + } + } + + /* count data bit errors, assuming that it is systematic */ + for (i=0;i