diff --git a/impl/src/layer1/rx.c b/impl/src/layer1/rx.c index 062be61..3943b54 100644 --- a/impl/src/layer1/rx.c +++ b/impl/src/layer1/rx.c @@ -10,11 +10,15 @@ #include "rx.h" +#include "utils.h" + #define HEADER_SIZE_BYTES 4 #define FREQ_EST_L 8 -#define AGC_BW_ACQUISITION 5e-2 -#define AGC_BW_TRACKING 1e-4 +#define AGC_BW_ACQUISITION 5e-2f +#define AGC_BW_TRACKING 1e-4f + +#define MAX_COARSE_FREQ_OFFSET 0.20f #define SHOW_DEBUG_LOG 0 @@ -83,6 +87,15 @@ static bool acquire_preamble(layer1_rx_t *rx, const float complex sample) float freq_adjustment = (freq_est / RRC_SPS) * 0.3f; nco_crcf_adjust_frequency(rx->carrier_coarse_nco, freq_adjustment); + float actual_freq = nco_crcf_get_frequency(rx->carrier_coarse_nco); + if(actual_freq > MAX_COARSE_FREQ_OFFSET) { + fprintf(stderr, ">"); + nco_crcf_set_frequency(rx->carrier_coarse_nco, MAX_COARSE_FREQ_OFFSET); + } else if(actual_freq < -MAX_COARSE_FREQ_OFFSET) { + fprintf(stderr, "<"); + nco_crcf_set_frequency(rx->carrier_coarse_nco, -MAX_COARSE_FREQ_OFFSET); + } + DEBUG_LOG("Frequency adjustment: %.6f - carrier frequency: %.6f\n", freq_adjustment, nco_crcf_get_frequency(rx->carrier_coarse_nco)); freq_est_history_write_idx = 0; @@ -101,12 +114,19 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t static size_t symbol_counter = 0; static uint8_t symbols_int[1 << 12]; + float complex samples2dump[sample_count]; + size_t nsamples2dump = 0; + + // filter the input + float complex filtered_samples[sample_count]; + firfilt_crcf_execute_block(rx->channel_filter, (float complex *)samples, sample_count, filtered_samples); + for(unsigned int i = 0; i < sample_count; i++) { rx_state_t last_state = rx->state; // Apply the AGC. float complex agc_out; - agc_crcf_execute(rx->agc, samples[i], &agc_out); + agc_crcf_execute(rx->agc, filtered_samples[i], &agc_out); // Mix the input signal with the carrier NCO, which oscillates at the // frequency coarsly estimated so far. @@ -114,6 +134,8 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t nco_crcf_step(rx->carrier_coarse_nco); nco_crcf_mix_down(rx->carrier_coarse_nco, agc_out, &mixed_sample); + samples2dump[nsamples2dump++] = mixed_sample; + // run the timing synchronizer (works even with shifted frequency) unsigned int out_len; float complex symsync_out; @@ -124,6 +146,14 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t // Try to acquire packets by synchronizing the frequency // (symbol-independent search) and correlating the preamble. case RX_STATE_ACQUISITION: + // reset the acquisition periodically if the preamble is not found. + symbol_counter++; + if(symbol_counter == 30 * SYMBOL_RATE) { + symbol_counter = 0; + nco_crcf_set_frequency(rx->carrier_coarse_nco, 0.0f); + nco_crcf_set_phase(rx->carrier_coarse_nco, 0.0f); + } + if(acquire_preamble(rx, symsync_out)) { // Preamble found and frequency corrected! rx->callback(RX_EVT_PREAMBLE_FOUND, NULL, 0); @@ -250,6 +280,8 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t } } + dump_array_cf(samples2dump, nsamples2dump, 1.0f, "/tmp/rx_dbg.cpx64"); + return OK; } @@ -260,6 +292,9 @@ result_t layer1_rx_init(layer1_rx_t *rx, rx_callback_t callback) rx->state = RX_STATE_ACQUISITION; + // create channel FIR filter to remove out-of-band interferers + rx->channel_filter = firfilt_crcf_create_kaiser(21, 0.28f * RRC_SPS / 4, 60.0f, 0.0f); + // create the AGC rx->agc = agc_crcf_create(); agc_crcf_set_bandwidth(rx->agc, AGC_BW_ACQUISITION); @@ -296,6 +331,8 @@ result_t layer1_rx_init(layer1_rx_t *rx, rx_callback_t callback) result_t layer1_rx_shutdown(layer1_rx_t *rx) { + firfilt_crcf_destroy(rx->channel_filter); + agc_crcf_destroy(rx->agc); nco_crcf_destroy(rx->carrier_coarse_nco); diff --git a/impl/src/layer1/rx.h b/impl/src/layer1/rx.h index 783213e..d632346 100644 --- a/impl/src/layer1/rx.h +++ b/impl/src/layer1/rx.h @@ -27,6 +27,9 @@ typedef void (*rx_callback_t)(rx_evt_t evt, uint8_t *packet_data, size_t packet_ typedef struct { + // Input channel filter + firfilt_crcf channel_filter; + // AGC agc_crcf agc;