diff options
| author | drowe67 <[email protected]> | 2023-07-20 08:59:48 +0930 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-07-20 08:59:48 +0930 |
| commit | 06d4c11e699b0351765f10398abb4f663a984f36 (patch) | |
| tree | 33e22af0814c5b6c3d676f096ae8c2ac8a3ed9f0 /src/ldpc_dec.c | |
| parent | 6588e77f38bdebd7adffe091b22e7760d95d0ccb (diff) | |
| parent | 4d6c143c0abec15e1d6ed1fd95d36f80e6cb7df8 (diff) | |
Merge pull request #3 from drowe67/dr-cleanup21.2.0
Cleanup Part 2
Diffstat (limited to 'src/ldpc_dec.c')
| -rw-r--r-- | src/ldpc_dec.c | 430 |
1 files changed, 231 insertions, 199 deletions
diff --git a/src/ldpc_dec.c b/src/ldpc_dec.c index 94d5c33..82bdacb 100644 --- a/src/ldpc_dec.c +++ b/src/ldpc_dec.c @@ -1,4 +1,4 @@ -/* +/* FILE...: ldpc_dec.c AUTHOR.: Matthew C. Valenti, Rohit Iyer Seshadri, David Rowe CREATED: Sep 2016 @@ -10,227 +10,259 @@ #include <assert.h> #include <errno.h> #include <math.h> -#include <stdlib.h> #include <stdint.h> -#include <string.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> -#include "mpdecode_core.h" #include "ldpc_codes.h" +#include "mpdecode_core.h" #include "ofdm_internal.h" int opt_exists(char *argv[], int argc, char opt[]) { - int i; - for (i=0; i<argc; i++) { - if (strcmp(argv[i], opt) == 0) { - return i; - } + int i; + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], opt) == 0) { + return i; } - return 0; + } + return 0; } - -int main(int argc, char *argv[]) -{ - int CodeLength, NumberParityBits; - int i, codename, parityCheckCount, mute, testframes; - int data_bits_per_frame; - struct LDPC ldpc; - int iter, total_iters; - int Tbits, Terrs, Tbits_raw, Terrs_raw, Tpackets, Tpacketerrs; - - int unused_data_bits = 84; - - if (argc < 2) { - fprintf(stderr, "\n"); - fprintf(stderr, "usage: %s --listcodes\n\n", argv[0]); - fprintf(stderr, " List supported codes (more can be added via using Octave ldpc scripts)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "usage: %s InOneSymbolPerFloat OutOneBitPerByte [--sd] [--half] [--code CodeName] [--testframes]", argv[0]); - fprintf(stderr, " [--unused numUnusedDataBits]\n\n"); - fprintf(stderr, " InOneSymbolPerFloat Input file of float LLRs, use - for the \n"); - fprintf(stderr, " file names to use stdin/stdout\n"); - fprintf(stderr, " --code Use LDPC code CodeName\n"); - fprintf(stderr, " --listcodes List available LDPC codes\n"); - fprintf(stderr, " --sd Treat input file samples as BPSK Soft Decision\n"); - fprintf(stderr, " demod outputs rather than LLRs\n"); - fprintf(stderr, " --mute Only output frames with < 10%% parity check fails\n"); - fprintf(stderr, " --testframes built in test frame modem, requires --testframes at encoder\n"); - fprintf(stderr, " --unused number of unused data bits, which are set to 1's at enc and dec\n"); - fprintf(stderr, "\n"); - - fprintf(stderr, "Example in testframe mode:\n\n"); - fprintf(stderr, " $ ./ldpc_enc /dev/zero - --sd --code HRA_112_112 --testframes 10 |\n"); - fprintf(stderr, " ./ldpc_dec - /dev/null --code HRA_112_112 --sd --testframes\n"); - exit(0); +int main(int argc, char *argv[]) { + int CodeLength, NumberParityBits; + int i, codename, parityCheckCount, mute, testframes; + int data_bits_per_frame; + struct LDPC ldpc; + int iter, total_iters; + int Tbits, Terrs, Tbits_raw, Terrs_raw, Tpackets, Tpacketerrs; + + int unused_data_bits = 84; + + if (argc < 2) { + fprintf(stderr, "\n"); + fprintf(stderr, "usage: %s --listcodes\n\n", argv[0]); + fprintf(stderr, + " List supported codes (more can be added via using Octave ldpc " + "scripts)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, + "usage: %s InOneSymbolPerFloat OutOneBitPerByte [--sd] [--half] " + "[--code CodeName] [--testframes]", + argv[0]); + fprintf(stderr, " [--unused numUnusedDataBits]\n\n"); + fprintf(stderr, + " InOneSymbolPerFloat Input file of float LLRs, use - for " + "the \n"); + fprintf(stderr, + " file names to use stdin/stdout\n"); + fprintf(stderr, " --code Use LDPC code CodeName\n"); + fprintf(stderr, " --listcodes List available LDPC codes\n"); + fprintf(stderr, + " --sd Treat input file samples as BPSK Soft " + "Decision\n"); + fprintf(stderr, + " demod outputs rather than LLRs\n"); + fprintf(stderr, + " --mute Only output frames with < 10%% parity " + "check fails\n"); + fprintf(stderr, + " --testframes built in test frame modem, requires " + "--testframes at encoder\n"); + fprintf(stderr, + " --unused number of unused data bits, which are " + "set to 1's at enc and dec\n"); + fprintf(stderr, "\n"); + + fprintf(stderr, "Example in testframe mode:\n\n"); + fprintf(stderr, + " $ ./ldpc_enc /dev/zero - --sd --code HRA_112_112 --testframes 10 " + "|\n"); + fprintf(stderr, + " ./ldpc_dec - /dev/null --code HRA_112_112 --sd --testframes\n"); + exit(0); + } + + if ((codename = opt_exists(argv, argc, "--listcodes")) != 0) { + ldpc_codes_list(); + exit(0); + } + + /* set up LDPC code */ + + int code_index = 0; + if ((codename = opt_exists(argv, argc, "--code")) != 0) + code_index = ldpc_codes_find(argv[codename + 1]); + memcpy(&ldpc, &ldpc_codes[code_index], sizeof(struct LDPC)); + fprintf(stderr, "Using: %s\n", ldpc.name); + + CodeLength = ldpc.CodeLength; /* length of entire codeword */ + NumberParityBits = ldpc.NumberParityBits; + data_bits_per_frame = ldpc.NumberRowsHcols; + unsigned char ibits[data_bits_per_frame]; + unsigned char pbits[NumberParityBits]; + uint8_t out_char[CodeLength]; + + testframes = 0; + total_iters = 0; + Tbits = Terrs = Tbits_raw = Terrs_raw = Tpackets = Tpacketerrs = 0; + + FILE *fin, *fout; + int sdinput, nread, offset = 0; + + /* File I/O mode ------------------------------------------------*/ + + if (strcmp(argv[1], "-") == 0) + fin = stdin; + else if ((fin = fopen(argv[1], "rb")) == NULL) { + fprintf(stderr, "Error opening input SD file: %s: %s.\n", argv[1], + strerror(errno)); + exit(1); + } + + if (strcmp(argv[2], "-") == 0) + fout = stdout; + else if ((fout = fopen(argv[2], "wb")) == NULL) { + fprintf(stderr, "Error opening output bit file: %s: %s.\n", argv[2], + strerror(errno)); + exit(1); + } + + sdinput = 0; + mute = 0; + testframes = 0; + if (opt_exists(argv, argc, "--sd")) { + sdinput = 1; + } + if (opt_exists(argv, argc, "--mute")) { + mute = 1; + } + unused_data_bits = 0; + int arg; + if ((arg = opt_exists(argv, argc, "--unused"))) { + unused_data_bits = atoi(argv[arg + 1]); + } + if (opt_exists(argv, argc, "--testframes")) { + testframes = 1; + uint16_t r[data_bits_per_frame]; + ofdm_rand(r, data_bits_per_frame); + + for (i = 0; i < data_bits_per_frame - unused_data_bits; i++) { + ibits[i] = r[i] > 16384; } - - if ((codename = opt_exists(argv, argc, "--listcodes")) != 0) { - ldpc_codes_list(); - exit(0); + for (i = data_bits_per_frame - unused_data_bits; i < data_bits_per_frame; + i++) { + ibits[i] = 1; } + encode(&ldpc, ibits, pbits); + } - /* set up LDPC code */ - - int code_index = 0; - if ((codename = opt_exists(argv, argc, "--code")) != 0) - code_index = ldpc_codes_find(argv[codename+1]); - memcpy(&ldpc,&ldpc_codes[code_index],sizeof(struct LDPC)); - fprintf(stderr, "Using: %s\n", ldpc.name); - - CodeLength = ldpc.CodeLength; /* length of entire codeword */ - NumberParityBits = ldpc.NumberParityBits; - data_bits_per_frame = ldpc.NumberRowsHcols; - unsigned char ibits[data_bits_per_frame]; - unsigned char pbits[NumberParityBits]; - uint8_t out_char[CodeLength]; - - testframes = 0; - total_iters = 0; - Tbits = Terrs = Tbits_raw = Terrs_raw = Tpackets = Tpacketerrs = 0; - - FILE *fin, *fout; - int sdinput, nread, offset=0; - - /* File I/O mode ------------------------------------------------*/ - - if (strcmp(argv[1], "-") == 0) fin = stdin; - else if ( (fin = fopen(argv[1],"rb")) == NULL ) { - fprintf(stderr, "Error opening input SD file: %s: %s.\n", - argv[1], strerror(errno)); - exit(1); - } - - if (strcmp(argv[2], "-") == 0) fout = stdout; - else if ( (fout = fopen(argv[2],"wb")) == NULL ) { - fprintf(stderr, "Error opening output bit file: %s: %s.\n", - argv[2], strerror(errno)); - exit(1); - } + float *input_float = calloc(CodeLength, sizeof(float)); - sdinput = 0; mute = 0; testframes = 0; - if (opt_exists(argv, argc, "--sd")) { - sdinput = 1; - } - if (opt_exists(argv, argc, "--mute")) { - mute = 1; - } - unused_data_bits = 0; int arg; - if ((arg = opt_exists(argv, argc, "--unused"))) { - unused_data_bits = atoi(argv[arg+1]); - } - if (opt_exists(argv, argc, "--testframes")) { - testframes = 1; - uint16_t r[data_bits_per_frame]; - ofdm_rand(r, data_bits_per_frame); + nread = CodeLength - unused_data_bits; + fprintf(stderr, "CodeLength: %d offset: %d\n", CodeLength, offset); - for(i=0; i<data_bits_per_frame-unused_data_bits; i++) { - ibits[i] = r[i] > 16384; + while (fread(input_float, sizeof(float), nread, fin) == nread) { + if (testframes) { + /* BPSK SD and bit LLRs get mapped roughly the same way so this just + * happens to work for both */ + char in_char; + for (i = 0; i < data_bits_per_frame - unused_data_bits; i++) { + in_char = input_float[i] < 0; + if (in_char != ibits[i]) { + Terrs_raw++; } - for(i=data_bits_per_frame-unused_data_bits; i<data_bits_per_frame; i++) { - ibits[i] = 1; + Tbits_raw++; + } + for (i = 0; i < NumberParityBits; i++) { + in_char = input_float[i + data_bits_per_frame - unused_data_bits] < 0; + if (in_char != pbits[i]) { + Terrs_raw++; } - encode(&ldpc, ibits, pbits); + Tbits_raw++; + } } - float *input_float = calloc(CodeLength, sizeof(float)); - - nread = CodeLength - unused_data_bits; - fprintf(stderr, "CodeLength: %d offset: %d\n", CodeLength, offset); - - while(fread(input_float, sizeof(float), nread, fin) == nread) { - if (testframes) { - /* BPSK SD and bit LLRs get mapped roughly the same way so this just happens to work for both */ - char in_char; - for (i=0; i<data_bits_per_frame-unused_data_bits; i++) { - in_char = input_float[i] < 0; - if (in_char != ibits[i]) { - Terrs_raw++; - } - Tbits_raw++; - } - for (i=0; i<NumberParityBits; i++) { - in_char = input_float[i+data_bits_per_frame-unused_data_bits] < 0; - if (in_char != pbits[i]) { - Terrs_raw++; - } - Tbits_raw++; - } - } - - if (sdinput) { - /* map BPSK SDs to bit LLRs */ - float llr[CodeLength-unused_data_bits]; - sd_to_llr(llr, input_float, CodeLength-unused_data_bits); - - /* insert unused data LLRs */ - - float llr_tmp[CodeLength]; - for(i=0; i<data_bits_per_frame-unused_data_bits; i++) - llr_tmp[i] = llr[i]; // rx data bits - for(i=data_bits_per_frame-unused_data_bits; i<data_bits_per_frame; i++) - llr_tmp[i] = -10.0; // known data bits high likelhood - for(i=data_bits_per_frame; i<CodeLength; i++) - llr_tmp[i] = llr[i-unused_data_bits]; // rx parity bits - memcpy(input_float, llr_tmp, sizeof(float)*CodeLength); - } - - iter = run_ldpc_decoder(&ldpc, out_char, input_float, &parityCheckCount); - //fprintf(stderr, "iter: %d\n", iter); - total_iters += iter; - - if (mute) { - - // Output data bits only if decoder converged, or was - // within 10% of all parity checks converging (10% est - // BER). Useful for real world operation as it can - // resync and won't send crappy packets to the decoder - - float ber_est = (float)(ldpc.NumberParityBits - parityCheckCount)/ldpc.NumberParityBits; - //fprintf(stderr, "iter: %4d parityCheckErrors: %4d ber: %3.2f\n", iter, ldpc.NumberParityBits - parityCheckCount, ber_est); - if (ber_est < 0.1) { - fwrite(out_char, sizeof(char), ldpc.NumberRowsHcols, fout); - } - - } - - fwrite(out_char, sizeof(char), data_bits_per_frame, fout); - - if (testframes) { - int perr = 0; - for (i=0; i<data_bits_per_frame; i++) { - if (out_char[i] != ibits[i]) { - Terrs++; - perr = 1; - } - Tbits++; - } - Tpackets++; if (perr) { Tpacketerrs++; fprintf(stderr,"x"); } else fprintf(stderr,"."); - } - //fprintf(stderr, "Terrs_raw: %d Tbits_raw: %d Terr: %d Tbits: %d\n", Terrs_raw, Tbits_raw, Terrs, Tbits); + if (sdinput) { + /* map BPSK SDs to bit LLRs */ + float llr[CodeLength - unused_data_bits]; + sd_to_llr(llr, input_float, CodeLength - unused_data_bits); + + /* insert unused data LLRs */ + + float llr_tmp[CodeLength]; + for (i = 0; i < data_bits_per_frame - unused_data_bits; i++) + llr_tmp[i] = llr[i]; // rx data bits + for (i = data_bits_per_frame - unused_data_bits; i < data_bits_per_frame; + i++) + llr_tmp[i] = -10.0; // known data bits high likelhood + for (i = data_bits_per_frame; i < CodeLength; i++) + llr_tmp[i] = llr[i - unused_data_bits]; // rx parity bits + memcpy(input_float, llr_tmp, sizeof(float) * CodeLength); } - free(input_float); - if (fin != NULL) fclose(fin); - if (fout != NULL) fclose(fout); + iter = run_ldpc_decoder(&ldpc, out_char, input_float, &parityCheckCount); + // fprintf(stderr, "iter: %d\n", iter); + total_iters += iter; + + if (mute) { + // Output data bits only if decoder converged, or was + // within 10% of all parity checks converging (10% est + // BER). Useful for real world operation as it can + // resync and won't send crappy packets to the decoder + + float ber_est = (float)(ldpc.NumberParityBits - parityCheckCount) / + ldpc.NumberParityBits; + // fprintf(stderr, "iter: %4d parityCheckErrors: %4d ber: %3.2f\n", iter, + // ldpc.NumberParityBits - parityCheckCount, ber_est); + if (ber_est < 0.1) { + fwrite(out_char, sizeof(char), ldpc.NumberRowsHcols, fout); + } + } - fprintf(stderr, "total iters %d\n", total_iters); + fwrite(out_char, sizeof(char), data_bits_per_frame, fout); if (testframes) { - fprintf(stderr, "Raw Tbits: %6d Terr: %6d BER: %4.3f\n", Tbits_raw, Terrs_raw, - (float)Terrs_raw/(Tbits_raw+1E-12)); - float coded_ber = (float)Terrs/(Tbits+1E-12); - fprintf(stderr, "Coded Tbits: %6d Terr: %6d BER: %4.3f\n", Tbits, Terrs, coded_ber); - fprintf(stderr, " Tpkts: %6d Tper: %6d PER: %4.3f\n", Tpackets, Tpacketerrs, Tpacketerrs/(Tpackets+1E-12)); - - /* set return code for Ctest */ - if (Tpackets && (coded_ber < 0.01)) - return 0; - else - return 1; + int perr = 0; + for (i = 0; i < data_bits_per_frame; i++) { + if (out_char[i] != ibits[i]) { + Terrs++; + perr = 1; + } + Tbits++; + } + Tpackets++; + if (perr) { + Tpacketerrs++; + fprintf(stderr, "x"); + } else + fprintf(stderr, "."); } - - return 0; + // fprintf(stderr, "Terrs_raw: %d Tbits_raw: %d Terr: %d Tbits: %d\n", + // Terrs_raw, Tbits_raw, Terrs, Tbits); + } + + free(input_float); + if (fin != NULL) fclose(fin); + if (fout != NULL) fclose(fout); + + fprintf(stderr, "total iters %d\n", total_iters); + + if (testframes) { + fprintf(stderr, "Raw Tbits: %6d Terr: %6d BER: %4.3f\n", Tbits_raw, + Terrs_raw, (float)Terrs_raw / (Tbits_raw + 1E-12)); + float coded_ber = (float)Terrs / (Tbits + 1E-12); + fprintf(stderr, "Coded Tbits: %6d Terr: %6d BER: %4.3f\n", Tbits, Terrs, + coded_ber); + fprintf(stderr, " Tpkts: %6d Tper: %6d PER: %4.3f\n", Tpackets, + Tpacketerrs, Tpacketerrs / (Tpackets + 1E-12)); + + /* set return code for Ctest */ + if (Tpackets && (coded_ber < 0.01)) + return 0; + else + return 1; + } + + return 0; } - - |
