% load real samples from file
- Ascale= 2E5*1.1491;
- frx=fopen(filename,"rb"); rx = 2*fread(frx, Inf, "short")/4E5; fclose(frx);
+ Ascale= 2E5*1.1491/2.0;
+ frx=fopen(filename,"rb"); rx = fread(frx, Inf, "short")/Ascale; fclose(frx);
Nsam = length(rx); Nframes = floor(Nsam/Nsamperframe);
prx = 1;
rx_np(Nsymbolsperinterleavedframe-Nsymbolsperframe+1:Nsymbolsperinterleavedframe) = arx_np(Nuwtxtsymbolsperframe+1:end);
rx_amp(1:Nsymbolsperinterleavedframe-Nsymbolsperframe) = rx_amp(Nsymbolsperframe+1:Nsymbolsperinterleavedframe);
rx_amp(Nsymbolsperinterleavedframe-Nsymbolsperframe+1:Nsymbolsperinterleavedframe) = arx_amp(Nuwtxtsymbolsperframe+1:end);
+
+ % de-interleave QPSK symbols and symbol amplitudes
+
+ rx_np_de = gp_deinterleave(rx_np);
+ rx_amp_de = gp_deinterleave(rx_amp);
% Interleaver Sync:
% Needs to work on any data
% Attempt a decode on every frame, when it converges we have sync
next_sync_state_interleaver = states.sync_state_interleaver;
+ Nerrs_raw = Nerrs_coded = 0;
- if strcmp(states.sync_state_interleaver,'searching')
- arx_np = gp_deinterleave(rx_np);
- arx_amp = gp_deinterleave(rx_amp);
+ if strcmp(states.sync_state_interleaver,'searching')
st = 1; en = Ncodedbitsperframe/bps;
- [rx_codeword parity_checks] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, arx_np(st:en), min(EsNo,30), arx_amp(st:en));
- if find(parity_checks == code_param.data_bits_per_frame)
- % sucessful decode!
+ [rx_codeword parity_checks] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_np_de(st:en), min(EsNo,30), rx_amp_de(st:en));
+ Nerrs = code_param.data_bits_per_frame - max(parity_checks);
+ %printf("Nerrs: %d\n", Nerrs);
+ if Nerrs < 10
+ % sucessful(ish) decode!
next_sync_state_interleaver = 'synced';
states.frame_count_interleaver = interleave_frames;
end
states.sync_state_interleaver = next_sync_state_interleaver;
- Nerrs_raw = Nerrs_coded = 0;
if strcmp(states.sync_state_interleaver,'synced') && (states.frame_count_interleaver == interleave_frames)
states.frame_count_interleaver = 0;
- printf("decode!\n");
+ %printf("decode!\n");
- % de-interleave QPSK symbols and symbol amplitudes
-
- arx_np = gp_deinterleave(rx_np);
- arx_amp = gp_deinterleave(rx_amp);
-
% measure uncoded bit errors over interleaver frame
rx_bits_raw = [];
for s=1:Nsymbolsperinterleavedframe
- rx_bits_raw = [rx_bits_raw qpsk_demod(rx_np(s))];
+ rx_bits_raw = [rx_bits_raw qpsk_demod(rx_np_de(s))];
end
for ff=1:interleave_frames
st = (ff-1)*Ncodedbitsperframe+1; en = st+Ncodedbitsperframe-1;
rx_bits = [];
for ff=1:interleave_frames
st = (ff-1)*Ncodedbitsperframe/bps+1; en = st + Ncodedbitsperframe/bps - 1;
- [rx_codeword ldpc_errors] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, arx_np(st:en), min(EsNo,30), arx_amp(st:en));
+ [rx_codeword ldpc_errors] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, rx_np_de(st:en), min(EsNo,30), rx_amp_de(st:en));
rx_bits = [rx_bits rx_codeword(1:code_param.data_bits_per_frame)];
end
Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 17; Ns = 8;
states = ofdm_init(bps, Rs, Tcp, Ns, Nc);
ofdm_load_const;
-
+ ldpc;
+ gp_interleaver;
+
% Set up LDPC code
mod_order = 4; bps = 2; modulation = 'QPSK'; mapping = 'gray';
for m=1:length(test_bits_ofdm)-1
fprintf(f," %d,\n",test_bits_ofdm(m));
endfor
- fprintf(f," %d\n};\n",test_bits_ofdm(length(payload_data_bits)));
+ fprintf(f," %d\n};\n",test_bits_ofdm(end));
fprintf(f,"\nconst int payload_data_bits[]={\n");
for m=1:length(payload_data_bits)-1
fprintf(f," %d,\n",payload_data_bits(m));
endfor
- fprintf(f," %d\n};\n",payload_data_bits(length(payload_data_bits)));
+ fprintf(f," %d\n};\n",payload_data_bits(end));
fclose(f);
endfunction
states.last_sync_state_interleaver = states.sync_state_interleaver;
states.sync_state = next_state;
endfunction
+
+
+% test function, kind of like a CRC for QPSK symbols, to compare two vectors
+
+function acc = test_acc(v)
+ sre = 0; sim = 0;
+ for i=1:length(v)
+ x = v(i);
+ re = round(real(x)); im = round(imag(x));
+ sre += re; sim += im;
+ %printf("%d %10f %10f %10f %10f\n", i, re, im, sre, sim);
+ end
+ acc = sre + j*sim;
+end
AUTHOR......: David Rowe
DATE CREATED: April 2018
- Golden Prime Interleaver. My interprestation of "On the Analysis and
+ Golden Prime Interleaver. My interpretation of "On the Analysis and
Design of Good Algebraic Interleavers", Xie et al,eq (5).
See also octvae/gp_interleaver.m
*/
#include <assert.h>
+#include <stdio.h>
#include "gp_interleaver.h"
/*
*/
int b_table[] = {
- 112,71,
+ 112,71,
224,139,
448,277,
672,419,
void gp_interleave_comp(COMP interleaved_frame[], COMP frame[], int Nbits) {
int b = choose_interleaver_b(Nbits);
int i,j;
-
for (i=0; i<Nbits; i++) {
- j = b*i % Nbits;
+ j = (b*i) % Nbits;
interleaved_frame[j] = frame[i];
}
}
+void gp_deinterleave_comp(COMP frame[], COMP interleaved_frame[], int Nbits) {
+ int b = choose_interleaver_b(Nbits);
+ int i,j;
+ for (i=0; i<Nbits; i++) {
+ j = (b*i) % Nbits;
+ frame[i] = interleaved_frame[j];
+ }
+}
+
void gp_interleave_float(float interleaved_frame[], float frame[], int Nbits) {
int b = choose_interleaver_b(Nbits);
int i,j;
for (i=0; i<Nbits; i++) {
- j = b*i % Nbits;
+ j = (b*i) % Nbits;
interleaved_frame[j] = frame[i];
}
}
+void gp_deinterleave_float(float frame[], float interleaved_frame[], int Nbits) {
+ int b = choose_interleaver_b(Nbits);
+ int i,j;
+
+ for (i=0; i<Nbits; i++) {
+ j = (b*i) % Nbits;
+ frame[i] = interleaved_frame[j];
+ }
+}
+
#include "comp.h"
void gp_interleave_comp(COMP interleaved_frame[], COMP frame[], int Nbits);
+void gp_deinterleave_comp(COMP frame[], COMP interleaved_frame[], int Nbits);
void gp_interleave_float(float frame[], float interleaved_frame[], int Nbits);
+void gp_deinterleave_float(float interleaved_frame[], float frame[], int Nbits);
#endif
fprintf(stderr,"\n");
fprintf(stderr,"InputModemRawFile 48 kHz 16 bit shorts real modem signal from radio\n");
fprintf(stderr," -m RTTY|binary\n");
- fprintf(stderr,"--mode=RTTY|binary[r] RTTY or binary Horus protcols\n");
+ fprintf(stderr,"--mode=RTTY|binary RTTY or binary Horus protcols\n");
fprintf(stderr," -t[r] --stats=[r] Print out modem statistics to stderr in JSON.\n");
fprintf(stderr," r, if provided, sets the number of modem frames\n"
" between statistic printouts\n");
#include <stdio.h>
#include "mpdecode_core.h"
+#define QPSK_CONSTELLATION_SIZE 4
+#define QPSK_BITS_PER_SYMBOL 2
+
+/* QPSK constellation for symbol likelihood calculations */
+
+static COMP S_matrix[] = {
+ { 1.0f, 0.0f},
+ { 0.0f, 1.0f},
+ { 0.0f, -1.0f},
+ {-1.0f, 0.0f}
+};
+
+
int extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[],
int max_iter, int CodeLength, int NumberParityBits);
float fading[], /* real fading values, number_symbols */
int number_symbols)
{
- int M=4;
+ int M=QPSK_CONSTELLATION_SIZE;
int i,j;
double tempsr, tempsi, Er, Ei;
double symbol_likelihood[], /* M*number_symbols */
int number_symbols)
{
- int M=4, bps = 2;
+ int M=QPSK_CONSTELLATION_SIZE, bps = QPSK_BITS_PER_SYMBOL;
int n,i,j,k,mask;
double num[bps], den[bps];
double metric;
return iter;
}
+int 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];
+ double bit_likelihood[nsyms*QPSK_BITS_PER_SYMBOL];
+
+ Demod2D(symbol_likelihood, rx_qpsk_symbols, S_matrix, EsNo, rx_amps, nsyms);
+ Somap(bit_likelihood, symbol_likelihood, nsyms);
+ for(i=0; i<nsyms*QPSK_BITS_PER_SYMBOL; i++) {
+ llr[i] = -bit_likelihood[i];
+ }
+}
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);
struct v_node {
int degree;
static void idft(struct OFDM *, complex float *, complex float *);
static complex float vector_sum(complex float *, int);
static complex float qpsk_mod(int *);
-static void qpsk_demod(complex float, 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);
/* Gray coded QPSK demodulation function */
-static void qpsk_demod(complex float symbol, int *bits) {
+void qpsk_demod(complex float symbol, int *bits) {
complex float rotate = symbol * cexpf(I * (M_PI / 4.0f));
bits[0] = crealf(rotate) < 0.0f;
bits[1] = cimagf(rotate) < 0.0f;
ofdm->sync_start = 0;
ofdm->sync_end = 0;
+ strcpy(ofdm->sync_state_interleaver,"searching");
+ strcpy(ofdm->last_sync_state_interleaver,"searching");
+ ofdm->frame_count_interleaver = 0;
+
/* create the OFDM waveform */
complex float temp[OFDM_M];
void ofdm_sync_state_machine(struct OFDM *ofdm, int *rx_uw) {
char next_state[OFDM_STATE_STR];
- int i, j, sync_counter_thresh;
+ int i, j, sync_counter_thresh, uw_thresh;
strcpy(next_state, ofdm->sync_state);
ofdm->sync_start = ofdm->sync_end = 0;
}
}
- if ((strcmp(ofdm->sync_state,"synced") == 0) || (strcmp(ofdm->sync_state, "trial_sync") == 0)) {
+ if (!strcmp(ofdm->sync_state,"synced") || !strcmp(ofdm->sync_state, "trial_sync")) {
ofdm->frame_count++;
-
- /* during trial sync we don't tolerate errors so much, once we have synced up
- we are willing to wait out a fade */
-
- if (ofdm->frame_count == 3) {
- strcpy(next_state, "synced");
- }
-
- if (strcmp(ofdm->sync_state, "synced") == 0) {
- sync_counter_thresh = 6;
- } else {
- sync_counter_thresh = 3;
- }
-
+ ofdm->frame_count_interleaver++;
+
/* freq offset est may be too far out, and has aliases every 1/Ts, so
we use a Unique Word to get a really solid indication of sync. */
for (i=0; i<OFDM_NUWBITS; i++) {
ofdm->uw_errors += rx_uw[i];
}
- if (ofdm->uw_errors > 2) {
- ofdm->sync_counter++;
- if (ofdm->sync_counter == sync_counter_thresh) {
+
+ /* during trial sync we don't tolerate errors so much, we look
+ for 3 consecutive frames with low error rate to confirm
+ sync */
+
+ if (!strcmp(ofdm->sync_state, "trial_sync")) {
+ if (ofdm->uw_errors > 1) {
+ /* if we exceed thresh stay in trial sync */
+ ofdm->sync_counter++;
+ ofdm->frame_count = 0;
+ }
+ if (ofdm->sync_counter == 2) {
+ /* if we get two bad frames drop sync and start again */
strcpy(next_state, "searching");
+ strcpy(ofdm->sync_state_interleaver, "searching");
}
- } else {
- ofdm->sync_counter = 0;
+
+ if (ofdm->frame_count == 3) {
+ /* three good frames, sync is OK! */
+ strcpy(next_state, "synced");
+ }
+ }
+
+ /* once we have synced up we tolerate a higher error rate to wait out fades */
+
+ if (!strcmp(ofdm->sync_state, "synced")) {
+ if (ofdm->uw_errors > 2) {
+ ofdm->sync_counter++;
+ } else {
+ if (ofdm->sync_counter) {
+ ofdm->sync_counter--;
+ }
+ }
+
+ if (ofdm->sync_counter == 6) {
+ /* run of consective bad frames ... drop sync */
+ strcpy(next_state, "searching");
+ strcpy(ofdm->sync_state_interleaver, "searching");
+ }
}
}
strcpy(ofdm->last_sync_state, ofdm->sync_state);
+ strcpy(ofdm->last_sync_state_interleaver, ofdm->sync_state_interleaver);
strcpy(ofdm->sync_state, next_state);
}
#include "mpdecode_core.h"
#include "gp_interleaver.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 */
+#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 */
-#include "HRA_112_112.h" /* generated by ldpc_fsk_lib.m:ldpc_decode() */
-#define CODED_BITSPERFRAME 224 /* number of LDPC codeword 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;
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; i<n; i++) {
+ acc.real += round(v[i].real);
+ acc.imag += round(v[i].imag);
+ //fprintf(stderr, "%d %10f %10f %10f %10f\n", i, round(v[i].real), round(v[i].imag), acc.real, acc.imag);
+ }
+ return acc;
+}
+
+void printf_n(COMP v[], int n) {
+ int i;
+ for(i=0; i<n; i++) {
+ fprintf(stderr, "%d %10f %10f\n", i, round(v[i].real), round(v[i].imag));
+ }
+}
+
int main(int argc, char *argv[])
{
FILE *fin, *fout, *foct;
float foff_hz_log[NFRAMES];
int timing_est_log[NFRAMES];
- int i, j, f, oct, logframes, arg, llr_en;
+ int i, j, f, oct, logframes, arg, llr_en, interleave_frames;
int Nerrs, Terrs, Tbits, Terrs2, Tbits2, testframes, frame_count;
- int ldpc_en, Nerrs_coded, Tbits_coded, Terrs_coded;
+ int ldpc_en, Nerrs_coded, Tbits_coded, Terrs_coded, Nerrs_raw;
struct LDPC ldpc;
ldpc.max_iter = HRA_112_112_MAX_ITER;
llr_en = 1;
}
+ interleave_frames = 1;
+ if ((arg = opt_exists(argv, argc, "--interleave"))) {
+ interleave_frames = atoi(argv[arg+1]);
+ fprintf(stderr, "interleave_frames: %d\n", interleave_frames);
+ /* we can't de-interleave without LDPC for sync, so switch that on */
+ ldpc_en = 1;
+ llr_en = 1;
+ }
+
ofdm = ofdm_create(OFDM_CONFIG_700D);
assert(ofdm != NULL);
float EsNo = 10;
fprintf(stderr,"Warning EsNo: %f hard coded\n", EsNo);
+ COMP codeword_symbols[interleave_frames*CODED_SYMSPERFRAME];
+ float codeword_amps[interleave_frames*CODED_SYMSPERFRAME];
+ COMP codeword_symbols_de[interleave_frames*CODED_SYMSPERFRAME];
+ float codeword_amps_de[interleave_frames*CODED_SYMSPERFRAME];
+
nin_frame = ofdm_get_nin(ofdm);
while(fread(rx_scaled, sizeof(short), nin_frame, fin) == nin_frame) {
ofdm_demod(ofdm, rx_bits, rxbuf_in);
if (llr_en) {
- double symbol_likelihood[ (CODED_BITSPERFRAME/OFDM_BPS) * (1<<OFDM_BPS) ];
- double bit_likelihood[CODED_BITSPERFRAME];
- double llr[CODED_BITSPERFRAME];
-
- /* first few symbols are used for UW and txt bits, find start of (224,112) LDPC codeword */
+
+ /* first few symbols are used for UW and txt bits, find start of (224,112) LDPC codeword
+ and extract QPSK symbols and amplitude estimates */
assert((OFDM_NUWBITS+OFDM_NTXTBITS+CODED_BITSPERFRAME) == OFDM_BITSPERFRAME);
- COMP ldpc_codeword_symbols[CODED_BITSPERFRAME/OFDM_BPS];
- for(i=0, j=(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS; i<(CODED_BITSPERFRAME/OFDM_BPS); i++,j++) {
- ldpc_codeword_symbols[i].real = crealf(ofdm->rx_np[j]);
- ldpc_codeword_symbols[i].imag = cimagf(ofdm->rx_np[j]);
- }
- float *ldpc_codeword_symbol_amps = &ofdm->rx_amp[(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS];
-
- COMP codeword_symbols_de[CODED_BITSPERFRAME/OFDM_BPS];
- float codeword_amps_de[CODED_BITSPERFRAME/OFDM_BPS];
-
- gp_interleave_comp(codeword_symbols_de, ldpc_codeword_symbols, CODED_BITSPERFRAME/OFDM_BPS);
- gp_interleave_float(codeword_amps_de, ldpc_codeword_symbol_amps, CODED_BITSPERFRAME/OFDM_BPS);
+ /* now we need to buffer for de-interleaving -------------------------------------*/
- Demod2D(symbol_likelihood, codeword_symbols_de, S_matrix, EsNo, codeword_amps_de, CODED_BITSPERFRAME/OFDM_BPS);
- Somap(bit_likelihood, symbol_likelihood, CODED_BITSPERFRAME/OFDM_BPS);
- for(i=0; i<CODED_BITSPERFRAME; i++) {
- llr[i] = -bit_likelihood[i];
- }
+ /* shift interleaved symbol buffers to make room for new symbols */
- char out_char[CODED_BITSPERFRAME];
+ for(i=0, j=CODED_SYMSPERFRAME; j<interleave_frames*CODED_SYMSPERFRAME; i++,j++) {
+ codeword_symbols[i] = codeword_symbols[j];
+ codeword_amps[i] = codeword_amps[j];
+ }
+
+ /* newest symbols at end of buffer (uses final i from last loop), note we
+ change COMP formats from what modem uses internally */
- for(i=0; i<CODED_BITSPERFRAME; i++) {
- llr[i] = -bit_likelihood[i];
+ for(i=(interleave_frames-1)*CODED_SYMSPERFRAME,j=(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS; i<interleave_frames*CODED_SYMSPERFRAME; i++,j++) {
+ codeword_symbols[i].real = crealf(ofdm->rx_np[j]);
+ codeword_symbols[i].imag = cimagf(ofdm->rx_np[j]);
+ codeword_amps[i] = ofdm->rx_amp[j];
}
+
+ /* 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);
+
+ double llr[CODED_BITSPERFRAME];
+
if (ldpc_en) {
+ char out_char[CODED_BITSPERFRAME];
+
+ /*
+ Interleaver Sync:
+ Needs to work on any data
+ Use indication of LDPC convergence, may need to patch CML code for that
+ Attempt a decode on every frame, when it converges we have sync
+ */
- /* run LDPC decoder and output decoded bits */
-
- iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount);
-
- if (testframes) {
- Nerrs_coded = 0;
- for(i=0; i<DATA_BITSPERFRAME; i++) {
- if (payload_data_bits[i] != out_char[i]) {
- Nerrs_coded++;
- }
+ char next_sync_state_interleaver[OFDM_STATE_STR];
+ strcpy(next_sync_state_interleaver, ofdm->sync_state_interleaver);
+ if (strcmp(ofdm->sync_state_interleaver,"searching") == 0) {
+ symbols_to_llrs(llr, codeword_symbols_de, codeword_amps_de, EsNo, CODED_SYMSPERFRAME);
+ iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount);
+ Nerrs = DATA_BITSPERFRAME - parityCheckCount;
+ fprintf(stderr, "iter: %d pcc: %d Nerrs: %d\n", iter, parityCheckCount, Nerrs);
+ if (Nerrs < 10) {
+ /* sucessful decode! */
+ strcpy(next_sync_state_interleaver, "synced");
+ ofdm->frame_count_interleaver = interleave_frames;
}
- Terrs_coded += Nerrs_coded;
- Tbits_coded += DATA_BITSPERFRAME;
}
- fwrite(out_char, sizeof(char), CODED_BITSPERFRAME, fout);
+ strcpy(ofdm->sync_state_interleaver, next_sync_state_interleaver);
+
+ Nerrs_raw = Nerrs_coded = 0;
+ if (!strcmp(ofdm->sync_state_interleaver,"synced") && (ofdm->frame_count_interleaver == interleave_frames)) {
+ ofdm->frame_count_interleaver = 0;
+ // printf("decode!\n");
+
+ if (testframes) {
+
+ /* measure uncoded (raw) bit errors over interleaver frame */
+
+ int rx_bits_raw[CODED_BITSPERFRAME];
+ for (j=0; j<interleave_frames; j++) {
+ for(i=0; i<CODED_SYMSPERFRAME; i++) {
+ complex float s = codeword_symbols_de[j*CODED_SYMSPERFRAME+i].real + I*codeword_symbols_de[j*CODED_SYMSPERFRAME+i].imag;
+ qpsk_demod(s, &rx_bits_raw[OFDM_BPS*i]);
+ }
+ Nerrs = 0;
+ for(i=0; i<CODED_BITSPERFRAME; i++) {
+ //fprintf(stderr, "%d %d %d\n", i, test_bits_ofdm[i], rx_bits_raw[i]);
+ if (test_bits_ofdm[i] != rx_bits_raw[i]) {
+ Nerrs++;
+ }
+ }
+ Nerrs_raw += Nerrs;
+ }
+ Terrs += Nerrs_raw;
+ Tbits += Nbitsperframe;
+ }
+
+ for (j=0; j<interleave_frames; j++) {
+ symbols_to_llrs(llr, &codeword_symbols_de[j*CODED_SYMSPERFRAME],
+ &codeword_amps_de[j*CODED_SYMSPERFRAME],
+ EsNo, CODED_SYMSPERFRAME);
+ iter = run_ldpc_decoder(&ldpc, out_char, llr, &parityCheckCount);
+
+ if (testframes) {
+ Nerrs_coded = 0;
+ for(i=0; i<DATA_BITSPERFRAME; i++) {
+ if (payload_data_bits[i] != out_char[i]) {
+ Nerrs_coded++;
+ }
+ }
+ Terrs_coded += Nerrs_coded;
+ Tbits_coded += DATA_BITSPERFRAME;
+ }
+ fwrite(out_char, sizeof(char), CODED_BITSPERFRAME, fout);
+ }
+ } /* if interleaver synced ..... */
+
} else {
- /* external LDPC decoder, so output LLRs */
- fwrite(llr, sizeof(double), CODED_BITSPERFRAME, fout);
+ /* lpdc_en == 0, external LDPC decoder, so output LLRs */
+ symbols_to_llrs(llr, codeword_symbols_de, codeword_amps_de, EsNo, CODED_SYMSPERFRAME);
+ fwrite(llr, sizeof(double), CODED_BITSPERFRAME, fout);
}
-
} else {
/* simple hard decision output for uncoded testing, all bits in frame dumped inlcuding UW and txt */
for(i=0; i<Nbitsperframe; i++) {
rx_uw[i] = rx_bits[i];
}
- /* optional error counting in testframe mode */
+ /* optional error counting on uncoded data in non-LDPC testframe mode */
- if (testframes) {
+ if (testframes && (ldpc_en == 0)) {
Nerrs = 0;
for(i=0; i<Nbitsperframe; i++) {
if (test_bits_ofdm[i] != rx_bits[i]) {
/* act on any events returned by state machine */
if (ofdm->sync_start) {
- Terrs = Tbits = Terrs2 = Tbits2 = frame_count = 0;
+ Terrs = Tbits = Terrs2 = Tbits2 = Terrs_coded = Tbits_coded = frame_count = 0;
}
if (ofdm->verbose) {
- fprintf(stderr, "f: %2d state: %-10s uw_errors: %2d %1d Nerrs: %3d foff: %3.1f",
- f, ofdm->last_sync_state, ofdm->uw_errors, ofdm->sync_counter, Nerrs, ofdm->foff_est_hz);
- if (ldpc_en) {
- fprintf(stderr, " Nerrs_coded: %3d iter: %3d pCC: %3d", Nerrs_coded, iter, parityCheckCount);
- }
+ fprintf(stderr, "f: %2d st: %-10s uw_errs: %2d %1d inter_st: %-10s inter_fr: %d Nerrs_raw: %3d Nerrs_coded: %3d foff: %4.1f",
+ f, ofdm->last_sync_state, ofdm->uw_errors, ofdm->sync_counter,
+ ofdm->last_sync_state_interleaver, ofdm->frame_count_interleaver,
+ Nerrs_raw, Nerrs_coded, ofdm->foff_est_hz);
fprintf(stderr, "\n");
}
if (testframes) {
fprintf(stderr, "BER......: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs/Tbits, Tbits, Terrs);
- fprintf(stderr, "BER2.....: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs2/Tbits2, Tbits2, Terrs2);
+ if (!ldpc_en) {
+ fprintf(stderr, "BER2.....: %5.4f Tbits: %5d Terrs: %5d\n", (float)Terrs2/Tbits2, Tbits2, Terrs2);
+ }
if (ldpc_en) {
fprintf(stderr, "Coded BER: %5.4f Tbits: %5d Terrs: %5d\n",
(float)Terrs_coded/Tbits_coded, Tbits_coded, Terrs_coded);
float rx_amp[OFDM_ROWSPERFRAME * OFDM_NC];
float aphase_est_pilot_log[OFDM_ROWSPERFRAME * OFDM_NC];
- /* sync state machine */
+ /* modem sync state machine */
char sync_state[OFDM_STATE_STR];
char last_sync_state[OFDM_STATE_STR];
int frame_count;
int sync_start;
int sync_end;
-};
-
-/* QPSK constellation for symbol likelihood calculations */
-static COMP S_matrix[] = {
- { 1.0f, 0.0f},
- { 0.0f, 1.0f},
- { 0.0f, -1.0f},
- {-1.0f, 0.0f}
+ /* interleaver sync state machine */
+
+ char sync_state_interleaver[OFDM_STATE_STR];
+ char last_sync_state_interleaver[OFDM_STATE_STR];
+ int frame_count_interleaver;
};
-
+
#ifdef __cplusplus
}
#endif
0,
0,
0,
- 0
+ 1
};
const int payload_data_bits[]={