aboutsummaryrefslogtreecommitdiffstats
path: root/host/docs/gpio_api.dox
blob: d3bb4f0a99a8396b742b219dd4da125d6a7f4760 (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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*! \page page_gpio_api E3x0/X3x0 GPIO API

\tableofcontents

\section xgpio_fpanel The E3x0/X3x0 Front Panel GPIO

The E3x0/X3x0 are the first USRP devices to offer an auxiliary GPIO connection
on the motherboard itself (independent of the daughterboards). These
GPIO pins are controlled directly by the FPGA, where they are controlled
by an ATR (Automatic Transmit / Receive). This allows them to be toggled
simultaneously with other radio-level changes (e.g., enabling or
disabling a TX or RX mixer).

\subsection xgpio_fpanel_gpio X3x0 Front Panel GPIO

\subsubsection xgpio_fpanel_conn Connector

\image html x3x0_gpio_conn.png "X3x0 GPIO Connectors"

\subsubsection xgpio_fpanel_pins Pin Mapping

-   Pin 1: +3.3V
-   Pin 2: Data[0]
-   Pin 3: Data[1]
-   Pin 4: Data[2]
-   Pin 5: Data[3]
-   Pin 6: Data[4]
-   Pin 7: Data[5]
-   Pin 8: Data[6]
-   Pin 9: Data[7]
-   Pin 10: Data[8]
-   Pin 11: Data[9]
-   Pin 12: Data[10]
-   Pin 13: Data[11]
-   Pin 14: 0V
-   Pin 15: 0V

\subsection egpio_internal_gpio E3x0 Internal GPIO

\subsubsection egpio_internal_conn Connector

\image html e3x0_gpio_conn.png "E3x0 GPIO Connector"

### Pin Mapping

- Pin 1:   +3.3V
- Pin 2:   Reserved
- Pin 3:   Data[5]
- Pin 4:   Reserved
- Pin 5:   Data[4]
- Pin 6:   Data[0]
- Pin 7:   Data[3]
- Pin 8:   Data[1]
- Pin 9:   0V
- Pin 10:  Data[2]


\subsection xgpio_fpanel_atr Explaining ATR

ATR works by defining the value of the GPIO pins for certain states of
the radio. This is the "automatic" part of it. For example, you can tell
UHD that when the radio is transmitting and receiving (full duplex),
GPIO6 should be high, but when it is only transmitting, GPI06 should be
low. This state machine is set up using a series of GPIO attributes,
with paired values and a mask, which you will want to define for the
GPIO pins you intend to use. To set up the ATR, you use uhd::usrp::multi_usrp::set_gpio_attr().

-   **CTRL**: Is this pin controlled by ATR (automatic), or by manual
    control only?
-   **DDR**: "Data Direction Register" - defines whether or not a GPIO
    is an output or an input.
-   **OUT**: Manually set the value of a pin (only to be used in non-ATR
    mode).
-   **ATR_0X**: The status of the pins when the radio is **idle**.
-   **ATR_RX**: The status of the pins when the radio is only
    **receiving**.
-   **ATR_TX**: The status of the pins when the radio is only
    **transmitting**.
-   **ATR_XX**: The status of the pins when the radio is in
    **full-duplex** mode.

The counterpart to setting the ATR (the "getter"), is called
uhd::usrp::multi_usrp::get_gpio_attr().
t has the exact same attributes as above, and has
one more:

-   **READBACK**: Readback the GPIOs marked as inputs.

\subsection xgpio_fpanel_xample An Example

The front panel X3x0 GPIO bank is enumerated in the motherboard property
tree (`<mb_path>/gpio/FP0/\*`), the E3x0 internal GPIO bank as (`<mb_path>/gpio/INT0/\`) and so are easily accessible through
the standard uhd::usrp::multi_usrp UHD interface.

You can discover this using the uhd::usrp::multi_usrp::get_gpio_banks() function.
This will tell you that there is a GPIO bank on your
X3x0 called "FP0" (for E3x0 this will be called "INT0"). This is the bank we want to set-up.

Let's say we want to use GPIO6 for an external amp. We want it to be
automatically controlled by ATR as an output, and we want it to be high
when we are transmitting, and low in all other cases. We are also using
GPIO4, which we want to control manually, as an output. We can set this
up with the following code:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
    // set up our masks, defining the pin numbers
    #define AMP_GPIO_MASK   (1 << 6)
    #define MAN_GPIO_MASK   (1 << 4)

    #define ATR_MASKS       (AMP_GPIO_MASK | MAN_GPIO_MASK)

    // set up our values for ATR control: 1 for ATR, 0 for manual
    #define ATR_CONTROL     (AMP_GPIO_MASK & ~MAN_GPIO_MASK)

    // set up the GPIO directions: 1 for output, 0 for input
    #define GPIO_DDR        (AMP_GPIO_MASK & ~MAN_GPIO_MASK)

    // assume an existing USRP device handle, called "usrp_x300"

    // now, let's do the basic ATR setup
    usrp_x300->set_gpio_attr("FP0", "CTRL", ATR_CONTROL, ATR_MASKS);
    usrp_x300->set_gpio_attr("FP0", "DDR", GPIO_DDR, ATR_MASKS);

    // let's manually set GPIO4 high
    usrp_x300->set_gpio_attr("FP0", "OUT", 1, MAN_GPIO_MASK);

    // finally, let's set up GPIO6 as we described above
    usrp_x300->set_gpio_attr("FP0", "ATR_0X", 0, AMP_GPIO_MASK);
    usrp_x300->set_gpio_attr("FP0", "ATR_RX", 0, AMP_GPIO_MASK);
    usrp_x300->set_gpio_attr("FP0", "ATR_TX", 0, AMP_GPIO_MASK);
    usrp_x300->set_gpio_attr("FP0", "ATR_XX", 0, AMP_GPIO_MASK);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After the above code is run, the ATR in the FPGA will automatically
control GPIO6, as we have described, based on the radio state, and we
have direct manual control over GPIO4.

The following example has been modified to work with he E3x0's internal
GPIO bank, where the controlled GPIO is now GPIO3 instead of GPIO6.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
    // set up our masks, defining the pin numbers
    #define AMP_GPIO_MASK   (1 << 3)
    #define MAN_GPIO_MASK   (1 << 4)

    #define ATR_MASKS       (AMP_GPIO_MASK | MAN_GPIO_MASK)

    // set up our values for ATR control: 1 for ATR, 0 for manual
    #define ATR_CONTROL     (AMP_GPIO_MASK & ~MAN_GPIO_MASK)

    // set up the GPIO directions: 1 for output, 0 for input
    #define GPIO_DDR        (AMP_GPIO_MASK & ~MAN_GPIO_MASK)

    // assume an existing USRP device handle, called "usrp_e300"

    // now, let's do the basic ATR setup
    usrp_e300->set_gpio_attr("INT0", "CTRL", ATR_CONTROL, ATR_MASKS);
    usrp_e300->set_gpio_attr("INT0", "DDR", GPIO_DDR, ATR_MASKS);

    // let's manually set GPIO4 high
    usrp_e300->set_gpio_attr("INT0", "OUT", (1 << 4), MAN_GPIO_MASK);

    // finally, let's set up GPIO6 as we described above
    usrp_e300->set_gpio_attr("INT0", "ATR_0X", 0, AMP_GPIO_MASK);
    usrp_e300->set_gpio_attr("INT0", "ATR_RX", 0, AMP_GPIO_MASK);
    usrp_e300->set_gpio_attr("INT0", "ATR_TX", 0, AMP_GPIO_MASK);
    usrp_e300->set_gpio_attr("INT0", "ATR_XX", 0, AMP_GPIO_MASK);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After the above code is run, the ATR in the FPGA will automatically
control GPIO3, as we have described, based on the radio state, and we
have direct manual control over GPIO4.


*/
// vim:ft=doxygen: