Skip to content

Commit fd3f930

Browse files
committed
drivers: rf-transceiver: navassa: Added README for ADRV9001/2
Added the readme file for the ADRV9001 driver. Modified the sphinx drivers_doc.rst file to add the corresponding source. Signed-off-by: Joyce Velasco <joyce.velasco@analog.com>
1 parent be0e3e6 commit fd3f930

File tree

3 files changed

+321
-0
lines changed

3 files changed

+321
-0
lines changed

doc/sphinx/source/drivers/navassa.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.. include:: ../../../../drivers/rf-transceiver/navassa/README.rst

doc/sphinx/source/drivers_doc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ RF TRANSCEIVER
128128
:maxdepth: 1
129129

130130
drivers/madura
131+
drivers/navassa
131132

132133
drivers/talise
133134

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
ADRV9001 no-OS Driver
2+
=====================
3+
4+
Supported Devices
5+
-----------------
6+
7+
- `ADRV9002 <https://www.analog.com/en/products/adrv9002.html>`_
8+
9+
Overview
10+
--------
11+
12+
The ADRV9002 is a dual-mode RF transceiver supporting both narrow-band
13+
and wideband operations from 30 MHz to 6000 MHz, suitable for VHF, UHF,
14+
ISM, and cellular bands with bandwidths up to 40 MHz. It features dual
15+
transmitters and receivers, customizable synthesizers, and digital
16+
filters for improved performance. The transceiver supports TDD and FDD
17+
applications, offering high linearity and dynamic range, and includes
18+
capabilities such as low power monitoring, dynamic profile switching,
19+
rapid frequency hopping, and synchronization across multiple chips. In
20+
addition, several auxiliary functions, such as auxiliary
21+
analog-to-digital converters (ADCs), auxiliary digital-to-analog
22+
converters (DACs), and general-purpose inputs/outputs (GPIOs), are
23+
integrated to provide additional monitoring and control capability.
24+
25+
Applications
26+
------------
27+
28+
- Mission Critical Communications
29+
- Very High Frequency (VHF), Ultra High Frequency (UHF),
30+
and Cellular to 6 GHz
31+
- Time Division Duplex (TDD) and Frequency Division Duplex (FDD)
32+
Applications
33+
34+
Operation Modes
35+
---------------
36+
37+
+-------------------------+-------------------------+-----------------+-------------------------+
38+
| Mode Name | Description | Configuration | Typical Use |
39+
| | | Bits | Case |
40+
+-------------------------+-------------------------+-----------------+-------------------------+
41+
| ADI_ADRV9001_LDO_POWER | Sets all LDO power | 0x00 | Used during low-power |
42+
| _SAVING_MODE_1 | saving modes for the | | operations to save |
43+
| | device. | | power. |
44+
+-------------------------+-------------------------+-----------------+-------------------------+
45+
| ADI_ADRV9001_SPI_MODE | Allows operations | SPI | Used when direct |
46+
| | through the SPI | | control via SPI is |
47+
| | interface. | | required. |
48+
+-------------------------+-------------------------+-----------------+-------------------------+
49+
| ADI_ADRV9001_CHANNEL | State in which the | Channel Mask | Initial state for |
50+
| _PRIMED | channel is ready but | | channels in TDD mode. |
51+
| | not transmitting/ | | |
52+
| | receiving. | | |
53+
+-------------------------+-------------------------+-----------------+-------------------------+
54+
| ADI_ADRV9001_CHANNEL | State allowing full RF | N/A | Used in FDD mode for |
55+
| _RF_ENABLED | functionality. | | active transmission or |
56+
| | | | reception. |
57+
+-------------------------+-------------------------+-----------------+-------------------------+
58+
| ADI_ADRV9001_INT_LO1 | Uses internal LO1 for | LO1 | Standard operation with |
59+
| | operations. | Configuration | internal local |
60+
| | | | oscillator. |
61+
+-------------------------+-------------------------+-----------------+-------------------------+
62+
63+
Device Configuration
64+
--------------------
65+
66+
Initialization and Configuration
67+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68+
69+
The ADRV9002 initialization and configuration functions handle initial
70+
setup, ensuring optimal operation of the RF transceiver. Key functions
71+
like ``adrv9002_setup`` integrate device channels, configure GPIOs,
72+
manage power, and perform initial calibrations. These operations align
73+
the device parameters with application-specific requirements,
74+
facilitating effective device boot-up and functionality. Key operations
75+
include implementing error-handling routines throughout the
76+
initialization process to report and manage issues encountered, allowing
77+
for a robust configuration adaptable to numerous RF applications.
78+
79+
Transceiver Path Management
80+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
81+
82+
Transceiver path management functions in the ADRV9002 handle the
83+
configuration of RX and TX paths, adjusting gain, transmit power, and
84+
data interfaces to meet specific operation needs. For instance,
85+
``adrv9002_tx_path_config`` and ``adrv9001_rx_path_config`` set channel
86+
states and apply gain control settings through API calls. These
87+
functions ensure that the signal paths remain robust under various
88+
operational modes, such as TDD and FDD. They dynamically manage the
89+
transceiver’s performance metrics to maintain signal integrity aligned
90+
with predetermined operational conditions.
91+
92+
Frequency Hopping and Calibration
93+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94+
95+
These functions support dynamic frequency switching and system
96+
calibration tasks, vital for efficient multi-frequency operations. The
97+
frequency hopping is managed through modes and configurations set during
98+
initialization with precise timing requirements, allowing the ADRV9002
99+
to dynamically adapt its operating frequency to limit interference, as
100+
seen in frequency hopping functions that control PLL retunes and hop
101+
tables efficiently. Calibration routines like
102+
``adi_adrv9001_cals_InitCals_Run`` maintain performance by aligning
103+
internal parameters with environmental conditions and hardware states,
104+
offset by the frequency hopping capabilities.
105+
106+
Test Pattern and Performance Tuning
107+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108+
109+
Performance tuning functions for the ADRV9002 focus on validating and
110+
enhancing signal integrity through digital interface tuning and test
111+
pattern configurations. Functions like
112+
``adrv9002_axi_tx_test_pattern_set`` and
113+
``adrv9002_axi_rx_test_pattern_pn_sel`` set specific test patterns and
114+
perform interface tuning to optimize transmission and reception paths.
115+
These tasks involve iterative adjustments of clock and data delays,
116+
logging test results, and storing configurations, creating a refined
117+
tuning approach that ensures device operation at desired performance
118+
thresholds. Functions like ``adrv9002_check_tx_test_pattern`` further
119+
assess signal correctness, providing a comprehensive tuning suite.
120+
121+
Driver Initialization Example
122+
-----------------------------
123+
124+
.. code-block:: C
125+
126+
#include <stdio.h>
127+
#include "no_os_spi.h"
128+
#include "no_os_gpio.h"
129+
#include "no_os_error.h"
130+
#include "adrv9002.h"
131+
132+
int adrv9002_driver_init(void)
133+
{
134+
int ret;
135+
struct no_os_spi_init_param spi_init = {
136+
.device_id = XPAR_PS7_SPI_0_DEVICE_ID,
137+
.max_speed_hz = 20000000,
138+
.mode = NO_OS_SPI_MODE_0,
139+
.chip_select = 0,
140+
.platform_ops = &xil_spi_ops,
141+
};
142+
143+
struct no_os_gpio_init_param gpio_reset_init = {
144+
.number = 46 + GPIO_OFFSET,
145+
.platform_ops = &xil_gpio_ops,
146+
};
147+
148+
struct no_os_gpio_desc *gpio_reset;
149+
struct no_os_spi_desc *spi_desc;
150+
151+
/* Initialize GPIO for reset */
152+
ret = no_os_gpio_get(&gpio_reset, &gpio_reset_init);
153+
if (ret) {
154+
printf("GPIO initialization failed\n");
155+
return ret;
156+
}
157+
158+
ret = no_os_gpio_direction_output(gpio_reset, NO_OS_GPIO_LOW);
159+
if (ret) {
160+
printf("GPIO direction set failed\n");
161+
no_os_gpio_remove(gpio_reset);
162+
return ret;
163+
}
164+
165+
/* Initialize SPI */
166+
ret = no_os_spi_init(&spi_desc, &spi_init);
167+
if (ret) {
168+
printf("SPI initialization failed\n");
169+
no_os_gpio_remove(gpio_reset);
170+
return ret;
171+
}
172+
173+
/* Reset the device */
174+
ret = no_os_gpio_set_value(gpio_reset, NO_OS_GPIO_HIGH);
175+
if (ret) {
176+
printf("GPIO set value failed\n");
177+
no_os_spi_remove(spi_desc);
178+
no_os_gpio_remove(gpio_reset);
179+
return ret;
180+
}
181+
182+
/* Call additional initialization/configuration functions */
183+
ret = adrv9002_setup(spi_desc);
184+
if (ret) {
185+
printf("adrv9002_setup failed\n");
186+
no_os_spi_remove(spi_desc);
187+
no_os_gpio_remove(gpio_reset);
188+
return ret;
189+
}
190+
191+
ret = adrv9002_tx_path_config(spi_desc);
192+
if (ret) {
193+
printf("adrv9002_tx_path_config failed\n");
194+
no_os_spi_remove(spi_desc);
195+
no_os_gpio_remove(gpio_reset);
196+
return ret;
197+
}
198+
199+
printf("Driver initialization complete\n");
200+
201+
/* Cleanup */
202+
no_os_spi_remove(spi_desc);
203+
no_os_gpio_remove(gpio_reset);
204+
205+
return 0;
206+
}
207+
208+
IIO Device Initialization Example
209+
---------------------------------
210+
211+
.. code-block:: C
212+
213+
static uint8_t adc_buffers[IIO_DEV_COUNT][1024];
214+
static uint8_t dac_buffers[IIO_DEV_COUNT][1024];
215+
216+
struct {
217+
struct axi_dmac *tx1_dmac;
218+
struct axi_dmac *rx1_dmac;
219+
} phy;
220+
221+
static int32_t iio_run(struct iio_axi_adc_init_param *adc_pars,
222+
struct iio_axi_dac_init_param *dac_pars)
223+
{
224+
struct iio_axi_adc_desc *adcs[IIO_DEV_COUNT];
225+
struct iio_axi_dac_desc *dacs[IIO_DEV_COUNT];
226+
struct iio_data_buffer iio_dac_buffers[IIO_DEV_COUNT];
227+
struct iio_data_buffer iio_adc_buffers[IIO_DEV_COUNT];
228+
struct iio_device *iio_descs[IIO_DEV_COUNT * 2];
229+
struct iio_app_device app_devices[IIO_DEV_COUNT * 2] = {0};
230+
struct xil_uart_init_param platform_uart_init_par = {
231+
.type = UART_PS,
232+
.irq_id = UART_IRQ_ID
233+
};
234+
struct no_os_uart_init_param iio_uart_ip = {
235+
.device_id = UART_DEVICE_ID,
236+
.irq_id = UART_IRQ_ID,
237+
.baud_rate = UART_BAUDRATE,
238+
.size = NO_OS_UART_CS_8,
239+
.parity = NO_OS_UART_PAR_NO,
240+
.stop = NO_OS_UART_STOP_1_BIT,
241+
.extra = &platform_uart_init_par,
242+
.platform_ops = &xil_uart_ops
243+
};
244+
struct iio_app_desc *app;
245+
struct iio_app_init_param app_init_param = { 0 };
246+
int32_t ret;
247+
248+
for (int i = 0; i < IIO_DEV_COUNT; i++) {
249+
/* Initialize ADC */
250+
iio_adc_buffers[i].buff = adc_buffers[i];
251+
iio_adc_buffers[i].size = sizeof(adc_buffers[i]);
252+
253+
ret = iio_axi_adc_init(&adcs[i], &adc_pars[i]);
254+
if (ret < 0)
255+
goto error;
256+
257+
int a = 2 * i;
258+
iio_axi_adc_get_dev_descriptor(adcs[i], &iio_descs[a]);
259+
app_devices[a].name = (char *)adc_pars[i].rx_adc->name;
260+
app_devices[a].dev = adcs[i];
261+
app_devices[a].dev_descriptor = iio_descs[a];
262+
app_devices[a].read_buff = &iio_adc_buffers[i];
263+
264+
/* Initialize DAC */
265+
iio_dac_buffers[i].buff = dac_buffers[i];
266+
iio_dac_buffers[i].size = sizeof(dac_buffers[i]);
267+
268+
ret = iio_axi_dac_init(&dacs[i], &dac_pars[i]);
269+
if (ret < 0)
270+
goto error;
271+
272+
a = 2 * i + 1;
273+
iio_axi_dac_get_dev_descriptor(dacs[i], &iio_descs[a]);
274+
app_devices[a].name = (char *)dac_pars[i].tx_dac->name;
275+
app_devices[a].dev = dacs[i];
276+
app_devices[a].dev_descriptor = iio_descs[a];
277+
app_devices[a].write_buff = &iio_dac_buffers[i];
278+
}
279+
280+
struct axi_dmac_init rx1_dmac_init = {
281+
"rx_dmac",
282+
RX1_DMA_BASEADDR,
283+
IRQ_DISABLED
284+
};
285+
286+
struct axi_dmac_init tx1_dmac_init = {
287+
"tx_dmac",
288+
TX1_DMA_BASEADDR,
289+
IRQ_DISABLED
290+
};
291+
292+
/* Initialize DMA Controllers */
293+
ret = axi_dmac_init(&phy.tx1_dmac, &tx1_dmac_init);
294+
if (ret) {
295+
printf("axi_dmac_init(tx) failed with status %d\n", ret);
296+
goto error;
297+
}
298+
299+
ret = axi_dmac_init(&phy.rx1_dmac, &rx1_dmac_init);
300+
if (ret) {
301+
printf("axi_dmac_init(rx) failed with status %d\n", ret);
302+
goto error;
303+
}
304+
305+
/* Initialize IIO application */
306+
app_init_param.devices = app_devices;
307+
app_init_param.nb_devices = NO_OS_ARRAY_SIZE(app_devices);
308+
app_init_param.uart_init_params = iio_uart_ip;
309+
310+
ret = iio_app_init(&app, app_init_param);
311+
if (ret)
312+
goto error;
313+
314+
return iio_app_run(app);
315+
316+
error:
317+
printf("iio_run() failed with status %d\n", ret);
318+
return ret;
319+
}

0 commit comments

Comments
 (0)