// // Copyright 2020 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // #pragma once #include #include #include #include #include #include #include #include #include #include using namespace uhd::usrp; namespace uhd { namespace test { namespace { constexpr double DEFAULT_MCR = 122.88e6; } //! Mock MPM server for X410/ZBX // // This is a mock server that mimicks an X410 with a ZBX daughterboard. class x4xx_mock_rpc_server : public x400_rpc_iface, public mpmd_rpc_iface, public dboard_base_rpc_iface, public zbx_rpc_iface, public dio_rpc_iface { public: x4xx_mock_rpc_server(const uhd::device_addr_t& device_info) : _device_info(device_info) {} uhd::rpc_client::sptr get_raw_rpc_client() override { // This function is unimplemented! Perhaps you need to: // - Add it to the appropriate RPC interface, // - Retrofit all calls to your desired function to directly use the RPC interface, and // - Add a mock implementation here. UHD_THROW_INVALID_CODE_PATH(); } /************************************************************************** * RPC Call Mockups * * The following public methods are replacements of that normally happens in * the Python-based MPM. Some notes on writing mocks: * - These are mocks, so don't go fancy and only let them do the bare * minimum required for tests * - Remember to add them to _init_rpc() further down *************************************************************************/ size_t get_num_timekeepers() override { return 1; } std::vector get_mb_sensors() override { return {"ref_locked"}; } std::vector get_gpio_banks() override { return {"GPIO0", "GPIO1"}; } bool supports_feature(const std::string& feature) override { return feature == "ref_clk_calibration"; } std::vector> get_dboard_info() override { return {{ // One entry per dboard info {"pid", std::to_string(uhd::usrp::zbx::ZBX_PID)} // End of entries }}; } bool is_db_gpio_ifc_present(const size_t) override { return true; } void set_tick_period(const size_t, const uint64_t) override { // nop } double get_master_clock_rate() override { return _device_info.cast("master_clock_rate", DEFAULT_MCR); } std::vector get_sensors(const std::string&) override { return {}; } std::map get_sensor(const std::string&, const std::string&, size_t) override { return {}; } void set_cal_frozen(bool, size_t, size_t) override { // nop } std::vector get_cal_frozen(size_t, size_t) override { return {}; } std::map> get_db_eeprom(const size_t) override { return {{ // One line per entry {"pid", s2u8("mock")}, // Used to specify power cal API {"serial", s2u8("BADCODE")} // End of entries }}; } double get_dboard_prc_rate() override { const double mcr = _device_info.cast("master_clock_rate", DEFAULT_MCR); static const std::map prc_map{ {122.88e6, 61.44e6}, {125e6, 62.5e6}}; return prc_map.at(mcr); } double rfdc_set_nco_freq(const std::string& trx, const size_t /*db_id*/, const size_t chan, const double freq) override { BOOST_REQUIRE(trx == "rx" || trx == "tx"); BOOST_REQUIRE(chan < uhd::usrp::zbx::ZBX_NUM_CHANS); nco_freq[trx][chan] = freq; return freq; } double rfdc_get_nco_freq( const std::string& trx, const size_t /*db_id*/, const size_t chan) override { BOOST_REQUIRE(trx == "rx" || trx == "tx"); BOOST_REQUIRE(chan < uhd::usrp::zbx::ZBX_NUM_CHANS); // On construction, the expert will ask for the current nco frequency, and our // nco_freq map won't have a value yet. if (nco_freq.find(trx) == nco_freq.end() || nco_freq.at(trx).find(chan) == nco_freq.at(trx).end()) { return 0; } return nco_freq.at(trx).at(chan); } double get_dboard_sample_rate() override { const double mcr = _device_info.cast("master_clock_rate", DEFAULT_MCR); static const std::map spll_map{ // One line per entry {122.88e6, 2.94912e9}, {122.88e6 * 4, 2.94912e9} // End of entries }; return spll_map.at(mcr); } void enable_iq_swap(const bool, const std::string&, const size_t) override { // nop } std::vector get_gpio_srcs(const std::string& /*bank*/) override { return {}; } uint64_t get_timekeeper_time(size_t /*timekeeper_idx*/, bool /*last_pps*/) override { return 0; } void set_timekeeper_time(size_t /*timekeeper_idx*/, uint64_t /*ticks*/, bool /*last_pps*/) override { // nop } std::string get_time_source() override { return ""; } std::vector get_time_sources() override { return {}; } std::string get_clock_source() override { return ""; } std::vector get_clock_sources() override { return {}; } std::map get_sync_source() override { return {}; } std::vector> get_sync_sources() override { return {}; } void set_clock_source_out(bool /*enb*/) override { // nop } void set_trigger_io(const std::string& /*direction*/) override { // nop } std::map get_mb_eeprom() override { return {}; } std::vector get_gpio_src(const std::string& /*bank*/) override { return {}; } void set_gpio_src(const std::string& /*bank*/, const std::vector& /*src*/) override { // nop } void set_ref_clk_tuning_word(uint32_t /*tuning_word*/) override { // nop } uint32_t get_ref_clk_tuning_word() override { return 0; } void store_ref_clk_tuning_word(uint32_t /*tuning_word*/) override { // nop } sensor_value_t::sensor_map_t get_mb_sensor(const std::string& /*sensor*/) override { return {}; } void set_time_source(const std::string& /*source*/) override { // nop } void set_clock_source(const std::string& /*source*/) override { // nop } void set_sync_source(const std::map& /*source*/) override { // nop } bool get_threshold_status(size_t /*db_number*/, size_t /*chan*/, size_t /*threshold_block*/) override { return false; } void set_dac_mux_enable(size_t /*motherboard_channel_number*/, int /*enable*/) override { // nop } void set_dac_mux_data(size_t /*i*/, size_t /*q*/) override { // nop } double get_spll_freq() override { return 0.0; } void setup_threshold( size_t /*db_number*/, size_t /*chan*/, size_t /*threshold_block*/, const std::string& /*mode*/, size_t /*delay*/, size_t /*under*/, size_t /*over*/) override { // nop } std::vector dio_get_supported_voltage_levels(const std::string&) override { return {"OFF", "1V8", "2V5", "3V3"}; } void dio_set_voltage_level(const std::string&, const std::string&) override { // nop } std::string dio_get_voltage_level(const std::string&) override { return "3V3"; } void dio_set_port_mapping(const std::string&) override { // nop } void dio_set_pin_directions(const std::string&, uint32_t) override { // nop } void dio_set_external_power(const std::string&, bool) override { // nop } std::string dio_get_external_power_state(const std::string&) override { return "OFF"; } /////////////////////////////////////////////////////////////////////////// // Public attributes for easy inspection // // Use this in the mock functions to cache values, or expose values that get // tested later std::map> if2_freq; std::map> nco_freq; // /////////////////////////////////////////////////////////////////////////// private: uhd::device_addr_t _device_info; static std::vector s2u8(const std::string& s) { return std::vector(s.begin(), s.end()); } }; }} // namespace uhd::test