aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/include/uhdlib/usrp/common/mpmd_mb_controller.hpp
blob: e7498b9f5b54a12b3a01f031c92fc647e09cb918 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//
// Copyright 2019 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#pragma once

#include <uhd/features/ref_clk_calibration_iface.hpp>
#include <uhd/rfnoc/mb_controller.hpp>
#include <uhdlib/usrp/common/rpc.hpp>
#include <uhdlib/features/discoverable_feature_registry.hpp>
#include <uhdlib/features/fpga_load_notification_iface.hpp>
#include <uhdlib/utils/rpc.hpp>
#include <memory>

namespace uhd { namespace rfnoc {

/*! MPM-Specific version of the mb_controller
 *
 * Reminder: There is one of these per motherboard.
 *
 * This motherboard controller abstracts out a bunch of RPC calls.
 */
class mpmd_mb_controller : public mb_controller,
                           public ::uhd::features::discoverable_feature_registry
{
public:
    using sptr = std::shared_ptr<mpmd_mb_controller>;

    mpmd_mb_controller(uhd::usrp::mpmd_rpc_iface::sptr rpcc, uhd::device_addr_t device_info);

    //! Return reference to the RPC client
    uhd::rpc_client::sptr get_rpc_client()
    {
        return _rpc->get_raw_rpc_client();
    }

    template<typename T>
    std::shared_ptr<T> dynamic_cast_rpc_as()
    {
        return std::dynamic_pointer_cast<T>(_rpc);
    }

    /**************************************************************************
     * Timekeeper API
     *************************************************************************/
    //! MPM-specific version of the timekeeper controls
    //
    // MPM devices talk to MPM via RPC to control the timekeeper
    class mpmd_timekeeper : public mb_controller::timekeeper
    {
    public:
        using sptr = std::shared_ptr<mpmd_timekeeper>;

        mpmd_timekeeper(const size_t tk_idx, uhd::usrp::mpmd_rpc_iface::sptr rpc_client)
            : _tk_idx(tk_idx), _rpc(rpc_client)
        {
            // nop
        }

        uint64_t get_ticks_now() override;
        uint64_t get_ticks_last_pps() override;
        void set_ticks_now(const uint64_t ticks) override;
        void set_ticks_next_pps(const uint64_t ticks) override;
        void set_period(const uint64_t period_ns) override;

        /*! Update the tick rate
         *  Note: This is separate from set_tick_rate because the latter is
         *  protected, and we need to implement mpmd-specific functionality here
         */
        void update_tick_rate(const double tick_rate);

    private:
        const size_t _tk_idx;
        uhd::usrp::mpmd_rpc_iface::sptr _rpc;
    };

    /**************************************************************************
     * Motherboard Control API (see mb_controller.hpp)
     *************************************************************************/
    std::string get_mboard_name() const override;
    void set_time_source(const std::string& source) override;
    std::string get_time_source() const override;
    std::vector<std::string> get_time_sources() const override;
    void set_clock_source(const std::string& source) override;
    std::string get_clock_source() const override;
    std::vector<std::string> get_clock_sources() const override;
    void set_sync_source(
        const std::string& clock_source, const std::string& time_source) override;
    void set_sync_source(const uhd::device_addr_t& sync_source) override;
    uhd::device_addr_t get_sync_source() const override;
    std::vector<uhd::device_addr_t> get_sync_sources() override;
    void set_clock_source_out(const bool enb) override;
    void set_time_source_out(const bool enb) override;
    uhd::sensor_value_t get_sensor(const std::string& name) override;
    std::vector<std::string> get_sensor_names() override;
    uhd::usrp::mboard_eeprom_t get_eeprom() override;
    std::vector<std::string> get_gpio_banks() const override;
    std::vector<std::string> get_gpio_srcs(const std::string& bank) const override;
    std::vector<std::string> get_gpio_src(const std::string& bank) override;
    void set_gpio_src(
        const std::string& bank, const std::vector<std::string>& src) override;
    void register_sync_source_updater(
        mb_controller::sync_source_updater_t callback_f) override;

private:
    /**************************************************************************
     * Attributes
     *************************************************************************/
    //! Reference to RPC interface
    mutable uhd::usrp::mpmd_rpc_iface::sptr _rpc;

    uhd::device_addr_t _device_info;

    //! List of MB sensor names
    std::unordered_set<std::string> _sensor_names;

    //! Cache of available GPIO sources
    std::vector<std::string> _gpio_banks;
    std::unordered_map<std::string, std::vector<std::string>> _gpio_srcs;

    std::vector<mb_controller::sync_source_updater_t> _sync_source_updaters;

public:
    /*! When the FPGA is reloaded, pass the notification to every Radio block
     *  Public to allow other classes to register for notifications.
     */
    class fpga_onload : public uhd::features::fpga_load_notification_iface {
    public:
        using sptr = std::shared_ptr<fpga_onload>;

        fpga_onload();

        void onload() override;

        void request_cb(uhd::features::fpga_load_notification_iface::sptr handler);

    private:
        std::vector<std::weak_ptr<uhd::features::fpga_load_notification_iface>> _cbs;
    };

    //! Class to expose the ref_clk_calibration discoverable feature functions.
    class ref_clk_calibration : public uhd::features::ref_clk_calibration_iface {
    public:
        using sptr = std::shared_ptr<ref_clk_calibration>;

        ref_clk_calibration(uhd::usrp::mpmd_rpc_iface::sptr rpcc);

        void set_ref_clk_tuning_word(uint32_t tuning_word) override;
        uint32_t get_ref_clk_tuning_word() override;
        void store_ref_clk_tuning_word(uint32_t tuning_word) override;

    private:
        uhd::usrp::mpmd_rpc_iface::sptr _rpcc;
    };

    fpga_onload::sptr _fpga_onload;
    ref_clk_calibration::sptr _ref_clk_cal;
};

}} // namespace uhd::rfnoc