stem_sig_and_error(1, 211, tx_bits_log_c(1:n), tx_bits_log(1:n) - tx_bits_log_c(1:n), 'tx bits', [1 n -1.5 1.5])
stem_sig_and_error(1, 212, real(tx_symbols_log_c(1:n/2)), real(tx_symbols_log(1:n/2) - tx_symbols_log_c(1:n/2)), 'tx symbols real', [1 n/2 -1.5 1.5])
-% tx_filter()
-
-diff = tx_baseband_log - tx_baseband_log_c;
-c=1;
-plot_sig_and_error(2, 211, real(tx_baseband_log_c(c,:)), real(tx_baseband_log(c,:) - tx_baseband_log_c(c,:)), 'tx baseband real')
-plot_sig_and_error(2, 212, imag(tx_baseband_log_c(c,:)), imag(tx_baseband_log(c,:) - tx_baseband_log_c(c,:)), 'tx baseband imag')
-
% fdm_upconvert()
plot_sig_and_error(3, 211, real(tx_fdm_log_c), real(tx_fdm_log - tx_fdm_log_c), 'tx fdm real')
check(tx_bits_log, tx_bits_log_c, 'tx_bits');
check(tx_symbols_log, tx_symbols_log_c, 'tx_symbols');
-check(tx_baseband_log, tx_baseband_log_c, 'tx_baseband');
check(tx_fdm_log, tx_fdm_log_c, 'tx_fdm');
check(pilot_lut, pilot_lut_c, 'pilot_lut');
check(pilot_coeff, pilot_coeff_c, 'pilot_coeff');
static float cabsolute(COMP a)
{
- return sqrtf(pow(a.real, 2.0) + pow(a.imag, 2.0));
+ return sqrtf(powf(a.real, 2.0) + powf(a.imag, 2.0));
}
/*---------------------------------------------------------------------------*\
*pilot_bit = 1;
}
+
/*---------------------------------------------------------------------------*\
FUNCTION....: tx_filter()
}
}
+
+/*---------------------------------------------------------------------------*\
+
+ FUNCTION....: tx_filter_and_upconvert()
+ AUTHOR......: David Rowe
+ DATE CREATED: 13 August 2014
+
+ Given Nc*NB bits construct M samples (1 symbol) of Nc+1 filtered
+ symbols streams.
+
+\*---------------------------------------------------------------------------*/
+
+void tx_filter_and_upconvert(COMP tx_fdm[], int Nc, COMP tx_symbols[],
+ COMP tx_filter_memory[NC+1][NSYM],
+ COMP phase_tx[], COMP freq[],
+ COMP *fbb_phase, COMP fbb_rect)
+{
+ int c;
+ int i,j,k;
+ float acc;
+ COMP gain;
+ COMP tx_baseband;
+ COMP two = {2.0, 0.0};
+ float mag;
+
+ gain.real = sqrtf(2.0)/2.0;
+ gain.imag = 0.0;
+
+ for(i=0; i<M; i++) {
+ tx_fdm[i].real = 0.0;
+ tx_fdm[i].imag = 0.0;
+ }
+
+ for(c=0; c<Nc+1; c++)
+ tx_filter_memory[c][NSYM-1] = cmult(tx_symbols[c], gain);
+
+ /*
+ tx filter each symbol, generate M filtered output samples for
+ each symbol, which we then freq shift and sum with other
+ carriers. Efficient polyphase filter techniques used as
+ tx_filter_memory is sparse
+ */
+
+ for(c=0; c<Nc+1; c++) {
+ for(i=0; i<M; i++) {
+
+ /* filter real sample of symbol for carrier c */
+
+ acc = 0.0;
+ for(j=0,k=M-i-1; j<NSYM; j++,k+=M)
+ acc += M * tx_filter_memory[c][j].real * gt_alpha5_root[k];
+ tx_baseband.real = acc;
+
+ /* filter imag sample of symbol for carrier c */
+
+ acc = 0.0;
+ for(j=0,k=M-i-1; j<NSYM; j++,k+=M)
+ acc += M * tx_filter_memory[c][j].imag * gt_alpha5_root[k];
+ tx_baseband.imag = acc;
+
+ /* freq shift and sum */
+
+ phase_tx[c] = cmult(phase_tx[c], freq[c]);
+ tx_fdm[i] = cadd(tx_fdm[i], cmult(tx_baseband, phase_tx[c]));
+ }
+ }
+
+ /* shift whole thing up to carrier freq */
+
+ for (i=0; i<M; i++) {
+ *fbb_phase = cmult(*fbb_phase, fbb_rect);
+ tx_fdm[i] = cmult(tx_fdm[i], *fbb_phase);
+ }
+
+ /*
+ Scale such that total Carrier power C of real(tx_fdm) = Nc. This
+ excludes the power of the pilot tone.
+ We return the complex (single sided) signal to make frequency
+ shifting for the purpose of testing easier
+ */
+
+ for (i=0; i<M; i++)
+ tx_fdm[i] = cmult(two, tx_fdm[i]);
+
+ /* normalise digital oscillators as the magnitude can drift over time */
+
+ for (c=0; c<Nc+1; c++) {
+ mag = cabsolute(phase_tx[c]);
+ phase_tx[c].real /= mag;
+ phase_tx[c].imag /= mag;
+ }
+
+ mag = cabsolute(*fbb_phase);
+ fbb_phase->real /= mag;
+ fbb_phase->imag /= mag;
+
+ /* shift memory, inserting zeros at end */
+
+ for(i=0; i<NSYM-1; i++)
+ for(c=0; c<Nc+1; c++)
+ tx_filter_memory[c][i] = tx_filter_memory[c][i+1];
+
+ for(c=0; c<Nc+1; c++) {
+ tx_filter_memory[c][NSYM-1].real = 0.0;
+ tx_filter_memory[c][NSYM-1].imag = 0.0;
+ }
+}
+
+
/*---------------------------------------------------------------------------*\
FUNCTION....: fdm_upconvert()
for (i=0; i<M; i++)
tx_fdm[i] = cmult(two, tx_fdm[i]);
- /* normalise digital oscilators as the magnitude can drfift over time */
+ /* normalise digital oscilators as the magnitude can drift over time */
for (c=0; c<Nc+1; c++) {
mag = cabsolute(phase_tx[c]);
void fdmdv_mod(struct FDMDV *fdmdv, COMP tx_fdm[], int tx_bits[], int *sync_bit)
{
COMP tx_symbols[NC+1];
- COMP tx_baseband[NC+1][M];
- PROFILE_VAR(mod_start, tx_filter_start, fdm_upconvert_start);
+ PROFILE_VAR(mod_start, tx_filter_and_upconvert_start);
PROFILE_SAMPLE(mod_start);
bits_to_dqpsk_symbols(tx_symbols, fdmdv->Nc, fdmdv->prev_tx_symbols, tx_bits, &fdmdv->tx_pilot_bit, fdmdv->old_qpsk_mapping);
memcpy(fdmdv->prev_tx_symbols, tx_symbols, sizeof(COMP)*(fdmdv->Nc+1));
- PROFILE_SAMPLE_AND_LOG(tx_filter_start, mod_start, " bits_to_dqpsk_symbols");
- tx_filter(tx_baseband, fdmdv->Nc, tx_symbols, fdmdv->tx_filter_memory);
- PROFILE_SAMPLE_AND_LOG(fdm_upconvert_start, tx_filter_start, " tx_filter");
- fdm_upconvert(tx_fdm, fdmdv->Nc, tx_baseband, fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect);
- PROFILE_SAMPLE_AND_LOG2(fdm_upconvert_start, " fdm_upconvert");
+ PROFILE_SAMPLE_AND_LOG(tx_filter_and_upconvert_start, mod_start, " bits_to_dqpsk_symbols");
+ tx_filter_and_upconvert(tx_fdm, fdmdv->Nc, tx_symbols, fdmdv->tx_filter_memory,
+ fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect);
*sync_bit = fdmdv->tx_pilot_bit;
}
void tx_filter(COMP tx_baseband[NC+1][M], int Nc, COMP tx_symbols[], COMP tx_filter_memory[NC+1][NSYM]);
void fdm_upconvert(COMP tx_fdm[], int Nc, COMP tx_baseband[NC+1][M], COMP phase_tx[], COMP freq_tx[],
COMP *fbb_phase, COMP fbb_rect);
+void tx_filter_and_upconvert(COMP tx_fdm[], int Nc, COMP tx_symbols[],
+ COMP tx_filter_memory[NC+1][NSYM],
+ COMP phase_tx[], COMP freq[], COMP *fbb_phase, COMP fbb_rect);
void generate_pilot_fdm(COMP *pilot_fdm, int *bit, float *symbol, float *filter_mem, COMP *phase, COMP *freq);
void generate_pilot_lut(COMP pilot_lut[], COMP *pilot_freq);
float rx_est_freq_offset(struct FDMDV *f, COMP rx_fdm[], int nin);
struct FDMDV *fdmdv;
int tx_bits[FDMDV_BITS_PER_FRAME];
COMP tx_symbols[FDMDV_NC+1];
- COMP tx_baseband[NC+1][M];
COMP tx_fdm[M];
float channel[CHANNEL_BUF_SIZE];
int channel_count;
int tx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES];
COMP tx_symbols_log[(FDMDV_NC+1)*FRAMES];
- COMP tx_baseband_log[(NC+1)][M*FRAMES];
COMP tx_fdm_log[M*FRAMES];
COMP pilot_baseband1_log[NPILOTBASEBAND*FRAMES];
COMP pilot_baseband2_log[NPILOTBASEBAND*FRAMES];
fdmdv_get_test_bits(fdmdv, tx_bits);
bits_to_dqpsk_symbols(tx_symbols, FDMDV_NC, fdmdv->prev_tx_symbols, tx_bits, &fdmdv->tx_pilot_bit, 0);
memcpy(fdmdv->prev_tx_symbols, tx_symbols, sizeof(COMP)*(FDMDV_NC+1));
- tx_filter(tx_baseband, FDMDV_NC, tx_symbols, fdmdv->tx_filter_memory);
- fdm_upconvert(tx_fdm, FDMDV_NC, tx_baseband, fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect);
+ tx_filter_and_upconvert(tx_fdm, FDMDV_NC , tx_symbols, fdmdv->tx_filter_memory,
+ fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect);
/* --------------------------------------------------------*\
Channel
memcpy(&tx_bits_log[FDMDV_BITS_PER_FRAME*f], tx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME);
memcpy(&tx_symbols_log[(FDMDV_NC+1)*f], tx_symbols, sizeof(COMP)*(FDMDV_NC+1));
- for(c=0; c<FDMDV_NC+1; c++)
- for(i=0; i<M; i++)
- tx_baseband_log[c][f*M+i] = tx_baseband[c][i];
memcpy(&tx_fdm_log[M*f], tx_fdm, sizeof(COMP)*M);
memcpy(&pilot_baseband1_log[f*NPILOTBASEBAND], fdmdv->pilot_baseband1, sizeof(COMP)*NPILOTBASEBAND);
fprintf(fout, "# Created by tfdmdv.c\n");
octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, FDMDV_BITS_PER_FRAME*FRAMES);
octave_save_complex(fout, "tx_symbols_log_c", tx_symbols_log, 1, (FDMDV_NC+1)*FRAMES, (FDMDV_NC+1)*FRAMES);
- octave_save_complex(fout, "tx_baseband_log_c", (COMP*)tx_baseband_log, (FDMDV_NC+1), M*FRAMES, M*FRAMES);
- octave_save_complex(fout, "tx_fdm_log_c", (COMP*)tx_fdm_log, 1, M*FRAMES, M*FRAMES);
+octave_save_complex(fout, "tx_fdm_log_c", (COMP*)tx_fdm_log, 1, M*FRAMES, M*FRAMES);
octave_save_complex(fout, "pilot_lut_c", (COMP*)fdmdv->pilot_lut, 1, NPILOT_LUT, NPILOT_LUT);
octave_save_complex(fout, "pilot_baseband1_log_c", pilot_baseband1_log, 1, NPILOTBASEBAND*FRAMES, NPILOTBASEBAND*FRAMES);
octave_save_complex(fout, "pilot_baseband2_log_c", pilot_baseband2_log, 1, NPILOTBASEBAND*FRAMES, NPILOTBASEBAND*FRAMES);