-
-
Notifications
You must be signed in to change notification settings - Fork 892
/
RF24.h
410 lines (386 loc) · 11.3 KB
/
RF24.h
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2018 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* Based on maniacbug's RF24 library, copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
* RF24 driver refactored and optimized for speed and size, copyright (C) 2017 Olivier Mauti <olivier@mysensors.org>
*
* Definitions for Nordic NRF24L01+ radios:
* https://www.nordicsemi.com/eng/Products/2.4GHz-RF/nRF24L01P
*
*/
/**
* @file RF24.h
*
* @defgroup RF24grp RF24
* @ingroup internals
* @{
*
* RF24 driver-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE
* - [!] Exclamation mark is prepended in case of error
*
* |E| SYS | SUB | Message | Comment
* |-|------|------|----------------------|---------------------------------------------------------------------
* | | RF24 | INIT | | Initialise RF24 radio
* | | RF24 | INIT | PIN,CE=%%d,CS=%%d | Pin configuration: chip enable (CE), chip select (CS)
* |!| RF24 | INIT | SANCHK FAIL | Sanity check failed, check wiring or replace module
* | | RF24 | SPP | PCT=%%d,TX LEVEL=%%d | Set TX level, input TX percent (PCT)
* | | RF24 | RBR | REG=%%d,VAL=%%d | Read register (REG), value=(VAL)
* | | RF24 | WBR | REG=%%d,VAL=%%d | Write register (REG), value=(VAL)
* | | RF24 | FRX | | Flush RX buffer
* | | RF24 | FTX | | Flush TX buffer
* | | RF24 | OWP | RCPT=%%d | Open writing pipe, recipient=(RCPT)
* | | RF24 | STL | | Start listening
* | | RF24 | SPL | | Stop listening
* | | RF24 | SLP | | Set radio to sleep
* | | RF24 | SBY | | Set radio to standby
* | | RF24 | TXM | TO=%%d,LEN=%%d | Transmit message to=(TO), length=(LEN)
* |!| RF24 | TXM | MAX_RT | Max TX retries, no ACK received
* |!| RF24 | GDP | PYL INV | Invalid payload size
* | | RF24 | RXM | LEN=%%d | Read message, length=(LEN)
* | | RF24 | STX | LEVEL=%%d | Set TX level, level=(LEVEL)
*
*/
#ifndef __RF24_H__
#define __RF24_H__
#include "RF24registers.h"
#if defined(ARDUINO_ARCH_AVR)
#define DEFAULT_RF24_CE_PIN (9) //!< DEFAULT_RF24_CE_PIN
#elif defined(ARDUINO_ARCH_ESP8266)
#define DEFAULT_RF24_CE_PIN (4) //!< DEFAULT_RF24_CE_PIN
#elif defined(ARDUINO_ARCH_ESP32)
#define DEFAULT_RF24_CE_PIN (17) //!< DEFAULT_RF24_CE_PIN
#elif defined(ARDUINO_ARCH_SAMD)
#define DEFAULT_RF24_CE_PIN (27) //!< DEFAULT_RF24_CE_PIN
#elif defined(LINUX_ARCH_RASPBERRYPI)
#define DEFAULT_RF24_CE_PIN (22) //!< DEFAULT_RF24_CE_PIN
//#define DEFAULT_RF24_CS_PIN (24) //!< DEFAULT_RF24_CS_PIN
#elif defined(ARDUINO_ARCH_STM32F1)
#define DEFAULT_RF24_CE_PIN (PB0) //!< DEFAULT_RF24_CE_PIN
#elif defined(TEENSYDUINO)
#define DEFAULT_RF24_CE_PIN (9) //!< DEFAULT_RF24_CE_PIN
#else
#define DEFAULT_RF24_CE_PIN (9) //!< DEFAULT_RF24_CE_PIN
#endif
#define DEFAULT_RF24_CS_PIN (SS) //!< DEFAULT_RF24_CS_PIN
#define LOCAL static //!< static
// SPI settings
#define RF24_SPI_DATA_ORDER MSBFIRST //!< RF24_SPI_DATA_ORDER
#define RF24_SPI_DATA_MODE SPI_MODE0 //!< RF24_SPI_DATA_MODE
#define RF24_BROADCAST_ADDRESS (255u) //!< RF24_BROADCAST_ADDRESS
#if defined(ARDUINO) && !defined(__arm__) && !defined(RF24_SPI)
#include <SPI.h>
#if defined(MY_SOFTSPI)
SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, RF24_SPI_DATA_MODE>
RF24_SPI;
#else
#define RF24_SPI SPI //!< SPI
#endif
#else
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#if defined(__arm__) || defined(__linux__)
#include <SPI.h>
#else
extern HardwareSPI SPI; //!< SPI
#endif
#if !defined(RF24_SPI)
#define RF24_SPI SPI //!< SPI
#endif
#endif
// verify RF24 IRQ defs
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
#if !defined(MY_RF24_IRQ_PIN)
#error Message buffering feature requires MY_RF24_IRQ_PIN to be defined!
#endif
// SoftSPI does not support usingInterrupt()
#ifdef MY_SOFTSPI
#error RF24 IRQ usage cannot be used with Soft SPI
#endif
// ESP8266 does not support usingInterrupt()
#ifdef ARDUINO_ARCH_ESP8266
#error RF24 IRQ usage cannot be used with ESP8266
#endif
#ifndef SPI_HAS_TRANSACTION
#error RF24 IRQ usage requires transactional SPI support
#endif
#else
#ifdef MY_RX_MESSAGE_BUFFER_SIZE
#error Receive message buffering requires RF24 IRQ usage
#endif
#endif
// RF24 settings
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
#define RF24_CONFIGURATION (uint8_t) ((RF24_CRC_16 << 2) | (1 << RF24_MASK_TX_DS) | (1 << RF24_MASK_MAX_RT)) //!< MY_RF24_CONFIGURATION
#else
#define RF24_CONFIGURATION (uint8_t) (RF24_CRC_16 << 2) //!< RF24_CONFIGURATION
#endif
#define RF24_FEATURE (uint8_t)( _BV(RF24_EN_DPL)) //!< RF24_FEATURE
#define RF24_RF_SETUP (uint8_t)( ((MY_RF24_DATARATE & 0b10 ) << 4) | ((MY_RF24_DATARATE & 0b01 ) << 3) | (MY_RF24_PA_LEVEL << 1) ) + 1 //!< RF24_RF_SETUP, +1 for Si24R1 and LNA
// powerup delay
#define RF24_POWERUP_DELAY_MS (100u) //!< Power up delay, allow VCC to settle, transport to become fully operational
// pipes
#define RF24_BROADCAST_PIPE (1u) //!< RF24_BROADCAST_PIPE
#define RF24_NODE_PIPE (0u) //!< RF24_NODE_PIPE
// functions
/**
* @brief RF24_csn
* @param level
*/
LOCAL void RF24_csn(const bool level);
/**
* @brief RF24_ce
* @param level
*/
LOCAL void RF24_ce(const bool level);
/**
* @brief RF24_spiMultiByteTransfer
* @param cmd
* @param buf
* @param len
* @param readMode
* @return
*/
LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t *buf, const uint8_t len,
const bool readMode);
/**
* @brief RF24_spiByteTransfer
* @param cmd
* @return
*/
LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd);
/**
* @brief RF24_RAW_readByteRegister
* @param cmd
* @return
*/
LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd);
/**
* @brief RF24_RAW_writeByteRegister
* @param cmd
* @param value
* @return
*/
LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, const uint8_t value);
// helper macros
#define RF24_readByteRegister(__reg) RF24_RAW_readByteRegister(RF24_CMD_READ_REGISTER | (RF24_REGISTER_MASK & (__reg))) //!< RF24_readByteRegister
#define RF24_writeByteRegister(__reg,__value) RF24_RAW_writeByteRegister(RF24_CMD_WRITE_REGISTER | (RF24_REGISTER_MASK & (__reg)), __value) //!< RF24_writeByteRegister
#define RF24_writeMultiByteRegister(__reg,__buf,__len) RF24_spiMultiByteTransfer(RF24_CMD_WRITE_REGISTER | (RF24_REGISTER_MASK & (__reg)),(uint8_t *)__buf, __len,false) //!< RF24_writeMultiByteRegister
/**
* @brief RF24_flushRX
*/
LOCAL void RF24_flushRX(void);
/**
* @brief RF24_flushTX
*/
LOCAL void RF24_flushTX(void);
/**
* @brief RF24_getStatus
* @return
*/
LOCAL uint8_t RF24_getStatus(void);
/**
* @brief RF24_getFIFOStatus
* @return
*/
LOCAL uint8_t RF24_getFIFOStatus(void);
/**
* @brief RF24_openWritingPipe
* @param recipient
*/
LOCAL void RF24_openWritingPipe(const uint8_t recipient);
/**
* @brief RF24_startListening
*/
LOCAL void RF24_startListening(void);
/**
* @brief RF24_stopListening
*/
LOCAL void RF24_stopListening(void);
/**
* @brief RF24_sleep
*/
LOCAL void RF24_sleep(void);
/**
* @brief RF24_standBy
*/
LOCAL void RF24_standBy(void);
/**
* @brief RF24_powerDown
*/
LOCAL void RF24_powerDown(void);
/**
* @brief RF24_powerUp
*/
LOCAL void RF24_powerUp(void);
/**
* @brief RF24_sendMessage
* @param recipient
* @param buf
* @param len
* @param noACK set True if no ACK is required
* @return
*/
LOCAL bool RF24_sendMessage(const uint8_t recipient, const void *buf, const uint8_t len,
const bool noACK = false);
/**
* @brief RF24_getDynamicPayloadSize
* @return
*/
LOCAL uint8_t RF24_getDynamicPayloadSize(void);
/**
* @brief RF24_isDataAvailable
* @return
*/
LOCAL bool RF24_isDataAvailable(void);
/**
* @brief RF24_readMessage
* @return
*/
LOCAL uint8_t RF24_readMessage(void *buf);
/**
* @brief RF24_setNodeAddress
* @param address
*/
LOCAL void RF24_setNodeAddress(const uint8_t address);
/**
* @brief RF24_getNodeID
* @return
*/
LOCAL uint8_t RF24_getNodeID(void);
/**
* @brief RF24_sanityCheck
* @return
*/
LOCAL bool RF24_sanityCheck(void);
/**
* @brief RF24_initialize
* @return
*/
LOCAL bool RF24_initialize(void);
/**
* @brief RF24_setChannel
* @param channel
*/
LOCAL void RF24_setChannel(const uint8_t channel);
/**
* @brief RF24_setRetries
* @param retransmitDelay
* @param retransmitCount
*/
LOCAL void RF24_setRetries(const uint8_t retransmitDelay, const uint8_t retransmitCount);
/**
* @brief RF24_setAddressWidth
* @param addressWidth
*/
LOCAL void RF24_setAddressWidth(const uint8_t addressWidth);
/**
* @brief RF24_setRFSetup
* @param RFsetup
*/
LOCAL void RF24_setRFSetup(const uint8_t RFsetup);
/**
* @brief RF24_setFeature
* @param feature
*/
LOCAL void RF24_setFeature(const uint8_t feature);
/**
* @brief RF24_setPipe
* @param pipe
*/
LOCAL void RF24_setPipe(const uint8_t pipe);
/**
* @brief RF24_setAutoACK
* @param pipe
*/
LOCAL void RF24_setAutoACK(const uint8_t pipe);
/**
* @brief RF24_setDynamicPayload
* @param pipe
*/
LOCAL void RF24_setDynamicPayload(const uint8_t pipe);
/**
* @brief RF24_setRFConfiguration
* @param configuration
*/
LOCAL void RF24_setRFConfiguration(const uint8_t configuration);
/**
* @brief RF24_setPipeAddress
* @param pipe
* @param address
* @param addressWidth
*/
LOCAL void RF24_setPipeAddress(const uint8_t pipe, uint8_t *address, const uint8_t addressWidth);
/**
* @brief RF24_setPipeLSB
* @param pipe
* @param LSB
*/
LOCAL void RF24_setPipeLSB(const uint8_t pipe, const uint8_t LSB);
/**
* @brief RF24_getObserveTX
* @return
*/
LOCAL uint8_t RF24_getObserveTX(void);
/**
* @brief RF24_setStatus
* @param status
*/
LOCAL void RF24_setStatus(const uint8_t status);
/**
* @brief RF24_enableFeatures
*/
LOCAL void RF24_enableFeatures(void);
/**
* @brief RF24_getTxPowerPercent
* @return
*/
LOCAL uint8_t RF24_getTxPowerPercent(void);
/**
* @brief RF24_getTxPowerLevel
* @return
*/
LOCAL int16_t RF24_getTxPowerLevel(void);
/**
* @brief RF24_setTxPowerPercent
* @param newPowerPercent
* @return
*/
LOCAL bool RF24_setTxPowerPercent(const uint8_t newPowerPercent);
/**
* @brief RF24_getSendingRSSI
* @return Pseudo-RSSI based on ARC register
*/
LOCAL int16_t RF24_getSendingRSSI(void);
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
/**
* @brief Callback type
*/
typedef void (*RF24_receiveCallbackType)(void);
/**
* @brief RF24_registerReceiveCallback
* Register a callback, which will be called (from interrupt context) for every message received.
* @note When a callback is registered, it _must_ retrieve the message from the nRF24
* by calling RF24_readMessage(). Otherwise the interrupt will not get deasserted
* and message reception will stop.
* @param cb
*/
LOCAL void RF24_registerReceiveCallback(RF24_receiveCallbackType cb);
#endif
#endif // __RF24_H__
/** @}*/