[ ] block diagram
[ ] blog posts(s)
[ ] Codec 2 web page update
+[ ] demo modem C test program
Tests
% Estimate optimum timing offset, re-filter receive symbols
-function [rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, nin)
+function [rx_symbols rx_timing env] = rx_est_timing(rx_filt, rx_baseband, nin)
global M;
global Nt;
global Nc;
rx_timing += M;
end
- % rx_filt_mem_timing contains M + Nfilter + M samples of the
+ % rx_baseband_mem_timing contains M + Nfilter + M samples of the
% baseband signal at rate M this enables us to resample the filtered
% rx symbol with M sample precision once we have rx_timing
foff_log = [];
rx_baseband_log = [];
rx_filt_log = [];
+env_log = [];
+rx_timing_log = [];
+rx_symbols_log = [];
for f=1:frames
rx_baseband_log = [rx_baseband_log rx_baseband];
rx_filt = rx_filter(rx_baseband, M);
rx_filt_log = [rx_filt_log rx_filt];
-
+ [rx_symbols rx_timing env] = rx_est_timing(rx_filt, rx_baseband, M);
+ env_log = [env_log env];
+ rx_timing_log = [rx_timing_log rx_timing];
+ rx_symbols_log = [rx_symbols_log rx_symbols];
end
% Compare to the output from the C version
n = 28;
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)), tx_symbols_log(1:n/2) - tx_symbols_log_c(1:n/2), 'tx symbols real', [1 n/2 -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()
plot_sig_and_error(8, 212, imag(S2_log), imag(S2_log - S2_log_c), 'S2 imag' )
plot_sig_and_error(9, 211, real(foff_log), real(foff_log - foff_log_c), 'Freq Offset' )
+plot_sig_and_error(9, 212, rx_timing_log, rx_timing_log - rx_timing_log_c, 'Rx Timing' )
c=10;
plot_sig_and_error(10, 211, real(rx_baseband_log(c,:)), real(rx_baseband_log(c,:) - rx_baseband_log_c(c,:)), 'Rx baseband real' )
plot_sig_and_error(11, 211, real(rx_filt_log(c,:)), real(rx_filt_log(c,:) - rx_filt_log_c(c,:)), 'Rx filt real' )
plot_sig_and_error(11, 212, imag(rx_filt_log(c,:)), imag(rx_filt_log(c,:) - rx_filt_log_c(c,:)), 'Rx filt imag' )
+plot_sig_and_error(12, 211, env_log, env_log - env_log_c, 'env' )
+plot_sig_and_error(12, 212, real(rx_symbols_log(c,:)), real(rx_symbols_log(c,:) - rx_symbols_log_c(c,:)), 'rx symbols' )
+
% ---------------------------------------------------------------------------------------
% AUTOMATED CHECKS ------------------------------------------
% ---------------------------------------------------------------------------------------
check(foff_log, foff_log_c, 'rx_est_freq_offset');
check(rx_baseband_log, rx_baseband_log_c, 'fdm_downconvert');
check(rx_filt_log, rx_filt_log_c, 'fdm_downconvert');
+check(env_log, env_log_c, 'env');
+check(rx_timing_log, rx_timing_log_c, 'rx_est_timing');
+check(rx_symbols_log, rx_symbols_log_c, 'rx_symbols');
printf("\npasses: %d fails: %d\n", passes, fails);
for(c=0; c<NC+1; c++)
for(i=0,j=nin; i<NFILTERTIMING-nin; i++,j++)
- rx_baseband_mem_timing[c][i] = rx_filter_mem_timing[c][j];
+ rx_baseband_mem_timing[c][i] = rx_baseband_mem_timing[c][j];
for(c=0; c<NC+1; c++)
for(i=NFILTERTIMING-nin,j=0; i<NFILTERTIMING; i++,j++)
rx_baseband_mem_timing[c][i] = rx_baseband[c][j];
-
+
/* rx filter to get symbol for each carrier at estimated optimum
timing instant. We use rate M filter memory to get fine timing
resolution. */
{
struct FDMDV *fdmdv;
int tx_bits[FDMDV_BITS_PER_FRAME];
- COMP tx_symbols[(NC+1)];
- COMP tx_baseband[(NC+1)][M];
+ COMP tx_symbols[NC+1];
+ COMP tx_baseband[NC+1][M];
COMP tx_fdm[M];
float rx_fdm[M+M/P];
float foff;
COMP rx_fdm_fcorr[M+M/P];
COMP rx_baseband[NC+1][M+M/P];
COMP rx_filt[NC+1][P+1];
+ float rx_timing;
+ float env[NT*P];
+ COMP rx_symbols[NC+1];
int tx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES];
COMP tx_symbols_log[(NC+1)*FRAMES];
int rx_baseband_log_col_index;
COMP rx_filt_log[NC+1][(P+1)*FRAMES];
int rx_filt_log_col_index;
-
+ float env_log[NT*P*FRAMES];
+ float rx_timing_log[FRAMES];
+ COMP rx_symbols_log[NC+1][FRAMES];
+
FILE *fout;
int f,c,i;
fdm_downconvert(rx_baseband, rx_fdm_fcorr, fdmdv->phase_rx, fdmdv->freq, nin);
rx_filter(rx_filt, rx_baseband, fdmdv->rx_filter_memory, nin);
+ rx_timing = rx_est_timing(rx_symbols, rx_filt, rx_baseband, fdmdv->rx_filter_mem_timing, env, fdmdv->rx_baseband_mem_timing, nin);
/* save log of outputs ------------------------------------------------------*/
memcpy(&pilot_lpf2_log[f*NPILOTLPF], fdmdv->pilot_lpf2, sizeof(COMP)*NPILOTLPF);
memcpy(&S1_log[f*MPILOTFFT], fdmdv->S1, sizeof(COMP)*MPILOTFFT);
memcpy(&S2_log[f*MPILOTFFT], fdmdv->S2, sizeof(COMP)*MPILOTFFT);
- memcpy(&foff_log[f], &foff, sizeof(float));
+ foff_log[f] = foff;
/* rx down conversion */
}
rx_filt_log_col_index += (P*M)/nin;
+ /* timing estimation */
+
+ memcpy(&env_log[NT*P*f], env, sizeof(float)*NT*P);
+ rx_timing_log[f] = rx_timing;
+ for(c=0; c<NC+1; c++)
+ rx_symbols_log[c][f] = rx_symbols[c];
}
/* dump logs to Octave file for evaluation by tfdmdv.m Octave script */
octave_save_float(fout, "foff_log_c", foff_log, 1, FRAMES);
octave_save_complex(fout, "rx_baseband_log_c", (COMP*)rx_baseband_log, (NC+1), rx_baseband_log_col_index, (M+M/P)*FRAMES);
octave_save_complex(fout, "rx_filt_log_c", (COMP*)rx_filt_log, (NC+1), rx_filt_log_col_index, (P+1)*FRAMES);
+ octave_save_float(fout, "env_log_c", env_log, 1, NT*P*FRAMES);
+ octave_save_float(fout, "rx_timing_log_c", rx_timing_log, 1, FRAMES);
+ octave_save_complex(fout, "rx_symbols_log_c", (COMP*)rx_symbols_log, (NC+1), FRAMES, FRAMES);
fclose(fout);
codec2_destroy(fdmdv);