int Nc;
float snr_est; /* estimated SNR of rx signal in dB (3 kHz noise BW) */
COMP rx_symbols[FDMDV_NC_MAX+1]; /* latest received symbols, for scatter plot */
- int fest_coarse_fine; /* freq est state, 0-coarse 1-fine */
+ int sync; /* demod sync state */
float foff; /* estimated freq offset in Hz */
float rx_timing; /* estimated optimum timing offset in samples */
float clock_offset; /* Estimated tx/rx sample clock offset in ppm */
#include "hanning.h"
#include "os.h"
-/*---------------------------------------------------------------------------*\
+static int sync_uw[] = {1,-1,1,-1,1,-1};
+
+/*---------------------------------------------------------------------------* \
FUNCTIONS
f->foff_phase_rect.imag = 0.0;
f->fest_state = 0;
- f->coarse_fine = COARSE;
- f->bad_sync = 0;
+ f->sync = 0;
+ f->timer = 0;
+ for(i=0; i<NSYNC_MEM; i++)
+ f->sync_mem[i] = 0;
for(c=0; c<Nc+1; c++) {
f->sig_est[c] = 0.0;
\*---------------------------------------------------------------------------*/
-int freq_state(int sync_bit, int *state, int *bad_sync)
+int freq_state(int sync_bit, int *state, int *timer, int *sync_mem)
{
- int next_state, coarse_fine;
+ int next_state, sync, unique_word, i, corr;
+
+ /* look for 6 symbols (120ms) 010101 of sync sequence */
- /* acquire state, look for 6 symbol 010101 sequence from sync bit */
+ unique_word = 0;
+ for(i=0; i<NSYNC_MEM-1; i++)
+ sync_mem[i] = sync_mem[i+1];
+ sync_mem[i] = sync_bit;
+ corr = 0;
+ for(i=0; i<NSYNC_MEM; i++)
+ corr += sync_mem[i]*sync_uw[i];
+ if (corr == NSYNC_MEM)
+ unique_word = 1;
+
+ /* iterate state machine */
next_state = *state;
switch(*state) {
case 0:
- if (sync_bit == 0)
+ if (unique_word) {
next_state = 1;
+ *timer = 0;
+ }
break;
- case 1:
- if (sync_bit == 1)
- next_state = 2;
- else
- next_state = 0;
- break;
- case 2:
- if (sync_bit == 0)
- next_state = 3;
- else
- next_state = 0;
- break;
- case 3:
- if (sync_bit == 1)
- next_state = 4;
- else
- next_state = 0;
- break;
- case 4:
- if (sync_bit == 0)
- next_state = 5;
- else
- next_state = 0;
- break;
- case 5:
- if (sync_bit == 1) {
- next_state = 6;
- *bad_sync = 0;
+ case 1: /* tentative sync state */
+ if (unique_word) {
+ (*timer)++;
+ if (*timer == 25) /* sync has been good for 500ms */
+ next_state = 2;
}
else
- next_state = 0;
+ next_state = 0; /* quickly fall out of sync */
break;
-
- /* states 6 and above are track mode, make sure we keep
- getting 0101 sync bit sequence. bad_sync allows us to track
- through a few bad symbols when BPSK pilot is temporarilly
- faded out, avoiding a costly re-sync when valid data still
- exists on other carriers */
-
- case 6:
- next_state = 7;
- if (sync_bit == 0)
- *bad_sync = 0;
- else {
- (*bad_sync)++;
- if (*bad_sync > 2)
- next_state = 0;
+ case 2: /* good sync state */
+ if (unique_word == 0) {
+ *timer = 0;
+ next_state = 3;
}
-
break;
- case 7:
- next_state = 6;
- if (sync_bit == 1)
- *bad_sync = 0;
- else {
- (*bad_sync)++;
- if (*bad_sync > 2)
+ case 3: /* tentative bad state, but could be a fade */
+ if (unique_word)
+ next_state = 2;
+ else {
+ (*timer)++;
+ if (*timer == 50) /* wait for 1000ms in case sync comes back */
next_state = 0;
}
break;
}
*state = next_state;
- if (*state >= 6)
- coarse_fine = FINE;
+ if (*state)
+ sync = 1;
else
- coarse_fine = COARSE;
+ sync = 0;
- return coarse_fine;
+ return sync;
}
/*---------------------------------------------------------------------------*\
foff_coarse = rx_est_freq_offset(fdmdv, rx_fdm, *nin);
- if (fdmdv->coarse_fine == COARSE)
+ if (fdmdv->sync == 0)
fdmdv->foff = foff_coarse;
fdmdv_freq_shift(rx_fdm_fcorr, rx_fdm, -fdmdv->foff, &fdmdv->foff_rect, &fdmdv->foff_phase_rect, *nin);
/* freq offset estimation state machine */
- fdmdv->coarse_fine = freq_state(*sync_bit, &fdmdv->fest_state, &fdmdv->bad_sync);
+ fdmdv->sync = freq_state(*sync_bit, &fdmdv->fest_state, &fdmdv->timer, fdmdv->sync_mem);
fdmdv->foff -= TRACK_COEFF*foff_fine;
}
fdmdv_stats->Nc = fdmdv->Nc;
fdmdv_stats->snr_est = calc_snr(fdmdv->Nc, fdmdv->sig_est, fdmdv->noise_est);
- fdmdv_stats->fest_coarse_fine = fdmdv->coarse_fine;
+ fdmdv_stats->sync = fdmdv->sync;
fdmdv_stats->foff = fdmdv->foff;
fdmdv_stats->rx_timing = fdmdv->rx_timing;
fdmdv_stats->clock_offset = 0.0; /* TODO - implement clock offset estimation */
COMP *rx_fdm_log;
int rx_fdm_log_col_index;
COMP *rx_symbols_log;
- int coarse_fine_log[MAX_FRAMES];
+ int sync_log[MAX_FRAMES];
float rx_timing_log[MAX_FRAMES];
float foff_log[MAX_FRAMES];
int sync_bit_log[MAX_FRAMES];
rx_symbols_log[f*(Nc+1)+c] = stats.rx_symbols[c];
foff_log[f] = stats.foff;
rx_timing_log[f] = stats.rx_timing;
- coarse_fine_log[f] = stats.fest_coarse_fine;
+ sync_log[f] = stats.sync;
sync_bit_log[f] = sync_bit;
memcpy(&rx_bits_log[bits_per_fdmdv_frame*f], rx_bits, sizeof(int)*bits_per_fdmdv_frame);
snr_est_log[f] = stats.snr_est;
octave_save_complex(foct, "rx_symbols_log_c", (COMP*)rx_symbols_log, Nc+1, f, MAX_FRAMES);
octave_save_float(foct, "foff_log_c", foff_log, 1, f, MAX_FRAMES);
octave_save_float(foct, "rx_timing_log_c", rx_timing_log, 1, f, MAX_FRAMES);
- octave_save_int(foct, "coarse_fine_log_c", coarse_fine_log, 1, f);
+ octave_save_int(foct, "sync_log_c", sync_log, 1, f);
octave_save_int(foct, "rx_bits_log_c", rx_bits_log, 1, bits_per_fdmdv_frame*f);
octave_save_int(foct, "sync_bit_log_c", sync_bit_log, 1, f);
octave_save_float(foct, "snr_est_log_c", snr_est_log, 1, f, MAX_FRAMES);
#define NPILOTLPF (4*M) /* number of samples we DFT pilot over, pilot est window */
#define MPILOTFFT 256
-/* freq offset sestimation states */
-
-#define COARSE 0
-#define FINE 1
+#define NSYNC_MEM 6
/* averaging filter coeffs */
COMP phase_difference[NC+1];
COMP prev_rx_symbols[NC+1];
- /* freq est state machine */
+ /* sync state machine */
+ int sync_mem[NSYNC_MEM];
int fest_state;
- int coarse_fine;
- int bad_sync;
+ int sync;
+ int timer;
/* SNR estimation states */
int nin);
float qpsk_to_bits(int rx_bits[], int *sync_bit, int Nc, COMP phase_difference[], COMP prev_rx_symbols[], COMP rx_symbols[], int old_qpsk_mapping);
void snr_update(float sig_est[], float noise_est[], int Nc, COMP phase_difference[]);
-int freq_state(int sync_bit, int *state, int *bad_sync);
+int freq_state(int sync_bit, int *state, int *timer, int *sync_mem);
float calc_snr(int Nc, float sig_est[], float noise_est[]);
#endif