|
| 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