Skip to content

Commit 4d22158

Browse files
committed
wireless/lpwan/rn2xx3: Add documentation for RN2XX3 programming
interface and new WLIOC commands. Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
1 parent bc0c9f2 commit 4d22158

File tree

2 files changed

+363
-0
lines changed

2 files changed

+363
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
================
22
Wireless Drivers
33
================
4+
5+
.. toctree::
6+
:glob:
7+
:maxdepth: 1
8+
:titlesonly:
9+
:caption: Contents
10+
11+
./wireless/*
Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
======
2+
RN2XX3
3+
======
4+
5+
This driver provides support for the RN2XX3 family of LoRa radio transceivers by
6+
Microchip. This includes both the RN2903 and RN2483 modules.
7+
8+
.. warning::
9+
This driver only contains preliminary support for a few 'radio set' commands
10+
and raw radio transmit/receive. There is no support for the LoRaWAN stack
11+
yet. IT IS EXPERIMENTAL.
12+
13+
Application Programming Interface
14+
=================================
15+
16+
To register the device for use, you will need to enable the standard upper half
17+
serial drivers (``CONFIG_STANDARD_SERIAL``), since the RN2XX3 driver requires
18+
the path to the UART interface the module is connected to.
19+
20+
You will also need to ensure that the baud rate of the UART interface is set to
21+
57600, which is the baud rate of the RN2XX3.
22+
23+
At registration time, the driver will automatically determine if the device is
24+
the RN2903 or RN2483.
25+
26+
.. code-block:: c
27+
28+
#include <nuttx/wireless/lpwan/rn2xx3.h>
29+
30+
#ifdef CONFIG_LPWAN_RN2XX3
31+
32+
/* Register the RN2XX3 device driver */
33+
34+
ret = rn2xx3_register("/dev/rn2903", "/dev/ttyS1");
35+
if (ret < 0) {
36+
syslog(LOG_ERR, "Failed to register RN2XX3 device driver: %d\n", ret);
37+
}
38+
#endif
39+
40+
This driver uses the standard POSIX character device interface, implementing
41+
``read()``, ``write()`` and ``ioctl()``.
42+
43+
To transmit, the ``write()`` function can be used. Bytes in the provided buffer
44+
will be transmitted as a packet. This has the following behaviour:
45+
46+
* If the radio is in FSK modulation mode, packets will only contain up to 64
47+
bytes. A buffer of more than 64 bytes will only have 64 bytes transmitted.
48+
* If the radio is in LoRa modulation mode, packets will only contain up to 255
49+
bytes.
50+
* If the buffer contains less than the current packet size limit (64 or 255
51+
bytes), its contents will be transmitted as a single packet.
52+
53+
.. code-block:: c
54+
55+
int radio = open("/dev/rn2903", O_RDWR);
56+
if (radio < 0)
57+
{
58+
fprintf(stderr, "Couldn't open radio: %d\n", errno);
59+
return -1;
60+
}
61+
62+
char message[] = "Hello, world!";
63+
ssize_t b_sent = write(radio, message, sizeof(message));
64+
if (b_sent < 0)
65+
{
66+
fprintf(stderr, "Couldn't transmit: %d\n", errno);
67+
return -1;
68+
}
69+
70+
To receive, the ``read()`` function can be used. As much of the received packet
71+
as possible will be stored in the user buffer. This has the following behaviour:
72+
73+
* If the buffer is too small to contain the full received packet, as much of the
74+
packet as possible will be stored in the buffer.
75+
* When the packet is fully read, ``read()`` will return ``0``.
76+
* If only part of the packet has been read and a call to ``write()`` or
77+
``ioctl()`` is made, the remainder of the packet is discarded.
78+
79+
.. code-block:: c
80+
81+
int radio = open("/dev/rn2903", O_RDWR);
82+
if (radio < 0)
83+
{
84+
fprintf(stderr, "Couldn't open radio: %d\n", errno);
85+
return -1;
86+
}
87+
88+
char buffer[16];
89+
ssize_t b_read;
90+
91+
do {
92+
b_read = read(radio, buffer, sizeof(buffer));
93+
if (b_read < 0)
94+
{
95+
fprintf(stderr, "Couldn't receive: %d\n", errno);
96+
return -1;
97+
}
98+
write(0, buffer, b_read); /* Print received bytes to stdout */
99+
} while (b_read != 0);
100+
101+
Finally, the ``ioctl()`` interface provides access to some underlying module
102+
commands.
103+
104+
``WLIOC_GETSNR``
105+
----------------
106+
107+
Gets the signal to noise ration of the last received packet. If no packets have
108+
been received, it will default to -128. Argument is a pointer to an ``int8_t``.
109+
110+
.. code-block:: c
111+
112+
int8_t snr;
113+
err = ioctl(radio, WLIOC_GETSNR, &snr);
114+
115+
``WLIOC_SETRADIOFREQ``
116+
----------------------
117+
118+
Sets the operating frequency of the radio module. The argument is the desired
119+
frequency in Hz (``uint32_t``).
120+
121+
.. code-block:: c
122+
123+
err = ioctl(radio, WLIOC_SETRADIOFREQ, 902400000);
124+
125+
``WLIOC_GETRADIOFREQ``
126+
----------------------
127+
128+
Gets the current operating frequency of the radio module in Hz. The argument is
129+
a pointer to a ``uint32_t``.
130+
131+
.. code-block:: c
132+
133+
uint32_t freq;
134+
err = ioctl(radio, WLIOC_GETRADIOFREQ, &freq);
135+
136+
``WLIOC_SETTXPOWERF``
137+
---------------------
138+
139+
Sets the transmission power of the radio. Argument is a pointer to a ``int32_t``
140+
containing the desired transmission power in 0.01 dBm. After setting the
141+
transmission power successfully, this pointer will contain the new transmission
142+
power. This value may be different from the desired value, but will be the
143+
closest available setting that is greater than or equal to the desired value.
144+
145+
.. code-block:: c
146+
147+
int32_t txpower = 1200;
148+
err = ioctl(radio, WLIOC_SETTXPOWERF, &txpower);
149+
printf("Actual TX power: %.2f dBm\n", txpower / 100.0f);
150+
151+
``WLIOC_GETTXPOWERF``
152+
---------------------
153+
154+
Gets the current transmission power level in 0.01 dBm. The argument is a pointer
155+
to a ``int32_t``.
156+
157+
.. code-block:: c
158+
159+
int32_t txpwr;
160+
err = ioctl(radio, WLIOC_GETTXPOWER, &txpwr);
161+
162+
``WLIOC_SETBANDWIDTH``
163+
----------------------
164+
165+
Sets the operating bandwidth of the radio module. The argument is the desired
166+
bandwidth in kHz (``uint32_t``). The radio only supports exact values of 125,
167+
250 and 500.
168+
169+
.. code-block:: c
170+
171+
err = ioctl(radio, WLIOC_SETBANDWIDTH, 250);
172+
173+
``WLIOC_GETBANDWIDTH``
174+
----------------------
175+
176+
Gets the current operating bandwidth of the radio module in kHz. The argument is
177+
a pointer to a ``uint32_t``.
178+
179+
.. code-block:: c
180+
181+
uint32_t bandwidth;
182+
err = ioctl(radio, WLIOC_GETBANDWIDTH, &bandwidth);
183+
184+
``WLIOC_SETSPREAD``
185+
----------------------
186+
187+
Sets the operating spread factor of the radio module. The argument is a
188+
``uint8_t`` containing the desired spread factor between 7 and 12 (inclusive).
189+
190+
.. code-block:: c
191+
192+
err = ioctl(radio, WLIOC_SETSPREAD, 8);
193+
194+
``WLIOC_GETSPREAD``
195+
----------------------
196+
197+
Gets the current operating spread factor of the radio module. The argument is a
198+
pointer to a ``uint8_t``.
199+
200+
.. code-block:: c
201+
202+
uint8_t spread;
203+
err = ioctl(radio, WLIOC_GETSPREAD, &spread);
204+
205+
``WLIOC_SETPRLEN``
206+
----------------------
207+
208+
Sets the operating preamble length of the radio module. The argument is a
209+
``uint16_t`` containing the desired preamble length.
210+
211+
.. code-block:: c
212+
213+
err = ioctl(radio, WLIOC_SETPRLEN, 8);
214+
215+
``WLIOC_GETPRLEN``
216+
----------------------
217+
218+
Gets the current operating preamble length of the radio module. The argument is
219+
a pointer to a ``uint16_t``.
220+
221+
.. code-block:: c
222+
223+
uint16_t prlen;
224+
err = ioctl(radio, WLIOC_GETPRLEN, &prlen);
225+
226+
``WLIOC_SETMOD``
227+
----------------------
228+
229+
Sets the operating modulation of the radio module. The argument is one of the
230+
values in ``enum rn2xx3_mod_e``.
231+
232+
.. code-block:: c
233+
234+
err = ioctl(radio, WLIOC_SETMOD, RN2XX3_MOD_FSK);
235+
236+
``WLIOC_GETMOD``
237+
----------------------
238+
239+
Gets the current operating modulation of the radio module. The argument is a
240+
pointer to an ``enum rn2xx3_mod_e``.
241+
242+
.. code-block:: c
243+
244+
enum rn2xx3_mod_e modulation;
245+
err = ioctl(radio, WLIOC_GETMOD, &modulation);
246+
if (modulation == RN2XX3_MOD_LORA)
247+
{
248+
printf("LoRa modulation!\n");
249+
}
250+
251+
``WLIOC_RESET``
252+
---------------
253+
254+
Resets the RN2xx3 radio module. This command takes no arguments.
255+
256+
.. code-block:: c
257+
258+
err = ioctl(radio, WLIOC_RESET, 0);
259+
260+
``WLIOC_SETSYNC``
261+
-----------------
262+
263+
Sets the sync word parameter of the RN2xx3 module. The argument is a pointer to
264+
a ``uint64_t``. Please note that when operating using FSK modulation, the sync
265+
word can be a full 8 bytes (64 bits), but LoRa modulation only accepts a single
266+
byte sync word.
267+
268+
.. code-block:: c
269+
270+
/* Radio in FSK mode prior to this call */
271+
272+
uint64_t syncword = 0xdeadbeefdeadbeef;
273+
err = ioctl(radio, WLIOC_SETSYNC, &syncword);
274+
275+
``WLIOC_GETSYNC``
276+
-----------------
277+
278+
Gets the sync word parameter of the RN2xx3 module. The argument is a pointer to
279+
a ``uint64_t``.
280+
281+
.. code-block:: c
282+
283+
uint64_t syncword;
284+
err = ioctl(radio, WLIOC_GETSYNC, &syncword);
285+
286+
``WLIOC_SETBITRATE``
287+
--------------------
288+
289+
Sets the bit rate of the RN2xx3 module. The argument is a ``uint32_t``. The
290+
bit rate only applies to the module when it is in FSK modulation mode, and it
291+
must be between 1 - 300000.
292+
293+
.. code-block:: c
294+
295+
/* Radio in FSK mode prior to this call */
296+
297+
err = ioctl(radio, WLIOC_SETBITRATE, 300000);
298+
299+
``WLIOC_GETBITRATE``
300+
--------------------
301+
302+
Gets the configured bit rate of the RN2xx3 module. The argument is a pointer to
303+
a ``uint32_t``.
304+
305+
.. code-block:: c
306+
307+
uint32_t bitrate;
308+
err = ioctl(radio, WLIOC_GETBITRATE, &bitrate);
309+
310+
``WLIOC_IQIEN``
311+
---------------
312+
313+
Enables the invert IQ functionality of the module. The argument is boolean of
314+
either true (non-zero) or false (zero).
315+
316+
.. code-block:: c
317+
318+
/* Enables IQI */
319+
320+
err = ioctl(radio, WLIOC_IQIEN, 1);
321+
322+
``WLIOC_CRCEN``
323+
---------------
324+
325+
Enables adding a CRC header to packets. The argument is a boolean of either true
326+
(non-zero) or false (zero).
327+
328+
.. code-block:: c
329+
330+
/* Enables CRC */
331+
332+
err = ioctl(radio, WLIOC_CRCEN, 1);
333+
334+
``WLIOC_SETCODERATE``
335+
---------------------
336+
337+
Sets the coding rate of the RN2xx3 module. The argument is one of the values in
338+
``enum rn2xx3_cr_e``.
339+
340+
.. code-block:: c
341+
342+
/* Sets 4/7 coding rate */
343+
344+
err = ioctl(radio, WLIOC_SETCODERATE, RN2XX3_CR_4_7);
345+
346+
``WLIOC_GETCODERATE``
347+
---------------------
348+
349+
Gets the currently configured coding rate of the RN2xx3 module. The argument is
350+
a pointer to an ``enum rn2xx3_cr_e``.
351+
352+
.. code-block:: c
353+
354+
enum rn2xx3_cr_e coderate;
355+
err = ioctl(radio, WLIOC_GETCODERATE, &coderate);

0 commit comments

Comments
 (0)