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
|
//
// Copyright 2021 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#pragma once
#include <uhdlib/usrp/common/rpc.hpp>
#include <uhdlib/usrp/cores/gpio_atr_3000.hpp>
#include <uhdlib/usrp/cores/gpio_port_mapper.hpp>
#include <vector>
namespace uhd { namespace rfnoc { namespace x400 {
// The name of the X400's GPIO bank
extern const char* GPIO_BANK_NAME;
class x400_gpio_port_mapping : public uhd::mapper::gpio_port_mapper
{
public:
x400_gpio_port_mapping(){};
virtual ~x400_gpio_port_mapping() = default;
uint32_t map_value(const uint32_t& value) override;
uint32_t unmap_value(const uint32_t& value) override;
};
/*! Abstract X400's GPIO control to match the "gpio_attr" control scheme.
*
* The front panel has two ports on it, labelled GPIO0 and GPIO1. The registers
* to control all of the GPIOs contain 24 bits, split between bit indices
* [31:16] and [11:0]. Additionally, the underlying radio control registers
* support a full 16-entry lookup table for the ATR state, with the 4 bits
* being a combination of the ATR state for the two channels. The classic
* "gpio_attr" control scheme only considers channels independently - i.e.,
* a single 4-entry lookup table for each channel. X400 supports this behaviour
* as well via the "classic ATR" switch, which this class uses.
*
* All of the public values are exposed as a single 24-bit wide field, [23:0]
*
* The data direction registers (DDR) have to be set in two places: Both in the
* internal radio control registers, as well as in MPM to configure the DIO
* board.
*/
class gpio_control
{
public:
using sptr = std::shared_ptr<gpio_control>;
/*! Constructs a gpio_control given the given offset. Assumes that the
* 16-table ATR entry begins at address 0x0 in \p iface.
*
* \param rpcc RPC object to talk to MPM
* \param iface wb_iface to talk to the radio registers
*/
gpio_control(uhd::usrp::x400_rpc_iface::sptr rpcc, wb_iface::sptr iface);
/*! Set the given GPIO attribute. See gpio_atr_3000 for details.
*/
void set_gpio_attr(const usrp::gpio_atr::gpio_attr_t attr, const uint32_t value);
/*! Get the given GPIO attribute. See gpio_atr_3000 for details.
*/
uint32_t get_gpio_attr(const usrp::gpio_atr::gpio_attr_t attr);
private:
/*! Convert from the internal FPGA pin mapping to the "DIO" mapping. This
* matches the "DIO_PORT_MAP" field in MPM's x4xx_periphs.py file.
*/
uint32_t unmap_dio(const uint32_t raw_form);
/*! Convert from the "DIO" mapping to the internal FPGA pin mapping. This
* matches the "DIO_PORT_MAP" field in MPM's x4xx_periphs.py file.
*/
uint32_t map_dio(const uint32_t user_form);
/*! Returns whether the given attribute is setting one of the ATR entries.
*/
static bool is_atr_attr(const usrp::gpio_atr::gpio_attr_t attr);
uhd::usrp::x400_rpc_iface::sptr _rpcc;
wb_iface::sptr _regs;
// There are two GPIOs, one for each channel. These two are set in unison.
std::vector<usrp::gpio_atr::gpio_atr_3000::sptr> _gpios;
x400_gpio_port_mapping _mapper;
};
}}} // namespace uhd::rfnoc::x400
|