aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp
blob: e5bb872166711e9f2b9855c35388fc1632954a3d (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
//
// Copyright 2017 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#include "magnesium_ad9371_iface.hpp"
#include "magnesium_constants.hpp"
#include <uhd/utils/log.hpp>

using namespace uhd;

namespace {
/*! Return a valid 'which' string for use with AD9371 API calls
 *
 * These strings take the form of "RX1", "TX2", ...
 */
std::string _get_which(const direction_t dir, const size_t chan)
{
    UHD_ASSERT_THROW(dir == RX_DIRECTION || dir == TX_DIRECTION);
    UHD_ASSERT_THROW(chan == 0 || chan == 1);
    return (dir == RX_DIRECTION ? "RX" : "TX") + std::to_string(chan + 1);
}

/*! Return a valid 'which' string for use with AD9371 API duplex calls
 *
 * Extends _get_which by additionally allowing duplex values
 */
std::string _get_which_duplex(const direction_t dir, const size_t chan)
{
    if (dir == RX_DIRECTION || dir == TX_DIRECTION) {
        return _get_which(dir, chan);
    }
    UHD_ASSERT_THROW(dir == DX_DIRECTION);
    UHD_ASSERT_THROW(chan == 0 || chan == 1);
    return "DX" + std::to_string(chan + 1);
}
} // namespace

/******************************************************************************
 * Structors
 *****************************************************************************/
magnesium_ad9371_iface::magnesium_ad9371_iface(
    uhd::rpc_client::sptr rpcc, const size_t slot_idx)
    : _rpcc(rpcc)
    , _rpc_prefix((slot_idx == 0) ? "db_0_" : "db_1_")
    , _log_prefix((slot_idx == 0) ? "AD9371-0" : "AD9371-1")
{
    UHD_LOG_TRACE(_log_prefix,
        "Initialized controls with RPC prefix " << _rpc_prefix << " for slot "
                                                << slot_idx);
}

double magnesium_ad9371_iface::set_frequency(
    const double freq, const size_t chan, const direction_t dir)
{
    // Note: This sets the frequency for both channels (1 and 2).
    auto which = _get_which(dir, chan);
    auto actual_freq =
        request<double>(MAGNESIUM_TUNE_TIMEOUT, "set_freq", which, freq, false);
    UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "set_freq returned " << actual_freq);
    return actual_freq;
}

double magnesium_ad9371_iface::set_gain(
    const double gain, const size_t chan, const direction_t dir)
{
    auto which  = _get_which(dir, chan);
    auto retval = request<double>("set_gain", which, gain);
    UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "set_gain returned " << retval);

    return retval;
    // return 0.0;
}

/*! brief Sets the frontend bandwidth settings for the dboard. Requires
 * re-initializing the dboard, so it may take a significant amount of time.
 *
 * \param bandwidth target rf bandwidth value
 * \param chan -not important- the bandwidth settings affect both channels on
 *        the dboard
 * \param dir specifies which path to set the bandwidth filters for. Supports
 *        rx, tx, or dx for both
 * \return actual rf bandwidth value
 */
double magnesium_ad9371_iface::set_bandwidth(
    const double bandwidth, const size_t chan, const direction_t dir)
{
    const auto which = _get_which_duplex(dir, chan);
    const auto retval =
        request<double>(MAGNESIUM_TUNE_TIMEOUT, "set_bandwidth", which, bandwidth);
    UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "set_bandwidth returned " << retval);
    return retval;
}

double magnesium_ad9371_iface::get_frequency(const size_t chan, const direction_t dir)
{
    auto which  = _get_which(dir, chan);
    auto retval = request<double>("get_freq", which);
    UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "get_freq returned " << retval);
    return retval;
}

double magnesium_ad9371_iface::get_gain(const size_t chan, const direction_t dir)
{
    auto which  = _get_which(dir, chan);
    auto retval = request<double>("get_gain", which);
    UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "get_gain returned " << retval);
    return retval;
}

double magnesium_ad9371_iface::get_bandwidth(const size_t chan, const direction_t dir)
{
    const auto which  = _get_which(dir, chan);
    const auto retval = request<double>("get_bandwidth", which);
    UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "get_bandwidth returned " << retval);
    return retval;
}

std::string magnesium_ad9371_iface::set_lo_source(
    const std::string& source, const uhd::direction_t dir)
{
    // There is only one LO for 2 channels. Using channel 0 for 'which'
    auto which  = _get_which(dir, 0);
    auto retval = request<std::string>("set_lo_source", which, source);
    UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "set_lo_source returned " << retval);
    return retval;
}

std::string magnesium_ad9371_iface::get_lo_source(const uhd::direction_t dir)
{
    // There is only one LO for 2 channels. Using channel 0 for 'which'
    auto which  = _get_which(dir, 0);
    auto retval = request<std::string>("get_lo_source", which);
    UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "get_lo_source returned " << retval);
    return retval;
}

void magnesium_ad9371_iface::set_fir(
    const std::string& name, const int8_t gain, const std::vector<int16_t>& coeffs)
{
    request<void>("set_fir", name, gain, coeffs);
}

std::pair<int8_t, std::vector<int16_t>> magnesium_ad9371_iface::get_fir(
    const std::string& name)
{
    return request<std::pair<int8_t, std::vector<int16_t>>>("get_fir", name);
}