rx: integrate AGC
This commit is contained in:
parent
a60b8b1f87
commit
8a8ddc5ea3
|
@ -1,3 +1,4 @@
|
|||
#include <liquid/liquid.h>
|
||||
#include <math.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 **
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue