From: drowe67 Date: Wed, 18 Apr 2018 23:42:22 +0000 (+0000) Subject: refactoring of ldpc/interleaver code, added test mode, iterleaving, and ldpc to ofdm_... X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=3110f41e5cadfddd3891d6ad7ed3f4273a799150;p=freetel-svn-tracking.git refactoring of ldpc/interleaver code, added test mode, iterleaving, and ldpc to ofdm_mod, compiles but not tested git-svn-id: https://svn.code.sf.net/p/freetel/code@3501 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/src/CMakeLists.txt b/codec2-dev/src/CMakeLists.txt index bd3dcd93..18ce356a 100644 --- a/codec2-dev/src/CMakeLists.txt +++ b/codec2-dev/src/CMakeLists.txt @@ -337,10 +337,10 @@ target_link_libraries(ofdm_get_test_bits ${CMAKE_REQUIRED_LIBRARIES} codec2) add_executable(ofdm_put_test_bits ofdm_put_test_bits.c) target_link_libraries(ofdm_put_test_bits ${CMAKE_REQUIRED_LIBRARIES} codec2) -add_executable(ofdm_mod ofdm_mod.c) +add_executable(ofdm_mod ofdm_mod.c interldpc.c mpdecode_core.c gp_interleaver.c) target_link_libraries(ofdm_mod ${CMAKE_REQUIRED_LIBRARIES} codec2) -add_executable(ofdm_demod ofdm_demod.c octave.c mpdecode_core.c gp_interleaver.c) +add_executable(ofdm_demod ofdm_demod.c octave.c mpdecode_core.c gp_interleaver.c interldpc.c) target_link_libraries(ofdm_demod ${CMAKE_REQUIRED_LIBRARIES} codec2) add_executable(fmfsk_mod fmfsk_mod.c) diff --git a/codec2-dev/src/interldpc.c b/codec2-dev/src/interldpc.c new file mode 100644 index 00000000..9d4b2ec7 --- /dev/null +++ b/codec2-dev/src/interldpc.c @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------*\ + + FILE........: interldpc.c + AUTHOR......: David Rowe + DATE CREATED: April 2018 + + Helper functions for interleaved LDPC modems. + +\*---------------------------------------------------------------------------*/ + +/* + Copyright (C) 2018 David Rowe + + All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2, as + published by the Free Software Foundation. This program is + distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, see . +*/ + +#include +#include +#include +#include +#include + +#include "interldpc.h" +#include "codec2_ofdm.h" +#include "ofdm_internal.h" +#include "mpdecode_core.h" +#include "gp_interleaver.h" +#include "HRA_112_112.h" + +/* CRC type function, used to compare QPSK vectors when debugging */ + +COMP test_acc(COMP v[], int n) { + COMP acc = {0.0,0.0}; + int i; + for(i=0; imax_iter = HRA_112_112_MAX_ITER; + ldpc->dec_type = 0; + ldpc->q_scale_factor = 1; + ldpc->r_scale_factor = 1; + ldpc->CodeLength = HRA_112_112_CODELENGTH; + ldpc->NumberParityBits = HRA_112_112_NUMBERPARITYBITS; + ldpc->NumberRowsHcols = HRA_112_112_NUMBERROWSHCOLS; + ldpc->max_row_weight = HRA_112_112_MAX_ROW_WEIGHT; + ldpc->max_col_weight = HRA_112_112_MAX_COL_WEIGHT; + ldpc->H_rows = HRA_112_112_H_rows; + ldpc->H_cols = HRA_112_112_H_cols; + + /* provided for convenience and to match Octave vaiable names */ + + ldpc->data_bits_per_frame = HRA_112_112_CODELENGTH - HRA_112_112_NUMBERPARITYBITS; + ldpc->coded_bits_per_frame = HRA_112_112_CODELENGTH; + ldpc->coded_syms_per_frame = ldpc->coded_bits_per_frame/OFDM_BPS; +} + +void ldpc_encode_frame(struct LDPC *ldpc, int codeword[], unsigned char tx_bits_char[]) { + unsigned char pbits[ldpc->coded_bits_per_frame]; + int i,j; + + encode(ldpc, tx_bits_char, pbits); + for(i=0; idata_bits_per_frame; i++) { + codeword[i] = tx_bits_char[i]; + } + for(j=0; icoded_bits_per_frame; i++,j++) { + codeword[i] = pbits[i]; + } +} + +void qpsk_modulate_frame(COMP tx_symbols[], int codeword[], int n) { + int s,i; + int dibit[2]; + complex float qpsk_symb; + + for(s=0,i=0; i. +*/ + +#ifndef __INTERLDPC__ +#define __INTERLDPC__ + +#include "comp.h" +#include "mpdecode_core.h" + +/* CRC type function, used to compare QPSK vectors when debugging */ + +COMP test_acc(COMP v[], int n); +void printf_n(COMP v[], int n); +void set_up_hra_112_112(struct LDPC *ldpc); +void ldpc_encode_frame(struct LDPC *ldpc, int codeword[], unsigned char tx_bits_char[]); +void qpsk_modulate_frame(COMP tx_symbols[], int codeword[], int n); + +#endif diff --git a/codec2-dev/src/mpdecode_core.c b/codec2-dev/src/mpdecode_core.c index 62172e05..8b425a3d 100644 --- a/codec2-dev/src/mpdecode_core.c +++ b/codec2-dev/src/mpdecode_core.c @@ -871,7 +871,7 @@ int extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[], i return iter; } -int symbols_to_llrs(double llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, int nsyms) { +void symbols_to_llrs(double llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, int nsyms) { int i; double symbol_likelihood[nsyms*QPSK_CONSTELLATION_SIZE]; diff --git a/codec2-dev/src/mpdecode_core.h b/codec2-dev/src/mpdecode_core.h index 50517a40..e0ba45a7 100644 --- a/codec2-dev/src/mpdecode_core.h +++ b/codec2-dev/src/mpdecode_core.h @@ -23,6 +23,9 @@ struct LDPC { int NumberRowsHcols; int max_row_weight; int max_col_weight; + int data_bits_per_frame; + int coded_bits_per_frame; + int coded_syms_per_frame; double *H_rows; double *H_cols; }; @@ -35,7 +38,7 @@ void sd_to_llr(double llr[], double sd[], int n); void Demod2D(double symbol_likelihood[], COMP r[], COMP S_matrix[], float EsNo, float fading[], int number_symbols); void Somap(double bit_likelihood[], double symbol_likelihood[], int number_symbols); -int symbols_to_llrs(double llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, int nsyms); +void symbols_to_llrs(double llr[], COMP rx_qpsk_symbols[], float rx_amps[], float EsNo, int nsyms); struct v_node { int degree; diff --git a/codec2-dev/src/ofdm.c b/codec2-dev/src/ofdm.c index 6ee6037a..d3352c34 100644 --- a/codec2-dev/src/ofdm.c +++ b/codec2-dev/src/ofdm.c @@ -51,9 +51,6 @@ const struct OFDM_CONFIG * OFDM_CONFIG_700D = &OFDM_CONFIG_700D_C; static void dft(struct OFDM *, complex float *, complex float *); static void idft(struct OFDM *, complex float *, complex float *); static complex float vector_sum(complex float *, int); -static complex float qpsk_mod(int *); -void qpsk_demod(complex float, int *); -static void ofdm_txframe(struct OFDM *, complex float [OFDM_SAMPLESPERFRAME], complex float *); static int coarse_sync(struct OFDM *, complex float *, int, float *foff_est); /* Defines */ @@ -88,7 +85,7 @@ static const int tx_uw[] = {1,0,0,1,0,1,0,0,1,0}; /* Gray coded QPSK modulation function */ -static complex float qpsk_mod(int *bits) { +complex float qpsk_mod(int *bits) { return constellation[(bits[1] << 1) | bits[0]]; } @@ -245,8 +242,11 @@ static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length, float * * ---------------------------------------------- */ -static void ofdm_txframe(struct OFDM *ofdm, complex float tx[OFDM_SAMPLESPERFRAME], - complex float *tx_sym_lin) { +void ofdm_txframe( + struct OFDM *ofdm, + complex float tx[OFDM_SAMPLESPERFRAME], + complex float *tx_sym_lin) +{ complex float aframe[OFDM_NS][OFDM_NC + 2]; complex float asymbol[OFDM_M]; complex float asymbol_cp[OFDM_M + OFDM_NCP]; diff --git a/codec2-dev/src/ofdm_demod.c b/codec2-dev/src/ofdm_demod.c index 66aac11a..c1219be1 100644 --- a/codec2-dev/src/ofdm_demod.c +++ b/codec2-dev/src/ofdm_demod.c @@ -45,20 +45,11 @@ #include "test_bits_ofdm.h" #include "mpdecode_core.h" #include "gp_interleaver.h" +#include "interldpc.h" #define ASCALE (2E5*1.1491/2.0) /* scale from shorts back to floats */ #define NFRAMES 100 /* just log the first 100 frames */ #define NDISCARD 20 /* BER2measure disctrds first 20 frames */ -#define CODED_BITSPERFRAME 224 /* number of LDPC codeword bits/frame */ -#define DATA_BITSPERFRAME 112 /* number of LDPC payload data bits/frame */ - -/* number of LDPC codeword QPSK symbols/frame */ - -#define CODED_SYMSPERFRAME (CODED_BITSPERFRAME/OFDM_BPS) - -#include "HRA_112_112.h" /* generated by ldpc_fsk_lib.m:ldpc_decode() */ - -void qpsk_demod(complex float symbol, int *bits); int opt_exists(char *argv[], int argc, char opt[]) { int i; @@ -70,25 +61,6 @@ int opt_exists(char *argv[], int argc, char opt[]) { return 0; } -/* CRC type function, used to compare QPSK vectors when debugging */ - -COMP test_acc(COMP v[], int n) { - COMP acc = {0.0,0.0}; - int i; - for(i=0; irx_np[j]); codeword_symbols[i].imag = cimagf(ofdm->rx_np[j]); codeword_amps[i] = ofdm->rx_amp[j]; @@ -261,13 +229,13 @@ int main(int argc, char *argv[]) /* run de-interleaver */ - gp_deinterleave_comp (codeword_symbols_de, codeword_symbols, interleave_frames*CODED_SYMSPERFRAME); - gp_deinterleave_float(codeword_amps_de , codeword_amps , interleave_frames*CODED_SYMSPERFRAME); + gp_deinterleave_comp (codeword_symbols_de, codeword_symbols, interleave_frames*coded_syms_per_frame); + gp_deinterleave_float(codeword_amps_de , codeword_amps , interleave_frames*coded_syms_per_frame); - double llr[CODED_BITSPERFRAME]; + double llr[coded_bits_per_frame]; if (ldpc_en) { - char out_char[CODED_BITSPERFRAME]; + char out_char[coded_bits_per_frame]; /* Interleaver Sync: @@ -279,9 +247,9 @@ int main(int argc, char *argv[]) char next_sync_state_interleaver[OFDM_STATE_STR]; strcpy(next_sync_state_interleaver, ofdm->sync_state_interleaver); if (strcmp(ofdm->sync_state_interleaver,"search") == 0) { - symbols_to_llrs(llr, codeword_symbols_de, codeword_amps_de, EsNo, CODED_SYMSPERFRAME); + symbols_to_llrs(llr, codeword_symbols_de, codeword_amps_de, EsNo, coded_syms_per_frame); iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount); - Nerrs = DATA_BITSPERFRAME - parityCheckCount; + Nerrs = data_bits_per_frame - parityCheckCount; //fprintf(stderr, "iter: %d pcc: %d Nerrs: %d\n", iter, parityCheckCount, Nerrs); if (Nerrs < 10) { /* sucessful decode! */ @@ -299,18 +267,18 @@ int main(int argc, char *argv[]) /* measure uncoded (raw) bit errors over interleaver frame */ - int rx_bits_raw[CODED_BITSPERFRAME]; + int rx_bits_raw[coded_bits_per_frame]; for (j=0; j #include "codec2_ofdm.h" +#include "ofdm_internal.h" +#include "interldpc.h" +#include "gp_interleaver.h" +#include "test_bits_ofdm.h" #define ASCALE (2E5*1.1491) @@ -53,11 +57,25 @@ int main(int argc, char *argv[]) FILE *fin, *fout; struct OFDM *ofdm; int frames; - int i; - + int i, j, arg; + int testframes, ldpc_en, interleaver_frames; + + /* Set up default LPDC code. We could add other codes here if we like */ + + struct LDPC ldpc; + set_up_hra_112_112(&ldpc); + int data_bits_per_frame = ldpc.data_bits_per_frame; + int coded_bits_per_frame = ldpc.coded_bits_per_frame; + int coded_syms_per_frame = ldpc.coded_syms_per_frame; + if (argc < 3) { fprintf(stderr, "\n"); - fprintf(stderr, "usage: %s InputOneCharPerBitFile OutputModemRawFile\n", argv[0]); + fprintf(stderr, "usage: %s InputOneCharPerBitFile OutputModemRawFile [--lpdc] [--interleaver depth]\n\n", argv[0]); + fprintf(stderr, " -t Transmit test frames (adjusts test frames for raw and LDPC modes)\n"); + fprintf(stderr, " --ldpc Run (%d,%d) LDPC decoder. This forces 112, one char/bit output values\n" + " per frame. In testframe mode (-t) raw and coded errors will be counted\n", + coded_bits_per_frame, data_bits_per_frame); + fprintf(stderr, " --interleave Interleaver for LDPC frames, e.g. 1,2,4,8,16, default is 1\n"); fprintf(stderr, "\n"); exit(1); } @@ -78,30 +96,114 @@ int main(int argc, char *argv[]) ofdm = ofdm_create(OFDM_CONFIG_700D); assert(ofdm != NULL); - int Nbitsperframe = ofdm_get_bits_per_frame(ofdm); - int Nsamperframe = ofdm_get_samples_per_frame(); - char tx_bits_char[Nbitsperframe]; - int tx_bits[Nbitsperframe]; - COMP tx_sams[Nsamperframe]; - short tx_scaled[Nsamperframe]; + testframes = 0; + if (opt_exists(argv, argc, "-t")) { + testframes = 1; + } + + /* set for LDPC coded or uncoded frames */ - frames = 0; + ldpc_en = 0; interleaver_frames = 1; + int Nbitsperframe; + if (opt_exists(argv, argc, "--ldpc")) { - while(fread(tx_bits_char, sizeof(char), Nbitsperframe, fin) == Nbitsperframe) { - frames++; + assert((OFDM_NUWBITS+OFDM_NTXTBITS+coded_bits_per_frame) == OFDM_BITSPERFRAME); /* sanity check */ + + ldpc_en = 1; + if ((arg = opt_exists(argv, argc, "--interleaver"))) { + interleaver_frames = atoi(argv[arg]); + } + Nbitsperframe = interleaver_frames*data_bits_per_frame; - for(i=0; itx_uw[i]; + } + for(j=0; j