diff --git a/impl/src/layer1/rx.c b/impl/src/layer1/rx.c index ecf4fc4..db416c0 100644 --- a/impl/src/layer1/rx.c +++ b/impl/src/layer1/rx.c @@ -1,6 +1,7 @@ #include #include +#include #include "correlator.h" #include "preamble.h" @@ -8,6 +9,7 @@ #include "whitening.h" #include "config.h" +#include "options.h" #include "rx.h" @@ -48,7 +50,7 @@ static void update_nco_pll(nco_crcf nco, float phase_error, float bw) } -static bool acquire_preamble(layer1_rx_t *rx, const float complex sample) +static bool acquire_preamble(layer1_rx_t *rx, const float complex sample, bool do_coarse_freq_est) { static float complex freq_est_history[FREQ_EST_L]; static unsigned int freq_est_history_write_idx = 0; @@ -90,7 +92,7 @@ static bool acquire_preamble(layer1_rx_t *rx, const float complex sample) freq_est_history_write_idx = 0; freq_est_holdoff_samples = FREQ_EST_L; return true; // preamble found! - } else { + } else if(do_coarse_freq_est) { // preamble not found. //DEBUG_LOG("Preamble not found: %.3f < %.3f\n", cabsf(corr_out), 0.5f * preamble_get_symbol_count()); @@ -140,9 +142,9 @@ static bool acquire_preamble(layer1_rx_t *rx, const float complex sample) freq_est_history[freq_est_history_write_idx] = sample; freq_est_history_write_idx++; freq_est_history_write_idx %= FREQ_EST_L; - - return false; // preamble not found } + + return false; // preamble not found } @@ -172,8 +174,16 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t // 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, agc_out, &mixed_sample); + + if(is_central_node) { + // central nodes do not do coarse frequency tracking, as the clients + // shall lock onto the central’s carrier frequency and therefore not much + // frequency deviation is expected. + mixed_sample = agc_out; + } else { + nco_crcf_step(rx->carrier_coarse_nco); + nco_crcf_mix_down(rx->carrier_coarse_nco, agc_out, &mixed_sample); + } samples2dump[nsamples2dump++] = mixed_sample; @@ -183,7 +193,6 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t symsync_crcf_execute(rx->symsync, &mixed_sample, 1, &symsync_out, &out_len); if(out_len != 0) { - switch(rx->state) { // Try to acquire packets by synchronizing the frequency // (symbol-independent search) and correlating the preamble. @@ -196,7 +205,7 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t nco_crcf_set_phase(rx->carrier_coarse_nco, 0.0f); } - if(acquire_preamble(rx, symsync_out)) { + if(acquire_preamble(rx, symsync_out, !is_central_node)) { // Preamble found and frequency corrected! rx->callback(RX_EVT_PREAMBLE_FOUND, NULL, 0); @@ -439,3 +448,9 @@ bool layer1_rx_is_busy(const layer1_rx_t *rx) { return rx->state != RX_STATE_ACQUISITION; } + + +float layer1_rx_get_coarse_carrier_frequency(const layer1_rx_t *rx) +{ + return nco_crcf_get_frequency(rx->carrier_coarse_nco); +} diff --git a/impl/src/layer1/rx.h b/impl/src/layer1/rx.h index da9d883..38f1cb1 100644 --- a/impl/src/layer1/rx.h +++ b/impl/src/layer1/rx.h @@ -120,4 +120,15 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t */ bool layer1_rx_is_busy(const layer1_rx_t *rx); + +/*! + * \brief Retrieve the coarsely estimated carrier frequency. + * + * The carrier frequency is measured in radians per sample in the RRC-filtered baseband domain, i.e. the sampling rate is SYMBOL_RATE * RRC_SPS. + * + * \param rx Pointer to the receiver context. + * \returns The estimated carrier frequency in the RRC-filtered domain. + */ +float layer1_rx_get_coarse_carrier_frequency(const layer1_rx_t *rx); + #endif // LAYER1_RX_H diff --git a/impl/src/layer1/tx.c b/impl/src/layer1/tx.c index e1044d0..6a7e1c1 100644 --- a/impl/src/layer1/tx.c +++ b/impl/src/layer1/tx.c @@ -1,3 +1,5 @@ +#include + #include #include @@ -41,6 +43,8 @@ result_t layer1_tx_init(layer1_tx_t *tx) tx->samples_allocated = 0; tx->samples_used = 0; + tx->carrier_frequency_offset = 0.0f; + transmission_init(&tx->transmission); packet_mod_init(&tx->pmod); return OK; @@ -154,6 +158,28 @@ result_t layer1_tx_finalize_burst(layer1_tx_t *tx) } tx->samples_used += len; + + // mix the signal up to the carrier offset frequency + + // allocate a temporary buffer + float complex *tmp = malloc(sizeof(float complex) * tx->samples_used); + if(!tmp) { + fprintf(stderr, "Could not allocate buffer for TX frequency correction.\n", len, tx->samples_used); + return ERR_NO_MEM; + } + + nco_crcf carrier_nco = nco_crcf_create(LIQUID_NCO); + nco_crcf_set_frequency(carrier_nco, tx->carrier_frequency_offset); + + nco_crcf_mix_block_up(carrier_nco, tx->samples, tmp, tx->samples_used); + + nco_crcf_destroy(carrier_nco); + + // swap the buffers + free(tx->samples); + tx->samples = tmp; + tx->samples_allocated = tx->samples_used; + return OK; } @@ -168,3 +194,9 @@ const float complex* layer1_tx_get_sample_data(const layer1_tx_t *tx) { return tx->samples; } + + +void layer1_tx_set_carrier_frequency_offset(layer1_tx_t *tx, float freq) +{ + tx->carrier_frequency_offset = freq; +} diff --git a/impl/src/layer1/tx.h b/impl/src/layer1/tx.h index 7f62c5e..2ef49cb 100644 --- a/impl/src/layer1/tx.h +++ b/impl/src/layer1/tx.h @@ -16,6 +16,8 @@ typedef struct size_t samples_allocated; size_t samples_used; + float carrier_frequency_offset; + transmission_ctx_t transmission; packet_mod_ctx_t pmod; } layer1_tx_t; @@ -100,4 +102,14 @@ size_t layer1_tx_get_sample_count(const layer1_tx_t *tx); */ const float complex* layer1_tx_get_sample_data(const layer1_tx_t *tx); +/*! + * \brief Set the carrier frequency correction in the RRC-filtered domain. + * + * The carrier frequency is measured in radians per sample in the RRC-filtered baseband domain, i.e. the sampling rate is SYMBOL_RATE * RRC_SPS. + * + * \param tx Pointer to the transmitter context. + * \param freq The carrier frequency offset to use. + */ +void layer1_tx_set_carrier_frequency_offset(layer1_tx_t *tx, float freq); + #endif // LAYER1_TX_H diff --git a/impl/src/main.c b/impl/src/main.c index 8b03446..79977fa 100644 --- a/impl/src/main.c +++ b/impl/src/main.c @@ -315,6 +315,10 @@ int main(int argc, char **argv) if(!on_air) { RESULT_CHECK(sdr_stop_rx(&sdr)); + + // transmit packets on the frequency where the last packet was received. + layer1_tx_set_carrier_frequency_offset(&tx, layer1_rx_get_coarse_carrier_frequency(&rx)); + RESULT_CHECK(sdr_start_tx(&sdr, burst_len * SDR_OVERSAMPLING)); }