diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | OutputUHD.cpp | 99 | ||||
-rw-r--r-- | OutputUHD.hpp | 47 | ||||
-rw-r--r-- | main.cpp | 88 | ||||
-rw-r--r-- | utils.hpp | 9 |
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_ + |