/* Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org */ /* This file is part of ODR-DPD. ODR-DPD is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. ODR-DPD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with ODR-DPD. If not, see . */ #pragma once #include "utils.hpp" #include #include #include #include #include #include "fftw3.h" #define FFT_TYPE fftwf_complex using complexf = std::complex; using vec_cf = std::vector; struct CorrelationResult { CorrelationResult(size_t len) : correlation(len), rx_power(0), tx_power(0), rx_timestamp(0), tx_timestamp(0) {} vec_cf correlation; float rx_power; float tx_power; double rx_timestamp; double tx_timestamp; }; class AlignSample { public: AlignSample() { m_first_rx_sample_time = 0; m_first_tx_sample_time = 0; m_num_rx_samples_dropped = 0; m_num_tx_samples_dropped = 0; } void push_tx_samples(complexf* samps, size_t len, double first_sample_time); void push_rx_samples(complexf* samps, size_t len, double first_sample_time); void reset_rx(void); bool ready(size_t min_samples); void debug() { std::lock_guard lock(m_mutex); MDEBUG("Aligner\n"); MDEBUG(" RX: %f--%f %zu\n", m_rx_sample_time(), m_rx_sample_time() + (double)m_rxsamples.size() / (double)samplerate, m_rxsamples.size()); MDEBUG(" TX: %f--%f %zu\n", m_tx_sample_time(), m_tx_sample_time() + (double)m_txsamples.size() / (double)samplerate, m_txsamples.size()); } CorrelationResult crosscorrelate(size_t len); /* Drop delay samples from the rx_samples */ void delay_rx_samples(size_t delay); /* Calculate and compensate for subsample delay, assuming that the * RX and TX samples are already aligned */ std::pair get_samples( size_t len); void consume(size_t samples); private: bool align(); double m_rx_sample_time(size_t offset = 0) const { return m_first_rx_sample_time + (double)(m_num_rx_samples_dropped + offset) / (double)samplerate; } double m_tx_sample_time(size_t offset = 0) const { return m_first_tx_sample_time + (double)(m_num_tx_samples_dropped + offset) / (double)samplerate; } void m_drop_tx_samples(size_t samples) { m_txsamples.erase(m_txsamples.begin(), m_txsamples.begin() + samples); m_num_tx_samples_dropped += samples; } void m_drop_rx_samples(size_t samples) { m_rxsamples.erase(m_rxsamples.begin(), m_rxsamples.begin() + samples); m_num_rx_samples_dropped += samples; } std::mutex m_mutex; double m_first_rx_sample_time; size_t m_num_rx_samples_dropped; std::deque m_rxsamples; double m_first_tx_sample_time; size_t m_num_tx_samples_dropped; std::deque m_txsamples; };