}
+#ifdef NOT_USED
+/* UW never changes so we can pre-load tx_symbols with modulated UW */
+
+void build_modulated_uw(struct OFDM *ofdm, complex float tx_symbols[], uint8_t txt_bits[])
+{
+ int uw_txt_bits[OFDM_NUWBITS+OFDM_NTXTBITS];
+ COMP uw_txt_syms[(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS];
+ int i,j;
+
+ for(i=0; i<OFDM_NUWBITS; i++) {
+ uw_txt_bits[i] = ofdm->tx_uw[i];
+ }
+ /* clear txt bits for now, they can be added in later */
+ for(j=0; j<OFDM_NTXTBITS; j++,i++) {
+ uw_txt_bits[i] = txt_bits[j];
+ //fprintf(stderr, "txt_bits[%d] = %d\n", j, txt_bits[j]);
+ }
+ qpsk_modulate_frame(uw_txt_syms, uw_txt_bits, (OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS);
+ for(i=0; i<(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS; i++) {
+ tx_symbols[i] = uw_txt_syms[i].real + I * uw_txt_syms[i].imag;
+ }
+}
+#endif
+
/*
Given an array of tx_bits, LDPC encodes, interleaves, and OFDM
modulates.
COMP coded_symbols[interleave_frames*coded_syms_per_frame];
COMP coded_symbols_inter[interleave_frames*coded_syms_per_frame];
int Nsamperframe = ofdm_get_samples_per_frame();
- complex float tx_symbols[(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS + coded_syms_per_frame];
-
- int i,j;
+ complex float tx_symbols[OFDM_BITSPERFRAME/OFDM_BPS];
+ int j;
for (j=0; j<interleave_frames; j++) {
ldpc_encode_frame(ldpc, codeword, &tx_bits[j*data_bits_per_frame]);
}
gp_interleave_comp(coded_symbols_inter, coded_symbols, interleave_frames*coded_syms_per_frame);
for (j=0; j<interleave_frames; j++) {
- /* todo: we don't need to build modulated UW every time, just txt bits */
- build_modulated_uw(ofdm, tx_symbols, &txt_bits[OFDM_NTXTBITS*j]);
- for(i=0; i<coded_syms_per_frame; i++) {
- tx_symbols[(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS+i] = coded_symbols_inter[j*coded_syms_per_frame+i].real
- + I * coded_symbols_inter[j*coded_syms_per_frame+i].imag;
- }
+ ofdm_assemble_modem_frame(tx_symbols, &coded_symbols_inter[j*coded_syms_per_frame], &txt_bits[OFDM_NTXTBITS*j]);
ofdm_txframe(ofdm, &tx_sams[j*Nsamperframe], tx_symbols);
}
}
-/* UW never changes so we can pre-load tx_symbols with modulated UW */
-void build_modulated_uw(struct OFDM *ofdm, complex float tx_symbols[], uint8_t txt_bits[])
-{
- int uw_txt_bits[OFDM_NUWBITS+OFDM_NTXTBITS];
- COMP uw_txt_syms[(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS];
- int i,j;
-
- for(i=0; i<OFDM_NUWBITS; i++) {
- uw_txt_bits[i] = ofdm->tx_uw[i];
- }
- /* clear txt bits for now, they can be added in later */
- for(j=0; j<OFDM_NTXTBITS; j++,i++) {
- uw_txt_bits[i] = txt_bits[j];
- //fprintf(stderr, "txt_bits[%d] = %d\n", j, txt_bits[j]);
- }
- qpsk_modulate_frame(uw_txt_syms, uw_txt_bits, (OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS);
- for(i=0; i<(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS; i++) {
- tx_symbols[i] = uw_txt_syms[i].real + I * uw_txt_syms[i].imag;
- }
-}
};
/*
- * Unique word used to verify we have modem frame sync
+ * A Unique Word (UW) used to verify we have modem frame sync when we
+ * try a candidate coarse timing and freq offset. The UW bits/symbols
+ * are distributed through the modem frame using the index (ind)
+ * tables below. The indexes in uw_nd_sym [] and uw_ind are Octave
+ * start from 1 format, subtract 1 to index C arrays.
*/
-static const int tx_uw[] = {1,0,0,1,0,1,0,0,1,0};
+static const int tx_uw[] = {0,0,0,0,0,0,0,0,0,0}; /* UW bits */
+static complex float tx_uw_syms[] = {1.0f,1.0f,1.0f,1.0f,1.0f}; /* UW QPSK symbols */
+static const int uw_ind[] = {19,20,37,38,55,56,73,74,91,92}; /* index in modem frame of UW bits */
+static const int uw_ind_sym[] = {10,19,28,37,46}; /* index into modem frame of UW symbols */
/* Functions -------------------------------------------------------------------*/
}
}
+
+/* Assemble modem frame from UW, payload symbols, and txt bits */
+
+void ofdm_assemble_modem_frame(complex float modem_frame[],
+ COMP payload_syms[],
+ uint8_t txt_bits[])
+{
+ int Nsymsperframe = OFDM_BITSPERFRAME/OFDM_BPS;
+ int Nuwsyms = OFDM_NUWBITS/OFDM_BPS;
+ int Ntxtsyms = OFDM_NTXTBITS/OFDM_BPS;
+
+ int s,p=0,u=0;
+
+ for (s=0; s<Nsymsperframe-Ntxtsyms; s++) {
+ if ((u < Nuwsyms) && (s == (uw_ind_sym[u]-1))) {
+ modem_frame[s] = tx_uw_syms[u++];
+ } else {
+ modem_frame[s] = payload_syms[p].real + payload_syms[p].imag * I;
+ p++;
+ }
+ }
+ assert(u == Nuwsyms);
+ assert(p == (Nsymsperframe-Nuwsyms-Ntxtsyms));
+
+ int t; int dibit[2];
+
+ for (t=0; s<Nsymsperframe; s++,t+=OFDM_BPS) {
+ dibit[0] = txt_bits[t+1] & 0x1;
+ dibit[1] = txt_bits[t] & 0x1;
+ modem_frame[s] = qpsk_mod(dibit);
+ }
+ assert(t == OFDM_NTXTBITS);
+}
+
+
+void ofdm_disassemble_modem_frame(struct OFDM *ofdm,
+ int rx_uw[],
+ COMP codeword_syms[],
+ float codeword_amps[],
+ int txt_bits[])
+{
+ int Nsymsperframe = OFDM_BITSPERFRAME/OFDM_BPS;
+ int Nuwsyms = OFDM_NUWBITS/OFDM_BPS;
+ int Ntxtsyms = OFDM_NTXTBITS/OFDM_BPS;
+ int dibit[2];
+
+ int s,p=0,u=0;
+
+ for (s=0; s<Nsymsperframe-Ntxtsyms; s++) {
+ if ((u < Nuwsyms) && (s == (uw_ind_sym[u]-1))) {
+ qpsk_demod(ofdm->rx_np[s], dibit);
+ rx_uw[OFDM_BPS*u] = dibit[1];
+ rx_uw[OFDM_BPS*u+1] = dibit[0];
+ u++;
+ } else {
+ codeword_syms[p].real = crealf(ofdm->rx_np[s]);
+ codeword_syms[p].imag = cimagf(ofdm->rx_np[s]);
+ codeword_amps[p] = ofdm->rx_amp[s];
+ p++;
+ }
+ }
+ assert(u == Nuwsyms);
+ assert(p == (Nsymsperframe-Nuwsyms-Ntxtsyms));
+
+ int t;
+
+ for (t=0; s<Nsymsperframe; s++,t+=OFDM_BPS) {
+ qpsk_demod(ofdm->rx_np[s], dibit);
+ txt_bits[t] = dibit[1];
+ txt_bits[t+1] = dibit[0];
+ }
+ assert(t == OFDM_NTXTBITS);
+}
+
int rx_bits[Nbitsperframe];
char rx_bits_char[Nbitsperframe];
int rx_uw[OFDM_NUWBITS];
+ int txt_bits[OFDM_NTXTBITS];
f = 0; Nerrs = Terrs = Tbits = Terrs2 = Tbits2 = Terrs_coded = Tbits_coded = frame_count = 0;
float EsNo = 3;
float snr_est_smoothed_dB = 0.0;
+ COMP payload_syms[coded_syms_per_frame];
+ float payload_amps[coded_syms_per_frame];
COMP codeword_symbols[interleave_frames*coded_syms_per_frame];
float codeword_amps[interleave_frames*coded_syms_per_frame];
for (i=0; i<interleave_frames*coded_syms_per_frame; i++) {
if ((strcmp(ofdm->sync_state,"synced") == 0) || (strcmp(ofdm->sync_state,"trial") == 0) ) {
ofdm_demod(ofdm, rx_bits, rxbuf_in);
+ ofdm_disassemble_modem_frame(ofdm, rx_uw, payload_syms, payload_amps, txt_bits);
if (llr_en) {
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 */
+ /* newest symbols at end of buffer (uses final i from last loop) */
- for(i=(interleave_frames-1)*coded_syms_per_frame,j=(OFDM_NUWBITS+OFDM_NTXTBITS)/OFDM_BPS; i<interleave_frames*coded_syms_per_frame; 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];
+ for(i=(interleave_frames-1)*coded_syms_per_frame,j=0; i<interleave_frames*coded_syms_per_frame; i++,j++) {
+ codeword_symbols[i] = payload_syms[j];
+ codeword_amps[i] = payload_amps[j];
}
/* run de-interleaver */
fwrite(rx_bits_char, sizeof(char), Nbitsperframe, fout);
}
- /* extract Unique Word bits */
-
- for(i=0; i<OFDM_NUWBITS; i++) {
- rx_uw[i] = rx_bits[i];
- }
-
/* optional error counting on uncoded data in non-LDPC testframe mode */
if (testframes && (ldpc_en == 0)) {
#include <complex.h>
#include <stdbool.h>
+#include <stdint.h>
#include "codec2_ofdm.h"
complex float qpsk_mod(int *);
void qpsk_demod(complex float, int *);
void ofdm_txframe(struct OFDM *, complex float tx_samples[OFDM_SAMPLESPERFRAME], complex float tx_symbols_lin[]);
-
+void ofdm_assemble_modem_frame(complex float modem_frame[], COMP payload_syms[], uint8_t txt_bits[]);
+void ofdm_disassemble_modem_frame(struct OFDM *ofdm,
+ int rx_uw[],
+ COMP codeword_syms[],
+ float codeword_amps[],
+ int txt_bits[]);
#ifdef __cplusplus
}
#endif
const int test_bits_ofdm[]={
1,
- 0,
- 0,
1,
0,
1,
- 0,
- 0,
1,
0,
- 0,
- 0,
- 0,
- 0,
- 1,
1,
0,
- 1,
- 1,
0,
1,
0,
0,
- 1,
0,
0,
0,
0,
0,
0,
+ 0,
+ 0,
1,
0,
0,
1,
0,
0,
+ 0,
+ 0,
1,
1,
1,
1,
0,
0,
+ 0,
+ 0,
1,
0,
0,
0,
0,
0,
+ 0,
+ 0,
1,
0,
0,
0,
0,
0,
- 1
+ 1,
+ 0,
+ 0,
+ 0,
+ 0
};
const int payload_data_bits[]={