// // Copyright 2019 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // #include #include #include #include using namespace uhd; using namespace uhd::rfnoc; class mock_timekeeper : public mb_controller::timekeeper { public: uint64_t get_ticks_now() override { return _ticks; } uint64_t get_ticks_last_pps() override { return _ticks; } void set_ticks_now(const uint64_t ticks) override { _ticks = ticks; } void set_ticks_next_pps(const uint64_t ticks) override { _ticks = ticks; } uint64_t _ticks; uint64_t _period; void update_tick_rate(const double tick_rate) { set_tick_rate(tick_rate); } private: void set_period(const uint64_t period_ns) override { _period = period_ns; } }; class mock_mb_controller : public mb_controller, public ::uhd::features::discoverable_feature_registry { public: mock_mb_controller() { auto tk = std::make_shared(); register_timekeeper(0, tk); } /************************************************************************** * Motherboard Control API (see mb_controller.hpp) *************************************************************************/ std::string get_mboard_name() const override { return "MOCK-MB"; } void set_time_source(const std::string& source) override { time_source = source; } std::string get_time_source() const override { return time_source; } std::vector get_time_sources() const override { return {"internal", "external"}; } void set_clock_source(const std::string& source) override { clock_source = source; } std::string get_clock_source() const override { return clock_source; } std::vector get_clock_sources() const override { return {"internal", "external"}; } void set_sync_source( const std::string& /*clock_source*/, const std::string& /*time_source*/) override { } void set_sync_source(const device_addr_t& /*sync_source*/) override {} device_addr_t get_sync_source() const override { return {}; } std::vector get_sync_sources() override { return {}; } void set_clock_source_out(const bool enb) override { clock_source_out = enb; } void set_time_source_out(const bool enb) override { time_source_out = enb; } sensor_value_t get_sensor(const std::string& /*name*/) override { return sensor_value_t("Ref", false, "locked", "unlocked"); } std::vector get_sensor_names() override { return {"mock_sensor"}; } uhd::usrp::mboard_eeprom_t get_eeprom() override { return {}; } std::string clock_source = "internal"; std::string time_source = "internal"; bool clock_source_out = false; bool time_source_out = false; }; BOOST_AUTO_TEST_CASE(test_mb_controller) { auto mmbc = std::make_shared(); BOOST_REQUIRE_EQUAL(mmbc->get_num_timekeepers(), 1); auto tk = mmbc->get_timekeeper(0); auto tk_mock = std::dynamic_pointer_cast(tk); BOOST_REQUIRE(tk); constexpr double TICK_RATE = 200e6; constexpr double PERIOD_NS = 5; // This will call set_tick_rate() and thus set_period() tk_mock->update_tick_rate(TICK_RATE); BOOST_CHECK_EQUAL(tk->get_tick_rate(), TICK_RATE); BOOST_CHECK_EQUAL(tk_mock->_period, PERIOD_NS * (uint64_t(1) << 32)); constexpr double TIME_0 = 1.0; tk->set_time_now(uhd::time_spec_t(TIME_0)); BOOST_CHECK_EQUAL(tk->get_ticks_now(), TICK_RATE * TIME_0); constexpr double TIME_1 = 0.5; tk->set_time_next_pps(uhd::time_spec_t(TIME_1)); BOOST_CHECK_EQUAL(tk->get_ticks_last_pps(), TIME_1 * TICK_RATE); }