aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2015-11-06 17:55:46 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2015-11-06 17:55:46 +0100
commit823043497a9fd59ac86e9596c56df8e692340974 (patch)
tree0cba1739c400ae4c2d2c22549f99157ca25d7d24
parentff7a3d92d6192f6dd201ef165978b1d3df3815b6 (diff)
downloadodr-dpd-823043497a9fd59ac86e9596c56df8e692340974.tar.gz
odr-dpd-823043497a9fd59ac86e9596c56df8e692340974.tar.bz2
odr-dpd-823043497a9fd59ac86e9596c56df8e692340974.zip
Move AlignSample to separate file
-rw-r--r--AlignSample.cpp156
-rw-r--r--AlignSample.hpp98
-rw-r--r--CMakeLists.txt1
-rw-r--r--main.cpp176
-rw-r--r--utils.hpp6
5 files changed, 262 insertions, 175 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;
+}
diff --git a/AlignSample.hpp b/AlignSample.hpp
new file mode 100644
index 0000000..31b5de2
--- /dev/null
+++ b/AlignSample.hpp
@@ -0,0 +1,98 @@
+/*
+ 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 "utils.hpp"
+#include <thread>
+#include <vector>
+#include <deque>
+#include <mutex>
+#include <complex>
+
+typedef std::complex<float> complexf;
+
+struct CorrelationResult {
+ CorrelationResult(size_t len) :
+ correlation(len),
+ rx_power(0),
+ tx_power(0),
+ rx_timestamp(0),
+ tx_timestamp(0) {}
+
+ std::vector<complexf> correlation;
+ double rx_power;
+ double 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);
+
+ bool ready(size_t min_samples);
+
+ void debug() {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ MDEBUG("Aligner\n");
+ MDEBUG(" RX: %f %zu\n", m_rx_sample_time(), m_rxsamples.size());
+ MDEBUG(" TX: %f %zu\n", m_tx_sample_time(), m_txsamples.size());
+ }
+
+ CorrelationResult crosscorrelate(size_t max_offset, size_t len);
+
+ void consume(size_t samples);
+
+ private:
+ bool align();
+
+ double m_rx_sample_time() const {
+ return m_first_rx_sample_time +
+ (double)m_num_rx_samples_dropped / samplerate;
+ }
+
+ double m_tx_sample_time() const {
+ return m_first_tx_sample_time +
+ (double)m_num_tx_samples_dropped / samplerate;
+ }
+
+ std::mutex m_mutex;
+ double m_first_rx_sample_time;
+ size_t m_num_rx_samples_dropped;
+ std::deque<complexf> m_rxsamples;
+
+ double m_first_tx_sample_time;
+ size_t m_num_tx_samples_dropped;
+ std::deque<complexf> m_txsamples;
+};
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4a53a0..891b853 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,7 @@ find_package(Threads REQUIRED)
list(APPEND odrdpd_sources
main.cpp
OutputUHD.cpp
+ AlignSample.cpp
)
list(APPEND common_link_list ${UHD_LIBRARIES} ${ZMQ_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
diff --git a/main.cpp b/main.cpp
index 88edf6d..4477ef5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -22,6 +22,7 @@
*/
#include "OutputUHD.hpp"
+#include "AlignSample.hpp"
#include "utils.hpp"
#include <zmq.hpp>
#include <thread>
@@ -39,9 +40,6 @@ void sig_int_handler(int) {
running = false;
}
-const size_t samps_per_buffer = 20480;
-const size_t samplerate = 2048000;
-
size_t read_samples(FILE* fd, std::vector<complexf>& samples, size_t count)
{
if (samples.size() < count) {
@@ -58,178 +56,6 @@ size_t read_samples(FILE* fd, std::vector<complexf>& samples, size_t count)
return num_read;
}
-struct CorrelationResult {
- CorrelationResult(size_t len) :
- correlation(len),
- rx_power(0),
- tx_power(0),
- rx_timestamp(0),
- tx_timestamp(0) {}
-
- std::vector<complexf> correlation;
- double rx_power;
- double 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) {
- 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 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 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;
- }
-
- void debug() {
- std::lock_guard<std::mutex> lock(m_mutex);
- MDEBUG("Aligner\n");
- MDEBUG(" RX: %f %zu\n", m_rx_sample_time(), m_rxsamples.size());
- MDEBUG(" TX: %f %zu\n", m_tx_sample_time(), m_txsamples.size());
- }
-
- CorrelationResult 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 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;
- }
- }
-
- private:
- bool 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;
- }
-
- double m_rx_sample_time() {
- return m_first_rx_sample_time + (double)m_num_rx_samples_dropped / samplerate;
- }
-
- double m_tx_sample_time() {
- return m_first_tx_sample_time + (double)m_num_tx_samples_dropped / samplerate;
- }
-
- std::mutex m_mutex;
- double m_first_rx_sample_time;
- size_t m_num_rx_samples_dropped;
- std::deque<complexf> m_rxsamples;
-
- double m_first_tx_sample_time;
- size_t m_num_tx_samples_dropped;
- std::deque<complexf> m_txsamples;
-};
-
AlignSample aligner;
size_t do_receive(OutputUHD* output_uhd)
diff --git a/utils.hpp b/utils.hpp
index 813c597..e4d0fa9 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -1,5 +1,11 @@
#ifndef __UTILS_H_
+#include <cstddef>
+
+const size_t samps_per_buffer = 20480;
+const size_t samplerate = 2048000;
+
+
#include <cstdio>
#define MDEBUG(fmt, args...) fprintf (stderr, fmt , ## args)