diff --git a/impl/src/layer1/rx.c b/impl/src/layer1/rx.c index c83d425..45a58bf 100644 --- a/impl/src/layer1/rx.c +++ b/impl/src/layer1/rx.c @@ -1,3 +1,4 @@ +#include #include #include "correlator.h" @@ -12,6 +13,9 @@ #define HEADER_SIZE_BYTES 4 #define FREQ_EST_L 8 +#define AGC_BW_ACQUISITION 2e-2 +#define AGC_BW_TRACKING 1e-4 + #define SHOW_DEBUG_LOG 1 #if SHOW_DEBUG_LOG @@ -22,7 +26,7 @@ static void update_nco_pll(nco_crcf nco, float phase_error) { - static const float pll_alpha = 0.05f; // phase adjustment factor + static const float pll_alpha = 0.20f; // phase adjustment factor static const float pll_beta = (pll_alpha * pll_alpha) / 2.0f; // frequency adjustment factor nco_crcf_adjust_phase(nco, pll_alpha * phase_error); @@ -98,11 +102,17 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t static uint8_t symbols_int[1 << 12]; 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); + // Mix the input signal with the carrier NCO, which oscillates at the // frequency coarsly estimated so far. float complex mixed_sample; nco_crcf_step(rx->carrier_coarse_nco); - nco_crcf_mix_down(rx->carrier_coarse_nco, samples[i], &mixed_sample); + nco_crcf_mix_down(rx->carrier_coarse_nco, agc_out, &mixed_sample); // run the timing synchronizer (works even with shifted frequency) unsigned int out_len; @@ -118,6 +128,8 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t // Preamble found and frequency corrected! rx->callback(RX_EVT_PREAMBLE_FOUND, NULL, 0); + agc_crcf_set_bandwidth(rx->agc, AGC_BW_TRACKING); + // go on with decoding the header rx->state = RX_STATE_HEADER; symbol_counter = 0; @@ -226,6 +238,14 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t break; } } + + if(rx->state != last_state) { + if(rx->state == RX_STATE_ACQUISITION) { + // ensure the AGC is in acquisition mode again when + // RX_STATE_ACQUISITION is entered. + agc_crcf_set_bandwidth(rx->agc, AGC_BW_ACQUISITION); + } + } } return OK; @@ -238,6 +258,10 @@ result_t layer1_rx_init(layer1_rx_t *rx, rx_callback_t callback) rx->state = RX_STATE_ACQUISITION; + // create the AGC + rx->agc = agc_crcf_create(); + agc_crcf_set_bandwidth(rx->agc, AGC_BW_ACQUISITION); + // create NCOs for carrier frequency compensation rx->carrier_coarse_nco = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(rx->carrier_coarse_nco, 0.00f); @@ -270,6 +294,8 @@ result_t layer1_rx_init(layer1_rx_t *rx, rx_callback_t callback) result_t layer1_rx_shutdown(layer1_rx_t *rx) { + agc_crcf_destroy(rx->agc); + nco_crcf_destroy(rx->carrier_coarse_nco); nco_crcf_destroy(rx->carrier_fine_nco); diff --git a/impl/src/layer1/rx.h b/impl/src/layer1/rx.h index 2d49fca..ccb9ead 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 { + // AGC + agc_crcf agc; + // NCOs for carrier frequency offset correction nco_crcf carrier_coarse_nco; nco_crcf carrier_fine_nco; diff --git a/impl/src/main.c b/impl/src/main.c index 764b7e8..5ddb820 100644 --- a/impl/src/main.c +++ b/impl/src/main.c @@ -32,6 +32,9 @@ void cb_rx(rx_evt_t evt, uint8_t *packet_data, size_t packet_len) { case RX_EVT_CHECKSUM_ERROR: fprintf(stderr, "Received a message of %zu bytes, but decoding failed.\n", packet_len); + fprintf(stderr, "=== FAILED PAYLOAD ===\n"); + fprintf(stderr, "%s\n", packet_data); + fprintf(stderr, "=======================\n"); break; case RX_EVT_PACKET_RECEIVED: @@ -68,9 +71,10 @@ int main(void) channel_cccf channel = channel_cccf_create(); - float snr = 8.0f; + float snr = 10.0f; channel_cccf_add_awgn(channel, -snr, snr); channel_cccf_add_carrier_offset(channel, 0.20f, 1.00f); + channel_cccf_add_shadowing(channel, 1.00f, 0.1f); // channel float complex msg_received[burst_len]; @@ -78,6 +82,12 @@ int main(void) //memcpy(msg_received, whole_burst, sizeof(whole_burst)); // no noise in channel channel_cccf_execute_block(channel, whole_burst, burst_len, msg_received); + + // scale the entire signal to give the AGC something to do + for(size_t i = 0; i < burst_len; i++) { + msg_received[i] *= 0.02f; + } + dump_array_cf(msg_received, burst_len, 1.0f, "/tmp/rx.cpx"); // ** RX starts here ** diff --git a/impl/src/results.h b/impl/src/results.h index fc8df70..3219e46 100644 --- a/impl/src/results.h +++ b/impl/src/results.h @@ -7,6 +7,7 @@ typedef enum { ERR_NO_MEM, ERR_SIZE, ERR_LIQUID, + ERR_SYSCALL // a syscall failed. Use errno to determine the cause. } result_t; #ifdef DEBUG_LIQUID