rx: implement squelch + symsync reset

Whenever the squelch opens, the symsync is reset to prevent lock-up in
that module due to noise.
This commit is contained in:
Thomas Kolb 2024-04-08 22:03:09 +02:00
parent 4b46d87edb
commit 91db4e1f75
2 changed files with 64 additions and 0 deletions

View file

@ -148,6 +148,49 @@ static bool acquire_preamble(layer1_rx_t *rx, const float complex sample, bool d
} }
typedef enum squelch_state_t {
SQUELCH_CLOSED,
SQUELCH_OPEN,
SQUELCH_JUST_OPENED,
};
static enum squelch_state_t update_and_check_squelch(layer1_rx_t *rx, unsigned int sample_idx)
{
float level = agc_crcf_get_rssi(rx->agc);
enum squelch_state_t result = SQUELCH_CLOSED;
if((sample_idx & 0xFF) == 0) { // every 256 samples
if(level < rx->noise_floor_level) {
rx->noise_floor_level = level;
} else {
level += 1e-3; // slowly increase the measured noise floor level to compensate for drift
}
agc_crcf_squelch_set_threshold(rx->agc, rx->noise_floor_level + 3.0f); // in dB
}
switch(agc_crcf_squelch_get_status(rx->agc)) {
case LIQUID_AGC_SQUELCH_RISE:
DEBUG_LOG("Squelch disabled at RSSI = %.3f dB\n", level);
result = SQUELCH_JUST_OPENED;
break;
case LIQUID_AGC_SQUELCH_SIGNALHI:
result = SQUELCH_OPEN;
break;
case LIQUID_AGC_SQUELCH_FALL:
DEBUG_LOG("Squelch enabled at RSSI = %.3f dB\n", level);
case LIQUID_AGC_SQUELCH_SIGNALLO:
case LIQUID_AGC_SQUELCH_ENABLED:
case LIQUID_AGC_SQUELCH_TIMEOUT:
result = SQUELCH_CLOSED;
break;
}
return result;
}
result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t sample_count) result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t sample_count)
{ {
static size_t symbol_counter = 0; static size_t symbol_counter = 0;
@ -174,6 +217,20 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t
float complex agc_out; float complex agc_out;
agc_crcf_execute(rx->agc, filtered_samples[i], &agc_out); agc_crcf_execute(rx->agc, filtered_samples[i], &agc_out);
switch(update_and_check_squelch(rx, i)) {
case SQUELCH_CLOSED:
// ignore this sample
continue;
case SQUELCH_JUST_OPENED:
symsync_crcf_reset(rx->symsync);
// fall through
case SQUELCH_OPEN:
// sample processing continues
break;
}
// 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.
float complex mixed_sample; float complex mixed_sample;
@ -396,6 +453,11 @@ result_t layer1_rx_init(layer1_rx_t *rx, rx_callback_t callback)
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);
// set up squelch
rx->noise_floor_level = 0.0f;
agc_crcf_squelch_set_threshold(rx->agc, rx->noise_floor_level + 3.0f); // in dB
agc_crcf_squelch_enable(rx->agc);
// create NCOs for carrier frequency compensation // create NCOs for carrier frequency compensation
rx->carrier_coarse_nco = nco_crcf_create(LIQUID_NCO); rx->carrier_coarse_nco = nco_crcf_create(LIQUID_NCO);
nco_crcf_set_frequency(rx->carrier_coarse_nco, 0.00f); nco_crcf_set_frequency(rx->carrier_coarse_nco, 0.00f);

View file

@ -34,6 +34,8 @@ typedef struct
// AGC // AGC
agc_crcf agc; agc_crcf agc;
float noise_floor_level;
// NCOs for carrier frequency offset correction // NCOs for carrier frequency offset correction
nco_crcf carrier_coarse_nco; nco_crcf carrier_coarse_nco;
nco_crcf carrier_fine_nco; nco_crcf carrier_fine_nco;