forked from hallard/RadioHead
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RH_NRF51.h
302 lines (265 loc) · 12.9 KB
/
RH_NRF51.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
// RH_NRF51.h
// Author: Mike McCauley
// Copyright (C) 2015 Mike McCauley
// $Id: RH_NRF51.h,v 1.5 2017/07/25 05:26:50 mikem Exp $
//
#ifndef RH_NRF51_h
#define RH_NRF51_h
#include <RHGenericDriver.h>
// This is the maximum number of bytes that can be carried by the nRF51.
// We use some for headers, keeping fewer for RadioHead messages
#define RH_NRF51_MAX_PAYLOAD_LEN 254
// The length of the headers we add.
// The headers are inside the nRF51 payload
// We add:
// S0 (not used)
// LEN
// S1 (not used)
// to
// from
// id
// flags
#define RH_NRF51_HEADER_LEN 7
// This is the maximum RadioHead user message length that can be supported by this library. Limited by
// the supported message lengths in the nRF51
#define RH_NRF51_MAX_MESSAGE_LEN (RH_NRF51_MAX_PAYLOAD_LEN-RH_NRF51_HEADER_LEN)
// Define to be 1 if you want to support AES CCA encryption using the built-in
// encryption engine.
#define RH_NRF51_HAVE_ENCRYPTION 1
// When encryption is enabled, have a much shorter max message length
#define RH_NRF51_MAX_ENCRYPTED_MESSAGE_LEN (27-4)
// The required length of the AES encryption key
#define RH_NRF51_ENCRYPTION_KEY_LENGTH 16
// This is the size of the CCM data structure for AES encryption
// REVISIT: use a struct?
#define RH_NRF51_AES_CCM_CNF_SIZE 33
/////////////////////////////////////////////////////////////////////
/// \class RH_NRF51 RH_NRF51.h <RH_NRF51.h>
/// \brief Send and receive unaddressed, unreliable datagrams by nRF51 and nRF52 compatible transceivers.
///
/// Supported transceivers include:
/// - Nordic nRF51 based 2.4GHz radio modules, such as nRF51822
/// and other compatible chips, such as used in RedBearLabs devices like:
/// http://store.redbearlab.com/products/redbearlab-nrf51822
/// http://store.redbearlab.com/products/blenano
/// and
/// Sparkfun nRF52832 breakout board, with Arduino 1.6.13 and
/// Sparkfun nRF52 boards manager 0.2.3
///
/// This base class provides basic functions for sending and receiving unaddressed, unreliable datagrams
/// of arbitrary length to 254 octets per packet. Use one of the Manager classes to get addressing and
/// acknowledgement reliability, routing, meshes etc.
///
/// The nRF51822 (https://www.nordicsemi.com/eng/Products/Bluetooth-Smart-Bluetooth-low-energy/nRF51822)
/// and nRF52832 (https://learn.sparkfun.com/tutorials/nrf52832-breakout-board-hookup-guide)
/// is a complete SoC (system on a chip) with ARM microprocessor and 2.4 GHz radio, which supports a range of channels
/// and transmission bit rates. Chip antenna is on-board.
///
/// This library provides functions for sending and receiving messages of up to 254 octets on any
/// frequency supported by the nRF51822/nRF52832, at a selected data rate.
///
/// The nRF51 transceiver is configured to use Enhanced Shockburst with no acknowledgement and no retransmits.
/// TXADDRESS and RXADDRESSES:RXADDR0 (ie pipe 0) are the logical address used. The on-air network address
/// is set in BASE0 and PREFIX0. SHORTS is used to automatically transition the radio between Ready, Start and Disable.
/// No interrupts are used.
///
/// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
/// data rate, and with identical network addresses.
///
/// Example programs are included to show the main modes of use.
///
/// \par Packet Format
///
/// All messages sent and received by this class conform to this packet format. It is NOT compatible
/// with the one used by RH_NRF24 and the nRF24L01 product specification, mainly because the nRF24 only supports
/// 6 bits of message length.
///
/// - 1 octets PREAMBLE
/// - 3 to 5 octets NETWORK ADDRESS
/// - 1 octet S0 (not used, required if encryption used)
/// - 8 bits PAYLOAD LENGTH
/// - 1 octet S1 (not used, required if encryption used)
/// - 0 to 251 octets PAYLOAD (possibly encrypted), consisting of:
/// - 1 octet TO header
/// - 1 octet FROM header
/// - 1 octet ID header
/// - 1 octet FLAGS header
/// - 0 to 247 octets of user message
/// - 2 octets CRC (Algorithm x^16+x^12^x^5+1 with initial value 0xFFFF).
///
/// \par Example programs
///
/// Several example programs are provided.
///
/// The sample programs are designed to be built using Arduino 1.6.4 or later using the procedures outlined
/// in http://redbearlab.com/getting-started-nrf51822/
/// or with Sparkfun nRF52832 breakout board, with Arduino 1.6.13 and
/// Sparkfun nRF52 boards manager 0.2.3 using the procedures outlined in
/// https://learn.sparkfun.com/tutorials/nrf52832-breakout-board-hookup-guide
///
/// \par Radio Performance
///
/// At DataRate2Mbps (2Mb/s), payload length vs airtime:
/// 0 bytes takes about 70us, 128 bytes takes 520us, 254 bytes take 1020us.
/// You can extrapolate linearly to slower data rates.
///
/// The RF powers claimed by the chip manufacturer have not been independently verified here.
///
/// \par Memory
///
/// The compiled client and server sketches are about 42k bytes on Arduino.
/// The reliable client and server sketches compile to about 43k bytes on Arduino. Unfortunately the
/// Arduino build environmnet does not drop unused clsses and code, so the resulting programs include
/// all the unused classes ad code. This needs to be revisited.
/// RAM requirements are minimal.
///
class RH_NRF51 : public RHGenericDriver
{
public:
/// \brief Defines convenient values for setting data rates in setRF()
typedef enum
{
DataRate1Mbps = 0, ///< 1 Mbps
DataRate2Mbps, ///< 2 Mbps
DataRate250kbps ///< 250 kbps
} DataRate;
/// \brief Convenient values for setting transmitter power in setRF()
typedef enum
{
// Add 20dBm for nRF24L01p with PA and LNA modules
TransmitPower4dBm = 0, ///< 4 dBm
TransmitPower0dBm, ///< 0 dBm
TransmitPowerm4dBm, ///< -4 dBm
TransmitPowerm8dBm, ///< -8 dBm
TransmitPowerm12dBm, ///< -12 dBm
TransmitPowerm16dBm, ///< -16 dBm
TransmitPowerm20dBm, ///< -20 dBm
TransmitPowerm30dBm, ///< -30 dBm
} TransmitPower;
/// Constructor.
/// After constructing, you must call init() to initialise the interface
/// and the radio module
RH_NRF51();
/// Initialises this instance and the radio module connected to it.
/// The following steps are taken:
/// - Start the processors High Frequency clock DC/DC converter and
/// - Disable and reset the radio
/// - Set the logical channel to 0 for transmit and receive (only pipe 0 is used)
/// - Configure the CRC (2 octets, algorithm x^16+x^12^x^5+1 with initial value 0xffff)
/// - Set the default network address of 0xE7E7E7E7E7
/// - Set channel to 2
/// - Set data rate to DataRate2Mbps
/// - Set TX power to TransmitPower0dBm
/// \return true if everything was successful
bool init();
/// Sets the transmit and receive channel number.
/// The frequency used is (2400 + channel) MHz
/// \return true on success
bool setChannel(uint8_t channel);
/// Sets the Network address.
/// Only nodes with the same network address can communicate with each other. You
/// can set different network addresses in different sets of nodes to isolate them from each other.
/// Internally, this sets the nRF51 BASE0 and PREFIX0 to be the given network address.
/// The first octet of the address is used for PREFIX0 and the rest is used for BASE0. BALEN is
/// set to the approprtae base length.
/// The default network address is 0xE7E7E7E7E7.
/// \param[in] address The new network address. Must match the network address of any receiving node(s).
/// \param[in] len Number of bytes of address to set (3 to 5).
/// \return true on success, false if len is not in the range 3-5 inclusive.
bool setNetworkAddress(uint8_t* address, uint8_t len);
/// Sets the data rate and transmitter power to use.
/// \param [in] data_rate The data rate to use for all packets transmitted and received. One of RH_NRF51::DataRate.
/// \param [in] power Transmitter power. One of RH_NRF51::TransmitPower.
/// \return true on success
bool setRF(DataRate data_rate, TransmitPower power);
/// Sets the radio in power down mode, with the configuration set to the
/// last value from setOpMode().
/// Sets chip enable to LOW.
void setModeIdle();
/// Sets the radio in RX mode.
void setModeRx();
/// Sets the radio in TX mode.
void setModeTx();
/// Sends data to the address set by setTransmitAddress()
/// Sets the radio to TX mode.
/// Caution: when encryption is enabled, the maximum message length is reduced to 23 octets.
/// \param [in] data Data bytes to send.
/// \param [in] len Number of data bytes to send
/// \return true on success (which does not necessarily mean the receiver got the message, only that the message was
/// successfully transmitted). False if the message is too long or was otherwise not transmitted.
bool send(const uint8_t* data, uint8_t len);
/// Blocks until the current message (if any)
/// has been transmitted
/// \return true on success, false if the chip is not in transmit mode or other transmit failure
virtual bool waitPacketSent();
/// Indicates if the chip is in transmit mode and
/// there is a packet currently being transmitted
/// \return true if the chip is in transmit mode and there is a transmission in progress
bool isSending();
/// Prints the value of all NRF_RADIO registers.
/// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
/// For debugging purposes only.
/// Caution: there are 1024 of them (many reserved and set to 0).
/// \return true on success
bool printRegisters();
/// Checks whether a received message is available.
/// This can be called multiple times in a timeout loop
/// \return true if a complete, valid message has been received and is able to be retrieved by
/// recv()
bool available();
/// Turns the receiver on if it not already on.
/// Once a message with CRC correct is received, the receiver will be returned to Idle mode.
/// If there is a valid message available, copy it to buf and return true
/// else return false.
/// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
/// You should be sure to call this function frequently enough to not miss any messages
/// It is recommended that you call it in your main loop.
/// \param[in] buf Location to copy the received message
/// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
/// \return true if a valid message was copied to buf
bool recv(uint8_t* buf, uint8_t* len);
/// Enables AES encryption and sets the AES encryption key, used
/// to encrypt and decrypt all messages using the on-chip AES CCM mode encryption engine.
/// The default is disabled.
/// In the AES configuration, the message counter and IV is always set to 0, which
/// means the same keystream is used for every message with a given key.
/// Caution: when encryption is enabled, the maximum message length is reduced to 23 octets.
/// \param[in] key The key to use. Must be 16 bytes long. The same key must be installed
/// in other instances of RH_RF51, otherwise communications will not work correctly. If key is NULL,
/// encryption is disabled, which is the default.
void setEncryptionKey(uint8_t* key = NULL);
/// The maximum message length supported by this driver
/// \return The maximum message length supported by this driver
uint8_t maxMessageLength();
/// Reeads the current die temperature using the built in TEMP peripheral.
/// Blocks while the temperature is measured, which takes about 30 microseconds.
// \return the current die temperature in degrees C.
float get_temperature();
protected:
/// Examine the receive buffer to determine whether the message is for this node
void validateRxBuf();
/// Clear our local receive buffer
void clearRxBuf();
private:
/// The receiver/transmitter buffer
/// First octet is the payload length, remainder is the payload
uint8_t _buf[RH_NRF51_MAX_PAYLOAD_LEN+1];
/// True when there is a valid message in the buffer
bool _rxBufValid;
#if RH_NRF51_HAVE_ENCRYPTION
/// True if an AES key has been specified and that we are therfore encrypting
/// and decrypting messages on the fly
bool _encrypting;
/// Scratch area for AES encryption
uint8_t _scratch[RH_NRF51_MAX_PAYLOAD_LEN+1+16];
/// Where the AES encryption key and IV are stored
uint8_t _encryption_cnf[RH_NRF51_AES_CCM_CNF_SIZE];
#endif
};
/// @example nrf51_client.pde
/// @example nrf51_server.pde
/// @example nrf51_reliable_datagram_client.pde
/// @example nrf51_reliable_datagram_server.pde
/// @example nrf51_audio_tx.pde
/// @example nrf51_audio_rx.pde
#endif