aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--OutputUHD.cpp99
-rw-r--r--OutputUHD.hpp47
-rw-r--r--main.cpp88
-rw-r--r--utils.hpp9
5 files changed, 246 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 190837c..5e1ed2d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,6 +49,7 @@ add_definitions(-Wall)
########################################################################
find_package(PkgConfig)
+pkg_check_modules(UHD uhd)
# Threads
find_package(Threads REQUIRED)
@@ -59,9 +60,10 @@ find_package(Threads REQUIRED)
list(APPEND odrdpd_sources
main.cpp
+ OutputUHD.cpp
)
-#list(APPEND common_link_list stuff to link against)
+list(APPEND common_link_list ${UHD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
set_source_files_properties(
${odrdpd_sources}
diff --git a/OutputUHD.cpp b/OutputUHD.cpp
new file mode 100644
index 0000000..c337262
--- /dev/null
+++ b/OutputUHD.cpp
@@ -0,0 +1,99 @@
+/*
+ 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 "OutputUHD.hpp"
+#include "utils.hpp"
+#include <cmath>
+#include <iostream>
+#include <assert.h>
+#include <stdexcept>
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/utils/safe_main.hpp>
+
+using namespace std;
+
+void OutputUHD::Init(double txgain)
+{
+ m_txgain = txgain;
+
+ uhd::set_thread_priority_safe();
+
+ string device = "master_clock_rate=32768000";
+
+ m_usrp = uhd::usrp::multi_usrp::make(device);
+
+ m_samplerate = 2048000;
+ m_usrp->set_tx_rate(m_samplerate);
+ m_usrp->set_rx_rate(m_samplerate);
+
+ m_usrp->set_tx_freq(234.208e6);
+ double set_frequency = m_usrp->get_tx_freq();
+ MDEBUG("OutputUHD:Actual frequency: %f\n", set_frequency);
+
+ m_usrp->set_tx_gain(m_txgain);
+ MDEBUG("OutputUHD:Actual TX Gain: %f ...\n", m_usrp->get_tx_gain());
+
+
+ double tx_time = m_usrp->get_time_now().get_real_secs();
+ MDEBUG("OutputUHD: USRP time %f\n",
+ tx_time);
+
+ md.start_of_burst = false;
+ md.end_of_burst = false;
+ md.has_time_spec = true;
+ md.time_spec = uhd::time_spec_t(tx_time + 2);
+
+ uhd::stream_args_t stream_args("fc32"); //complex floats
+ myTxStream = m_usrp->get_tx_stream(stream_args);
+}
+
+size_t OutputUHD::Transmit(std::vector<complexf> samples, size_t sizeIn, double *first_sample_time)
+{
+ const double tx_timeout = 20.0;
+
+ size_t usrp_max_num_samps = myTxStream->get_max_num_samps();
+
+ *first_sample_time = md.time_spec.get_real_secs();
+
+ size_t num_acc_samps = 0; //number of accumulated samples
+ while (num_acc_samps < sizeIn) {
+ size_t samps_to_send = std::min(sizeIn - num_acc_samps, usrp_max_num_samps);
+
+ //send a single packet
+ size_t num_tx_samps = myTxStream->send(
+ &samples[num_acc_samps],
+ samps_to_send, md, tx_timeout);
+
+ num_acc_samps += num_tx_samps;
+
+ md.time_spec += uhd::time_spec_t(0, num_acc_samps/m_samplerate);
+ }
+
+ return num_acc_samps;
+}
+
diff --git a/OutputUHD.hpp b/OutputUHD.hpp
new file mode 100644
index 0000000..007e51f
--- /dev/null
+++ b/OutputUHD.hpp
@@ -0,0 +1,47 @@
+/*
+ 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/>.
+ */
+
+#ifndef __OUTPUT_UHD_H_
+#define __OUTPUT_UHD_H_
+
+#include <uhd/usrp/multi_usrp.hpp>
+
+typedef std::complex<float> complexf;
+
+
+class OutputUHD {
+ public:
+ void Init(double txgain);
+
+ size_t Transmit(std::vector<complexf> samples, size_t sizeIn, double *first_sample_time);
+
+ private:
+ double m_samplerate;
+ double m_txgain;
+ uhd::usrp::multi_usrp::sptr m_usrp;
+ uhd::tx_metadata_t md;
+ uhd::tx_streamer::sptr myTxStream;
+};
+
+#endif // __OUTPUT_UHD_H_
+
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..7c27b80
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,88 @@
+/*
+ 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 "OutputUHD.hpp"
+#include "utils.hpp"
+
+size_t read_samples(FILE* fd, std::vector<complexf>& samples, size_t count)
+{
+ if (samples.size() < count) {
+ MDEBUG("HAD TO RESIZE BUFFER!\n");
+ samples.resize(count);
+ }
+
+ size_t num_read = fread((char*)&samples.front(), sizeof(complexf), count, fd);
+ if (num_read == 0) {
+ rewind(fd);
+ num_read = fread((char*)&samples.front(), sizeof(complexf), count, fd);
+ }
+
+ return num_read;
+}
+
+int main(int argc, char **argv)
+{
+ double txgain = 0;
+
+ if (argc == 1) {
+ txgain = strtod(argv[1], nullptr);
+ if (!(0 <= txgain and txgain < 80)) {
+ MDEBUG("txgain wrong: %f\n", txgain);
+ return -1;
+ }
+ }
+
+ const size_t samps_per_buffer = 20480;
+
+ OutputUHD output_uhd;
+ output_uhd.Init(txgain);
+
+ FILE* fd = fopen("input.iq", "rb");
+ if (!fd) {
+ MDEBUG("Could not open file\n");
+ return -1;
+ }
+
+ std::vector<complexf> input_samples(samps_per_buffer);
+ size_t samps_read = 0;
+ size_t total_samps_read = samps_read;
+
+ double last_print_time = 0;
+
+ do {
+ samps_read = read_samples(fd, input_samples, samps_per_buffer);
+
+ double first_sample_time = 0;
+ output_uhd.Transmit(input_samples, samps_read, &first_sample_time);
+ if (first_sample_time - last_print_time > 1) {
+ MDEBUG("Tx %zu samples at t=%f\n", samps_read, first_sample_time);
+ last_print_time = first_sample_time;
+ }
+
+ total_samps_read += samps_read;
+ }
+ while (samps_read);
+
+ MDEBUG("Read %zu samples in total\n", total_samps_read);
+}
+
diff --git a/utils.hpp b/utils.hpp
new file mode 100644
index 0000000..813c597
--- /dev/null
+++ b/utils.hpp
@@ -0,0 +1,9 @@
+#ifndef __UTILS_H_
+
+#include <cstdio>
+
+#define MDEBUG(fmt, args...) fprintf (stderr, fmt , ## args)
+
+#define __UTILS_H_
+#endif // __UTILS_H_
+