RadioHead
RH_RF69.h
1// RH_RF69.h
2// Author: Mike McCauley (mikem@airspayce.com)
3// Copyright (C) 2014 Mike McCauley
4// $Id: RH_RF69.h,v 1.38 2020/04/09 23:40:34 mikem Exp $
5//
6///
7
8
9#ifndef RH_RF69_h
10#define RH_RF69_h
11
12#include <RHGenericSPI.h>
13#include <RHSPIDriver.h>
14
15// The crystal oscillator frequency of the RF69 module
16#define RH_RF69_FXOSC 32000000.0
17
18// The Frequency Synthesizer step = RH_RF69_FXOSC / 2^^19
19#define RH_RF69_FSTEP (RH_RF69_FXOSC / 524288)
20
21// This is the maximum number of interrupts the driver can support
22// Most Arduinos can handle 2, Megas can handle more
23#define RH_RF69_NUM_INTERRUPTS 3
24
25// This is the bit in the SPI address that marks it as a write
26#define RH_RF69_SPI_WRITE_MASK 0x80
27
28// Max number of octets the RH_RF69 Rx and Tx FIFOs can hold
29#define RH_RF69_FIFO_SIZE 66
30
31// Maximum encryptable payload length the RF69 can support
32#define RH_RF69_MAX_ENCRYPTABLE_PAYLOAD_LEN 64
33
34// The length of the headers we add.
35// The headers are inside the RF69's payload and are therefore encrypted if encryption is enabled
36#define RH_RF69_HEADER_LEN 4
37
38// This is the maximum message length that can be supported by this driver. Limited by
39// the size of the FIFO, since we are unable to support on-the-fly filling and emptying
40// of the FIFO.
41// Can be pre-defined to a smaller size (to save SRAM) prior to including this header
42// Here we allow for 4 bytes of address and header and payload to be included in the 64 byte encryption limit.
43// the one byte payload length is not encrpyted
44#ifndef RH_RF69_MAX_MESSAGE_LEN
45#define RH_RF69_MAX_MESSAGE_LEN (RH_RF69_MAX_ENCRYPTABLE_PAYLOAD_LEN - RH_RF69_HEADER_LEN)
46#endif
47
48// Keep track of the mode the RF69 is in
49#define RH_RF69_MODE_IDLE 0
50#define RH_RF69_MODE_RX 1
51#define RH_RF69_MODE_TX 2
52
53// This is the default node address,
54#define RH_RF69_DEFAULT_NODE_ADDRESS 0
55
56// You can define the following macro (either by editing here or by passing it as a compiler definition
57// to change the default value of the ishighpowermodule argument to setTxPower to true
58//
59// #define RFM69_HW
60#ifdef RFM69_HW
61#define RH_RF69_DEFAULT_HIGHPOWER true
62#else
63#define RH_RF69_DEFAULT_HIGHPOWER false
64#endif
65
66// Register names
67#define RH_RF69_REG_00_FIFO 0x00
68#define RH_RF69_REG_01_OPMODE 0x01
69#define RH_RF69_REG_02_DATAMODUL 0x02
70#define RH_RF69_REG_03_BITRATEMSB 0x03
71#define RH_RF69_REG_04_BITRATELSB 0x04
72#define RH_RF69_REG_05_FDEVMSB 0x05
73#define RH_RF69_REG_06_FDEVLSB 0x06
74#define RH_RF69_REG_07_FRFMSB 0x07
75#define RH_RF69_REG_08_FRFMID 0x08
76#define RH_RF69_REG_09_FRFLSB 0x09
77#define RH_RF69_REG_0A_OSC1 0x0a
78#define RH_RF69_REG_0B_AFCCTRL 0x0b
79#define RH_RF69_REG_0C_RESERVED 0x0c
80#define RH_RF69_REG_0D_LISTEN1 0x0d
81#define RH_RF69_REG_0E_LISTEN2 0x0e
82#define RH_RF69_REG_0F_LISTEN3 0x0f
83#define RH_RF69_REG_10_VERSION 0x10
84#define RH_RF69_REG_11_PALEVEL 0x11
85#define RH_RF69_REG_12_PARAMP 0x12
86#define RH_RF69_REG_13_OCP 0x13
87#define RH_RF69_REG_14_RESERVED 0x14
88#define RH_RF69_REG_15_RESERVED 0x15
89#define RH_RF69_REG_16_RESERVED 0x16
90#define RH_RF69_REG_17_RESERVED 0x17
91#define RH_RF69_REG_18_LNA 0x18
92#define RH_RF69_REG_19_RXBW 0x19
93#define RH_RF69_REG_1A_AFCBW 0x1a
94#define RH_RF69_REG_1B_OOKPEAK 0x1b
95#define RH_RF69_REG_1C_OOKAVG 0x1c
96#define RH_RF69_REG_1D_OOKFIX 0x1d
97#define RH_RF69_REG_1E_AFCFEI 0x1e
98#define RH_RF69_REG_1F_AFCMSB 0x1f
99#define RH_RF69_REG_20_AFCLSB 0x20
100#define RH_RF69_REG_21_FEIMSB 0x21
101#define RH_RF69_REG_22_FEILSB 0x22
102#define RH_RF69_REG_23_RSSICONFIG 0x23
103#define RH_RF69_REG_24_RSSIVALUE 0x24
104#define RH_RF69_REG_25_DIOMAPPING1 0x25
105#define RH_RF69_REG_26_DIOMAPPING2 0x26
106#define RH_RF69_REG_27_IRQFLAGS1 0x27
107#define RH_RF69_REG_28_IRQFLAGS2 0x28
108#define RH_RF69_REG_29_RSSITHRESH 0x29
109#define RH_RF69_REG_2A_RXTIMEOUT1 0x2a
110#define RH_RF69_REG_2B_RXTIMEOUT2 0x2b
111#define RH_RF69_REG_2C_PREAMBLEMSB 0x2c
112#define RH_RF69_REG_2D_PREAMBLELSB 0x2d
113#define RH_RF69_REG_2E_SYNCCONFIG 0x2e
114#define RH_RF69_REG_2F_SYNCVALUE1 0x2f
115// another 7 sync word bytes follow, 30 through 36 inclusive
116#define RH_RF69_REG_37_PACKETCONFIG1 0x37
117#define RH_RF69_REG_38_PAYLOADLENGTH 0x38
118#define RH_RF69_REG_39_NODEADRS 0x39
119#define RH_RF69_REG_3A_BROADCASTADRS 0x3a
120#define RH_RF69_REG_3B_AUTOMODES 0x3b
121#define RH_RF69_REG_3C_FIFOTHRESH 0x3c
122#define RH_RF69_REG_3D_PACKETCONFIG2 0x3d
123#define RH_RF69_REG_3E_AESKEY1 0x3e
124// Another 15 AES key bytes follow
125#define RH_RF69_REG_4E_TEMP1 0x4e
126#define RH_RF69_REG_4F_TEMP2 0x4f
127#define RH_RF69_REG_58_TESTLNA 0x58
128#define RH_RF69_REG_5A_TESTPA1 0x5a
129#define RH_RF69_REG_5C_TESTPA2 0x5c
130#define RH_RF69_REG_6F_TESTDAGC 0x6f
131#define RH_RF69_REG_71_TESTAFC 0x71
132
133// These register masks etc are named wherever possible
134// corresponding to the bit and field names in the RFM69 Manual
135
136// RH_RF69_REG_01_OPMODE
137#define RH_RF69_OPMODE_SEQUENCEROFF 0x80
138#define RH_RF69_OPMODE_LISTENON 0x40
139#define RH_RF69_OPMODE_LISTENABORT 0x20
140#define RH_RF69_OPMODE_MODE 0x1c
141#define RH_RF69_OPMODE_MODE_SLEEP 0x00
142#define RH_RF69_OPMODE_MODE_STDBY 0x04
143#define RH_RF69_OPMODE_MODE_FS 0x08
144#define RH_RF69_OPMODE_MODE_TX 0x0c
145#define RH_RF69_OPMODE_MODE_RX 0x10
146
147// RH_RF69_REG_02_DATAMODUL
148#define RH_RF69_DATAMODUL_DATAMODE 0x60
149#define RH_RF69_DATAMODUL_DATAMODE_PACKET 0x00
150#define RH_RF69_DATAMODUL_DATAMODE_CONT_WITH_SYNC 0x40
151#define RH_RF69_DATAMODUL_DATAMODE_CONT_WITHOUT_SYNC 0x60
152#define RH_RF69_DATAMODUL_MODULATIONTYPE 0x18
153#define RH_RF69_DATAMODUL_MODULATIONTYPE_FSK 0x00
154#define RH_RF69_DATAMODUL_MODULATIONTYPE_OOK 0x08
155#define RH_RF69_DATAMODUL_MODULATIONSHAPING 0x03
156#define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_NONE 0x00
157#define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT1_0 0x01
158#define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT0_5 0x02
159#define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT0_3 0x03
160#define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_NONE 0x00
161#define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_BR 0x01
162#define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_2BR 0x02
163
164// RH_RF69_REG_11_PALEVEL
165#define RH_RF69_PALEVEL_PA0ON 0x80
166#define RH_RF69_PALEVEL_PA1ON 0x40
167#define RH_RF69_PALEVEL_PA2ON 0x20
168#define RH_RF69_PALEVEL_OUTPUTPOWER 0x1f
169
170// RH_RF69_REG_23_RSSICONFIG
171#define RH_RF69_RSSICONFIG_RSSIDONE 0x02
172#define RH_RF69_RSSICONFIG_RSSISTART 0x01
173
174// RH_RF69_REG_25_DIOMAPPING1
175#define RH_RF69_DIOMAPPING1_DIO0MAPPING 0xc0
176#define RH_RF69_DIOMAPPING1_DIO0MAPPING_00 0x00
177#define RH_RF69_DIOMAPPING1_DIO0MAPPING_01 0x40
178#define RH_RF69_DIOMAPPING1_DIO0MAPPING_10 0x80
179#define RH_RF69_DIOMAPPING1_DIO0MAPPING_11 0xc0
180
181#define RH_RF69_DIOMAPPING1_DIO1MAPPING 0x30
182#define RH_RF69_DIOMAPPING1_DIO1MAPPING_00 0x00
183#define RH_RF69_DIOMAPPING1_DIO1MAPPING_01 0x10
184#define RH_RF69_DIOMAPPING1_DIO1MAPPING_10 0x20
185#define RH_RF69_DIOMAPPING1_DIO1MAPPING_11 0x30
186
187#define RH_RF69_DIOMAPPING1_DIO2MAPPING 0x0c
188#define RH_RF69_DIOMAPPING1_DIO2MAPPING_00 0x00
189#define RH_RF69_DIOMAPPING1_DIO2MAPPING_01 0x04
190#define RH_RF69_DIOMAPPING1_DIO2MAPPING_10 0x08
191#define RH_RF69_DIOMAPPING1_DIO2MAPPING_11 0x0c
192
193#define RH_RF69_DIOMAPPING1_DIO3MAPPING 0x03
194#define RH_RF69_DIOMAPPING1_DIO3MAPPING_00 0x00
195#define RH_RF69_DIOMAPPING1_DIO3MAPPING_01 0x01
196#define RH_RF69_DIOMAPPING1_DIO3MAPPING_10 0x02
197#define RH_RF69_DIOMAPPING1_DIO3MAPPING_11 0x03
198
199// RH_RF69_REG_26_DIOMAPPING2
200#define RH_RF69_DIOMAPPING2_DIO4MAPPING 0xc0
201#define RH_RF69_DIOMAPPING2_DIO4MAPPING_00 0x00
202#define RH_RF69_DIOMAPPING2_DIO4MAPPING_01 0x40
203#define RH_RF69_DIOMAPPING2_DIO4MAPPING_10 0x80
204#define RH_RF69_DIOMAPPING2_DIO4MAPPING_11 0xc0
205
206#define RH_RF69_DIOMAPPING2_DIO5MAPPING 0x30
207#define RH_RF69_DIOMAPPING2_DIO5MAPPING_00 0x00
208#define RH_RF69_DIOMAPPING2_DIO5MAPPING_01 0x10
209#define RH_RF69_DIOMAPPING2_DIO5MAPPING_10 0x20
210#define RH_RF69_DIOMAPPING2_DIO5MAPPING_11 0x30
211
212#define RH_RF69_DIOMAPPING2_CLKOUT 0x07
213#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_ 0x00
214#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_2 0x01
215#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_4 0x02
216#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_8 0x03
217#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_16 0x04
218#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_32 0x05
219#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_RC 0x06
220#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_OFF 0x07
221
222// RH_RF69_REG_27_IRQFLAGS1
223#define RH_RF69_IRQFLAGS1_MODEREADY 0x80
224#define RH_RF69_IRQFLAGS1_RXREADY 0x40
225#define RH_RF69_IRQFLAGS1_TXREADY 0x20
226#define RH_RF69_IRQFLAGS1_PLLLOCK 0x10
227#define RH_RF69_IRQFLAGS1_RSSI 0x08
228#define RH_RF69_IRQFLAGS1_TIMEOUT 0x04
229#define RH_RF69_IRQFLAGS1_AUTOMODE 0x02
230#define RH_RF69_IRQFLAGS1_SYNADDRESSMATCH 0x01
231
232// RH_RF69_REG_28_IRQFLAGS2
233#define RH_RF69_IRQFLAGS2_FIFOFULL 0x80
234#define RH_RF69_IRQFLAGS2_FIFONOTEMPTY 0x40
235#define RH_RF69_IRQFLAGS2_FIFOLEVEL 0x20
236#define RH_RF69_IRQFLAGS2_FIFOOVERRUN 0x10
237#define RH_RF69_IRQFLAGS2_PACKETSENT 0x08
238#define RH_RF69_IRQFLAGS2_PAYLOADREADY 0x04
239#define RH_RF69_IRQFLAGS2_CRCOK 0x02
240
241// RH_RF69_REG_2E_SYNCCONFIG
242#define RH_RF69_SYNCCONFIG_SYNCON 0x80
243#define RH_RF69_SYNCCONFIG_FIFOFILLCONDITION_MANUAL 0x40
244#define RH_RF69_SYNCCONFIG_SYNCSIZE 0x38
245#define RH_RF69_SYNCCONFIG_SYNCSIZE_1 0x00
246#define RH_RF69_SYNCCONFIG_SYNCSIZE_2 0x08
247#define RH_RF69_SYNCCONFIG_SYNCSIZE_3 0x10
248#define RH_RF69_SYNCCONFIG_SYNCSIZE_4 0x18
249#define RH_RF69_SYNCCONFIG_SYNCSIZE_5 0x20
250#define RH_RF69_SYNCCONFIG_SYNCSIZE_6 0x28
251#define RH_RF69_SYNCCONFIG_SYNCSIZE_7 0x30
252#define RH_RF69_SYNCCONFIG_SYNCSIZE_8 0x38
253#define RH_RF69_SYNCCONFIG_SYNCSIZE_SYNCTOL 0x07
254
255// RH_RF69_REG_37_PACKETCONFIG1
256#define RH_RF69_PACKETCONFIG1_PACKETFORMAT_VARIABLE 0x80
257#define RH_RF69_PACKETCONFIG1_DCFREE 0x60
258#define RH_RF69_PACKETCONFIG1_DCFREE_NONE 0x00
259#define RH_RF69_PACKETCONFIG1_DCFREE_MANCHESTER 0x20
260#define RH_RF69_PACKETCONFIG1_DCFREE_WHITENING 0x40
261#define RH_RF69_PACKETCONFIG1_DCFREE_RESERVED 0x60
262#define RH_RF69_PACKETCONFIG1_CRC_ON 0x10
263#define RH_RF69_PACKETCONFIG1_CRCAUTOCLEAROFF 0x08
264#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING 0x06
265#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NONE 0x00
266#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NODE 0x02
267#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NODE_BC 0x04
268#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_RESERVED 0x06
269
270// RH_RF69_REG_3B_AUTOMODES
271#define RH_RF69_AUTOMODE_ENTER_COND_NONE 0x00
272#define RH_RF69_AUTOMODE_ENTER_COND_FIFO_NOT_EMPTY 0x20
273#define RH_RF69_AUTOMODE_ENTER_COND_FIFO_LEVEL 0x40
274#define RH_RF69_AUTOMODE_ENTER_COND_CRC_OK 0x60
275#define RH_RF69_AUTOMODE_ENTER_COND_PAYLOAD_READY 0x80
276#define RH_RF69_AUTOMODE_ENTER_COND_SYNC_ADDRESS 0xa0
277#define RH_RF69_AUTOMODE_ENTER_COND_PACKET_SENT 0xc0
278#define RH_RF69_AUTOMODE_ENTER_COND_FIFO_EMPTY 0xe0
279
280#define RH_RF69_AUTOMODE_EXIT_COND_NONE 0x00
281#define RH_RF69_AUTOMODE_EXIT_COND_FIFO_EMPTY 0x04
282#define RH_RF69_AUTOMODE_EXIT_COND_FIFO_LEVEL 0x08
283#define RH_RF69_AUTOMODE_EXIT_COND_CRC_OK 0x0c
284#define RH_RF69_AUTOMODE_EXIT_COND_PAYLOAD_READY 0x10
285#define RH_RF69_AUTOMODE_EXIT_COND_SYNC_ADDRESS 0x14
286#define RH_RF69_AUTOMODE_EXIT_COND_PACKET_SENT 0x18
287#define RH_RF69_AUTOMODE_EXIT_COND_TIMEOUT 0x1c
288
289#define RH_RF69_AUTOMODE_INTERMEDIATE_MODE_SLEEP 0x00
290#define RH_RF69_AUTOMODE_INTERMEDIATE_MODE_STDBY 0x01
291#define RH_RF69_AUTOMODE_INTERMEDIATE_MODE_RX 0x02
292#define RH_RF69_AUTOMODE_INTERMEDIATE_MODE_TX 0x03
293
294// RH_RF69_REG_3C_FIFOTHRESH
295#define RH_RF69_FIFOTHRESH_TXSTARTCONDITION_NOTEMPTY 0x80
296#define RH_RF69_FIFOTHRESH_FIFOTHRESHOLD 0x7f
297
298// RH_RF69_REG_3D_PACKETCONFIG2
299#define RH_RF69_PACKETCONFIG2_INTERPACKETRXDELAY 0xf0
300#define RH_RF69_PACKETCONFIG2_RESTARTRX 0x04
301#define RH_RF69_PACKETCONFIG2_AUTORXRESTARTON 0x02
302#define RH_RF69_PACKETCONFIG2_AESON 0x01
303
304// RH_RF69_REG_4E_TEMP1
305#define RH_RF69_TEMP1_TEMPMEASSTART 0x08
306#define RH_RF69_TEMP1_TEMPMEASRUNNING 0x04
307
308// RH_RF69_REG_5A_TESTPA1
309#define RH_RF69_TESTPA1_NORMAL 0x55
310#define RH_RF69_TESTPA1_BOOST 0x5d
311
312// RH_RF69_REG_5C_TESTPA2
313#define RH_RF69_TESTPA2_NORMAL 0x70
314#define RH_RF69_TESTPA2_BOOST 0x7c
315
316// RH_RF69_REG_6F_TESTDAGC
317#define RH_RF69_TESTDAGC_CONTINUOUSDAGC_NORMAL 0x00
318#define RH_RF69_TESTDAGC_CONTINUOUSDAGC_IMPROVED_LOWBETAON 0x20
319#define RH_RF69_TESTDAGC_CONTINUOUSDAGC_IMPROVED_LOWBETAOFF 0x30
320
321// Define this to include Serial printing in diagnostic routines
322#define RH_RF69_HAVE_SERIAL
323
324
325/////////////////////////////////////////////////////////////////////
326/// \class RH_RF69 RH_RF69.h <RH_RF69.h>
327/// \brief Driver to send and receive unaddressed, unreliable datagrams via an RF69 and compatible radio transceiver.
328///
329/// Works with
330/// - the excellent Moteino and Moteino-USB
331/// boards from LowPowerLab http://lowpowerlab.com/moteino/
332/// - compatible chips and modules such as RFM69W, RFM69HW, RFM69CW, RFM69HCW (Semtech SX1231, SX1231H),
333/// - RFM69 modules from http://www.hoperfusa.com such as http://www.hoperfusa.com/details.jsp?pid=145
334/// - Anarduino MiniWireless -CW and -HW boards http://www.anarduino.com/miniwireless/ including
335/// the marvellous high powered MinWireless-HW (with 20dBm output for excellent range)
336/// - the excellent Rocket Scream Mini Ultra Pro with the RFM69HCW
337/// http://www.rocketscream.com/blog/product/mini-ultra-pro-with-radio/
338/// - The excellent Talk2 Whisper Node boards
339/// (https://talk2.wisen.com.au/ and https://bitbucket.org/talk2/whisper-node-avr),
340/// an Arduino compatible board, which include an on-board RF69 radio, external antenna,
341/// run on 2xAAA batteries and support low power operations. RF69 examples work without modification.
342/// Use Arduino Board Manager to install the Talk2 code support as described in
343/// https://bitbucket.org/talk2/whisper-node-avr. Upeload the code with an FTDI adapter set to 3.3V.
344/// - The excellent Adafruit Feather. These are excellent boards that are available with a variety of radios.
345/// We tested with the
346/// Feather 32u4 with RFM69HCW radio, with Arduino IDE 1.6.8 and the Adafruit AVR Boards board manager version 1.6.10.
347/// https://www.adafruit.com/products/3076
348///
349/// \par Overview
350///
351/// This class provides basic functions for sending and receiving unaddressed,
352/// unreliable datagrams of arbitrary length to 64 octets per packet.
353///
354/// Manager classes may use this class to implement reliable, addressed datagrams and streams,
355/// mesh routers, repeaters, translators etc.
356///
357/// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
358/// modulation scheme.
359///
360/// This Driver provides an object-oriented interface for sending and receiving data messages with Hope-RF
361/// RF69B and compatible radio modules, such as the RFM69 module.
362///
363/// The Hope-RF (http://www.hoperf.com) RF69 is a low-cost ISM transceiver
364/// chip. It supports FSK, GFSK, OOK over a wide range of frequencies and
365/// programmable data rates. It also suports AES encryption of up to 64 octets
366/// of payload It is available prepackaged on modules such as the RFM69W. And
367/// such modules can be prepacked on processor boards such as the Moteino from
368/// LowPowerLabs (which is what we used to develop the RH_RF69 driver)
369///
370/// This Driver provides functions for sending and receiving messages of up
371/// to 60 octets on any frequency supported by the RF69, in a range of
372/// predefined data rates and frequency deviations. Frequency can be set with
373/// 61Hz precision to any frequency from 240.0MHz to 960.0MHz. Caution: most modules only support a more limited
374/// range of frequencies due to antenna tuning.
375///
376/// Up to 2 RF69B modules can be connected to an Arduino (3 on a Mega),
377/// permitting the construction of translators and frequency changers, etc.
378///
379/// The following modulation types are suppported with a range of modem configurations for
380/// common data rates and frequency deviations:
381/// - GFSK Gaussian Frequency Shift Keying
382/// - FSK Frequency Shift Keying
383///
384/// Support for other RF69 features such as on-chip temperature measurement,
385/// transmitter power control etc is also provided.
386///
387/// Tested on USB-Moteino with arduino-1.0.5
388/// on OpenSuSE 13.1
389///
390/// \par Packet Format
391///
392/// All messages sent and received by this RH_RF69 Driver conform to this packet format:
393///
394/// - 4 octets PREAMBLE
395/// - 2 octets SYNC 0x2d, 0xd4 (configurable, so you can use this as a network filter)
396/// - 1 octet RH_RF69 payload length
397/// - 4 octets HEADER: (TO, FROM, ID, FLAGS)
398/// - 0 to 60 octets DATA
399/// - 2 octets CRC computed with CRC16(IBM), computed on HEADER and DATA
400///
401/// For technical reasons, the message format is not protocol compatible with the
402/// 'HopeRF Radio Transceiver Message Library for Arduino'
403/// http://www.airspayce.com/mikem/arduino/HopeRF from the same author. Nor is
404/// it compatible with messages sent by 'Virtual Wire'
405/// http://www.airspayce.com/mikem/arduino/VirtualWire.pdf also from the same
406/// author. Nor is it compatible with messages sent by 'RF22'
407/// http://www.airspayce.com/mikem/arduino/RF22 also from the same author.
408///
409/// \par Connecting RFM-69 to Arduino
410///
411/// We tested with Moteino, which is an Arduino Uno compatible with the RFM69W
412/// module on-board. Therefore it needs no connections other than the USB
413/// programming connection and an antenna to make it work.
414///
415/// If you have a bare RFM69W that you want to connect to an Arduino, you
416/// might use these connections: CAUTION: you must use a 3.3V type
417/// Arduino, otherwise you will also need voltage level shifters between the
418/// Arduino and the RFM69. CAUTION, you must also ensure you connect an
419/// antenna
420///
421/// \code
422/// Arduino RFM69W
423/// GND----------GND (ground in)
424/// 3V3----------3.3V (3.3V in)
425/// interrupt 0 pin D2-----------DIO0 (interrupt request out)
426/// SS pin D10----------NSS (chip select in)
427/// SCK pin D13----------SCK (SPI clock in)
428/// MOSI pin D11----------MOSI (SPI Data in)
429/// MISO pin D12----------MISO (SPI Data out)
430/// \endcode
431///
432/// For Arduino Due, use these connections:
433/// \code
434/// Arduino RFM69W
435/// GND----------GND (ground in)
436/// 3V3----------3.3V (3.3V in)
437/// interrupt 0 pin D2-----------DIO0 (interrupt request out)
438/// SS pin D10----------NSS (chip select in)
439/// SCK SPI pin 3----------SCK (SPI clock in)
440/// MOSI SPI pin 4----------MOSI (SPI Data in)
441/// MISO SPI pin 1----------MISO (SPI Data out)
442/// \endcode
443///
444/// With these connections, you can then use the default constructor RH_RF69().
445/// You can override the default settings for the SS pin and the interrupt in
446/// the RH_RF69 constructor if you wish to connect the slave select SS to other
447/// than the normal one for your Arduino (D10 for Diecimila, Uno etc and D53
448/// for Mega) or the interrupt request to other than pin D2 (Caution,
449/// different processors have different constraints as to the pins available
450/// for interrupts).
451///
452/// If you have a Teensy 3.1 and a compatible RFM69 breakout board, you will need to
453/// construct the RH_RF69 instance like this:
454/// \code
455/// RH_RF69 driver(15, 16);
456/// \endcode
457///
458/// If you have a MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
459/// with RFM69 on board, you dont need to make any wiring connections
460/// (the RFM69 module is soldered onto the MotienoMEGA), but you must initialise the RH_RF69
461/// constructor like this:
462/// \code
463/// RH_RF69 driver(4, 2);
464/// \endcode
465/// Make sure you have the MoteinoMEGA core installed in your Arduino hardware folder as described in the
466/// documentation for the MoteinoMEGA.
467///
468/// If you have an Arduino M0 Pro from arduino.org,
469/// you should note that you cannot use Pin 2 for the interrupt line
470/// (Pin 2 is for the NMI only). The same comments apply to Pin 4 on Arduino Zero from arduino.cc.
471/// Instead you can use any other pin (we use Pin 3) and initialise RH_RF69 like this:
472/// \code
473/// // Slave Select is pin 10, interrupt is Pin 3
474/// RH_RF69 driver(10, 3);
475/// \endcode
476///
477/// If you have a Rocket Scream Mini Ultra Pro with the RFM69HCW
478/// - Ensure you have Arduino SAMD board support 1.6.5 or later in Arduino IDE 1.6.8 or later.
479/// - The radio SS is hardwired to pin D5 and the DIO0 interrupt to pin D2,
480/// so you need to initialise the radio like this:
481/// \code
482/// RH_RF69 driver(5, 2);
483/// \endcode
484/// - The name of the serial port on that board is 'SerialUSB', not 'Serial', so this may be helpful at the top of our
485/// sample sketches:
486/// \code
487/// #define Serial SerialUSB
488/// \endcode
489/// - You also need this in setup before radio initialisation
490/// \code
491/// // Ensure serial flash is not interfering with radio communication on SPI bus
492/// pinMode(4, OUTPUT);
493/// digitalWrite(4, HIGH);
494/// \endcode
495/// - and if you have a 915MHz part, you need this after driver/manager intitalisation:
496/// \code
497/// rf69.setFrequency(915.0);
498/// rf69.setTxPower(20);
499/// \endcode
500/// which adds up to modifying sample sketches something like:
501/// \code
502/// #include <SPI.h>
503/// #include <RH_RF69.h>
504/// RH_RF69 rf69(5, 2); // Rocket Scream Mini Ultra Pro with the RFM69HCW
505/// #define Serial SerialUSB
506///
507/// void setup()
508/// {
509/// // Ensure serial flash is not interfering with radio communication on SPI bus
510/// pinMode(4, OUTPUT);
511/// digitalWrite(4, HIGH);
512///
513/// Serial.begin(9600);
514/// while (!Serial) ; // Wait for serial port to be available
515/// if (!rf69.init())
516/// Serial.println("init failed");
517/// rf69.setFrequency(915.0);
518/// rf69.setTxPower(20);
519/// }
520/// ...
521/// \endcode
522///
523/// If you have a talk2 Whisper Node board with on-board RF69 radio,
524/// the example rf69_* sketches work without modifications. Initialise the radio like
525/// with the default constructor:
526/// \code
527/// RH_RF69 driver;
528/// \endcode
529///
530/// If you have a Feather 32u4 with RFM69HCW you need to initialise the driver like:
531/// \code
532/// RH_RF69 driver(8, 7);
533/// \endcode
534/// and since the radio is the high power HCW model, you must set the Tx power in the
535/// range 14 to 20 like this:
536/// \code
537/// driver.setTxPower(14);
538/// \endcode
539///
540/// If you are connecting an RF69 to a ESP8266 board breakout board that exposes pins
541/// 12, 13, 14, 15 (ie NOT an ESP-01) you can connect like this:
542/// \code
543/// ESP8266 RFM69W
544/// GND-----------GND (ground in)
545/// VIN-----------3.3V (3.3V in)
546/// interrupt D0 pin GPIO0-----------DIO0 (interrupt request out)
547/// SS pin GPIO15----------NSS (chip select in)
548/// SCK SPI pin GPIO14----------SCK (SPI clock in)
549/// MOSI SPI pin GPIO13----------MOSI (SPI Data in)
550/// MISO SPI pin GPIO12----------MISO (SPI Data out)
551/// \endcode
552/// and initialise with
553/// \code
554/// RH_RF69 driver(15, 0);
555/// \endcode
556/// If you are connecting an RF69 to a Sparkfun nRF52832 Breakout board
557/// with Arduino 1.8.9 with board:
558/// "SparkFun nRF52 Boards by Sparkfun Electronics version 0.2.3",
559/// you can connect like this:
560/// \code
561/// nRF52832 RFM69W
562/// GND----------GND (ground in)
563/// 3V3----------3.3V (3.3V in)
564/// interrupt 0 pin 02-----------DIO0 (interrupt request out)
565/// SS pin 08-----------NSS (chip select in)
566/// SCK SPI pin 13-----------SCK (SPI clock in)
567/// MOSI SPI pin 11-----------MOSI (SPI Data in)
568/// MISO SPI pin 12-----------MISO (SPI Data out)
569/// \endcode
570/// and initialise with
571/// \code
572/// RHSoftwareSPI softwarespi;
573/// RH_RF69 driver(8, 2, softwarespi);
574/// and inside your setup() function:
575/// softwarespi.setPins(12, 11, 13);
576/// \endcode
577///
578/// It is possible to have 2 or more radios connected to one Arduino, provided
579/// each radio has its own SS and interrupt line (SCK, SDI and SDO are common
580/// to all radios)
581///
582/// Caution: on some Arduinos such as the Mega 2560, if you set the slave
583/// select pin to be other than the usual SS pin (D53 on Mega 2560), you may
584/// need to set the usual SS pin to be an output to force the Arduino into SPI
585/// master mode.
586///
587/// Caution: Power supply requirements of the RF69 module may be relevant in some circumstances:
588/// RF69 modules are capable of pulling 45mA+ at full power, where Arduino's 3.3V line can
589/// give 50mA. You may need to make provision for alternate power supply for
590/// the RF69, especially if you wish to use full transmit power, and/or you have
591/// other shields demanding power. Inadequate power for the RF69 is likely to cause symptoms such as:
592/// -reset's/bootups terminate with "init failed" messages
593/// -random termination of communication after 5-30 packets sent/received
594/// -"fake ok" state, where initialization passes fluently, but communication doesn't happen
595/// -shields hang Arduino boards, especially during the flashing
596///
597/// \par Encryption
598///
599/// This driver support the on-chip AES encryption provided by the RF69.
600/// You can enable encryption by calling setEncryptionKey() after init() has been called.
601/// If both transmitter and receiver have been configured with the same AES key,
602/// then the receiver will recover the unencrypted message sent by the receiver.
603/// However, you should note that there is no way for RF69 nor for the RadioHead
604/// drivers to know whether the AES
605/// key for a message is 'correct' or not. This is because the RF69 CRC covers the
606/// _encrypted_ payload not the plaintext.
607///
608/// In RadioHead managers that support addressing,
609/// the RF69 AES encryption includes the RadioHead payload and the TO and FROM addresses, so
610/// occasionally (average one in 256 messages), a message encrypted with the
611/// 'wrong' key will have the 'correct' destination address, and will therefore be
612/// accepted by RadioHead as a 'random' message content from a 'random' sender.
613/// Its up to your code to figure out whether the message makes sense or not.
614///
615/// \par Interrupts
616///
617/// The RH_RF69 driver uses interrupts to react to events in the RF69 module,
618/// such as the reception of a new packet, or the completion of transmission
619/// of a packet. The RH_RF69 driver interrupt service routine reads status from
620/// and writes data to the the RF69 module via the SPI interface. It is very
621/// important therefore, that if you are using the RH_RF69 driver with another
622/// SPI based deviced, that you disable interrupts while you transfer data to
623/// and from that other device. Use cli() to disable interrupts and sei() to
624/// reenable them.
625///
626/// \par Memory
627///
628/// The RH_RF69 driver requires non-trivial amounts of memory. The sample
629/// programs above all compile to about 8kbytes each, which will fit in the
630/// flash proram memory of most Arduinos. However, the RAM requirements are
631/// more critical. Therefore, you should be vary sparing with RAM use in
632/// programs that use the RH_RF69 driver.
633///
634/// It is often hard to accurately identify when you are hitting RAM limits on Arduino.
635/// The symptoms can include:
636/// - Mysterious crashes and restarts
637/// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements)
638/// - Hanging
639/// - Output from Serial.print() not appearing
640///
641/// \par Automatic Frequency Control (AFC)
642///
643/// The RF69 module is configured by the RH_RF69 driver to always use AFC.
644///
645/// \par Transmitter Power
646///
647/// You can control the transmitter power on the RF69 transceiver
648/// with the RH_RF69::setTxPower() function. The argument can be any of
649/// -18 to +13 (for RF69W) or -14 to 20 (for RF69HW)
650/// The default is 13. Eg:
651/// \code
652/// driver.setTxPower(-5);
653/// \endcode
654///
655/// We have made some actual power measurements against
656/// programmed power for Moteino (with RF69W)
657/// - Moteino (with RF69W), USB power
658/// - 10cm RG58C/U soldered direct to RFM69 module ANT and GND
659/// - bnc connecteor
660/// - 12dB attenuator
661/// - BNC-SMA adapter
662/// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
663/// - Tektronix TDS220 scope to measure the Vout from power head
664/// \code
665/// Program power Measured Power
666/// dBm dBm
667/// -18 -17
668/// -16 -16
669/// -14 -14
670/// -12 -12
671/// -10 -9
672/// -8 -7
673/// -6 -4
674/// -4 -3
675/// -2 -2
676/// 0 0.2
677/// 2 3
678/// 4 5
679/// 6 7
680/// 8 10
681/// 10 13
682/// 12 14
683/// 13 15
684/// 14 -51
685/// 20 -51
686/// \endcode
687/// We have also made some actual power measurements against
688/// programmed power for Anarduino MiniWireless with RFM69-HW
689/// Anarduino MiniWireless (with RFM69-HW), USB power
690/// - 10cm RG58C/U soldered direct to RFM69 module ANT and GND
691/// - bnc connecteor
692/// - 2x12dB attenuators
693/// - BNC-SMA adapter
694/// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
695/// - Tektronix TDS220 scope to measure the Vout from power head
696/// \code
697/// Program power Measured Power
698/// dBm dBm
699/// -18 no measurable output
700/// 0 no measurable output
701/// 13 no measurable output
702/// 14 11
703/// 15 12
704/// 16 12.4
705/// 17 14
706/// 18 15
707/// 19 15.8
708/// 20 17
709/// \endcode
710/// (Caution: we dont claim laboratory accuracy for these measurements)
711/// You would not expect to get anywhere near these powers to air with a simple 1/4 wavelength wire antenna.
712/// Caution: although the RFM69 appears to have a PC antenna on board, you will get much better power and range even
713/// with just a 1/4 wave wire antenna.
714///
715/// \par Performance
716///
717/// Some simple speed performance tests have been conducted.
718/// In general packet transmission rate will be limited by the modulation scheme.
719/// Also, if your code does any slow operations like Serial printing it will also limit performance.
720/// We disabled any printing in the tests below.
721/// We tested with RH_RF69::GFSK_Rb250Fd250, which is probably the fastest scheme available.
722/// We tested with a 13 octet message length, over a very short distance of 10cm.
723///
724/// Transmission (no reply) tests with modulation RH_RF69::GFSK_Rb250Fd250 and a
725/// 13 octet message show about 152 messages per second transmitted and received.
726///
727/// Transmit-and-wait-for-a-reply tests with modulation RH_RF69::GFSK_Rb250Fd250 and a
728/// 13 octet message (send and receive) show about 68 round trips per second.
729///
730class RH_RF69 : public RHSPIDriver
731{
732public:
733
734 /// \brief Defines register values for a set of modem configuration registers
735 ///
736 /// Defines register values for a set of modem configuration registers
737 /// that can be passed to setModemRegisters() if none of the choices in
738 /// ModemConfigChoice suit your need setModemRegisters() writes the
739 /// register values from this structure to the appropriate RF69 registers
740 /// to set the desired modulation type, data rate and deviation/bandwidth.
741 typedef struct
742 {
743 uint8_t reg_02; ///< Value for register RH_RF69_REG_02_DATAMODUL
744 uint8_t reg_03; ///< Value for register RH_RF69_REG_03_BITRATEMSB
745 uint8_t reg_04; ///< Value for register RH_RF69_REG_04_BITRATELSB
746 uint8_t reg_05; ///< Value for register RH_RF69_REG_05_FDEVMSB
747 uint8_t reg_06; ///< Value for register RH_RF69_REG_06_FDEVLSB
748 uint8_t reg_19; ///< Value for register RH_RF69_REG_19_RXBW
749 uint8_t reg_1a; ///< Value for register RH_RF69_REG_1A_AFCBW
750 uint8_t reg_37; ///< Value for register RH_RF69_REG_37_PACKETCONFIG1
751 } ModemConfig;
752
753 /// Choices for setModemConfig() for a selected subset of common
754 /// modulation types, and data rates. If you need another configuration,
755 /// use the register calculator. and call setModemRegisters() with your
756 /// desired settings.
757 /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
758 /// definitions and not their integer equivalents: its possible that new values will be
759 /// introduced in later versions (though we will try to avoid it).
760 /// CAUTION: some of these configurations do not work corectly and are marked as such.
761 typedef enum
762 {
763 FSK_Rb2Fd5 = 0, ///< FSK, Whitening, Rb = 2kbs, Fd = 5kHz
764 FSK_Rb2_4Fd4_8, ///< FSK, Whitening, Rb = 2.4kbs, Fd = 4.8kHz
765 FSK_Rb4_8Fd9_6, ///< FSK, Whitening, Rb = 4.8kbs, Fd = 9.6kHz
766 FSK_Rb9_6Fd19_2, ///< FSK, Whitening, Rb = 9.6kbs, Fd = 19.2kHz
767 FSK_Rb19_2Fd38_4, ///< FSK, Whitening, Rb = 19.2kbs, Fd = 38.4kHz
768 FSK_Rb38_4Fd76_8, ///< FSK, Whitening, Rb = 38.4kbs, Fd = 76.8kHz
769 FSK_Rb57_6Fd120, ///< FSK, Whitening, Rb = 57.6kbs, Fd = 120kHz
770 FSK_Rb125Fd125, ///< FSK, Whitening, Rb = 125kbs, Fd = 125kHz
771 FSK_Rb250Fd250, ///< FSK, Whitening, Rb = 250kbs, Fd = 250kHz
772 FSK_Rb55555Fd50, ///< FSK, Whitening, Rb = 55555kbs,Fd = 50kHz for RFM69 lib compatibility
773
774 GFSK_Rb2Fd5, ///< GFSK, Whitening, Rb = 2kbs, Fd = 5kHz
775 GFSK_Rb2_4Fd4_8, ///< GFSK, Whitening, Rb = 2.4kbs, Fd = 4.8kHz
776 GFSK_Rb4_8Fd9_6, ///< GFSK, Whitening, Rb = 4.8kbs, Fd = 9.6kHz
777 GFSK_Rb9_6Fd19_2, ///< GFSK, Whitening, Rb = 9.6kbs, Fd = 19.2kHz
778 GFSK_Rb19_2Fd38_4, ///< GFSK, Whitening, Rb = 19.2kbs, Fd = 38.4kHz
779 GFSK_Rb38_4Fd76_8, ///< GFSK, Whitening, Rb = 38.4kbs, Fd = 76.8kHz
780 GFSK_Rb57_6Fd120, ///< GFSK, Whitening, Rb = 57.6kbs, Fd = 120kHz
781 GFSK_Rb125Fd125, ///< GFSK, Whitening, Rb = 125kbs, Fd = 125kHz
782 GFSK_Rb250Fd250, ///< GFSK, Whitening, Rb = 250kbs, Fd = 250kHz
783 GFSK_Rb55555Fd50, ///< GFSK, Whitening, Rb = 55555kbs,Fd = 50kHz
784
785 OOK_Rb1Bw1, ///< OOK, Whitening, Rb = 1kbs, Rx Bandwidth = 1kHz.
786 OOK_Rb1_2Bw75, ///< OOK, Whitening, Rb = 1.2kbs, Rx Bandwidth = 75kHz.
787 OOK_Rb2_4Bw4_8, ///< OOK, Whitening, Rb = 2.4kbs, Rx Bandwidth = 4.8kHz.
788 OOK_Rb4_8Bw9_6, ///< OOK, Whitening, Rb = 4.8kbs, Rx Bandwidth = 9.6kHz.
789 OOK_Rb9_6Bw19_2, ///< OOK, Whitening, Rb = 9.6kbs, Rx Bandwidth = 19.2kHz.
790 OOK_Rb19_2Bw38_4, ///< OOK, Whitening, Rb = 19.2kbs, Rx Bandwidth = 38.4kHz.
791 OOK_Rb32Bw64, ///< OOK, Whitening, Rb = 32kbs, Rx Bandwidth = 64kHz.
792
793// Test,
795
796 /// Constructor. You can have multiple instances, but each instance must have its own
797 /// interrupt and slave select pin. After constructing, you must call init() to initialise the interface
798 /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
799 /// distinct interrupt lines, one for each instance.
800 /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF69 before
801 /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
802 /// \param[in] interruptPin The interrupt Pin number that is connected to the RF69 DIO0 interrupt line.
803 /// Defaults to pin 2.
804 /// Caution: You must specify an interrupt capable pin.
805 /// On many Arduino boards, there are limitations as to which pins may be used as interrupts.
806 /// On Leonardo pins 0, 1, 2 or 3. On Mega2560 pins 2, 3, 18, 19, 20, 21. On Due and Teensy, any digital pin.
807 /// On Arduino Zero from arduino.cc, any digital pin other than 4.
808 /// On Arduino M0 Pro from arduino.org, any digital pin other than 2.
809 /// On other Arduinos pins 2 or 3.
810 /// See http://arduino.cc/en/Reference/attachInterrupt for more details.
811 /// On Chipkit Uno32, pins 38, 2, 7, 8, 35.
812 /// On other boards, any digital pin may be used.
813 /// \param[in] spi Pointer to the SPI interface object to use.
814 /// Defaults to the standard Arduino hardware SPI interface
815 RH_RF69(uint8_t slaveSelectPin = SS, uint8_t interruptPin = 2, RHGenericSPI& spi = hardware_spi);
816
817 /// Initialises this instance and the radio module connected to it.
818 /// The following steps are taken:
819 /// - Initialise the slave select pin and the SPI interface library
820 /// - Checks the connected RF69 module can be communicated
821 /// - Attaches an interrupt handler
822 /// - Configures the RF69 module
823 /// - Sets the frequency to 434.0 MHz
824 /// - Sets the modem data rate to FSK_Rb2Fd5
825 /// \return true if everything was successful
826 bool init();
827
828 /// Reads the on-chip temperature sensor.
829 /// The RF69 must be in Idle mode (= RF69 Standby) to measure temperature.
830 /// The measurement is uncalibrated and without calibration, you can expect it to be far from
831 /// correct.
832 /// \return The measured temperature, in degrees C from -40 to 85 (uncalibrated)
833 int8_t temperatureRead();
834
835 /// Sets the transmitter and receiver
836 /// centre frequency
837 /// \param[in] centre Frequency in MHz. 240.0 to 960.0. Caution, RF69 comes in several
838 /// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
839 /// \param[in] afcPullInRange Not used
840 /// \return true if the selected frquency centre is within range
841 bool setFrequency(float centre, float afcPullInRange = 0.05);
842
843 /// Reads and returns the current RSSI value.
844 /// Causes the current signal strength to be measured and returned
845 /// If you want to find the RSSI
846 /// of the last received message, use lastRssi() instead.
847 /// \return The current RSSI value on units of 0.5dB.
848 int8_t rssiRead();
849
850 /// Sets the parameters for the RF69 OPMODE.
851 /// This is a low level device access function, and should not normally ned to be used by user code.
852 /// Instead can use stModeRx(), setModeTx(), setModeIdle()
853 /// \param[in] mode RF69 OPMODE to set, one of RH_RF69_OPMODE_MODE_*.
854 void setOpMode(uint8_t mode);
855
856 /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
857 /// disables them.
858 void setModeIdle();
859
860 /// If current mode is Tx or Idle, changes it to Rx.
861 /// Starts the receiver in the RF69.
862 void setModeRx();
863
864 /// If current mode is Rx or Idle, changes it to Rx. F
865 /// Starts the transmitter in the RF69.
866 void setModeTx();
867
868 /// Sets the transmitter power output level.
869 /// Be a good neighbour and set the lowest power level you need.
870 /// Caution: legal power limits may apply in certain countries.
871 /// After init(), the power will be set to 13dBm for a low power module.
872 /// If you are using a high p[ower modfule such as an RFM69HW, you MUST set the power level
873 /// with the ishighpowermodule flag set to true. Else you wil get no measurable power output.
874 /// Simlarly if you are not using a high power module, you must NOT set the ishighpowermodule
875 /// (which is the default)
876 /// \param[in] power Transmitter power level in dBm. For RF69W (ishighpowermodule = false),
877 /// valid values are from -18 to +13.; Values outside this range are trimmed.
878 /// For RF69HW (ishighpowermodule = true), valid values are from -2 to +20.
879 /// Caution: at +20dBm, duty cycle is limited to 1% and a
880 /// maximum VSWR of 3:1 at the antenna port.
881 /// \param ishighpowermodule Set to true if the connected module is a high power module RFM69HW
882 void setTxPower(int8_t power, bool ishighpowermodule = RH_RF69_DEFAULT_HIGHPOWER);
883
884 /// Sets all the registers required to configure the data modem in the RF69, including the data rate,
885 /// bandwidths etc. You can use this to configure the modem with custom configurations if none of the
886 /// canned configurations in ModemConfigChoice suit you.
887 /// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
888 void setModemRegisters(const ModemConfig* config);
889
890 /// Select one of the predefined modem configurations. If you need a modem configuration not provided
891 /// here, use setModemRegisters() with your own ModemConfig. The default after init() is RH_RF69::GFSK_Rb250Fd250.
892 /// \param[in] index The configuration choice.
893 /// \return true if index is a valid choice.
895
896 /// Starts the receiver and checks whether a received message is available.
897 /// This can be called multiple times in a timeout loop
898 /// \return true if a complete, valid message has been received and is able to be retrieved by
899 /// recv()
900 bool available();
901
902 /// Turns the receiver on if it not already on.
903 /// If there is a valid message available, copy it to buf and return true
904 /// else return false.
905 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
906 /// You should be sure to call this function frequently enough to not miss any messages
907 /// It is recommended that you call it in your main loop.
908 /// \param[in] buf Location to copy the received message
909 /// \param[in,out] len Pointer to the number of octets available in buf. The number be reset to the actual number of octets copied.
910 /// \return true if a valid message was copied to buf
911 bool recv(uint8_t* buf, uint8_t* len);
912
913 /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
914 /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
915 /// of 0 is NOT permitted.
916 /// \param[in] data Array of data to be sent
917 /// \param[in] len Number of bytes of data to send (> 0)
918 /// \return true if the message length was valid and it was correctly queued for transmit
919 bool send(const uint8_t* data, uint8_t len);
920
921 /// Sets the length of the preamble
922 /// in bytes.
923 /// Caution: this should be set to the same
924 /// value on all nodes in your network. Default is 4.
925 /// Sets the message preamble length in REG_0?_PREAMBLE?SB
926 /// \param[in] bytes Preamble length in bytes.
927 void setPreambleLength(uint16_t bytes);
928
929 /// Sets the sync words for transmit and receive
930 /// Caution: SyncWords should be set to the same
931 /// value on all nodes in your network. Nodes with different SyncWords set will never receive
932 /// each others messages, so different SyncWords can be used to isolate different
933 /// networks from each other. Default is { 0x2d, 0xd4 }.
934 /// Caution: tests here show that with a single sync word (ie where len == 1),
935 /// RFM69 reception can be unreliable.
936 /// To disable sync word generation and detection, call with the defaults: setSyncWords();
937 /// \param[in] syncWords Array of sync words, 1 to 4 octets long. NULL if no sync words to be used.
938 /// \param[in] len Number of sync words to set, 1 to 4. 0 if no sync words to be used.
939 void setSyncWords(const uint8_t* syncWords = NULL, uint8_t len = 0);
940
941 /// Enables AES encryption and sets the AES encryption key, used
942 /// to encrypt and decrypt all messages. The default is disabled.
943 /// \param[in] key The key to use. Must be 16 bytes long. The same key must be installed
944 /// in other instances of RF69, otherwise communications will not work correctly. If key is NULL,
945 /// encryption is disabled, which is the default.
946 void setEncryptionKey(uint8_t* key = NULL);
947
948 /// Returns the time in millis since the most recent preamble was received, and when the most recent
949 /// RSSI measurement was made.
951
952 /// The maximum message length supported by this driver
953 /// \return The maximum message length supported by this driver
954 uint8_t maxMessageLength();
955
956 /// Prints the value of a single register
957 /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
958 /// For debugging/testing only
959 /// \return true if successful
960 bool printRegister(uint8_t reg);
961
962 /// Prints the value of all the RF69 registers
963 /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
964 /// For debugging/testing only
965 /// \return true if successful
966 bool printRegisters();
967
968 /// Sets the radio operating mode for the case when the driver is idle (ie not
969 /// transmitting or receiving), allowing you to control the idle mode power requirements
970 /// at the expense of slower transitions to transmit and receive modes.
971 /// By default, the idle mode is RH_RF69_OPMODE_MODE_STDBY,
972 /// but eg setIdleMode(RH_RF69_OPMODE_MODE_SLEEP) will provide a much lower
973 /// idle current but slower transitions. Call this function after init().
974 /// \param[in] idleMode The chip operating mode to use when the driver is idle. One of RH_RF69_OPMODE_*
975 void setIdleMode(uint8_t idleMode);
976
977 /// Sets the radio into low-power sleep mode.
978 /// If successful, the transport will stay in sleep mode until woken by
979 /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
980 /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
981 /// \return true if sleep mode was successfully entered.
982 virtual bool sleep();
983
984 /// Return the integer value of the device type
985 /// as read from the device in from RH_RF69_REG_10_VERSION.
986 /// Expect 0x24, depending on the type of device actually
987 /// connected.
988 /// \return The integer device type
989 uint16_t deviceType() {return _deviceType;};
990
991protected:
992 /// This is a low level function to handle the interrupts for one instance of RF69.
993 /// Called automatically by isr*()
994 /// Should not need to be called by user code.
995 void handleInterrupt();
996
997 /// Low level function to read the FIFO and put the received data into the receive buffer
998 /// Should not need to be called by user code.
999 void readFifo();
1000
1001protected:
1002 /// Low level interrupt service routine for RF69 connected to interrupt 0
1003 static void isr0();
1004
1005 /// Low level interrupt service routine for RF69 connected to interrupt 1
1006 static void isr1();
1007
1008 /// Low level interrupt service routine for RF69 connected to interrupt 1
1009 static void isr2();
1010
1011 /// Array of instances connected to interrupts 0 and 1
1013
1014 /// Index of next interrupt number to use in _deviceForInterrupt
1015 static uint8_t _interruptCount;
1016
1017 /// The configured interrupt pin connected to this instance
1019
1020 /// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
1021 /// else 0xff
1023
1024 /// The radio OP mode to use when mode is RHModeIdle
1025 uint8_t _idleMode;
1026
1027 /// The reported device type
1029
1030 /// The selected output power in dBm
1031 int8_t _power;
1032
1033 /// The message length in _buf
1034 volatile uint8_t _bufLen;
1035
1036 /// Array of octets of teh last received message or the next to transmit message
1037 uint8_t _buf[RH_RF69_MAX_MESSAGE_LEN];
1038
1039 /// True when there is a valid message in the Rx buffer
1040 volatile bool _rxBufValid;
1041
1042 /// Time in millis since the last preamble was received (and the last time the RSSI was measured)
1044};
1045
1046/// @example rf69_client.ino
1047/// @example rf69_server.ino
1048/// @example rf69_reliable_datagram_client.ino
1049/// @example rf69_reliable_datagram_server.ino
1050
1051
1052#endif
virtual RHMode mode()
Definition: RHGenericDriver.cpp:165
Base class for SPI interfaces.
Definition: RHGenericSPI.h:31
Base class for RadioHead drivers that use the SPI bus to communicate with its transport hardware.
Definition: RHSPIDriver.h:39
Driver to send and receive unaddressed, unreliable datagrams via an RF69 and compatible radio transce...
Definition: RH_RF69.h:731
bool init()
Definition: RH_RF69.cpp:100
void setModemRegisters(const ModemConfig *config)
Definition: RH_RF69.cpp:434
static RH_RF69 * _deviceForInterrupt[]
Array of instances connected to interrupts 0 and 1.
Definition: RH_RF69.h:1012
uint32_t _lastPreambleTime
Time in millis since the last preamble was received (and the last time the RSSI was measured)
Definition: RH_RF69.h:1043
static void isr0()
Low level interrupt service routine for RF69 connected to interrupt 0.
Definition: RH_RF69.cpp:268
void handleInterrupt()
Definition: RH_RF69.cpp:201
void setEncryptionKey(uint8_t *key=NULL)
Definition: RH_RF69.cpp:476
void setModeRx()
Definition: RH_RF69.cpp:356
uint8_t _interruptPin
The configured interrupt pin connected to this instance.
Definition: RH_RF69.h:1018
static uint8_t _interruptCount
Index of next interrupt number to use in _deviceForInterrupt.
Definition: RH_RF69.h:1015
static void isr1()
Low level interrupt service routine for RF69 connected to interrupt 1.
Definition: RH_RF69.cpp:273
void setIdleMode(uint8_t idleMode)
Definition: RH_RF69.cpp:95
bool available()
Definition: RH_RF69.cpp:489
uint8_t _idleMode
The radio OP mode to use when mode is RHModeIdle.
Definition: RH_RF69.h:1025
uint16_t deviceType()
Definition: RH_RF69.h:989
uint32_t getLastPreambleTime()
int8_t temperatureRead()
Definition: RH_RF69.cpp:284
void setOpMode(uint8_t mode)
Definition: RH_RF69.cpp:319
ModemConfigChoice
Definition: RH_RF69.h:762
@ GFSK_Rb57_6Fd120
GFSK, Whitening, Rb = 57.6kbs, Fd = 120kHz.
Definition: RH_RF69.h:780
@ OOK_Rb2_4Bw4_8
OOK, Whitening, Rb = 2.4kbs, Rx Bandwidth = 4.8kHz.
Definition: RH_RF69.h:787
@ FSK_Rb38_4Fd76_8
FSK, Whitening, Rb = 38.4kbs, Fd = 76.8kHz.
Definition: RH_RF69.h:768
@ FSK_Rb9_6Fd19_2
FSK, Whitening, Rb = 9.6kbs, Fd = 19.2kHz.
Definition: RH_RF69.h:766
@ GFSK_Rb125Fd125
GFSK, Whitening, Rb = 125kbs, Fd = 125kHz.
Definition: RH_RF69.h:781
@ FSK_Rb2Fd5
FSK, Whitening, Rb = 2kbs, Fd = 5kHz.
Definition: RH_RF69.h:763
@ GFSK_Rb4_8Fd9_6
GFSK, Whitening, Rb = 4.8kbs, Fd = 9.6kHz.
Definition: RH_RF69.h:776
@ FSK_Rb250Fd250
FSK, Whitening, Rb = 250kbs, Fd = 250kHz.
Definition: RH_RF69.h:771
@ FSK_Rb57_6Fd120
FSK, Whitening, Rb = 57.6kbs, Fd = 120kHz.
Definition: RH_RF69.h:769
@ GFSK_Rb19_2Fd38_4
GFSK, Whitening, Rb = 19.2kbs, Fd = 38.4kHz.
Definition: RH_RF69.h:778
@ OOK_Rb19_2Bw38_4
OOK, Whitening, Rb = 19.2kbs, Rx Bandwidth = 38.4kHz.
Definition: RH_RF69.h:790
@ FSK_Rb2_4Fd4_8
FSK, Whitening, Rb = 2.4kbs, Fd = 4.8kHz.
Definition: RH_RF69.h:764
@ OOK_Rb9_6Bw19_2
OOK, Whitening, Rb = 9.6kbs, Rx Bandwidth = 19.2kHz.
Definition: RH_RF69.h:789
@ FSK_Rb19_2Fd38_4
FSK, Whitening, Rb = 19.2kbs, Fd = 38.4kHz.
Definition: RH_RF69.h:767
@ GFSK_Rb38_4Fd76_8
GFSK, Whitening, Rb = 38.4kbs, Fd = 76.8kHz.
Definition: RH_RF69.h:779
@ GFSK_Rb9_6Fd19_2
GFSK, Whitening, Rb = 9.6kbs, Fd = 19.2kHz.
Definition: RH_RF69.h:777
@ GFSK_Rb250Fd250
GFSK, Whitening, Rb = 250kbs, Fd = 250kHz.
Definition: RH_RF69.h:782
@ GFSK_Rb55555Fd50
GFSK, Whitening, Rb = 55555kbs,Fd = 50kHz.
Definition: RH_RF69.h:783
@ FSK_Rb4_8Fd9_6
FSK, Whitening, Rb = 4.8kbs, Fd = 9.6kHz.
Definition: RH_RF69.h:765
@ OOK_Rb1Bw1
OOK, Whitening, Rb = 1kbs, Rx Bandwidth = 1kHz.
Definition: RH_RF69.h:785
@ FSK_Rb125Fd125
FSK, Whitening, Rb = 125kbs, Fd = 125kHz.
Definition: RH_RF69.h:770
@ OOK_Rb4_8Bw9_6
OOK, Whitening, Rb = 4.8kbs, Rx Bandwidth = 9.6kHz.
Definition: RH_RF69.h:788
@ GFSK_Rb2Fd5
GFSK, Whitening, Rb = 2kbs, Fd = 5kHz.
Definition: RH_RF69.h:774
@ GFSK_Rb2_4Fd4_8
GFSK, Whitening, Rb = 2.4kbs, Fd = 4.8kHz.
Definition: RH_RF69.h:775
@ OOK_Rb32Bw64
OOK, Whitening, Rb = 32kbs, Rx Bandwidth = 64kHz.
Definition: RH_RF69.h:791
@ FSK_Rb55555Fd50
FSK, Whitening, Rb = 55555kbs,Fd = 50kHz for RFM69 lib compatibility.
Definition: RH_RF69.h:772
@ OOK_Rb1_2Bw75
OOK, Whitening, Rb = 1.2kbs, Rx Bandwidth = 75kHz.
Definition: RH_RF69.h:786
void setModeTx()
Definition: RH_RF69.cpp:372
int8_t rssiRead()
Definition: RH_RF69.cpp:307
void readFifo()
Definition: RH_RF69.cpp:232
RH_RF69(uint8_t slaveSelectPin=SS, uint8_t interruptPin=2, RHGenericSPI &spi=hardware_spi)
Definition: RH_RF69.cpp:86
bool setModemConfig(ModemConfigChoice index)
Definition: RH_RF69.cpp:443
bool send(const uint8_t *data, uint8_t len)
Definition: RH_RF69.cpp:515
uint8_t _buf[RH_RF69_MAX_MESSAGE_LEN]
Array of octets of teh last received message or the next to transmit message.
Definition: RH_RF69.h:1037
virtual bool sleep()
Definition: RH_RF69.cpp:346
void setPreambleLength(uint16_t bytes)
Definition: RH_RF69.cpp:455
bool printRegister(uint8_t reg)
Definition: RH_RF69.cpp:552
bool setFrequency(float centre, float afcPullInRange=0.05)
Definition: RH_RF69.cpp:294
volatile uint8_t _bufLen
The message length in _buf.
Definition: RH_RF69.h:1034
bool printRegisters()
Definition: RH_RF69.cpp:562
void setTxPower(int8_t power, bool ishighpowermodule=RH_RF69_DEFAULT_HIGHPOWER)
Definition: RH_RF69.cpp:389
static void isr2()
Low level interrupt service routine for RF69 connected to interrupt 1.
Definition: RH_RF69.cpp:278
uint8_t maxMessageLength()
Definition: RH_RF69.cpp:547
uint8_t _deviceType
The reported device type.
Definition: RH_RF69.h:1028
bool recv(uint8_t *buf, uint8_t *len)
Definition: RH_RF69.cpp:497
void setSyncWords(const uint8_t *syncWords=NULL, uint8_t len=0)
Definition: RH_RF69.cpp:461
int8_t _power
The selected output power in dBm.
Definition: RH_RF69.h:1031
uint8_t _myInterruptIndex
Definition: RH_RF69.h:1022
void setModeIdle()
Definition: RH_RF69.cpp:331
volatile bool _rxBufValid
True when there is a valid message in the Rx buffer.
Definition: RH_RF69.h:1040
Defines register values for a set of modem configuration registers.
Definition: RH_RF69.h:742
uint8_t reg_02
Value for register RH_RF69_REG_02_DATAMODUL.
Definition: RH_RF69.h:743
uint8_t reg_19
Value for register RH_RF69_REG_19_RXBW.
Definition: RH_RF69.h:748
uint8_t reg_05
Value for register RH_RF69_REG_05_FDEVMSB.
Definition: RH_RF69.h:746
uint8_t reg_04
Value for register RH_RF69_REG_04_BITRATELSB.
Definition: RH_RF69.h:745
uint8_t reg_37
Value for register RH_RF69_REG_37_PACKETCONFIG1.
Definition: RH_RF69.h:750
uint8_t reg_06
Value for register RH_RF69_REG_06_FDEVLSB.
Definition: RH_RF69.h:747
uint8_t reg_03
Value for register RH_RF69_REG_03_BITRATEMSB.
Definition: RH_RF69.h:744
uint8_t reg_1a
Value for register RH_RF69_REG_1A_AFCBW.
Definition: RH_RF69.h:749