Line data Source code
1 : #if !defined(_RADIOLIB_MODULE_H)
2 : #define _RADIOLIB_MODULE_H
3 :
4 : #include "TypeDef.h"
5 : #include "Hal.h"
6 : #include "utils/Utils.h"
7 :
8 : #if defined(RADIOLIB_BUILD_ARDUINO)
9 : #include <SPI.h>
10 : #endif
11 :
12 : /*!
13 : \def END_OF_MODE_TABLE Value to use as the last element in a mode table to indicate the
14 : end of the table. See \ref setRfSwitchTable for details.
15 : */
16 : #define END_OF_MODE_TABLE { Module::MODE_END_OF_TABLE, {} }
17 :
18 : /*!
19 : \def RFSWITCH_PIN_FLAG Bit flag used to mark unused pins in RF switch pin map. This can be either
20 : unconnected pin marked with RADIOLIB_NC, or a pin controlled by the radio (e.g. DIOx pins on LR11x0),
21 : as opposed to an MCU-controlled GPIO pin.
22 : */
23 : #define RFSWITCH_PIN_FLAG (0x01UL << 31)
24 :
25 : /*!
26 : \defgroup module_spi_command_pos Position of commands in Module::spiConfig command array.
27 : \{
28 : */
29 :
30 : /*! \def RADIOLIB_MODULE_SPI_COMMAND_READ Position of the read command. */
31 : #define RADIOLIB_MODULE_SPI_COMMAND_READ (0)
32 :
33 : /*! \def RADIOLIB_MODULE_SPI_COMMAND_WRITE Position of the write command. */
34 : #define RADIOLIB_MODULE_SPI_COMMAND_WRITE (1)
35 :
36 : /*! \def RADIOLIB_MODULE_SPI_COMMAND_NOP Position of the no-operation command. */
37 : #define RADIOLIB_MODULE_SPI_COMMAND_NOP (2)
38 :
39 : /*! \def RADIOLIB_MODULE_SPI_COMMAND_STATUS Position of the status command. */
40 : #define RADIOLIB_MODULE_SPI_COMMAND_STATUS (3)
41 :
42 : /*!
43 : \}
44 : */
45 :
46 : /*!
47 : \defgroup module_spi_width_pos Position of bit field widths in Module::spiConfig width array.
48 : \{
49 : */
50 :
51 : /*! \def RADIOLIB_MODULE_SPI_WIDTH_ADDR Position of the address width. */
52 : #define RADIOLIB_MODULE_SPI_WIDTH_ADDR (0)
53 :
54 : /*! \def RADIOLIB_MODULE_SPI_WIDTH_CMD Position of the command width. */
55 : #define RADIOLIB_MODULE_SPI_WIDTH_CMD (1)
56 :
57 : /*! \def RADIOLIB_MODULE_SPI_WIDTH_STATUS Position of the status width. */
58 : #define RADIOLIB_MODULE_SPI_WIDTH_STATUS (2)
59 :
60 : /*!
61 : \}
62 : */
63 :
64 : /*!
65 : \class Module
66 : \brief Implements all common low-level methods to control the wireless module.
67 : Every module class contains one private instance of this class.
68 : */
69 : class Module {
70 : public:
71 : /*!
72 : \brief The maximum number of pins supported by the RF switch code.
73 : Note: It is not recommended to use this constant in your sketch
74 : when defining a rfswitch pins array, to prevent issues when this
75 : value is ever increased and such an array gets extra zero
76 : elements (that will be interpreted as pin 0).
77 : */
78 : static const size_t RFSWITCH_MAX_PINS = 5;
79 :
80 : /*!
81 : \struct RfSwitchMode_t
82 : \brief Description of RF switch pin states for a single mode.
83 : See \ref setRfSwitchTable for details.
84 : */
85 : struct RfSwitchMode_t {
86 : /*! \brief RF switching mode, one of \ref OpMode_t or a custom radio-defined value. */
87 : uint8_t mode;
88 :
89 : /*! \brief Output pin values */
90 : uint32_t values[RFSWITCH_MAX_PINS];
91 : };
92 :
93 : /*!
94 : \enum OpMode_t
95 : \brief Constants to use in a mode table set be setRfSwitchTable. These
96 : constants work for most radios, but some radios define their own
97 : constants to be used instead.
98 :
99 : See \ref setRfSwitchTable for details.
100 : */
101 : enum OpMode_t {
102 : /*!
103 : \brief End of table marker, use \ref END_OF_MODE_TABLE constant instead.
104 : Value is zero to ensure zero-initialized mode ends the table.
105 : */
106 : MODE_END_OF_TABLE = 0,
107 :
108 : /*! \brief Idle mode */
109 : MODE_IDLE,
110 :
111 : /*! \brief Receive mode */
112 : MODE_RX,
113 :
114 : /*! \brief Transmission mode */
115 : MODE_TX,
116 : };
117 :
118 : #if defined(RADIOLIB_BUILD_ARDUINO)
119 : /*!
120 : \brief Arduino Module constructor. Will use the default SPI interface and automatically initialize it.
121 : \param cs Arduino pin to be used as chip select.
122 : \param irq Arduino pin to be used as interrupt/GPIO.
123 : \param rst Arduino pin to be used as hardware reset for the module.
124 : \param gpio Arduino pin to be used as additional interrupt/GPIO.
125 : */
126 : Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio = RADIOLIB_NC);
127 :
128 : /*!
129 : \brief Arduino Module constructor. Will not attempt SPI interface initialization.
130 : \param cs Arduino pin to be used as chip select.
131 : \param irq Arduino pin to be used as interrupt/GPIO.
132 : \param rst Arduino pin to be used as hardware reset for the module.
133 : \param gpio Arduino pin to be used as additional interrupt/GPIO.
134 : \param spi SPI interface to be used, can also use software SPI implementations.
135 : \param spiSettings SPI interface settings.
136 : */
137 : Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio, SPIClass& spi, SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS);
138 : #endif
139 :
140 : /*!
141 : \brief Module constructor.
142 : \param hal A Hardware abstraction layer instance. An ArduinoHal instance for example.
143 : \param cs Pin to be used as chip select.
144 : \param irq Pin to be used as interrupt/GPIO.
145 : \param rst Pin to be used as hardware reset for the module.
146 : \param gpio Pin to be used as additional interrupt/GPIO.
147 : */
148 : Module(RadioLibHal *hal, uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio = RADIOLIB_NC);
149 :
150 : /*!
151 : \brief Copy constructor.
152 : \param mod Module instance to copy.
153 : */
154 : Module(const Module& mod);
155 :
156 : /*!
157 : \brief Overload for assignment operator.
158 : \param mod rvalue Module.
159 : */
160 : Module& operator=(const Module& mod);
161 :
162 : // public member variables
163 : /*! \brief Hardware abstraction layer to be used. */
164 : RadioLibHal* hal = NULL;
165 :
166 : /*! \brief Callback for parsing SPI status. */
167 : typedef int16_t (*SPIparseStatusCb_t)(uint8_t in);
168 :
169 : /*! \brief Callback for validation SPI status. */
170 : typedef int16_t (*SPIcheckStatusCb_t)(Module* mod);
171 :
172 : enum BitWidth_t {
173 : BITS_0 = 0,
174 : BITS_8 = 8,
175 : BITS_16 = 16,
176 : BITS_24 = 24,
177 : BITS_32 = 32,
178 : };
179 :
180 : /*!
181 : \struct SPIConfig_t
182 : \brief SPI configuration structure.
183 : */
184 : struct SPIConfig_t {
185 : /*! \brief Whether the SPI module is stream-type (SX126x/8x) or registrer access type (SX127x, CC1101 etc). */
186 : bool stream;
187 :
188 : /*! \brief Last recorded SPI error - only updated for modules that return status during SPI transfers. */
189 : int16_t err;
190 :
191 : /*! \brief SPI commands */
192 : uint16_t cmds[4];
193 :
194 : /*! \brief Bit widths of SPI addresses, commands and status bytes */
195 : BitWidth_t widths[3];
196 :
197 : /*! \brief Byte position of status command in SPI stream */
198 : uint8_t statusPos;
199 :
200 : /*! \brief Callback for parsing SPI status. */
201 : SPIparseStatusCb_t parseStatusCb;
202 :
203 : /*! \brief Callback for validation SPI status. */
204 : SPIcheckStatusCb_t checkStatusCb;
205 :
206 : /*! \brief Timeout in ms when waiting for GPIO signals. */
207 : RadioLibTime_t timeout;
208 : };
209 :
210 : /*! \brief SPI configuration structure. The default configuration corresponds to register-access modules, such as SX127x. */
211 : SPIConfig_t spiConfig = {
212 : .stream = false,
213 : .err = RADIOLIB_ERR_UNKNOWN,
214 : .cmds = { 0x00, 0x80, 0x00, 0x00 },
215 : .widths = { Module::BITS_8, Module::BITS_0, Module::BITS_8 },
216 : .statusPos = 0,
217 : .parseStatusCb = nullptr,
218 : .checkStatusCb = nullptr,
219 : .timeout = 1000,
220 : };
221 :
222 : #if RADIOLIB_INTERRUPT_TIMING
223 :
224 : /*!
225 : \brief Timer interrupt setup callback typedef.
226 : */
227 : typedef void (*TimerSetupCb_t)(uint32_t len);
228 :
229 : /*!
230 : \brief Callback to timer interrupt setup function when running in interrupt timing control mode.
231 : */
232 : TimerSetupCb_t TimerSetupCb = nullptr;
233 :
234 : /*!
235 : \brief Timer flag variable to be controlled by a platform-dependent interrupt.
236 : */
237 : volatile bool TimerFlag = false;
238 :
239 : #endif
240 :
241 : // basic methods
242 :
243 : /*!
244 : \brief Initialize low-level module control.
245 : */
246 : void init();
247 :
248 : /*!
249 : \brief Terminate low-level module control.
250 : */
251 : void term();
252 :
253 : // SPI methods
254 :
255 : /*!
256 : \brief SPI read method that automatically masks unused bits. This method is the preferred SPI read mechanism.
257 : \param reg Address of SPI register to read.
258 : \param msb Most significant bit of the register variable. Bits above this one will be masked out.
259 : \param lsb Least significant bit of the register variable. Bits below this one will be masked out.
260 : \returns Masked register value or status code.
261 : */
262 : int16_t SPIgetRegValue(uint32_t reg, uint8_t msb = 7, uint8_t lsb = 0);
263 :
264 : /*!
265 : \brief Overwrite-safe SPI write method with verification. This method is the preferred SPI write mechanism.
266 : \param reg Address of SPI register to write.
267 : \param value Single byte value that will be written to the SPI register.
268 : \param msb Most significant bit of the register variable. Bits above this one will not be affected by the write operation.
269 : \param lsb Least significant bit of the register variable. Bits below this one will not be affected by the write operation.
270 : \param checkInterval Number of milliseconds between register writing and verification reading. Some registers need up to 10ms to process the change.
271 : \param checkMask Mask of bits to check, only bits set to 1 will be verified.
272 : \param force Write new value even if the old value is the same.
273 : \returns \ref status_codes
274 : */
275 : int16_t SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF, bool force = false);
276 :
277 : /*!
278 : \brief SPI burst read method.
279 : \param reg Address of SPI register to read.
280 : \param numBytes Number of bytes that will be read.
281 : \param inBytes Pointer to array that will hold the read data.
282 : */
283 : void SPIreadRegisterBurst(uint32_t reg, size_t numBytes, uint8_t* inBytes);
284 :
285 : /*!
286 : \brief SPI basic read method. Use of this method is reserved for special cases, SPIgetRegValue should be used instead.
287 : \param reg Address of SPI register to read.
288 : \returns Value that was read from register.
289 : */
290 : uint8_t SPIreadRegister(uint32_t reg);
291 :
292 : /*!
293 : \brief SPI burst write method.
294 : \param reg Address of SPI register to write.
295 : \param data Pointer to array that holds the data that will be written.
296 : \param numBytes Number of bytes that will be written.
297 : */
298 : void SPIwriteRegisterBurst(uint32_t reg, const uint8_t* data, size_t numBytes);
299 :
300 : /*!
301 : \brief SPI basic write method. Use of this method is reserved for special cases, SPIsetRegValue should be used instead.
302 : \param reg Address of SPI register to write.
303 : \param data Value that will be written to the register.
304 : */
305 : void SPIwriteRegister(uint32_t reg, uint8_t data);
306 :
307 : /*!
308 : \brief SPI single transfer method.
309 : \param cmd SPI access command (read/write/burst/...).
310 : \param reg Address of SPI register to transfer to/from.
311 : \param dataOut Data that will be transferred from master to slave.
312 : \param dataIn Data that was transferred from slave to master.
313 : \param numBytes Number of bytes to transfer.
314 : */
315 : void SPItransfer(uint16_t cmd, uint32_t reg, const uint8_t* dataOut, uint8_t* dataIn, size_t numBytes);
316 :
317 : /*!
318 : \brief Method to check the result of last SPI stream transfer.
319 : \returns \ref status_codes
320 : */
321 : int16_t SPIcheckStream();
322 :
323 : /*!
324 : \brief Method to perform a read transaction with SPI stream.
325 : \param cmd SPI operation command.
326 : \param data Data that will be transferred from slave to master.
327 : \param numBytes Number of bytes to transfer.
328 : \param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
329 : \param verify Whether to verify the result of the transaction after it is finished.
330 : \returns \ref status_codes
331 : */
332 : int16_t SPIreadStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
333 :
334 : /*!
335 : \brief Method to perform a read transaction with SPI stream.
336 : \param cmd SPI operation command.
337 : \param cmdLen SPI command length in bytes.
338 : \param data Data that will be transferred from slave to master.
339 : \param numBytes Number of bytes to transfer.
340 : \param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
341 : \param verify Whether to verify the result of the transaction after it is finished.
342 : \returns \ref status_codes
343 : */
344 : int16_t SPIreadStream(const uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
345 :
346 : /*!
347 : \brief Method to perform a write transaction with SPI stream.
348 : \param cmd SPI operation command.
349 : \param data Data that will be transferred from master to slave.
350 : \param numBytes Number of bytes to transfer.
351 : \param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
352 : \param verify Whether to verify the result of the transaction after it is finished.
353 : \returns \ref status_codes
354 : */
355 : int16_t SPIwriteStream(uint16_t cmd, const uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
356 :
357 : /*!
358 : \brief Method to perform a write transaction with SPI stream.
359 : \param cmd SPI operation command.
360 : \param cmdLen SPI command length in bytes.
361 : \param data Data that will be transferred from master to slave.
362 : \param numBytes Number of bytes to transfer.
363 : \param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
364 : \param verify Whether to verify the result of the transaction after it is finished.
365 : \returns \ref status_codes
366 : */
367 : int16_t SPIwriteStream(const uint8_t* cmd, uint8_t cmdLen, const uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
368 :
369 : /*!
370 : \brief SPI single transfer method for modules with stream-type SPI interface (SX126x, SX128x etc.).
371 : \param cmd SPI operation command.
372 : \param cmdLen SPI command length in bytes.
373 : \param write Set to true for write commands, false for read commands.
374 : \param dataOut Data that will be transferred from master to slave.
375 : \param dataIn Data that was transferred from slave to master.
376 : \param numBytes Number of bytes to transfer.
377 : \param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
378 : \returns \ref status_codes
379 : */
380 : int16_t SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, const uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio);
381 :
382 : // pin number access methods
383 : // getCs is omitted on purpose, as it can interfere when accessing the SPI in a concurrent environment
384 : // so it is considered to be part of the SPI pins and hence not accessible from outside
385 : // see https://github.com/jgromes/RadioLib/discussions/1364
386 :
387 : /*!
388 : \brief Access method to get the pin number of interrupt/GPIO.
389 : \returns Pin number of interrupt/GPIO configured in the constructor.
390 : */
391 0 : uint32_t getIrq() const { return(irqPin); }
392 :
393 : /*!
394 : \brief Access method to get the pin number of hardware reset pin.
395 : \returns Pin number of hardware reset pin configured in the constructor.
396 : */
397 0 : uint32_t getRst() const { return(rstPin); }
398 :
399 : /*!
400 : \brief Access method to get the pin number of second interrupt/GPIO.
401 : \returns Pin number of second interrupt/GPIO configured in the constructor.
402 : */
403 0 : uint32_t getGpio() const { return(gpioPin); }
404 :
405 : /*!
406 : \brief Some modules contain external RF switch controlled by pins.
407 : This function gives RadioLib control over those pins to
408 : automatically switch between various modes: When idle both pins
409 : will be LOW, during TX the `txEn` pin will be HIGH, during RX the
410 : `rxPin` will be HIGH.
411 :
412 : Radiolib will automatically set the pin mode and value of these
413 : pins, so do not control them from the sketch.
414 :
415 : When more than two pins or more control over the output values are
416 : needed, use the setRfSwitchTable() function.
417 :
418 : \param rxEn RX enable pin.
419 : \param txEn TX enable pin.
420 : */
421 : void setRfSwitchPins(uint32_t rxEn, uint32_t txEn);
422 :
423 : /*!
424 : \brief Some modules contain external RF switch controlled by pins.
425 : This function gives RadioLib control over those pins to
426 : automatically switch between various modes.
427 :
428 : Radiolib will automatically set the pin mode and value of these
429 : pins, so do not control them from the sketch.
430 :
431 :
432 : \param pins A reference to an array of pins to control. This
433 : should always be an array of 3 elements. If you need less pins,
434 : use RADIOLIB_NC for the unused elements.
435 :
436 : \param table A reference to an array of pin values to use for each
437 : supported mode. Each element is an RfSwitchMode_T struct that
438 : lists the mode for which it applies and the values for each of the
439 : pins passed in the pins argument respectively.
440 :
441 : The `pins` array will be copied into the Module object, so the
442 : original array can be deallocated after this call. However,
443 : a reference to the `table` array will be stored, so that array
444 : must remain valid as long RadioLib is being used.
445 :
446 : The `mode` field in each table row should normally use any of the
447 : `MODE_*` constants from the Module::OpMode_t enum. However, some
448 : radios support additional modes and will define their own OpMode_t
449 : enum.
450 :
451 : The length of the table is variable (to support radios that add
452 : additional modes), so the table must always be terminated with the
453 : special END_OF_MODE_TABLE value.
454 :
455 : Normally all modes should be listed in the table, but for some
456 : radios, modes can be omitted to indicate they are not supported
457 : (e.g. when a radio has a high power and low power TX mode but
458 : external circuitry only supports low power). If applicable, this
459 : is documented in the radio class itself.
460 :
461 : #### Example
462 : For example, on a board that has an RF switch with an enable pin
463 : connected to PA0 and a TX/RX select pin connected to PA1:
464 :
465 : \code
466 : // In global scope, define the pin array and mode table
467 : static const uint32_t rfswitch_pins[] =
468 : {PA0, PA1, RADIOLIB_NC};
469 : static const Module::RfSwitchMode_t rfswitch_table[] = {
470 : {Module::MODE_IDLE, {LOW, LOW}},
471 : {Module::MODE_RX, {HIGH, LOW}},
472 : {Module::MODE_TX, {HIGH, HIGH}},
473 : Module::END_OF_MODE_TABLE,
474 : };
475 :
476 : void setup() {
477 : ...
478 : // Then somewhere in setup, pass them to radiolib
479 : radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
480 : ...
481 : }
482 : \endcode
483 : */
484 :
485 : void setRfSwitchTable(const uint32_t (&pins)[RFSWITCH_MAX_PINS], const RfSwitchMode_t table[]);
486 :
487 : /*!
488 : \brief Find a mode in the RfSwitchTable.
489 : \param mode The mode to find.
490 : \returns A pointer to the RfSwitchMode_t struct in the table that
491 : matches the passed mode. Returns nullptr if no rfswitch pins are
492 : configured, or the passed mode is not listed in the table.
493 : */
494 : const RfSwitchMode_t *findRfSwitchMode(uint8_t mode) const;
495 :
496 : /*!
497 : \brief Set RF switch state.
498 : \param mode The mode to set. This must be one of the MODE_ constants, or a radio-specific constant.
499 : */
500 : void setRfSwitchState(uint8_t mode);
501 :
502 : /*!
503 : \brief Wait for time to elapse, either using the microsecond timer, or the TimerFlag.
504 : Note that in interrupt timing mode, it is up to the user to set up the timing interrupt!
505 :
506 : \param start Waiting start timestamp, in microseconds.
507 : \param len Waiting duration, in microseconds;
508 : */
509 : void waitForMicroseconds(RadioLibTime_t start, RadioLibTime_t len);
510 :
511 : #if RADIOLIB_DEBUG
512 : /*!
513 : \brief Function to dump device registers as hex into the debug port.
514 : \param level RadioLib debug level, set to NULL to not print.
515 : \param start First address to dump.
516 : \param len Number of bytes to dump.
517 : */
518 : void regdump(const char* level, uint16_t start, size_t len);
519 : #endif
520 :
521 : #if !RADIOLIB_GODMODE
522 : private:
523 : #endif
524 : uint32_t csPin = RADIOLIB_NC;
525 : uint32_t irqPin = RADIOLIB_NC;
526 : uint32_t rstPin = RADIOLIB_NC;
527 : uint32_t gpioPin = RADIOLIB_NC;
528 :
529 : // RF switch pins and table
530 : uint32_t rfSwitchPins[RFSWITCH_MAX_PINS] = { RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC };
531 : const RfSwitchMode_t *rfSwitchTable = nullptr;
532 :
533 : #if RADIOLIB_INTERRUPT_TIMING
534 : uint32_t prevTimingLen = 0;
535 : #endif
536 : };
537 :
538 : #endif
|