diff options
Diffstat (limited to 'Transceiver52M/device/uhd/UHDDevice.cpp')
-rw-r--r-- | Transceiver52M/device/uhd/UHDDevice.cpp | 362 |
1 files changed, 1 insertions, 361 deletions
diff --git a/Transceiver52M/device/uhd/UHDDevice.cpp b/Transceiver52M/device/uhd/UHDDevice.cpp index 46284e5..67b7416 100644 --- a/Transceiver52M/device/uhd/UHDDevice.cpp +++ b/Transceiver52M/device/uhd/UHDDevice.cpp @@ -23,11 +23,9 @@ #include <map> #include "radioDevice.h" +#include "UHDDevice.h" #include "Threads.h" #include "Logger.h" -#include <uhd/version.hpp> -#include <uhd/property_tree.hpp> -#include <uhd/usrp/multi_usrp.hpp> #ifdef HAVE_CONFIG_H #include "config.h" @@ -58,20 +56,6 @@ */ #define UMTRX_VGA1_DEF -18 -enum uhd_dev_type { - USRP1, - USRP2, - B100, - B200, - B210, - B2XX_MCBTS, - E1XX, - E3XX, - X3XX, - UMTRX, - LIMESDR, -}; - /* * USRP version dependent device timings */ @@ -136,190 +120,6 @@ static const std::map<dev_key, dev_desc> dev_param_map { { std::make_tuple(B2XX_MCBTS, 4, 4), { 1, 51.2e6, MCBTS_SPACING*4, B2XX_TIMING_MCBTS, "B200/B210 4 SPS Multi-ARFCN" } }, }; -/* - Sample Buffer - Allows reading and writing of timed samples using osmo-trx - or UHD style timestamps. Time conversions are handled - internally or accessable through the static convert calls. -*/ -class smpl_buf { -public: - /** Sample buffer constructor - @param len number of 32-bit samples the buffer should hold - @param rate sample clockrate - @param timestamp - */ - smpl_buf(size_t len, double rate); - ~smpl_buf(); - - /** Query number of samples available for reading - @param timestamp time of first sample - @return number of available samples or error - */ - ssize_t avail_smpls(TIMESTAMP timestamp) const; - ssize_t avail_smpls(uhd::time_spec_t timestamp) const; - - /** Read and write - @param buf pointer to buffer - @param len number of samples desired to read or write - @param timestamp time of first stample - @return number of actual samples read or written or error - */ - ssize_t read(void *buf, size_t len, TIMESTAMP timestamp); - ssize_t read(void *buf, size_t len, uhd::time_spec_t timestamp); - ssize_t write(void *buf, size_t len, TIMESTAMP timestamp); - ssize_t write(void *buf, size_t len, uhd::time_spec_t timestamp); - - /** Buffer status string - @return a formatted string describing internal buffer state - */ - std::string str_status(size_t ts) const; - - /** Formatted error string - @param code an error code - @return a formatted error string - */ - static std::string str_code(ssize_t code); - - enum err_code { - ERROR_TIMESTAMP = -1, - ERROR_READ = -2, - ERROR_WRITE = -3, - ERROR_OVERFLOW = -4 - }; - -private: - uint32_t *data; - size_t buf_len; - - double clk_rt; - - TIMESTAMP time_start; - TIMESTAMP time_end; - - size_t data_start; - size_t data_end; -}; - -/* - uhd_device - UHD implementation of the Device interface. Timestamped samples - are sent to and received from the device. An intermediate buffer - on the receive side collects and aligns packets of samples. - Events and errors such as underruns are reported asynchronously - by the device and received in a separate thread. -*/ -class uhd_device : public RadioDevice { -public: - uhd_device(size_t tx_sps, size_t rx_sps, InterfaceType type, - size_t chans, double offset, - const std::vector<std::string>& tx_paths, - const std::vector<std::string>& rx_paths); - ~uhd_device(); - - int open(const std::string &args, int ref, bool swap_channels); - bool start(); - bool stop(); - bool restart(); - void setPriority(float prio); - enum TxWindowType getWindowType() { return tx_window; } - - int readSamples(std::vector<short *> &bufs, int len, bool *overrun, - TIMESTAMP timestamp, bool *underrun, unsigned *RSSI); - - int writeSamples(std::vector<short *> &bufs, int len, bool *underrun, - TIMESTAMP timestamp, bool isControl); - - bool updateAlignment(TIMESTAMP timestamp); - - bool setTxFreq(double wFreq, size_t chan); - bool setRxFreq(double wFreq, size_t chan); - - TIMESTAMP initialWriteTimestamp(); - TIMESTAMP initialReadTimestamp(); - - double fullScaleInputValue(); - double fullScaleOutputValue(); - - double setRxGain(double db, size_t chan); - double getRxGain(size_t chan); - double maxRxGain(void) { return rx_gain_max; } - double minRxGain(void) { return rx_gain_min; } - - double setTxGain(double db, size_t chan); - double maxTxGain(void) { return tx_gain_max; } - double minTxGain(void) { return tx_gain_min; } - - double getTxFreq(size_t chan); - double getRxFreq(size_t chan); - double getRxFreq(); - - bool setRxAntenna(const std::string &ant, size_t chan); - std::string getRxAntenna(size_t chan); - bool setTxAntenna(const std::string &ant, size_t chan); - std::string getTxAntenna(size_t chan); - - bool requiresRadioAlign(); - - GSM::Time minLatency(); - - inline double getSampleRate() { return tx_rate; } - inline double numberRead() { return rx_pkt_cnt; } - inline double numberWritten() { return 0; } - - /** Receive and process asynchronous message - @return true if message received or false on timeout or error - */ - bool recv_async_msg(); - - enum err_code { - ERROR_TIMING = -1, - ERROR_TIMEOUT = -2, - ERROR_UNRECOVERABLE = -3, - ERROR_UNHANDLED = -4, - }; - -private: - uhd::usrp::multi_usrp::sptr usrp_dev; - uhd::tx_streamer::sptr tx_stream; - uhd::rx_streamer::sptr rx_stream; - enum TxWindowType tx_window; - enum uhd_dev_type dev_type; - - double tx_rate, rx_rate; - - double tx_gain_min, tx_gain_max; - double rx_gain_min, rx_gain_max; - - std::vector<double> tx_gains, rx_gains; - std::vector<double> tx_freqs, rx_freqs; - size_t tx_spp, rx_spp; - - bool started; - bool aligned; - - size_t rx_pkt_cnt; - size_t drop_cnt; - uhd::time_spec_t prev_ts; - - TIMESTAMP ts_initial, ts_offset; - std::vector<smpl_buf *> rx_buffers; - - void init_gains(); - void set_channels(bool swap); - void set_rates(); - bool parse_dev_type(); - bool flush_recv(size_t num_pkts); - int check_rx_md_err(uhd::rx_metadata_t &md, ssize_t num_smpls); - - std::string str_code(uhd::rx_metadata_t metadata); - std::string str_code(uhd::async_metadata_t metadata); - - uhd::tune_request_t select_freq(double wFreq, size_t chan, bool tx); - bool set_freq(double freq, size_t chan, bool tx); - - Thread *async_event_thrd; - Mutex tune_lock; -}; - void *async_event_loop(uhd_device *dev) { set_selfthread_name("UHDAsyncEvent"); @@ -1386,166 +1186,6 @@ std::string uhd_device::str_code(uhd::async_metadata_t metadata) return ost.str(); } -smpl_buf::smpl_buf(size_t len, double rate) - : buf_len(len), clk_rt(rate), - time_start(0), time_end(0), data_start(0), data_end(0) -{ - data = new uint32_t[len]; -} - -smpl_buf::~smpl_buf() -{ - delete[] data; -} - -ssize_t smpl_buf::avail_smpls(TIMESTAMP timestamp) const -{ - if (timestamp < time_start) - return ERROR_TIMESTAMP; - else if (timestamp >= time_end) - return 0; - else - return time_end - timestamp; -} - -ssize_t smpl_buf::avail_smpls(uhd::time_spec_t timespec) const -{ - return avail_smpls(timespec.to_ticks(clk_rt)); -} - -ssize_t smpl_buf::read(void *buf, size_t len, TIMESTAMP timestamp) -{ - int type_sz = 2 * sizeof(short); - - // Check for valid read - if (timestamp < time_start) - return ERROR_TIMESTAMP; - if (timestamp >= time_end) - return 0; - if (len >= buf_len) - return ERROR_READ; - - // How many samples should be copied - size_t num_smpls = time_end - timestamp; - if (num_smpls > len) - num_smpls = len; - - // Starting index - size_t read_start = (data_start + (timestamp - time_start)) % buf_len; - - // Read it - if (read_start + num_smpls < buf_len) { - size_t numBytes = len * type_sz; - memcpy(buf, data + read_start, numBytes); - } else { - size_t first_cp = (buf_len - read_start) * type_sz; - size_t second_cp = len * type_sz - first_cp; - - memcpy(buf, data + read_start, first_cp); - memcpy((char*) buf + first_cp, data, second_cp); - } - - data_start = (read_start + len) % buf_len; - time_start = timestamp + len; - - if (time_start > time_end) - return ERROR_READ; - else - return num_smpls; -} - -ssize_t smpl_buf::read(void *buf, size_t len, uhd::time_spec_t ts) -{ - return read(buf, len, ts.to_ticks(clk_rt)); -} - -ssize_t smpl_buf::write(void *buf, size_t len, TIMESTAMP timestamp) -{ - int type_sz = 2 * sizeof(short); - - // Check for valid write - if ((len == 0) || (len >= buf_len)) - return ERROR_WRITE; - if ((timestamp + len) <= time_end) - return ERROR_TIMESTAMP; - - if (timestamp < time_end) { - LOGC(DDEV, ERR) << "Overwriting old buffer data: timestamp="<<timestamp<<" time_end="<<time_end; - uhd::time_spec_t ts = uhd::time_spec_t::from_ticks(timestamp, clk_rt); - LOGC(DDEV, DEBUG) << "Requested timestamp = " << timestamp << " (real_sec=" << std::fixed << ts.get_real_secs() << " = " << ts.to_ticks(clk_rt) << ") rate=" << clk_rt; - // Do not return error here, because it's a rounding error and is not fatal - } - if (timestamp > time_end && time_end != 0) { - LOGC(DDEV, ERR) << "Skipping buffer data: timestamp="<<timestamp<<" time_end="<<time_end; - uhd::time_spec_t ts = uhd::time_spec_t::from_ticks(timestamp, clk_rt); - LOGC(DDEV, DEBUG) << "Requested timestamp = " << timestamp << " (real_sec=" << std::fixed << ts.get_real_secs() << " = " << ts.to_ticks(clk_rt) << ") rate=" << clk_rt; - // Do not return error here, because it's a rounding error and is not fatal - } - - // Starting index - size_t write_start = (data_start + (timestamp - time_start)) % buf_len; - - // Write it - if ((write_start + len) < buf_len) { - size_t numBytes = len * type_sz; - memcpy(data + write_start, buf, numBytes); - } else { - size_t first_cp = (buf_len - write_start) * type_sz; - size_t second_cp = len * type_sz - first_cp; - - memcpy(data + write_start, buf, first_cp); - memcpy(data, (char*) buf + first_cp, second_cp); - } - - data_end = (write_start + len) % buf_len; - time_end = timestamp + len; - - if (!data_start) - data_start = write_start; - - if (((write_start + len) > buf_len) && (data_end > data_start)) - return ERROR_OVERFLOW; - else if (time_end <= time_start) - return ERROR_WRITE; - else - return len; -} - -ssize_t smpl_buf::write(void *buf, size_t len, uhd::time_spec_t ts) -{ - return write(buf, len, ts.to_ticks(clk_rt)); -} - -std::string smpl_buf::str_status(size_t ts) const -{ - std::ostringstream ost("Sample buffer: "); - - ost << "timestamp = " << ts; - ost << ", length = " << buf_len; - ost << ", time_start = " << time_start; - ost << ", time_end = " << time_end; - ost << ", data_start = " << data_start; - ost << ", data_end = " << data_end; - - return ost.str(); -} - -std::string smpl_buf::str_code(ssize_t code) -{ - switch (code) { - case ERROR_TIMESTAMP: - return "Sample buffer: Requested timestamp is not valid"; - case ERROR_READ: - return "Sample buffer: Read error"; - case ERROR_WRITE: - return "Sample buffer: Write error"; - case ERROR_OVERFLOW: - return "Sample buffer: Overrun"; - default: - return "Sample buffer: Unknown error"; - } -} - RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset, const std::vector<std::string>& tx_paths, |