RadioHead
RH_NRF51.h
1// RH_NRF51.h
2// Author: Mike McCauley
3// Copyright (C) 2015 Mike McCauley
4// $Id: RH_NRF51.h,v 1.5 2017/07/25 05:26:50 mikem Exp $
5//
6
7#ifndef RH_NRF51_h
8#define RH_NRF51_h
9
10#include <RHGenericDriver.h>
11
12// This is the maximum number of bytes that can be carried by the nRF51.
13// We use some for headers, keeping fewer for RadioHead messages
14#define RH_NRF51_MAX_PAYLOAD_LEN 254
15
16// The length of the headers we add.
17// The headers are inside the nRF51 payload
18// We add:
19// S0 (not used)
20// LEN
21// S1 (not used)
22// to
23// from
24// id
25// flags
26#define RH_NRF51_HEADER_LEN 7
27
28// This is the maximum RadioHead user message length that can be supported by this library. Limited by
29// the supported message lengths in the nRF51
30#define RH_NRF51_MAX_MESSAGE_LEN (RH_NRF51_MAX_PAYLOAD_LEN-RH_NRF51_HEADER_LEN)
31
32// Define to be 1 if you want to support AES CCA encryption using the built-in
33// encryption engine.
34#define RH_NRF51_HAVE_ENCRYPTION 1
35
36// When encryption is enabled, have a much shorter max message length
37#define RH_NRF51_MAX_ENCRYPTED_MESSAGE_LEN (27-4)
38
39// The required length of the AES encryption key
40#define RH_NRF51_ENCRYPTION_KEY_LENGTH 16
41
42// This is the size of the CCM data structure for AES encryption
43// REVISIT: use a struct?
44#define RH_NRF51_AES_CCM_CNF_SIZE 33
45
46/////////////////////////////////////////////////////////////////////
47/// \class RH_NRF51 RH_NRF51.h <RH_NRF51.h>
48/// \brief Send and receive unaddressed, unreliable datagrams by nRF51 and nRF52 compatible transceivers.
49///
50/// Supported transceivers include:
51/// - Nordic nRF51 based 2.4GHz radio modules, such as nRF51822
52/// and other compatible chips, such as used in RedBearLabs devices like:
53/// http://store.redbearlab.com/products/redbearlab-nrf51822
54/// http://store.redbearlab.com/products/blenano
55/// and
56/// Sparkfun nRF52832 breakout board, with Arduino 1.6.13 and
57/// Sparkfun nRF52 boards manager 0.2.3
58///
59/// This base class provides basic functions for sending and receiving unaddressed, unreliable datagrams
60/// of arbitrary length to 254 octets per packet. Use one of the Manager classes to get addressing and
61/// acknowledgement reliability, routing, meshes etc.
62///
63/// The nRF51822 (https://www.nordicsemi.com/eng/Products/Bluetooth-Smart-Bluetooth-low-energy/nRF51822)
64/// and nRF52832 (https://learn.sparkfun.com/tutorials/nrf52832-breakout-board-hookup-guide)
65/// is a complete SoC (system on a chip) with ARM microprocessor and 2.4 GHz radio, which supports a range of channels
66/// and transmission bit rates. Chip antenna is on-board.
67///
68/// This library provides functions for sending and receiving messages of up to 254 octets on any
69/// frequency supported by the nRF51822/nRF52832, at a selected data rate.
70///
71/// The nRF51 transceiver is configured to use Enhanced Shockburst with no acknowledgement and no retransmits.
72/// TXADDRESS and RXADDRESSES:RXADDR0 (ie pipe 0) are the logical address used. The on-air network address
73/// is set in BASE0 and PREFIX0. SHORTS is used to automatically transition the radio between Ready, Start and Disable.
74/// No interrupts are used.
75///
76/// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
77/// data rate, and with identical network addresses.
78///
79/// Example programs are included to show the main modes of use.
80///
81/// \par Packet Format
82///
83/// All messages sent and received by this class conform to this packet format. It is NOT compatible
84/// with the one used by RH_NRF24 and the nRF24L01 product specification, mainly because the nRF24 only supports
85/// 6 bits of message length.
86///
87/// - 1 octets PREAMBLE
88/// - 3 to 5 octets NETWORK ADDRESS
89/// - 1 octet S0 (not used, required if encryption used)
90/// - 8 bits PAYLOAD LENGTH
91/// - 1 octet S1 (not used, required if encryption used)
92/// - 0 to 251 octets PAYLOAD (possibly encrypted), consisting of:
93/// - 1 octet TO header
94/// - 1 octet FROM header
95/// - 1 octet ID header
96/// - 1 octet FLAGS header
97/// - 0 to 247 octets of user message
98/// - 2 octets CRC (Algorithm x^16+x^12^x^5+1 with initial value 0xFFFF).
99///
100/// \par Example programs
101///
102/// Several example programs are provided.
103///
104/// The sample programs are designed to be built using Arduino 1.6.4 or later using the procedures outlined
105/// in http://redbearlab.com/getting-started-nrf51822/
106/// or with Sparkfun nRF52832 breakout board, with Arduino 1.6.13 and
107/// Sparkfun nRF52 boards manager 0.2.3 using the procedures outlined in
108/// https://learn.sparkfun.com/tutorials/nrf52832-breakout-board-hookup-guide
109///
110/// \par Radio Performance
111///
112/// At DataRate2Mbps (2Mb/s), payload length vs airtime:
113/// 0 bytes takes about 70us, 128 bytes takes 520us, 254 bytes take 1020us.
114/// You can extrapolate linearly to slower data rates.
115///
116/// The RF powers claimed by the chip manufacturer have not been independently verified here.
117///
118/// \par Memory
119///
120/// The compiled client and server sketches are about 42k bytes on Arduino.
121/// The reliable client and server sketches compile to about 43k bytes on Arduino. Unfortunately the
122/// Arduino build environmnet does not drop unused clsses and code, so the resulting programs include
123/// all the unused classes ad code. This needs to be revisited.
124/// RAM requirements are minimal.
125///
127{
128public:
129
130 /// \brief Defines convenient values for setting data rates in setRF()
131 typedef enum
132 {
133 DataRate1Mbps = 0, ///< 1 Mbps
134 DataRate2Mbps, ///< 2 Mbps
135 DataRate250kbps ///< 250 kbps
137
138 /// \brief Convenient values for setting transmitter power in setRF()
139 typedef enum
140 {
141 // Add 20dBm for nRF24L01p with PA and LNA modules
142 TransmitPower4dBm = 0, ///< 4 dBm
151
152 /// Constructor.
153 /// After constructing, you must call init() to initialise the interface
154 /// and the radio module
156
157 /// Initialises this instance and the radio module connected to it.
158 /// The following steps are taken:
159 /// - Start the processors High Frequency clock DC/DC converter and
160 /// - Disable and reset the radio
161 /// - Set the logical channel to 0 for transmit and receive (only pipe 0 is used)
162 /// - Configure the CRC (2 octets, algorithm x^16+x^12^x^5+1 with initial value 0xffff)
163 /// - Set the default network address of 0xE7E7E7E7E7
164 /// - Set channel to 2
165 /// - Set data rate to DataRate2Mbps
166 /// - Set TX power to TransmitPower0dBm
167 /// \return true if everything was successful
168 bool init();
169
170 /// Sets the transmit and receive channel number.
171 /// The frequency used is (2400 + channel) MHz
172 /// \return true on success
173 bool setChannel(uint8_t channel);
174
175 /// Sets the Network address.
176 /// Only nodes with the same network address can communicate with each other. You
177 /// can set different network addresses in different sets of nodes to isolate them from each other.
178 /// Internally, this sets the nRF51 BASE0 and PREFIX0 to be the given network address.
179 /// The first octet of the address is used for PREFIX0 and the rest is used for BASE0. BALEN is
180 /// set to the approprtae base length.
181 /// The default network address is 0xE7E7E7E7E7.
182 /// \param[in] address The new network address. Must match the network address of any receiving node(s).
183 /// \param[in] len Number of bytes of address to set (3 to 5).
184 /// \return true on success, false if len is not in the range 3-5 inclusive.
185 bool setNetworkAddress(uint8_t* address, uint8_t len);
186
187 /// Sets the data rate and transmitter power to use.
188 /// \param [in] data_rate The data rate to use for all packets transmitted and received. One of RH_NRF51::DataRate.
189 /// \param [in] power Transmitter power. One of RH_NRF51::TransmitPower.
190 /// \return true on success
191 bool setRF(DataRate data_rate, TransmitPower power);
192
193 /// Sets the radio in power down mode, with the configuration set to the
194 /// last value from setOpMode().
195 /// Sets chip enable to LOW.
197
198 /// Sets the radio in RX mode.
199 void setModeRx();
200
201 /// Sets the radio in TX mode.
202 void setModeTx();
203
204 /// Sends data to the address set by setTransmitAddress()
205 /// Sets the radio to TX mode.
206 /// Caution: when encryption is enabled, the maximum message length is reduced to 23 octets.
207 /// \param [in] data Data bytes to send.
208 /// \param [in] len Number of data bytes to send
209 /// \return true on success (which does not necessarily mean the receiver got the message, only that the message was
210 /// successfully transmitted). False if the message is too long or was otherwise not transmitted.
211 bool send(const uint8_t* data, uint8_t len);
212
213 /// Blocks until the current message (if any)
214 /// has been transmitted
215 /// \return true on success, false if the chip is not in transmit mode or other transmit failure
216 virtual bool waitPacketSent();
217
218 /// Indicates if the chip is in transmit mode and
219 /// there is a packet currently being transmitted
220 /// \return true if the chip is in transmit mode and there is a transmission in progress
221 bool isSending();
222
223 /// Prints the value of all NRF_RADIO registers.
224 /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
225 /// For debugging purposes only.
226 /// Caution: there are 1024 of them (many reserved and set to 0).
227 /// \return true on success
229
230 /// Checks whether a received message is available.
231 /// This can be called multiple times in a timeout loop
232 /// \return true if a complete, valid message has been received and is able to be retrieved by
233 /// recv()
234 bool available();
235
236 /// Turns the receiver on if it not already on.
237 /// Once a message with CRC correct is received, the receiver will be returned to Idle mode.
238 /// If there is a valid message available, copy it to buf and return true
239 /// else return false.
240 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
241 /// You should be sure to call this function frequently enough to not miss any messages
242 /// It is recommended that you call it in your main loop.
243 /// \param[in] buf Location to copy the received message
244 /// \param[in,out] len Pointer to the number of octets available in buf. The number be reset to the actual number of octets copied.
245 /// \return true if a valid message was copied to buf
246 bool recv(uint8_t* buf, uint8_t* len);
247
248 /// Enables AES encryption and sets the AES encryption key, used
249 /// to encrypt and decrypt all messages using the on-chip AES CCM mode encryption engine.
250 /// The default is disabled.
251 /// In the AES configuration, the message counter and IV is always set to 0, which
252 /// means the same keystream is used for every message with a given key.
253 /// Caution: when encryption is enabled, the maximum message length is reduced to 23 octets.
254 /// \param[in] key The key to use. Must be 16 bytes long. The same key must be installed
255 /// in other instances of RH_RF51, otherwise communications will not work correctly. If key is NULL,
256 /// encryption is disabled, which is the default.
257 void setEncryptionKey(uint8_t* key = NULL);
258
259 /// The maximum message length supported by this driver
260 /// \return The maximum message length supported by this driver
262
263 /// Reeads the current die temperature using the built in TEMP peripheral.
264 /// Blocks while the temperature is measured, which takes about 30 microseconds.
265 // \return the current die temperature in degrees C.
267
268protected:
269 /// Examine the receive buffer to determine whether the message is for this node
271
272 /// Clear our local receive buffer
274
275private:
276 /// The receiver/transmitter buffer
277 /// First octet is the payload length, remainder is the payload
278 uint8_t _buf[RH_NRF51_MAX_PAYLOAD_LEN+1];
279
280 /// True when there is a valid message in the buffer
281 bool _rxBufValid;
282
283#if RH_NRF51_HAVE_ENCRYPTION
284 /// True if an AES key has been specified and that we are therfore encrypting
285 /// and decrypting messages on the fly
286 bool _encrypting;
287
288 /// Scratch area for AES encryption
289 uint8_t _scratch[RH_NRF51_MAX_PAYLOAD_LEN+1+16];
290
291 /// Where the AES encryption key and IV are stored
292 uint8_t _encryption_cnf[RH_NRF51_AES_CCM_CNF_SIZE];
293#endif
294};
295
296/// @example nrf51_client.ino
297/// @example nrf51_server.ino
298/// @example nrf51_reliable_datagram_client.ino
299/// @example nrf51_reliable_datagram_server.ino
300/// @example nrf51_audio_tx.ino
301/// @example nrf51_audio_rx.ino
302#endif
Abstract base class for a RadioHead driver.
Definition: RHGenericDriver.h:42
Send and receive unaddressed, unreliable datagrams by nRF51 and nRF52 compatible transceivers.
Definition: RH_NRF51.h:127
bool printRegisters()
uint8_t maxMessageLength()
bool available()
bool setChannel(uint8_t channel)
void setModeTx()
Sets the radio in TX mode.
TransmitPower
Convenient values for setting transmitter power in setRF()
Definition: RH_NRF51.h:140
@ TransmitPowerm8dBm
-8 dBm
Definition: RH_NRF51.h:145
@ TransmitPowerm4dBm
-4 dBm
Definition: RH_NRF51.h:144
@ TransmitPowerm12dBm
-12 dBm
Definition: RH_NRF51.h:146
@ TransmitPower4dBm
4 dBm
Definition: RH_NRF51.h:142
@ TransmitPowerm30dBm
-30 dBm
Definition: RH_NRF51.h:149
@ TransmitPowerm20dBm
-20 dBm
Definition: RH_NRF51.h:148
@ TransmitPower0dBm
0 dBm
Definition: RH_NRF51.h:143
@ TransmitPowerm16dBm
-16 dBm
Definition: RH_NRF51.h:147
DataRate
Defines convenient values for setting data rates in setRF()
Definition: RH_NRF51.h:132
@ DataRate250kbps
250 kbps
Definition: RH_NRF51.h:135
@ DataRate1Mbps
1 Mbps
Definition: RH_NRF51.h:133
@ DataRate2Mbps
2 Mbps
Definition: RH_NRF51.h:134
void validateRxBuf()
Examine the receive buffer to determine whether the message is for this node.
void setEncryptionKey(uint8_t *key=NULL)
void setModeIdle()
bool setRF(DataRate data_rate, TransmitPower power)
void setModeRx()
Sets the radio in RX mode.
virtual bool waitPacketSent()
float get_temperature()
void clearRxBuf()
Clear our local receive buffer.
bool isSending()
bool recv(uint8_t *buf, uint8_t *len)
bool setNetworkAddress(uint8_t *address, uint8_t len)
bool init()
bool send(const uint8_t *data, uint8_t len)