diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2015-11-06 17:55:46 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2015-11-06 17:55:46 +0100 |
commit | 823043497a9fd59ac86e9596c56df8e692340974 (patch) | |
tree | 0cba1739c400ae4c2d2c22549f99157ca25d7d24 /AlignSample.cpp | |
parent | ff7a3d92d6192f6dd201ef165978b1d3df3815b6 (diff) | |
download | odr-dpd-823043497a9fd59ac86e9596c56df8e692340974.tar.gz odr-dpd-823043497a9fd59ac86e9596c56df8e692340974.tar.bz2 odr-dpd-823043497a9fd59ac86e9596c56df8e692340974.zip |
Move AlignSample to separate file
Diffstat (limited to 'AlignSample.cpp')
-rw-r--r-- | AlignSample.cpp | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/AlignSample.cpp b/AlignSample.cpp new file mode 100644 index 0000000..d2d9339 --- /dev/null +++ b/AlignSample.cpp @@ -0,0 +1,156 @@ +/* + Copyright (C) 2015 + 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 <http://www.gnu.org/licenses/>. + */ + +#include "AlignSample.hpp" + +void AlignSample::push_tx_samples(complexf* samps, size_t len, double first_sample_time) +{ + std::lock_guard<std::mutex> lock(m_mutex); + std::copy(samps, samps + len, std::back_inserter(m_txsamples)); + + if (m_first_tx_sample_time == 0) { + m_first_tx_sample_time = first_sample_time; + } +} + +void AlignSample::push_rx_samples(complexf* samps, size_t len, double first_sample_time) +{ + std::lock_guard<std::mutex> lock(m_mutex); + std::copy(samps, samps + len, std::back_inserter(m_rxsamples)); + + if (m_first_rx_sample_time == 0) { + m_first_rx_sample_time = first_sample_time; + } +} + +bool AlignSample::ready(size_t min_samples) +{ + std::lock_guard<std::mutex> lock(m_mutex); + return align() and m_rxsamples.size() > min_samples and m_txsamples.size() > min_samples; +} + +CorrelationResult AlignSample::crosscorrelate(size_t max_offset, size_t len) +{ + std::vector<complexf> rxsamps; + std::vector<complexf> txsamps; + double rx_ts = 0; + double tx_ts = 0; + + // Do a quick copy, so as to free the mutex + { + std::lock_guard<std::mutex> lock(m_mutex); + + if (!align() or + m_rxsamples.size() < len or + m_txsamples.size() < len + max_offset) { + CorrelationResult result(0); + return result; + } + + std::copy(m_rxsamples.begin(), m_rxsamples.begin() + len, std::back_inserter(rxsamps)); + std::copy(m_txsamples.begin(), m_txsamples.begin() + len + max_offset, std::back_inserter(txsamps)); + + m_rxsamples.erase(m_rxsamples.begin(), m_rxsamples.begin() + len); + m_txsamples.erase(m_txsamples.begin(), m_txsamples.begin() + len + max_offset); + + rx_ts = m_rx_sample_time(); + tx_ts = m_tx_sample_time(); + } + + CorrelationResult result(max_offset); + result.rx_timestamp = rx_ts; + result.tx_timestamp = tx_ts; + + auto& xcorrs = result.correlation; + + // Calculate power + for (auto sample : rxsamps) { + result.rx_power += std::norm(sample); + } + result.rx_power = std::sqrt(result.rx_power); + + for (auto sample : txsamps) { + result.tx_power += std::norm(sample); + } + result.tx_power = std::sqrt(result.tx_power); + + // Calculate correlation + for (size_t offset = 0; offset < max_offset; offset++) { + complexf xcorr(0, 0); + + for (size_t i = 0; i < len; i++) { + xcorr += rxsamps[i] * std::conj(txsamps[i+offset]); + } + xcorrs[offset] = xcorr; + } + + return result; +} + +void AlignSample::consume(size_t samples) +{ + std::lock_guard<std::mutex> lock(m_mutex); + if (align() and m_rxsamples.size() > samples and m_txsamples.size() > samples) { + m_rxsamples.erase(m_rxsamples.begin(), m_rxsamples.begin() + samples); + m_num_rx_samples_dropped += samples; + + m_txsamples.erase(m_txsamples.begin(), m_txsamples.begin() + samples); + m_num_tx_samples_dropped += samples; + } +} + +bool AlignSample::align() +{ + if (std::abs(m_rx_sample_time() - m_tx_sample_time()) < 1e-6) { + return true; + } + else if (m_rx_sample_time() < m_tx_sample_time()) { + size_t rx_samples_to_skip = + (m_tx_sample_time() - m_rx_sample_time()) * samplerate; + + if (rx_samples_to_skip > m_rxsamples.size()) { + return false; + } + + m_rxsamples.erase( + m_rxsamples.begin(), m_rxsamples.begin() + rx_samples_to_skip); + + m_num_rx_samples_dropped += rx_samples_to_skip; + return true; + } + else if (m_rx_sample_time() > m_tx_sample_time()) { + size_t tx_samples_to_skip = + (m_rx_sample_time() - m_tx_sample_time()) * samplerate; + + if (tx_samples_to_skip > m_txsamples.size()) { + return false; + } + + m_txsamples.erase( + m_txsamples.begin(), m_txsamples.begin() + tx_samples_to_skip); + + m_num_tx_samples_dropped += tx_samples_to_skip; + return true; + } + return false; +} |