rx: improvements made during on-air testing
- limit frequency adjustment range - pre-filter the baseband signal to remove out-of-band interference - reset the frequency acquisition periodically (every 30s) if no preamble is found
This commit is contained in:
parent
2d0bf7eeda
commit
ec99cedaf4
|
@ -10,11 +10,15 @@
|
||||||
|
|
||||||
#include "rx.h"
|
#include "rx.h"
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#define HEADER_SIZE_BYTES 4
|
#define HEADER_SIZE_BYTES 4
|
||||||
#define FREQ_EST_L 8
|
#define FREQ_EST_L 8
|
||||||
|
|
||||||
#define AGC_BW_ACQUISITION 5e-2
|
#define AGC_BW_ACQUISITION 5e-2f
|
||||||
#define AGC_BW_TRACKING 1e-4
|
#define AGC_BW_TRACKING 1e-4f
|
||||||
|
|
||||||
|
#define MAX_COARSE_FREQ_OFFSET 0.20f
|
||||||
|
|
||||||
#define SHOW_DEBUG_LOG 0
|
#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;
|
float freq_adjustment = (freq_est / RRC_SPS) * 0.3f;
|
||||||
nco_crcf_adjust_frequency(rx->carrier_coarse_nco, freq_adjustment);
|
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));
|
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;
|
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 size_t symbol_counter = 0;
|
||||||
static uint8_t symbols_int[1 << 12];
|
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++) {
|
for(unsigned int i = 0; i < sample_count; i++) {
|
||||||
rx_state_t last_state = rx->state;
|
rx_state_t last_state = rx->state;
|
||||||
|
|
||||||
// Apply the AGC.
|
// Apply the AGC.
|
||||||
float complex agc_out;
|
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
|
// Mix the input signal with the carrier NCO, which oscillates at the
|
||||||
// frequency coarsly estimated so far.
|
// 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_step(rx->carrier_coarse_nco);
|
||||||
nco_crcf_mix_down(rx->carrier_coarse_nco, agc_out, &mixed_sample);
|
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)
|
// run the timing synchronizer (works even with shifted frequency)
|
||||||
unsigned int out_len;
|
unsigned int out_len;
|
||||||
float complex symsync_out;
|
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
|
// Try to acquire packets by synchronizing the frequency
|
||||||
// (symbol-independent search) and correlating the preamble.
|
// (symbol-independent search) and correlating the preamble.
|
||||||
case RX_STATE_ACQUISITION:
|
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)) {
|
if(acquire_preamble(rx, symsync_out)) {
|
||||||
// Preamble found and frequency corrected!
|
// Preamble found and frequency corrected!
|
||||||
rx->callback(RX_EVT_PREAMBLE_FOUND, NULL, 0);
|
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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +292,9 @@ result_t layer1_rx_init(layer1_rx_t *rx, rx_callback_t callback)
|
||||||
|
|
||||||
rx->state = RX_STATE_ACQUISITION;
|
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
|
// create the AGC
|
||||||
rx->agc = agc_crcf_create();
|
rx->agc = agc_crcf_create();
|
||||||
agc_crcf_set_bandwidth(rx->agc, AGC_BW_ACQUISITION);
|
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)
|
result_t layer1_rx_shutdown(layer1_rx_t *rx)
|
||||||
{
|
{
|
||||||
|
firfilt_crcf_destroy(rx->channel_filter);
|
||||||
|
|
||||||
agc_crcf_destroy(rx->agc);
|
agc_crcf_destroy(rx->agc);
|
||||||
|
|
||||||
nco_crcf_destroy(rx->carrier_coarse_nco);
|
nco_crcf_destroy(rx->carrier_coarse_nco);
|
||||||
|
|
|
@ -27,6 +27,9 @@ typedef void (*rx_callback_t)(rx_evt_t evt, uint8_t *packet_data, size_t packet_
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
// Input channel filter
|
||||||
|
firfilt_crcf channel_filter;
|
||||||
|
|
||||||
// AGC
|
// AGC
|
||||||
agc_crcf agc;
|
agc_crcf agc;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue