#include "kiss_fft.h"
#include "hanning.h"
#include "os.h"
+#include "machdep.h"
static int sync_uw[] = {1,-1,1,-1,1,-1};
-/*---------------------------------------------------------------------------* \
+#ifdef __EMBEDDED__
+#define printf gdb_stdio_printf
+#endif
+
+/*---------------------------------------------------------------------------*\
FUNCTIONS
{
COMP tx_symbols[NC+1];
COMP tx_baseband[NC+1][M];
+ TIMER_VAR(mod_start, tx_filter_start, fdm_upconvert_start);
+ TIMER_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));
+ TIMER_SAMPLE_AND_LOG(tx_filter_start, mod_start, " bits_to_dqpsk_symbols");
tx_filter(tx_baseband, fdmdv->Nc, tx_symbols, fdmdv->tx_filter_memory);
+ TIMER_SAMPLE_AND_LOG(fdm_upconvert_start, tx_filter_start, " tx_filter");
fdm_upconvert(tx_fdm, fdmdv->Nc, tx_baseband, fdmdv->phase_tx, fdmdv->freq);
+ TIMER_SAMPLE_AND_LOG2(fdm_upconvert_start, " fdm_upconvert");
*sync_bit = fdmdv->tx_pilot_bit;
}
float windback_phase, mag;
COMP windback_phase_rect;
COMP rx_baseband[NFILTER+M];
+ TIMER_VAR(windback_start, downconvert_start, filter_start);
/* update memory of rx_fdm */
phase continuity.
*/
+ TIMER_SAMPLE(windback_start);
windback_phase = -freq_pol[c]*NFILTER;
windback_phase_rect.real = cosf(windback_phase);
windback_phase_rect.imag = sinf(windback_phase);
phase_rx[c] = cmult(phase_rx[c],windback_phase_rect);
+ TIMER_SAMPLE_AND_LOG(downconvert_start, windback_start, " windback");
/* down convert all samples in buffer */
phase_rx[c] = cmult(phase_rx[c], freq[c]);
rx_baseband[i] = cmult(rx_fdm_mem[i],cconj(phase_rx[c]));
}
+ TIMER_SAMPLE_AND_LOG(filter_start, downconvert_start, " downconvert");
/* now we can filter this carrier's P symbols */
for(m=0; m<NFILTER; m++)
rx_filt[c][k] = cadd(rx_filt[c][k], fcmult(gt_alpha5_root[m], rx_baseband[st+i+m]));
}
+ TIMER_SAMPLE_AND_LOG2(filter_start, " filter");
/* normalise digital oscilators as the magnitude can drift over time */
COMP rx_symbols[NC+1];
float env[NT*P];
int sync_bit;
+ TIMER_VAR(demod_start, fdmdv_freq_shift_start, down_convert_and_rx_filter_start);
+ TIMER_VAR(rx_est_timing_start, qpsk_to_bits_start, snr_update_start, freq_state_start);
/* freq offset estimation and correction */
+ TIMER_SAMPLE(demod_start);
foff_coarse = rx_est_freq_offset(fdmdv, rx_fdm, *nin);
+ TIMER_SAMPLE_AND_LOG(fdmdv_freq_shift_start, demod_start, " rx_est_freq_offset");
if (fdmdv->sync == 0)
fdmdv->foff = foff_coarse;
fdmdv_freq_shift(rx_fdm_fcorr, rx_fdm, -fdmdv->foff, &fdmdv->foff_phase_rect, *nin);
-
+ TIMER_SAMPLE_AND_LOG(down_convert_and_rx_filter_start, fdmdv_freq_shift_start, " fdmdv_freq_shift");
+
/* baseband processing */
down_convert_and_rx_filter(rx_filt, fdmdv->Nc, rx_fdm_fcorr, fdmdv->rx_fdm_mem, fdmdv->phase_rx, fdmdv->freq,
fdmdv->freq_pol, *nin);
+ TIMER_SAMPLE_AND_LOG(rx_est_timing_start, down_convert_and_rx_filter_start, " down_convert_and_rx_filter");
fdmdv->rx_timing = rx_est_timing(rx_symbols, fdmdv->Nc, rx_filt, fdmdv->rx_filter_mem_timing, env, *nin);
+ TIMER_SAMPLE_AND_LOG(qpsk_to_bits_start, rx_est_timing_start, " rx_est_timing");
/* Adjust number of input samples to keep timing within bounds */
foff_fine = qpsk_to_bits(rx_bits, &sync_bit, fdmdv->Nc, fdmdv->phase_difference, fdmdv->prev_rx_symbols, rx_symbols,
fdmdv->old_qpsk_mapping);
memcpy(fdmdv->prev_rx_symbols, rx_symbols, sizeof(COMP)*(fdmdv->Nc+1));
+ TIMER_SAMPLE_AND_LOG(snr_update_start, qpsk_to_bits_start, " qpsk_to_bits");
snr_update(fdmdv->sig_est, fdmdv->noise_est, fdmdv->Nc, fdmdv->phase_difference);
+ TIMER_SAMPLE_AND_LOG(freq_state_start, snr_update_start, " snr_update");
/* freq offset estimation state machine */
fdmdv->sync = freq_state(reliable_sync_bit, sync_bit, &fdmdv->fest_state, &fdmdv->timer, fdmdv->sync_mem);
+ TIMER_SAMPLE_AND_LOG2(freq_state_start, " freq_state");
fdmdv->foff -= TRACK_COEFF*foff_fine;
}
S = 0.0;
for(c=0; c<Nc+1; c++)
- S += pow(sig_est[c], 2.0);
- SdB = 10.0*log10(S+1E-12);
+ S += powf(sig_est[c], 2.0);
+ SdB = 10.0*log10f(S+1E-12);
/* Average noise mag across all carriers and square to get an
average noise power. This is an estimate of the noise power in
for(c=0; c<Nc+1; c++)
mean += noise_est[c];
mean /= (Nc+1);
- N50 = pow(mean, 2.0);
- N50dB = 10.0*log10(N50+1E-12);
+ N50 = powf(mean, 2.0);
+ N50dB = 10.0*log10f(N50+1E-12);
/* Now multiply by (3000 Hz)/(50 Hz) to find the total noise power
in 3000 Hz */
- N3000dB = N50dB + 10.0*log10(3000.0/RS);
+ N3000dB = N50dB + 10.0*log10f(3000.0/RS);
snr_dB = SdB - N3000dB;
/* scale and convert to dB */
for(i=0; i<FDMDV_NSPEC; i++) {
- mag_spec_dB[i] = 10.0*log10(fft_out[i].real*fft_out[i].real + fft_out[i].imag*fft_out[i].imag + 1E-12);
+ mag_spec_dB[i] = 10.0*log10f(fft_out[i].real*fft_out[i].real + fft_out[i].imag*fft_out[i].imag + 1E-12);
mag_spec_dB[i] -= full_scale_dB;
}
}
fprintf(stderr, "phase_tx[]:\n");
for(i=0; i<=f->Nc; i++)
- fprintf(stderr," %1.3f", cabsolute(f->phase_tx[i]));
+ fprintf(stderr," %1.3f", (double)cabsolute(f->phase_tx[i]));
fprintf(stderr,"\nfreq[]:\n");
for(i=0; i<=f->Nc; i++)
- fprintf(stderr," %1.3f", cabsolute(f->freq[i]));
- fprintf(stderr,"\nfoff_phase_rect: %1.3f", cabsolute(f->foff_phase_rect));
+ fprintf(stderr," %1.3f", (double)cabsolute(f->freq[i]));
+ fprintf(stderr,"\nfoff_phase_rect: %1.3f", (double)cabsolute(f->foff_phase_rect));
fprintf(stderr,"\nphase_rx[]:\n");
for(i=0; i<=f->Nc; i++)
- fprintf(stderr," %1.3f", cabsolute(f->phase_rx[i]));
+ fprintf(stderr," %1.3f", (double)cabsolute(f->phase_rx[i]));
fprintf(stderr, "\n\n");
}
#endif\r
\r
#define TEST_FRAMES 25\r
+#define CHANNEL_BUF_SIZE (10*FDMDV_NOM_SAMPLES_PER_FRAME)\r
+\r
+static int channel_count = 0;\r
+static COMP channel[CHANNEL_BUF_SIZE];\r
+\r
+static void channel_in(COMP tx_fdm[], int nout) {\r
+ int i;\r
+\r
+ /* add M tx samples to end of buffer */\r
+\r
+ assert((channel_count + nout) < CHANNEL_BUF_SIZE);\r
+ for(i=0; i<nout; i++)\r
+ channel[channel_count+i] = tx_fdm[i];\r
+ channel_count += M;\r
+}\r
+\r
+static void channel_out(COMP rx_fdm[], int nin) {\r
+ int i,j;\r
+\r
+ /* take nin samples from start of buffer */\r
+\r
+ for(i=0; i<nin; i++) {\r
+ rx_fdm[i] = channel[i];\r
+ }\r
+\r
+ /* shift buffer back */\r
+\r
+ for(i=0,j=nin; j<channel_count; i++,j++)\r
+ channel[i] = channel[j];\r
+ channel_count -= nin;\r
+}\r
\r
int main(int argc, char *argv[]) {\r
struct FDMDV *fdmdv;\r
int bits_per_fdmdv_frame, bits_per_codec_frame;\r
int *tx_bits;\r
int *rx_bits;\r
+ int *codec_bits;\r
COMP tx_fdm[2*FDMDV_NOM_SAMPLES_PER_FRAME];\r
- int i, nin, reliable_sync_bit, sync_bit, bit_errors, ntest_bits, test_frame_sync;\r
+ COMP rx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME];\r
+ int i, j, nin, reliable_sync_bit[2], sync_bit, bit_errors, ntest_bits, test_frame_sync;\r
short *error_pattern;\r
struct FDMDV_STATS stats;\r
TIMER_VAR(mod_start, demod_start);\r
bits_per_codec_frame = 2*fdmdv_bits_per_frame(fdmdv);\r
tx_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(tx_bits != NULL);\r
rx_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(rx_bits != NULL);\r
+ codec_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame); assert(rx_bits != NULL);\r
error_pattern = (short*)malloc(fdmdv_error_pattern_size(fdmdv)*sizeof(int)); assert(error_pattern != NULL);\r
\r
nin = FDMDV_NOM_SAMPLES_PER_FRAME;\r
+ test_frame_sync = 0;\r
\r
for(i=0; i<TEST_FRAMES; i++) {\r
fdmdv_get_test_bits(fdmdv, tx_bits);\r
assert(sync_bit == 1);\r
fdmdv_mod(fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &tx_bits[bits_per_fdmdv_frame], &sync_bit);\r
assert(sync_bit == 0);\r
+ channel_in(tx_fdm, 2*FDMDV_NOM_SAMPLES_PER_FRAME);\r
\r
TIMER_SAMPLE_AND_LOG(demod_start, mod_start, " mod"); \r
\r
- fdmdv_demod(fdmdv, rx_bits, &reliable_sync_bit, tx_fdm, &nin);\r
- fdmdv_demod(fdmdv, &rx_bits[bits_per_fdmdv_frame], &reliable_sync_bit, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &nin);\r
+ for(j=0; j<2; j++) {\r
+ channel_out(rx_fdm, nin);\r
+ fdmdv_demod(fdmdv, rx_bits, &reliable_sync_bit[j], rx_fdm, &nin);\r
+ if (reliable_sync_bit[j] == 0)\r
+ memcpy(codec_bits, rx_bits, bits_per_fdmdv_frame*sizeof(int));\r
+ else {\r
+ memcpy(&codec_bits[bits_per_fdmdv_frame], rx_bits, bits_per_fdmdv_frame*sizeof(int));\r
+ fdmdv_put_test_bits(fdmdv, &test_frame_sync, error_pattern, &bit_errors, &ntest_bits, codec_bits);\r
+ fdmdv_put_test_bits(fdmdv, &test_frame_sync, error_pattern, &bit_errors, &ntest_bits, &codec_bits[bits_per_fdmdv_frame]);\r
+ }\r
+ }\r
TIMER_SAMPLE_AND_LOG2(demod_start, " demod"); \r
TIMER_SAMPLE_AND_LOG2(mod_start, " mod & demod"); \r
\r
fdmdv_get_demod_stats(fdmdv, &stats);\r
- fdmdv_put_test_bits(fdmdv, &test_frame_sync, error_pattern, &bit_errors, &ntest_bits, rx_bits);\r
\r
- printf("frame: %d sync: %d reliable_sync_bit: %d SNR: %3.2f test_frame_sync: %d\n", \r
- i, stats.sync, reliable_sync_bit, (double)stats.snr_est, test_frame_sync);\r
+ printf("frame: %d sync: %d reliable_sync_bit: %d %d SNR: %3.2f test_frame_sync: %d\n", \r
+ i, stats.sync, reliable_sync_bit[0], reliable_sync_bit[1], (double)stats.snr_est, \r
+ test_frame_sync);\r
machdep_timer_print_logged_samples();\r
}\r
\r