main: restructure state management; evaluate a found preamble
This commit is contained in:
parent
423f1d6416
commit
465d9a1c26
188
impl/src/main.c
188
impl/src/main.c
|
@ -18,6 +18,17 @@ typedef enum {
|
|||
RX_STATE_DATA,
|
||||
} rx_state_t;
|
||||
|
||||
|
||||
void print_complex_array(const char *varname, float complex const *array, size_t len)
|
||||
{
|
||||
printf("%s=np.array([%f%+fj", varname, crealf(array[0]), cimagf(array[0]));
|
||||
for(size_t k = 1; k < len; k++) {
|
||||
printf(", %f%+fj", crealf(array[k]), cimagf(array[k]));
|
||||
}
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t msg_org[] = "Hello Liquid! This is the message to transmit. Hopefully it can be decoded correctly...";
|
||||
|
@ -28,7 +39,7 @@ int main(void)
|
|||
|
||||
channel_cccf channel = channel_cccf_create();
|
||||
|
||||
float snr = 50.0f;
|
||||
float snr = 20.0f;
|
||||
channel_cccf_add_awgn(channel, -snr, snr);
|
||||
channel_cccf_add_carrier_offset(channel, 0.20f, 1.00f);
|
||||
|
||||
|
@ -119,81 +130,110 @@ int main(void)
|
|||
unsigned int out_len;
|
||||
symsync_crcf_execute(symsync, &mixed_sample, 1, symsync_out + symsync_out_len, &out_len);
|
||||
|
||||
switch(rx_state) {
|
||||
case RX_STATE_ACQUISITION:
|
||||
if(out_len != 0) {
|
||||
// for all the output samples produced, run the frequency
|
||||
// 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) {
|
||||
memmove(phase_history,
|
||||
phase_history + out_len,
|
||||
(FREQ_EST_L-out_len) * sizeof(phase_history[0]));
|
||||
}
|
||||
|
||||
for(unsigned int j = 0; j < out_len; j++) {
|
||||
float complex *psymbol = symsync_out + symsync_out_len + j;
|
||||
|
||||
// square the symbol to remove BPSK ambiguity
|
||||
float phase = cargf((*psymbol) * (*psymbol));
|
||||
|
||||
phase_history[FREQ_EST_L - out_len + j] = phase;
|
||||
}
|
||||
|
||||
// update the frequency estimate
|
||||
if(((i/RRC_SPS) % FREQ_EST_L) == 0) {
|
||||
float unwrapped_phase_history[FREQ_EST_L];
|
||||
memcpy(unwrapped_phase_history, phase_history, sizeof(unwrapped_phase_history));
|
||||
liquid_unwrap_phase(unwrapped_phase_history, FREQ_EST_L);
|
||||
|
||||
// calculate slope of LMS-fitted line
|
||||
float mean_index = (FREQ_EST_L-1) / 2.0f;
|
||||
float mean_phase = 0.0f;
|
||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||
mean_phase += unwrapped_phase_history[j];
|
||||
}
|
||||
mean_phase /= FREQ_EST_L;
|
||||
|
||||
float numerator = 0.0f;
|
||||
float denominator = 0.0f;
|
||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||
float delta_index = j - mean_index;
|
||||
numerator += delta_index * (unwrapped_phase_history[j] - mean_phase);
|
||||
denominator += delta_index*delta_index;
|
||||
}
|
||||
|
||||
float lms_phase_change = numerator / denominator;
|
||||
|
||||
float freq_adjustment = (lms_phase_change / RRC_SPS / 2) * 0.3f;
|
||||
nco_crcf_adjust_frequency(carrier_nco, freq_adjustment);
|
||||
|
||||
printf("Frequency adjustment: %.6f - carrier frequency: %.6f\n", freq_adjustment, nco_crcf_get_frequency(carrier_nco));
|
||||
|
||||
if(i/RRC_SPS == 2*FREQ_EST_L) {
|
||||
float complex tmp[FREQ_EST_L];
|
||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||
tmp[j] = unwrapped_phase_history[j];
|
||||
}
|
||||
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]);
|
||||
float complex corr_out;
|
||||
switch(rx_state) {
|
||||
// Try to acquire packets by synchronizing the frequency
|
||||
// (symbol-independent search) and correlating the preamble.
|
||||
case RX_STATE_ACQUISITION:
|
||||
// preamble search
|
||||
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());
|
||||
if(cabsf(corr_out) > 0.5f * preamble_get_symbol_count()) {
|
||||
// Preamble found!
|
||||
printf("Preamble found at symbol %u: %.3f > %.3f\n", i/RRC_SPS, cabsf(corr_out), 0.5f * preamble_get_symbol_count());
|
||||
|
||||
float mean_phase_error = correlator_get_mean_phase_deviation(&preamble_correlator);
|
||||
float mean_frequency_error = correlator_get_mean_frequency_deviation(&preamble_correlator);
|
||||
|
||||
printf("Preamble phase deviation: %.6f rad\n", mean_phase_error);
|
||||
printf("Preamble frequency deviation: %.6f rad/symbol\n", mean_frequency_error);
|
||||
|
||||
// adjust the frequency and phase of the NCO with the estimations from the preamble
|
||||
nco_crcf_adjust_frequency(carrier_nco, -mean_frequency_error / RRC_SPS);
|
||||
nco_crcf_adjust_phase(carrier_nco, mean_phase_error);
|
||||
|
||||
printf("New estimated carrier frequency: %.6f\n", nco_crcf_get_frequency(carrier_nco));
|
||||
|
||||
float complex input_history[preamble_get_symbol_count()];
|
||||
correlator_get_input_history(&preamble_correlator, input_history);
|
||||
|
||||
printf("import numpy as np\n");
|
||||
printf("import matplotlib.pyplot as pp\n");
|
||||
print_complex_array("pre", preamble_get_symbols(), preamble_get_symbol_count());
|
||||
print_complex_array("recv", input_history, preamble_get_symbol_count());
|
||||
printf("pp.plot(recv * pre.conj())\n");
|
||||
printf("pp.show()\n");
|
||||
|
||||
// receive and decode the header
|
||||
rx_state = RX_STATE_HEADER;
|
||||
} else {
|
||||
// preamble not found.
|
||||
|
||||
// for all the output samples produced, run the frequency
|
||||
// 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) {
|
||||
memmove(phase_history,
|
||||
phase_history + out_len,
|
||||
(FREQ_EST_L-out_len) * sizeof(phase_history[0]));
|
||||
}
|
||||
|
||||
for(unsigned int j = 0; j < out_len; j++) {
|
||||
float complex *psymbol = symsync_out + symsync_out_len + j;
|
||||
|
||||
// square the symbol to remove BPSK ambiguity
|
||||
float phase = cargf((*psymbol) * (*psymbol));
|
||||
|
||||
phase_history[FREQ_EST_L - out_len + j] = phase;
|
||||
}
|
||||
|
||||
// update the frequency estimate
|
||||
if(((i/RRC_SPS) % FREQ_EST_L) == 0) {
|
||||
float unwrapped_phase_history[FREQ_EST_L];
|
||||
memcpy(unwrapped_phase_history, phase_history, sizeof(unwrapped_phase_history));
|
||||
liquid_unwrap_phase(unwrapped_phase_history, FREQ_EST_L);
|
||||
|
||||
// calculate slope of LMS-fitted line
|
||||
float mean_index = (FREQ_EST_L-1) / 2.0f;
|
||||
float mean_phase = 0.0f;
|
||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||
mean_phase += unwrapped_phase_history[j];
|
||||
}
|
||||
mean_phase /= FREQ_EST_L;
|
||||
|
||||
float numerator = 0.0f;
|
||||
float denominator = 0.0f;
|
||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||
float delta_index = j - mean_index;
|
||||
numerator += delta_index * (unwrapped_phase_history[j] - mean_phase);
|
||||
denominator += delta_index*delta_index;
|
||||
}
|
||||
|
||||
float lms_phase_change = numerator / denominator;
|
||||
|
||||
float freq_adjustment = (lms_phase_change / RRC_SPS / 2) * 0.5f;
|
||||
nco_crcf_adjust_frequency(carrier_nco, freq_adjustment);
|
||||
|
||||
printf("Frequency adjustment: %.6f - carrier frequency: %.6f\n", freq_adjustment, nco_crcf_get_frequency(carrier_nco));
|
||||
|
||||
if(i/RRC_SPS == 2*FREQ_EST_L) {
|
||||
float complex tmp[FREQ_EST_L];
|
||||
for(unsigned int j = 0; j < FREQ_EST_L; j++) {
|
||||
tmp[j] = unwrapped_phase_history[j];
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue