// // Copyright 2014 Ettus Research LLC // // This program 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. // // This program 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 this program. If not, see . // #include "e300_remote_codec_ctrl.hpp" #include #include #include #include #include namespace uhd { namespace usrp { namespace e300 { class e300_remote_codec_ctrl_impl : public e300_remote_codec_ctrl { public: e300_remote_codec_ctrl_impl(uhd::transport::zero_copy_if::sptr xport) : _xport(xport) { } virtual ~e300_remote_codec_ctrl_impl(void) { } void set_timed_spi(uhd::spi_iface::sptr, uint32_t ) {}; void set_safe_spi(uhd::spi_iface::sptr, uint32_t ) {}; double set_gain(const std::string &which, const double value) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_SET_GAIN); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); _args.gain = value; _transact(); return _retval.gain; } double set_clock_rate(const double rate) { _clear(); _args.action = uhd::htonx( transaction_t::ACTION_SET_CLOCK_RATE); _args.which = uhd::htonx( transaction_t::CHAIN_NONE); /*Unused*/ _args.rate = rate; _transact(); return _retval.gain; } void set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2) { _clear(); _args.action = uhd::htonx( transaction_t::ACTION_SET_ACTIVE_CHANS); /*Unused*/ _args.which = uhd::htonx( transaction_t::CHAIN_NONE); _args.bits = uhd::htonx( (tx1 ? (1<<0) : 0) | (tx2 ? (1<<1) : 0) | (rx1 ? (1<<2) : 0) | (rx2 ? (1<<3) : 0)); _transact(); } double tune(const std::string &which, const double value) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_TUNE); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); _args.freq = value; _transact(); return _retval.freq; } double get_freq(const std::string &which) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_GET_FREQ); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); _transact(); return _retval.freq; } void data_port_loopback(const bool on) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_SET_LOOPBACK); _args.which = uhd::htonx(transaction_t::CHAIN_NONE); /*Unused*/ _args.bits = uhd::htonx(on ? 1 : 0); _transact(); } sensor_value_t get_rssi(const std::string &which) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_GET_RSSI); if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); _args.bits = uhd::htonx(0); _transact(); return sensor_value_t("RSSI", _retval.rssi, "dB"); } sensor_value_t get_temperature() { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_GET_TEMPERATURE); _args.which = uhd::htonx(transaction_t::CHAIN_NONE); /*Unused*/ _args.bits = uhd::htonx(0); _transact(); return sensor_value_t("temp", _retval.temp, "C"); } void set_dc_offset_auto(const std::string &which, const bool on) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_SET_DC_OFFSET_AUTO); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); _args.use_dc_correction = on ? 1 : 0; _transact(); } void set_iq_balance_auto(const std::string &which, const bool on) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_SET_IQ_BALANCE_AUTO); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); _args.use_iq_correction = on ? 1 : 0; _transact(); } void set_agc(const std::string &which, bool enable) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_SET_AGC); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); _args.use_agc = enable ? 1 : 0; _transact(); } void set_agc_mode(const std::string &which, const std::string &mode) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_SET_AGC_MODE); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); if(mode == "slow") { _args.agc_mode = 0; } else if (mode == "fast") { _args.agc_mode = 1; } else { throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect agc mode."); } _transact(); } //! set the filter bandwidth for the frontend's analog low pass double set_bw_filter(const std::string &which, const double bw) { _clear(); _args.action = uhd::htonx(transaction_t::ACTION_SET_BW); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); _args.bw = bw; _transact(); return _retval.bw; } //! List all available filters by name std::vector get_filter_names(const std::string &) { return std::vector(); } //! Return a list of all filters filter_info_base::sptr get_filter(const std::string &, const std::string &) { UHD_THROW_INVALID_CODE_PATH(); } //! Write back a filter void set_filter(const std::string &, const std::string &, const filter_info_base::sptr) { UHD_MSG(warning) << "Attempting to set filter on E300 in network mode." << std::endl; } void output_digital_test_tone(UHD_UNUSED(bool enb)) { UHD_THROW_INVALID_CODE_PATH(); } private: void _transact() { { uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); if (not buff or buff->size() < sizeof(_args)) throw std::runtime_error("e300_remote_codec_ctrl_impl send timeout"); std::memcpy(buff->cast(), &_args, sizeof(_args)); buff->commit(sizeof(_args)); } { uhd::transport::managed_recv_buffer::sptr buff = _xport->get_recv_buff(10.0); if (not buff or buff->size() < sizeof(_retval)) throw std::runtime_error("e300_remote_codec_ctrl_impl recv timeout"); std::memcpy(&_retval, buff->cast(), sizeof(_retval)); } if (_args.action != _retval.action) throw std::runtime_error("e300_remote_codec_ctrl_impl transaction failed."); } void _clear() { _args.action = 0; _args.which = 0; _args.bits = 0; _retval.action = 0; _retval.which = 0; _retval.bits = 0; } uhd::transport::zero_copy_if::sptr _xport; transaction_t _args; transaction_t _retval; }; ad9361_ctrl::sptr e300_remote_codec_ctrl::make(uhd::transport::zero_copy_if::sptr xport) { return sptr(new e300_remote_codec_ctrl_impl(xport)); } }}};