// // Copyright 2014-2016 Ettus Research LLC // Copyright 2018 Ettus Research, a National Instruments Company // // SPDX-License-Identifier: GPL-3.0-or-later // #ifndef INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_IMPL_HPP #define INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_IMPL_HPP #include #include #include #include #include #include #include #include //! Shorthand for radio block constructor #define UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR_DECL(CLASS_NAME) \ CLASS_NAME##_impl(const make_args_t &make_args); #define UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(CLASS_NAME) \ CLASS_NAME##_impl::CLASS_NAME##_impl( \ const make_args_t &make_args \ ) : block_ctrl_base(make_args), radio_ctrl_impl() namespace uhd { namespace rfnoc { /*! \brief Provide access to a radio. * */ class radio_ctrl_impl : public radio_ctrl { public: /************************************************************************ * Structors ***********************************************************************/ radio_ctrl_impl(); virtual ~radio_ctrl_impl() {}; /************************************************************************ * Public Radio API calls ***********************************************************************/ virtual double set_rate(double rate); virtual void set_tx_antenna(const std::string &ant, const size_t chan); virtual void set_rx_antenna(const std::string &ant, const size_t chan); virtual double set_tx_frequency(const double freq, const size_t chan); virtual double set_rx_frequency(const double freq, const size_t chan); virtual double set_tx_gain(const double gain, const size_t chan); virtual double set_rx_gain(const double gain, const size_t chan); virtual double set_tx_bandwidth(const double bandwidth, const size_t chan); virtual double set_rx_bandwidth(const double bandwidth, const size_t chan); virtual double get_rate() const; virtual std::string get_tx_antenna(const size_t chan) /* const */; virtual std::string get_rx_antenna(const size_t chan) /* const */; virtual double get_tx_frequency(const size_t) /* const */; virtual double get_rx_frequency(const size_t) /* const */; virtual double get_tx_gain(const size_t) /* const */; virtual double get_rx_gain(const size_t) /* const */; virtual double get_tx_bandwidth(const size_t) /* const */; virtual double get_rx_bandwidth(const size_t) /* const */; virtual std::vector get_rx_lo_names(const size_t chan); virtual std::vector get_rx_lo_sources(const std::string &name, const size_t chan); virtual freq_range_t get_rx_lo_freq_range(const std::string &name, const size_t chan); virtual void set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan); virtual const std::string get_rx_lo_source(const std::string &name, const size_t chan); virtual void set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan); virtual bool get_rx_lo_export_enabled(const std::string &name, const size_t chan); virtual double set_rx_lo_freq(const double freq, const std::string &name, const size_t chan); virtual double get_rx_lo_freq(const std::string &name, const size_t chan); virtual std::vector get_tx_lo_names(const size_t chan); virtual std::vector get_tx_lo_sources(const std::string &name, const size_t chan); virtual freq_range_t get_tx_lo_freq_range(const std::string &name, const size_t chan); virtual void set_tx_lo_source(const std::string &src, const std::string &name, const size_t chan); virtual const std::string get_tx_lo_source(const std::string &name, const size_t chan); virtual void set_tx_lo_export_enabled(const bool enabled, const std::string &name, const size_t chan); virtual bool get_tx_lo_export_enabled(const std::string &name, const size_t chan); virtual double set_tx_lo_freq(const double freq, const std::string &name, const size_t chan); virtual double get_tx_lo_freq(const std::string &name, const size_t chan); void set_time_now(const time_spec_t &time_spec); void set_time_next_pps(const time_spec_t &time_spec); void set_time_sync(const uhd::time_spec_t &time); time_spec_t get_time_now(); time_spec_t get_time_last_pps(); virtual void set_time_source(const std::string &source); virtual std::string get_time_source(); virtual std::vector get_time_sources(); virtual void set_clock_source(const std::string &source); virtual std::string get_clock_source(); virtual std::vector get_clock_sources(); virtual std::vector get_gpio_banks() const; virtual void set_gpio_attr( const std::string &bank, const std::string &attr, const uint32_t value, const uint32_t mask ); virtual uint32_t get_gpio_attr(const std::string &bank, const std::string &attr); void enable_rx_timestamps(const bool, const size_t); /*********************************************************************** * Block control API calls **********************************************************************/ void set_rx_streamer(bool active, const size_t port); void set_tx_streamer(bool active, const size_t port); void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd, const size_t port); virtual double get_input_samp_rate(size_t /* port */) { return get_rate(); } virtual double get_output_samp_rate(size_t /* port */) { return get_rate(); } double _get_tick_rate() { return get_rate(); } std::vector get_active_rx_ports(); bool in_continuous_streaming_mode(const size_t chan) { return _continuous_streaming.at(chan); } void rx_ctrl_clear_cmds(const size_t port) { sr_write(regs::RX_CTRL_CLEAR_CMDS, 0, port); } protected: // TODO see what's protected and what's private void _register_loopback_self_test(size_t chan); /*********************************************************************** * Registers **********************************************************************/ struct regs { static inline uint32_t sr_addr(const uint32_t offset) { return offset * 4; } static inline uint32_t rb_addr(const uint32_t offset) { return offset * 8; } static const uint32_t BASE = 128; // defined in radio_core_regs.vh static const uint32_t TIME = 128; // time hi - 128, time lo - 129, ctrl - 130 static const uint32_t CLEAR_CMDS = 131; // Any write to this reg clears the command FIFO static const uint32_t LOOPBACK = 132; static const uint32_t TEST = 133; static const uint32_t CODEC_IDLE = 134; static const uint32_t TX_CTRL_ERROR_POLICY = 144; static const uint32_t RX_CTRL_CMD = 152; static const uint32_t RX_CTRL_TIME_HI = 153; static const uint32_t RX_CTRL_TIME_LO = 154; static const uint32_t RX_CTRL_HALT = 155; static const uint32_t RX_CTRL_MAXLEN = 156; static const uint32_t RX_CTRL_CLEAR_CMDS = 157; static const uint32_t RX_CTRL_OUTPUT_FORMAT= 158; static const uint32_t MISC_OUTS = 160; static const uint32_t DACSYNC = 161; static const uint32_t SPI = 168; static const uint32_t LEDS = 176; static const uint32_t FP_GPIO = 184; static const uint32_t GPIO = 192; // NOTE: Upper 32 registers (224-255) are reserved for the output settings bus for use with // device specific front end control // frontend control: needs rethinking TODO //static const uint32_t TX_FRONT = BASE + 96; //static const uint32_t RX_FRONT = BASE + 112; //static const uint32_t READBACK = BASE + 127; static const uint32_t RB_TIME_NOW = 0; static const uint32_t RB_TIME_PPS = 1; static const uint32_t RB_TEST = 2; static const uint32_t RB_CODEC_READBACK = 3; static const uint32_t RB_RADIO_NUM = 4; static const uint32_t RB_MISC_IO = 16; static const uint32_t RB_SPI = 17; static const uint32_t RB_LEDS = 18; static const uint32_t RB_DB_GPIO = 19; static const uint32_t RB_FP_GPIO = 20; }; /*********************************************************************** * Block control API calls **********************************************************************/ void _update_spp(int spp); inline size_t _get_num_radios() const { return std::max(_num_rx_channels, _num_tx_channels); } inline timed_wb_iface::sptr _get_ctrl(size_t radio_num) const { return _perifs.at(radio_num).ctrl; } inline bool _is_streamer_active(uhd::direction_t dir, const size_t chan) const { switch (dir) { case uhd::TX_DIRECTION: return _tx_streamer_active.count(chan) ? _tx_streamer_active.at(chan) : false; case uhd::RX_DIRECTION: return _rx_streamer_active.count(chan) ? _rx_streamer_active.at(chan) : false; case uhd::DX_DIRECTION: return (_tx_streamer_active.count(chan) and _rx_streamer_active.count(chan)) ? _rx_streamer_active.at(chan) and _tx_streamer_active.at(chan) : false; default: return false; } } virtual bool check_radio_config() { return true; }; //! There is always only one time core per radio time_core_3000::sptr _time64; std::mutex _mutex; size_t _num_tx_channels; size_t _num_rx_channels; std::vector _continuous_streaming; private: /************************************************************************ * Peripherals ***********************************************************************/ //! Stores pointers to all streaming-related radio cores struct radio_perifs_t { timed_wb_iface::sptr ctrl; }; std::map _perifs; // Cached values double _tick_rate; std::map _tx_antenna; std::map _rx_antenna; std::map _tx_freq; std::map _rx_freq; std::map _tx_gain; std::map _rx_gain; std::map _tx_bandwidth; std::map _rx_bandwidth; }; /* class radio_ctrl_impl */ }} /* namespace uhd::rfnoc */ #endif /* INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_IMPL_HPP */ // vim: sw=4 et: