Integrate preamble search
This commit is contained in:
parent
b6713909f7
commit
c17c7e060f
|
@ -19,6 +19,8 @@ set(sources
|
||||||
src/preamble.c
|
src/preamble.c
|
||||||
src/transmission.h
|
src/transmission.h
|
||||||
src/transmission.c
|
src/transmission.c
|
||||||
|
src/correlator.h
|
||||||
|
src/correlator.c
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
|
144
impl/src/main.c
144
impl/src/main.c
|
@ -4,11 +4,19 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <liquid/liquid.h>
|
#include <liquid/liquid.h>
|
||||||
|
|
||||||
|
#include "results.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "packet_mod.h"
|
#include "packet_mod.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "preamble.h"
|
#include "preamble.h"
|
||||||
#include "transmission.h"
|
#include "transmission.h"
|
||||||
|
#include "correlator.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RX_STATE_ACQUISITION,
|
||||||
|
RX_STATE_HEADER,
|
||||||
|
RX_STATE_DATA,
|
||||||
|
} rx_state_t;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
@ -93,6 +101,13 @@ int main(void)
|
||||||
float phase_history[FREQ_EST_L];
|
float phase_history[FREQ_EST_L];
|
||||||
memset(phase_history, 0, sizeof(phase_history));
|
memset(phase_history, 0, sizeof(phase_history));
|
||||||
|
|
||||||
|
// General receiver state
|
||||||
|
rx_state_t rx_state = RX_STATE_ACQUISITION;
|
||||||
|
|
||||||
|
// Correlator for preamble search
|
||||||
|
correlator_ctx_t preamble_correlator;
|
||||||
|
correlator_init(&preamble_correlator, preamble_get_symbols(), preamble_get_symbol_count());
|
||||||
|
|
||||||
for(unsigned int i = 0; i < burst_len; i++) {
|
for(unsigned int i = 0; i < burst_len; i++) {
|
||||||
// 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 estimated so far.
|
// frequency estimated so far.
|
||||||
|
@ -100,68 +115,85 @@ int main(void)
|
||||||
nco_crcf_step(carrier_nco);
|
nco_crcf_step(carrier_nco);
|
||||||
nco_crcf_mix_down(carrier_nco, msg_received[i], &mixed_sample);
|
nco_crcf_mix_down(carrier_nco, msg_received[i], &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;
|
||||||
symsync_crcf_execute(symsync, &mixed_sample, 1, symsync_out + symsync_out_len, &out_len);
|
symsync_crcf_execute(symsync, &mixed_sample, 1, symsync_out + symsync_out_len, &out_len);
|
||||||
|
|
||||||
if(out_len != 0) {
|
switch(rx_state) {
|
||||||
// for all the output samples produced, run the frequency
|
case RX_STATE_ACQUISITION:
|
||||||
// estimator. This is an implementation that works with unknown
|
if(out_len != 0) {
|
||||||
// BPSK symbols and therefore can be used during ramp-up and
|
// for all the output samples produced, run the frequency
|
||||||
// preamble.
|
// estimator. This is an implementation that works with unknown
|
||||||
|
// BPSK symbols and therefore can be used during ramp-up and
|
||||||
|
// preamble.
|
||||||
|
|
||||||
if(out_len < FREQ_EST_L) {
|
if(out_len < FREQ_EST_L) {
|
||||||
memmove(phase_history,
|
memmove(phase_history,
|
||||||
phase_history + out_len,
|
phase_history + out_len,
|
||||||
(FREQ_EST_L-out_len) * sizeof(phase_history[0]));
|
(FREQ_EST_L-out_len) * sizeof(phase_history[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int j = 0; j < out_len; j++) {
|
for(unsigned int j = 0; j < out_len; j++) {
|
||||||
float complex *psymbol = symsync_out + symsync_out_len + j;
|
float complex *psymbol = symsync_out + symsync_out_len + j;
|
||||||
|
|
||||||
// square the symbol to remove BPSK ambiguity
|
// square the symbol to remove BPSK ambiguity
|
||||||
float phase = cargf((*psymbol) * (*psymbol));
|
float phase = cargf((*psymbol) * (*psymbol));
|
||||||
|
|
||||||
phase_history[FREQ_EST_L - out_len + j] = phase;
|
phase_history[FREQ_EST_L - out_len + j] = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the frequency estimate
|
// update the frequency estimate
|
||||||
if(((i/RRC_SPS) % FREQ_EST_L) == 0) {
|
if(((i/RRC_SPS) % FREQ_EST_L) == 0) {
|
||||||
float unwrapped_phase_history[FREQ_EST_L];
|
float unwrapped_phase_history[FREQ_EST_L];
|
||||||
memcpy(unwrapped_phase_history, phase_history, sizeof(unwrapped_phase_history));
|
memcpy(unwrapped_phase_history, phase_history, sizeof(unwrapped_phase_history));
|
||||||
liquid_unwrap_phase(unwrapped_phase_history, FREQ_EST_L);
|
liquid_unwrap_phase(unwrapped_phase_history, FREQ_EST_L);
|
||||||
|
|
||||||
// calculate slope of LMS-fitted line
|
// calculate slope of LMS-fitted line
|
||||||
float mean_index = (FREQ_EST_L-1) / 2.0f;
|
float mean_index = (FREQ_EST_L-1) / 2.0f;
|
||||||
float mean_phase = 0.0f;
|
float mean_phase = 0.0f;
|
||||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||||
mean_phase += unwrapped_phase_history[j];
|
mean_phase += unwrapped_phase_history[j];
|
||||||
}
|
}
|
||||||
mean_phase /= FREQ_EST_L;
|
mean_phase /= FREQ_EST_L;
|
||||||
|
|
||||||
float numerator = 0.0f;
|
float numerator = 0.0f;
|
||||||
float denominator = 0.0f;
|
float denominator = 0.0f;
|
||||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||||
float delta_index = j - mean_index;
|
float delta_index = j - mean_index;
|
||||||
numerator += delta_index * (unwrapped_phase_history[j] - mean_phase);
|
numerator += delta_index * (unwrapped_phase_history[j] - mean_phase);
|
||||||
denominator += delta_index*delta_index;
|
denominator += delta_index*delta_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
float lms_phase_change = numerator / denominator;
|
float lms_phase_change = numerator / denominator;
|
||||||
|
|
||||||
float freq_adjustment = (lms_phase_change / RRC_SPS / 2) * 0.3f;
|
float freq_adjustment = (lms_phase_change / RRC_SPS / 2) * 0.3f;
|
||||||
nco_crcf_adjust_frequency(carrier_nco, freq_adjustment);
|
nco_crcf_adjust_frequency(carrier_nco, freq_adjustment);
|
||||||
|
|
||||||
printf("Frequency adjustment: %.6f - carrier frequency: %.6f\n", freq_adjustment, nco_crcf_get_frequency(carrier_nco));
|
printf("Frequency adjustment: %.6f - carrier frequency: %.6f\n", freq_adjustment, nco_crcf_get_frequency(carrier_nco));
|
||||||
|
|
||||||
if(i/RRC_SPS == 2*FREQ_EST_L) {
|
if(i/RRC_SPS == 2*FREQ_EST_L) {
|
||||||
float complex tmp[FREQ_EST_L];
|
float complex tmp[FREQ_EST_L];
|
||||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||||
tmp[j] = unwrapped_phase_history[j];
|
tmp[j] = unwrapped_phase_history[j];
|
||||||
|
}
|
||||||
|
dump_array_cf(tmp, FREQ_EST_L, 1.0f, "/tmp/freq_est.cpx");
|
||||||
|
printf("MARK\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dump_array_cf(tmp, FREQ_EST_L, 1.0f, "/tmp/freq_est.cpx");
|
|
||||||
printf("MARK\n");
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RX_STATE_HEADER:
|
||||||
|
case RX_STATE_DATA:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// preamble search
|
||||||
|
if(out_len != 0) {
|
||||||
|
float complex corr_out = correlator_step(&preamble_correlator, symsync_out[symsync_out_len]);
|
||||||
|
|
||||||
|
if(cabsf(corr_out) > 0.5f * preamble_get_symbol_count()) {
|
||||||
|
printf("Preamble found at sample %u: %.3f > %.3f\n", i/RRC_SPS, cabsf(corr_out), 0.5f * preamble_get_symbol_count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue