aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/common/ad936x_manager.hpp
blob: 99464d0af6d2cb0929cbe4cf4a8601b67f209123 (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
//
// Copyright 2015 Ettus Research
//
// 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 <http://www.gnu.org/licenses/>.
//

#ifndef INCLUDED_AD9361_MANAGER_HPP
#define INCLUDED_AD9361_MANAGER_HPP

#include <uhd/types/wb_iface.hpp>
#include <uhd/utils/math.hpp>
#include <uhd/property_tree.hpp>
#include <uhd/types/direction.hpp>
#include <boost/format.hpp>
#include <boost/shared_ptr.hpp>
#include "ad9361_ctrl.hpp"
#include <stdint.h>

namespace uhd { namespace usrp {

/*! AD936x Manager class
 *
 * This class performs higher (management) tasks on the AD936x.
 * It requires a uhd::usrp::ad9361_ctrl object to do the actual
 * register peeks/pokes etc.
 */
class ad936x_manager
{
public:
    typedef boost::shared_ptr<ad936x_manager> sptr;

    static const double DEFAULT_GAIN;
    static const double DEFAULT_BANDWIDTH;
    static const double DEFAULT_TICK_RATE;
    static const double DEFAULT_FREQ; // Hz
    static const uint32_t DEFAULT_DECIM;
    static const uint32_t DEFAULT_INTERP;
    static const bool DEFAULT_AUTO_DC_OFFSET;
    static const bool DEFAULT_AUTO_IQ_BALANCE;
    static const bool DEFAULT_AGC_ENABLE;

    /*!
     * \param codec_ctrl The actual AD936x control object
     * \param n_frontends Number of frontends (1 or 2)
     */
    static sptr make(
            const ad9361_ctrl::sptr &codec_ctrl,
            const size_t n_frontends
    );

    virtual ~ad936x_manager(void) {};

    /*! Put the AD936x into a default state.
     *
     * Sets gains, LOs, bandwidths, etc. according to the DEFAULT_* constants.
     */
    virtual void init_codec(void) = 0;

    /*! Run a loopback self test.
     *
     * This will write data to the AD936x and read it back again.
     * If this test fails, it generally means the interface is broken,
     * so we assume it passes and throw otherwise. Running this requires
     * a core that we can peek and poke the loopback values into.
     *
     * \param iface An interface to the associated radio control core
     * \param iface The radio control core's address to write the loopback value
     * \param iface The radio control core's readback address to read back the returned value
     *
     * \throws a uhd::runtime_error if the loopback value didn't match.
     */
    virtual void loopback_self_test(
            boost::function<void(uint32_t)> poker_functor,
            boost::function<uint64_t()> peeker_functor
    ) = 0;

    /*! Determine a tick rate that will work with a given sampling rate
     *  (assuming a DDC/DUC chain is also available elsewhere).
     *
     * Example: If we want to stream with a rate of 5 Msps, then the AD936x
     * must run at an integer multiple of that. Although not strictly necessary,
     * we always try and return a multiple of 2. Let's say we need those 5 Msps
     * on two channels, then a good rate is 20 MHz, which is 4 times the sampling
     * rate (thus we can use 2 halfbands elsewhere).
     * If different rates are used on different channels, this can be particularly
     * useful. The clock rate of the AD936x needs to be a multiple of the least
     * common multiple of all the rates. Example: We want to transmit with 3 Msps
     * and receive with 5 Msps. The LCM of this is 15 Msps, which is used as an
     * argument for this function. A good rate is then 30 MHz, which is twice
     * the LCM.
     *
     * \param lcm_rate Least Common Multiple of all the rates involved.
     * \param num_chans The number of channels used for the stream.
     *
     * \returns a valid tick rate that can be used with the given rate
     * \throws a uhd::value_error if \p lcm_rate exceeds the max tick rate
     */
    virtual double get_auto_tick_rate(
            const double lcm_rate,
            size_t num_chans
    ) = 0;

    /*! Check if a given sampling rate is within the available analog bandwidth.
     *
     * If not, outputs a warning message and returns false.
     */
    virtual bool check_bandwidth(double rate, const std::string dir) = 0;

    /*! Populate the property tree for the device frontend
     */
    virtual void populate_frontend_subtree(
            uhd::property_tree::sptr subtree,
            const std::string &key,
            uhd::direction_t dir
    ) = 0;

}; /* class ad936x_manager */

}} /* namespace uhd::usrp */

#endif /* INCLUDED_AD9361_MANAGER_HPP */