RadioHead
RH_RF22.h
1// RH_RF22.h
2// Author: Mike McCauley (mikem@airspayce.com)
3// Copyright (C) 2011 Mike McCauley
4// $Id: RH_RF22.h,v 1.39 2020/08/04 09:02:14 mikem Exp $
5//
6
7#ifndef RH_RF22_h
8#define RH_RF22_h
9
10#include <RHGenericSPI.h>
11#include <RHSPIDriver.h>
12
13// This is the maximum number of interrupts the library can support
14// Most Arduinos can handle 2, Megas can handle more
15#define RH_RF22_NUM_INTERRUPTS 3
16
17// This is the bit in the SPI address that marks it as a write
18#define RH_RF22_SPI_WRITE_MASK 0x80
19
20// This is the maximum message length that can be supported by this library. Limited by
21// the single message length octet in the header.
22// Yes, 255 is correct even though the FIFO size in the RF22 is only
23// 64 octets. We use interrupts to refill the Tx FIFO during transmission and to empty the
24// Rx FIFO during reception
25// Can be pre-defined to a smaller size (to save SRAM) prior to including this header
26#ifndef RH_RF22_MAX_MESSAGE_LEN
27//#define RH_RF22_MAX_MESSAGE_LEN 255
28#define RH_RF22_MAX_MESSAGE_LEN 50
29#endif
30
31// Max number of octets the RF22 Rx and Tx FIFOs can hold
32#define RH_RF22_FIFO_SIZE 64
33
34// These values we set for FIFO thresholds (4, 55) are actually the same as the POR values
35#define RH_RF22_TXFFAEM_THRESHOLD 4
36#define RH_RF22_RXFFAFULL_THRESHOLD 55
37
38// Number of registers to be passed to setModemConfig(). Obsolete.
39#define RH_RF22_NUM_MODEM_CONFIG_REGS 18
40
41// Register names
42#define RH_RF22_REG_00_DEVICE_TYPE 0x00
43#define RH_RF22_REG_01_VERSION_CODE 0x01
44#define RH_RF22_REG_02_DEVICE_STATUS 0x02
45#define RH_RF22_REG_03_INTERRUPT_STATUS1 0x03
46#define RH_RF22_REG_04_INTERRUPT_STATUS2 0x04
47#define RH_RF22_REG_05_INTERRUPT_ENABLE1 0x05
48#define RH_RF22_REG_06_INTERRUPT_ENABLE2 0x06
49#define RH_RF22_REG_07_OPERATING_MODE1 0x07
50#define RH_RF22_REG_08_OPERATING_MODE2 0x08
51#define RH_RF22_REG_09_OSCILLATOR_LOAD_CAPACITANCE 0x09
52#define RH_RF22_REG_0A_UC_OUTPUT_CLOCK 0x0a
53#define RH_RF22_REG_0B_GPIO_CONFIGURATION0 0x0b
54#define RH_RF22_REG_0C_GPIO_CONFIGURATION1 0x0c
55#define RH_RF22_REG_0D_GPIO_CONFIGURATION2 0x0d
56#define RH_RF22_REG_0E_IO_PORT_CONFIGURATION 0x0e
57#define RH_RF22_REG_0F_ADC_CONFIGURATION 0x0f
58#define RH_RF22_REG_10_ADC_SENSOR_AMP_OFFSET 0x10
59#define RH_RF22_REG_11_ADC_VALUE 0x11
60#define RH_RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION 0x12
61#define RH_RF22_REG_13_TEMPERATURE_VALUE_OFFSET 0x13
62#define RH_RF22_REG_14_WAKEUP_TIMER_PERIOD1 0x14
63#define RH_RF22_REG_15_WAKEUP_TIMER_PERIOD2 0x15
64#define RH_RF22_REG_16_WAKEUP_TIMER_PERIOD3 0x16
65#define RH_RF22_REG_17_WAKEUP_TIMER_VALUE1 0x17
66#define RH_RF22_REG_18_WAKEUP_TIMER_VALUE2 0x18
67#define RH_RF22_REG_19_LDC_MODE_DURATION 0x19
68#define RH_RF22_REG_1A_LOW_BATTERY_DETECTOR_THRESHOLD 0x1a
69#define RH_RF22_REG_1B_BATTERY_VOLTAGE_LEVEL 0x1b
70#define RH_RF22_REG_1C_IF_FILTER_BANDWIDTH 0x1c
71#define RH_RF22_REG_1D_AFC_LOOP_GEARSHIFT_OVERRIDE 0x1d
72#define RH_RF22_REG_1E_AFC_TIMING_CONTROL 0x1e
73#define RH_RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE 0x1f
74#define RH_RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE 0x20
75#define RH_RF22_REG_21_CLOCK_RECOVERY_OFFSET2 0x21
76#define RH_RF22_REG_22_CLOCK_RECOVERY_OFFSET1 0x22
77#define RH_RF22_REG_23_CLOCK_RECOVERY_OFFSET0 0x23
78#define RH_RF22_REG_24_CLOCK_RECOVERY_TIMING_LOOP_GAIN1 0x24
79#define RH_RF22_REG_25_CLOCK_RECOVERY_TIMING_LOOP_GAIN0 0x25
80#define RH_RF22_REG_26_RSSI 0x26
81#define RH_RF22_REG_27_RSSI_THRESHOLD 0x27
82#define RH_RF22_REG_28_ANTENNA_DIVERSITY1 0x28
83#define RH_RF22_REG_29_ANTENNA_DIVERSITY2 0x29
84#define RH_RF22_REG_2A_AFC_LIMITER 0x2a
85#define RH_RF22_REG_2B_AFC_CORRECTION_READ 0x2b
86#define RH_RF22_REG_2C_OOK_COUNTER_VALUE_1 0x2c
87#define RH_RF22_REG_2D_OOK_COUNTER_VALUE_2 0x2d
88#define RH_RF22_REG_2E_SLICER_PEAK_HOLD 0x2e
89#define RH_RF22_REG_30_DATA_ACCESS_CONTROL 0x30
90#define RH_RF22_REG_31_EZMAC_STATUS 0x31
91#define RH_RF22_REG_32_HEADER_CONTROL1 0x32
92#define RH_RF22_REG_33_HEADER_CONTROL2 0x33
93#define RH_RF22_REG_34_PREAMBLE_LENGTH 0x34
94#define RH_RF22_REG_35_PREAMBLE_DETECTION_CONTROL1 0x35
95#define RH_RF22_REG_36_SYNC_WORD3 0x36
96#define RH_RF22_REG_37_SYNC_WORD2 0x37
97#define RH_RF22_REG_38_SYNC_WORD1 0x38
98#define RH_RF22_REG_39_SYNC_WORD0 0x39
99#define RH_RF22_REG_3A_TRANSMIT_HEADER3 0x3a
100#define RH_RF22_REG_3B_TRANSMIT_HEADER2 0x3b
101#define RH_RF22_REG_3C_TRANSMIT_HEADER1 0x3c
102#define RH_RF22_REG_3D_TRANSMIT_HEADER0 0x3d
103#define RH_RF22_REG_3E_PACKET_LENGTH 0x3e
104#define RH_RF22_REG_3F_CHECK_HEADER3 0x3f
105#define RH_RF22_REG_40_CHECK_HEADER2 0x40
106#define RH_RF22_REG_41_CHECK_HEADER1 0x41
107#define RH_RF22_REG_42_CHECK_HEADER0 0x42
108#define RH_RF22_REG_43_HEADER_ENABLE3 0x43
109#define RH_RF22_REG_44_HEADER_ENABLE2 0x44
110#define RH_RF22_REG_45_HEADER_ENABLE1 0x45
111#define RH_RF22_REG_46_HEADER_ENABLE0 0x46
112#define RH_RF22_REG_47_RECEIVED_HEADER3 0x47
113#define RH_RF22_REG_48_RECEIVED_HEADER2 0x48
114#define RH_RF22_REG_49_RECEIVED_HEADER1 0x49
115#define RH_RF22_REG_4A_RECEIVED_HEADER0 0x4a
116#define RH_RF22_REG_4B_RECEIVED_PACKET_LENGTH 0x4b
117#define RH_RF22_REG_50_ANALOG_TEST_BUS_SELECT 0x50
118#define RH_RF22_REG_51_DIGITAL_TEST_BUS_SELECT 0x51
119#define RH_RF22_REG_52_TX_RAMP_CONTROL 0x52
120#define RH_RF22_REG_53_PLL_TUNE_TIME 0x53
121#define RH_RF22_REG_55_CALIBRATION_CONTROL 0x55
122#define RH_RF22_REG_56_MODEM_TEST 0x56
123#define RH_RF22_REG_57_CHARGE_PUMP_TEST 0x57
124#define RH_RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING 0x58
125#define RH_RF22_REG_59_DIVIDER_CURRENT_TRIMMING 0x59
126#define RH_RF22_REG_5A_VCO_CURRENT_TRIMMING 0x5a
127#define RH_RF22_REG_5B_VCO_CALIBRATION 0x5b
128#define RH_RF22_REG_5C_SYNTHESIZER_TEST 0x5c
129#define RH_RF22_REG_5D_BLOCK_ENABLE_OVERRIDE1 0x5d
130#define RH_RF22_REG_5E_BLOCK_ENABLE_OVERRIDE2 0x5e
131#define RH_RF22_REG_5F_BLOCK_ENABLE_OVERRIDE3 0x5f
132#define RH_RF22_REG_60_CHANNEL_FILTER_COEFFICIENT_ADDRESS 0x60
133#define RH_RF22_REG_61_CHANNEL_FILTER_COEFFICIENT_VALUE 0x61
134#define RH_RF22_REG_62_CRYSTAL_OSCILLATOR_POR_CONTROL 0x62
135#define RH_RF22_REG_63_RC_OSCILLATOR_COARSE_CALIBRATION 0x63
136#define RH_RF22_REG_64_RC_OSCILLATOR_FINE_CALIBRATION 0x64
137#define RH_RF22_REG_65_LDO_CONTROL_OVERRIDE 0x65
138#define RH_RF22_REG_66_LDO_LEVEL_SETTINGS 0x66
139#define RH_RF22_REG_67_DELTA_SIGMA_ADC_TUNING1 0x67
140#define RH_RF22_REG_68_DELTA_SIGMA_ADC_TUNING2 0x68
141#define RH_RF22_REG_69_AGC_OVERRIDE1 0x69
142#define RH_RF22_REG_6A_AGC_OVERRIDE2 0x6a
143#define RH_RF22_REG_6B_GFSK_FIR_FILTER_COEFFICIENT_ADDRESS 0x6b
144#define RH_RF22_REG_6C_GFSK_FIR_FILTER_COEFFICIENT_VALUE 0x6c
145#define RH_RF22_REG_6D_TX_POWER 0x6d
146#define RH_RF22_REG_6E_TX_DATA_RATE1 0x6e
147#define RH_RF22_REG_6F_TX_DATA_RATE0 0x6f
148#define RH_RF22_REG_70_MODULATION_CONTROL1 0x70
149#define RH_RF22_REG_71_MODULATION_CONTROL2 0x71
150#define RH_RF22_REG_72_FREQUENCY_DEVIATION 0x72
151#define RH_RF22_REG_73_FREQUENCY_OFFSET1 0x73
152#define RH_RF22_REG_74_FREQUENCY_OFFSET2 0x74
153#define RH_RF22_REG_75_FREQUENCY_BAND_SELECT 0x75
154#define RH_RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1 0x76
155#define RH_RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0 0x77
156#define RH_RF22_REG_79_FREQUENCY_HOPPING_CHANNEL_SELECT 0x79
157#define RH_RF22_REG_7A_FREQUENCY_HOPPING_STEP_SIZE 0x7a
158#define RH_RF22_REG_7C_TX_FIFO_CONTROL1 0x7c
159#define RH_RF22_REG_7D_TX_FIFO_CONTROL2 0x7d
160#define RH_RF22_REG_7E_RX_FIFO_CONTROL 0x7e
161#define RH_RF22_REG_7F_FIFO_ACCESS 0x7f
162
163// These register masks etc are named wherever possible
164// corresponding to the bit and field names in the RF-22 Manual
165// RH_RF22_REG_00_DEVICE_TYPE 0x00
166#define RH_RF22_DEVICE_TYPE_RX_TRX 0x08
167#define RH_RF22_DEVICE_TYPE_TX 0x07
168
169// RH_RF22_REG_02_DEVICE_STATUS 0x02
170#define RH_RF22_FFOVL 0x80
171#define RH_RF22_FFUNFL 0x40
172#define RH_RF22_RXFFEM 0x20
173#define RH_RF22_HEADERR 0x10
174#define RH_RF22_FREQERR 0x08
175#define RH_RF22_LOCKDET 0x04
176#define RH_RF22_CPS 0x03
177#define RH_RF22_CPS_IDLE 0x00
178#define RH_RF22_CPS_RX 0x01
179#define RH_RF22_CPS_TX 0x10
180
181// RH_RF22_REG_03_INTERRUPT_STATUS1 0x03
182#define RH_RF22_IFFERROR 0x80
183#define RH_RF22_ITXFFAFULL 0x40
184#define RH_RF22_ITXFFAEM 0x20
185#define RH_RF22_IRXFFAFULL 0x10
186#define RH_RF22_IEXT 0x08
187#define RH_RF22_IPKSENT 0x04
188#define RH_RF22_IPKVALID 0x02
189#define RH_RF22_ICRCERROR 0x01
190
191// RH_RF22_REG_04_INTERRUPT_STATUS2 0x04
192#define RH_RF22_ISWDET 0x80
193#define RH_RF22_IPREAVAL 0x40
194#define RH_RF22_IPREAINVAL 0x20
195#define RH_RF22_IRSSI 0x10
196#define RH_RF22_IWUT 0x08
197#define RH_RF22_ILBD 0x04
198#define RH_RF22_ICHIPRDY 0x02
199#define RH_RF22_IPOR 0x01
200
201// RH_RF22_REG_05_INTERRUPT_ENABLE1 0x05
202#define RH_RF22_ENFFERR 0x80
203#define RH_RF22_ENTXFFAFULL 0x40
204#define RH_RF22_ENTXFFAEM 0x20
205#define RH_RF22_ENRXFFAFULL 0x10
206#define RH_RF22_ENEXT 0x08
207#define RH_RF22_ENPKSENT 0x04
208#define RH_RF22_ENPKVALID 0x02
209#define RH_RF22_ENCRCERROR 0x01
210
211// RH_RF22_REG_06_INTERRUPT_ENABLE2 0x06
212#define RH_RF22_ENSWDET 0x80
213#define RH_RF22_ENPREAVAL 0x40
214#define RH_RF22_ENPREAINVAL 0x20
215#define RH_RF22_ENRSSI 0x10
216#define RH_RF22_ENWUT 0x08
217#define RH_RF22_ENLBDI 0x04
218#define RH_RF22_ENCHIPRDY 0x02
219#define RH_RF22_ENPOR 0x01
220
221// RH_RF22_REG_07_OPERATING_MODE 0x07
222#define RH_RF22_SWRES 0x80
223#define RH_RF22_ENLBD 0x40
224#define RH_RF22_ENWT 0x20
225#define RH_RF22_X32KSEL 0x10
226#define RH_RF22_TXON 0x08
227#define RH_RF22_RXON 0x04
228#define RH_RF22_PLLON 0x02
229#define RH_RF22_XTON 0x01
230
231// RH_RF22_REG_08_OPERATING_MODE2 0x08
232#define RH_RF22_ANTDIV 0xc0
233#define RH_RF22_RXMPK 0x10
234#define RH_RF22_AUTOTX 0x08
235#define RH_RF22_ENLDM 0x04
236#define RH_RF22_FFCLRRX 0x02
237#define RH_RF22_FFCLRTX 0x01
238
239// RH_RF22_REG_0F_ADC_CONFIGURATION 0x0f
240#define RH_RF22_ADCSTART 0x80
241#define RH_RF22_ADCDONE 0x80
242#define RH_RF22_ADCSEL 0x70
243#define RH_RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR 0x00
244#define RH_RF22_ADCSEL_GPIO0_SINGLE_ENDED 0x10
245#define RH_RF22_ADCSEL_GPIO1_SINGLE_ENDED 0x20
246#define RH_RF22_ADCSEL_GPIO2_SINGLE_ENDED 0x30
247#define RH_RF22_ADCSEL_GPIO0_GPIO1_DIFFERENTIAL 0x40
248#define RH_RF22_ADCSEL_GPIO1_GPIO2_DIFFERENTIAL 0x50
249#define RH_RF22_ADCSEL_GPIO0_GPIO2_DIFFERENTIAL 0x60
250#define RH_RF22_ADCSEL_GND 0x70
251#define RH_RF22_ADCREF 0x0c
252#define RH_RF22_ADCREF_BANDGAP_VOLTAGE 0x00
253#define RH_RF22_ADCREF_VDD_ON_3 0x08
254#define RH_RF22_ADCREF_VDD_ON_2 0x0c
255#define RH_RF22_ADCGAIN 0x03
256
257// RH_RF22_REG_10_ADC_SENSOR_AMP_OFFSET 0x10
258#define RH_RF22_ADCOFFS 0x0f
259
260// RH_RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION 0x12
261#define RH_RF22_TSRANGE 0xc0
262#define RH_RF22_TSRANGE_M64_64C 0x00
263#define RH_RF22_TSRANGE_M64_192C 0x40
264#define RH_RF22_TSRANGE_0_128C 0x80
265#define RH_RF22_TSRANGE_M40_216F 0xc0
266#define RH_RF22_ENTSOFFS 0x20
267#define RH_RF22_ENTSTRIM 0x10
268#define RH_RF22_TSTRIM 0x0f
269
270// RH_RF22_REG_14_WAKEUP_TIMER_PERIOD1 0x14
271#define RH_RF22_WTR 0x3c
272#define RH_RF22_WTD 0x03
273
274// RH_RF22_REG_1D_AFC_LOOP_GEARSHIFT_OVERRIDE 0x1d
275#define RH_RF22_AFBCD 0x80
276#define RH_RF22_ENAFC 0x40
277#define RH_RF22_AFCGEARH 0x38
278#define RH_RF22_AFCGEARL 0x07
279
280// RH_RF22_REG_1E_AFC_TIMING_CONTROL 0x1e
281#define RH_RF22_SWAIT_TIMER 0xc0
282#define RH_RF22_SHWAIT 0x38
283#define RH_RF22_ANWAIT 0x07
284
285// RH_RF22_REG_30_DATA_ACCESS_CONTROL 0x30
286#define RH_RF22_ENPACRX 0x80
287#define RH_RF22_MSBFRST 0x00
288#define RH_RF22_LSBFRST 0x40
289#define RH_RF22_CRCHDRS 0x00
290#define RH_RF22_CRCDONLY 0x20
291#define RH_RF22_SKIP2PH 0x10
292#define RH_RF22_ENPACTX 0x08
293#define RH_RF22_ENCRC 0x04
294#define RH_RF22_CRC 0x03
295#define RH_RF22_CRC_CCITT 0x00
296#define RH_RF22_CRC_CRC_16_IBM 0x01
297#define RH_RF22_CRC_IEC_16 0x02
298#define RH_RF22_CRC_BIACHEVA 0x03
299
300// RH_RF22_REG_32_HEADER_CONTROL1 0x32
301#define RH_RF22_BCEN 0xf0
302#define RH_RF22_BCEN_NONE 0x00
303#define RH_RF22_BCEN_HEADER0 0x10
304#define RH_RF22_BCEN_HEADER1 0x20
305#define RH_RF22_BCEN_HEADER2 0x40
306#define RH_RF22_BCEN_HEADER3 0x80
307#define RH_RF22_HDCH 0x0f
308#define RH_RF22_HDCH_NONE 0x00
309#define RH_RF22_HDCH_HEADER0 0x01
310#define RH_RF22_HDCH_HEADER1 0x02
311#define RH_RF22_HDCH_HEADER2 0x04
312#define RH_RF22_HDCH_HEADER3 0x08
313
314// RH_RF22_REG_33_HEADER_CONTROL2 0x33
315#define RH_RF22_HDLEN 0x70
316#define RH_RF22_HDLEN_0 0x00
317#define RH_RF22_HDLEN_1 0x10
318#define RH_RF22_HDLEN_2 0x20
319#define RH_RF22_HDLEN_3 0x30
320#define RH_RF22_HDLEN_4 0x40
321#define RH_RF22_VARPKLEN 0x00
322#define RH_RF22_FIXPKLEN 0x08
323#define RH_RF22_SYNCLEN 0x06
324#define RH_RF22_SYNCLEN_1 0x00
325#define RH_RF22_SYNCLEN_2 0x02
326#define RH_RF22_SYNCLEN_3 0x04
327#define RH_RF22_SYNCLEN_4 0x06
328#define RH_RF22_PREALEN8 0x01
329
330// RH_RF22_REG_6D_TX_POWER 0x6d
331// https://www.sparkfun.com/datasheets/Wireless/General/RFM22B.pdf
332#define RH_RF22_PAPEAKVAL 0x80
333#define RH_RF22_PAPEAKEN 0x40
334#define RH_RF22_PAPEAKLVL 0x30
335#define RH_RF22_PAPEAKLVL6_5 0x00
336#define RH_RF22_PAPEAKLVL7 0x10
337#define RH_RF22_PAPEAKLVL7_5 0x20
338#define RH_RF22_PAPEAKLVL8 0x30
339#define RH_RF22_LNA_SW 0x08
340#define RH_RF22_TXPOW 0x07
341#define RH_RF22_TXPOW_4X31 0x08 // Not used in RFM22B
342// For RFM22B:
343#define RH_RF22_TXPOW_1DBM 0x00
344#define RH_RF22_TXPOW_2DBM 0x01
345#define RH_RF22_TXPOW_5DBM 0x02
346#define RH_RF22_TXPOW_8DBM 0x03
347#define RH_RF22_TXPOW_11DBM 0x04
348#define RH_RF22_TXPOW_14DBM 0x05
349#define RH_RF22_TXPOW_17DBM 0x06
350#define RH_RF22_TXPOW_20DBM 0x07
351// RFM23B only:
352#define RH_RF22_RF23B_TXPOW_M8DBM 0x00 // -8dBm
353#define RH_RF22_RF23B_TXPOW_M5DBM 0x01 // -5dBm
354#define RH_RF22_RF23B_TXPOW_M2DBM 0x02 // -2dBm
355#define RH_RF22_RF23B_TXPOW_1DBM 0x03 // 1dBm
356#define RH_RF22_RF23B_TXPOW_4DBM 0x04 // 4dBm
357#define RH_RF22_RF23B_TXPOW_7DBM 0x05 // 7dBm
358#define RH_RF22_RF23B_TXPOW_10DBM 0x06 // 10dBm
359#define RH_RF22_RF23B_TXPOW_13DBM 0x07 // 13dBm
360// RFM23BP only:
361#define RH_RF22_RF23BP_TXPOW_28DBM 0x05 // 28dBm
362#define RH_RF22_RF23BP_TXPOW_29DBM 0x06 // 29dBm
363#define RH_RF22_RF23BP_TXPOW_30DBM 0x07 // 30dBm
364
365// RH_RF22_REG_71_MODULATION_CONTROL2 0x71
366#define RH_RF22_TRCLK 0xc0
367#define RH_RF22_TRCLK_NONE 0x00
368#define RH_RF22_TRCLK_GPIO 0x40
369#define RH_RF22_TRCLK_SDO 0x80
370#define RH_RF22_TRCLK_NIRQ 0xc0
371#define RH_RF22_DTMOD 0x30
372#define RH_RF22_DTMOD_DIRECT_GPIO 0x00
373#define RH_RF22_DTMOD_DIRECT_SDI 0x10
374#define RH_RF22_DTMOD_FIFO 0x20
375#define RH_RF22_DTMOD_PN9 0x30
376#define RH_RF22_ENINV 0x08
377#define RH_RF22_FD8 0x04
378#define RH_RF22_MODTYP 0x30
379#define RH_RF22_MODTYP_UNMODULATED 0x00
380#define RH_RF22_MODTYP_OOK 0x01
381#define RH_RF22_MODTYP_FSK 0x02
382#define RH_RF22_MODTYP_GFSK 0x03
383
384
385// RH_RF22_REG_75_FREQUENCY_BAND_SELECT 0x75
386#define RH_RF22_SBSEL 0x40
387#define RH_RF22_HBSEL 0x20
388#define RH_RF22_FB 0x1f
389
390// Define this to include Serial printing in diagnostic routines
391#define RH_RF22_HAVE_SERIAL
392
393/////////////////////////////////////////////////////////////////////
394/// \class RH_RF22 RH_RF22.h <RH_RF22.h>
395/// \brief Driver to send and receive unaddressed, unreliable datagrams via an RF22 and compatible radio transceiver.
396///
397/// Works with RF22, RF23 based radio modules, and compatible chips and modules, including:
398/// - RF22 bare module: http://www.sparkfun.com/products/10153
399/// (Caution, that is a 3.3V part, and requires a 3.3V CPU such as Teensy etc or level shifters)
400/// - RF22 shield: http://www.sparkfun.com/products/11018
401/// - RF22 integrated board http://www.anarduino.com/miniwireless
402/// - RFM23BP bare module: http://www.anarduino.com/details.jsp?pid=130
403/// - Silicon Labs Si4430/31/32 based modules. S4432 is equivalent to RF22. Si4431/30 is equivalent to RF23.
404///
405/// Data based on https://www.sparkfun.com/datasheets/Wireless/General/RFM22B.pdf
406///
407/// \par Overview
408///
409/// This base class provides basic functions for sending and receiving unaddressed,
410/// unreliable datagrams of arbitrary length to 255 octets per packet.
411///
412/// Manager classes may use this class to implement reliable, addressed datagrams and streams,
413/// mesh routers, repeaters, translators etc.
414///
415/// On transmission, the TO and FROM addresses default to 0x00, unless changed by a subclass.
416/// On reception the TO addressed is checked against the node address (defaults to 0x00) or the
417/// broadcast address (which is 0xff). The ID and FLAGS are set to 0, and not checked by this class.
418/// This permits use of the this base RH_RF22 class as an
419/// unaddressed, unreliable datagram service without the use of one the RadioHead Manager classes.
420///
421/// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
422/// modulation scheme.
423///
424/// \par Details
425///
426/// This Driver provides an object-oriented interface for sending and receiving data messages with Hope-RF
427/// RF22 and RF23 based radio modules, and compatible chips and modules,
428/// including the RFM22B transceiver module such as
429/// this bare module: http://www.sparkfun.com/products/10153
430/// and this shield: http://www.sparkfun.com/products/11018
431/// and this module: http://www.hoperfusa.com/details.jsp?pid=131
432/// and this integrated board: http://www.anarduino.com/miniwireless
433/// and RF23BP modules such as this http://www.anarduino.com/details.jsp?pid=130
434///
435/// The Hope-RF (http://www.hoperf.com) RFM22B (http://www.hoperf.com/rf_fsk/fsk/RFM22B.htm)
436/// is a low-cost ISM transceiver module. It supports FSK, GFSK, OOK over a wide
437/// range of frequencies and programmable data rates.
438/// Manual can be found at https://www.sparkfun.com/datasheets/Wireless/General/RFM22.PDF
439///
440/// This library provides functions for sending and receiving messages of up to 255 octets on any
441/// frequency supported by the RF22B, in a range of predefined data rates and frequency deviations.
442/// Frequency can be set with 312Hz precision to any frequency from 240.0MHz to 960.0MHz.
443///
444/// Up to 3 RF22B modules can be connected to an Arduino, permitting the construction of translators
445/// and frequency changers, etc.
446///
447/// The following modulation types are suppported with a range of modem configurations for
448/// common data rates and frequency deviations:
449/// - GFSK Gaussian Frequency Shift Keying
450/// - FSK Frequency Shift Keying
451/// - OOK On-Off Keying
452///
453/// Support for other RF22B features such as on-chip temperature measurement, analog-digital
454/// converter, transmitter power control etc is also provided.
455///
456/// Tested on Arduino Diecimila, Uno and Mega with arduino-0021, 1.0.5
457/// on OpenSuSE 13.1 and avr-libc-1.6.1-1.15,
458/// cross-avr-binutils-2.19-9.1, cross-avr-gcc-4.1.3_20080612-26.5.
459/// With HopeRF RFM22 modules that appear to have RF22B chips on board:
460/// - Device Type Code = 0x08 (RX/TRX)
461/// - Version Code = 0x06
462/// Works on Duo. Works with Sparkfun RFM22 Wireless shields. Works with RFM22 modules from http://www.hoperfusa.com/
463/// Works with Arduino 1.0 to at least 1.0.5. Works on Maple, Flymaple, Uno32 (with ChipKIT Core with Arduino IDE).
464///
465/// \par Packet Format
466///
467/// All messages sent and received by this Driver must conform to this packet format:
468///
469/// - 8 nibbles (4 octets) PREAMBLE
470/// - 2 octets SYNC 0x2d, 0xd4
471/// - 4 octets HEADER: (TO, FROM, ID, FLAGS)
472/// - 1 octet LENGTH (0 to 255), number of octets in DATA
473/// - 0 to 255 octets DATA
474/// - 2 octets CRC computed with CRC16(IBM), computed on HEADER, LENGTH and DATA
475///
476/// For technical reasons, the message format is not protocol compatible with the
477/// 'HopeRF Radio Transceiver Message Library for Arduino' http://www.airspayce.com/mikem/arduino/HopeRF from the same author. Nor is it compatible with
478/// 'Virtual Wire' http://www.airspayce.com/mikem/arduino/VirtualWire.pdf also from the same author.
479///
480/// \par Connecting RFM-22 to Arduino
481///
482/// If you have the Sparkfun RFM22 Shield (https://www.sparkfun.com/products/11018)
483/// the connections described below are done for you on the shield, no changes required,
484/// just add headers and plug it in to an Arduino (but not and Arduino Mega, see below)
485///
486/// The physical connection between the RF22B and the Arduino requires 3.3V,
487/// the 3 x SPI pins (SCK, SDI, SDO), a Slave Select pin and an interrupt pin.
488///
489/// Note: some devices may need a pullup resister on the SDO line.
490///
491/// Note also that on the RFM22B (but not the RFM23B), it is required to control the TX_ANT and
492/// RX_ANT pins of the RFM22 in order to control the antenna connection properly. The RH_RF22
493/// driver is configured by default so that GPIO0 and GPIO1 outputs can
494/// control TX_ANT and RX_ANT input pins respectively automatically. On RFM22,
495/// you must connect GPIO0
496/// to TX_ANT and GPIO1 to RX_ANT for this automatic antenna switching to
497/// occur. See setGpioReversed() for more details. These connections are not required on RFM23B.
498///
499/// If you are using the Sparkfun RF22 shield, it will work with any 5V arduino without modification.
500/// Connect the RFM-22 module to most Arduino's like this (Caution, Arduino Mega has different pins for SPI,
501/// see below).
502/// \code
503/// Arduino RFM-22B
504/// GND----------GND-\ (ground in)
505/// SDN-/ (shutdown in)
506/// 3V3----------VCC (3.3V in)
507/// interrupt 0 pin D2-----------NIRQ (interrupt request out)
508/// SS pin D10----------NSEL (chip select in)
509/// SCK pin D13----------SCK (SPI clock in)
510/// MOSI pin D11----------SDI (SPI Data in)
511/// MISO pin D12----------SDO (SPI data out)
512/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
513/// \--TX_ANT (TX antenna control in) RFM22B only
514/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
515/// \--RX_ANT (RX antenna control in) RFM22B only
516/// \endcode
517/// For an Arduino Mega:
518/// \code
519/// Mega RFM-22B
520/// GND----------GND-\ (ground in)
521/// SDN-/ (shutdown in)
522/// 3V3----------VCC (3.3V in)
523/// interrupt 0 pin D2-----------NIRQ (interrupt request out)
524/// SS pin D10----------NSEL (chip select in)
525/// SCK pin D52----------SCK (SPI clock in)
526/// MOSI pin D51----------SDI (SPI Data in)
527/// MISO pin D50----------SDO (SPI data out)
528/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
529/// \--TX_ANT (TX antenna control in) RFM22B only
530/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
531/// \--RX_ANT (RX antenna control in) RFM22B only
532/// \endcode
533/// For Chipkit Uno32. Caution: you must also ensure jumper JP4 on the Uno32 is set to RD4
534/// \code
535/// Arduino RFM-22B
536/// GND----------GND-\ (ground in)
537/// SDN-/ (shutdown in)
538/// 3V3----------VCC (3.3V in)
539/// interrupt 0 pin D38----------NIRQ (interrupt request out)
540/// SS pin D10----------NSEL (chip select in)
541/// SCK pin D13----------SCK (SPI clock in)
542/// MOSI pin D11----------SDI (SPI Data in)
543/// MISO pin D12----------SDO (SPI data out)
544/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
545/// \--TX_ANT (TX antenna control in) RFM22B only
546/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
547/// \--RX_ANT (RX antenna control in) RFM22B only
548/// \endcode
549/// For Teensy 3.1
550/// \code
551/// Teensy RFM-22B
552/// GND----------GND-\ (ground in)
553/// SDN-/ (shutdown in)
554/// 3V3----------VCC (3.3V in)
555/// interrupt 2 pin D2-----------NIRQ (interrupt request out)
556/// SS pin D10----------NSEL (chip select in)
557/// SCK pin D13----------SCK (SPI clock in)
558/// MOSI pin D11----------SDI (SPI Data in)
559/// MISO pin D12----------SDO (SPI data out)
560/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
561/// \--TX_ANT (TX antenna control in) RFM22B only
562/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
563/// \--RX_ANT (RX antenna control in) RFM22B only
564/// \endcode
565/// For an Arduino Due (the SPI pins do not come out on the Digital pins as for normal Arduino, but only
566/// appear on the SPI header)
567/// \code
568/// Due RFM-22B
569/// GND----------GND-\ (ground in)
570/// SDN-/ (shutdown in)
571/// 5V-----------VCC (5V in)
572/// interrupt 0 pin D2-----------NIRQ (interrupt request out)
573/// SS pin D10----------NSEL (chip select in)
574/// SCK SPI pin 3----------SCK (SPI clock in)
575/// MOSI SPI pin 4----------SDI (SPI Data in)
576/// MISO SPI pin 1----------SDO (SPI data out)
577/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
578/// \--TX_ANT (TX antenna control in) RFM22B only
579/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
580/// \--RX_ANT (RX antenna control in) RFM22B only
581/// \endcode
582/// and use the default constructor:
583/// RH_RF22 driver;
584/// For connecting an Arduino to an RFM23BP module. Note that the antenna control pins are reversed
585/// compared to the RF22.
586/// \code
587/// Arduino RFM-23BP
588/// GND----------GND-\ (ground in)
589/// SDN-/ (shutdown in)
590/// 5V-----------VCC (5V in)
591/// interrupt 0 pin D2-----------NIRQ (interrupt request out)
592/// SS pin D10----------NSEL (chip select in)
593/// SCK pin D13----------SCK (SPI clock in)
594/// MOSI pin D11----------SDI (SPI Data in)
595/// MISO pin D12----------SDO (SPI data out)
596/// /--GPIO0 (GPIO0 out to control receiver antenna RXON)
597/// \--RXON (RX antenna control in)
598/// /--GPIO1 (GPIO1 out to control transmitter antenna TXON)
599/// \--TXON (TX antenna control in)
600/// \endcode
601///
602/// and you can then use the default constructor RH_RF22().
603/// You can override the default settings for the SS pin and the interrupt
604/// in the RH_RF22 constructor if you wish to connect the slave select SS to other than the normal one for your
605/// Arduino (D10 for Diecimila, Uno etc and D53 for Mega)
606/// or the interrupt request to other than pin D2 (Caution, different processors have different constraints as to the
607/// pins available for interrupts).
608///
609/// Caution: some people have had problems with some batches of
610/// RFM23BP chips burning out their nIRQ outputs for unknown
611/// reasons when run at 5V. Some users assert that running RFM23BP with voltage
612/// dividers at 3.3V is to be preferred. We have not tested or verified
613/// either the cause or the supposed cure.
614//
615///
616/// If you have an Arduino Zero, you should note that you cannot use Pin 2 for the interrupt line
617/// (Pin 2 is for the NMI only), instead you can use any other pin (we use Pin 3) and initialise RH_RF69 like this:
618/// \code
619/// // Slave Select is pin 10, interrupt is Pin 3
620/// RH_RF22 driver(10, 3);
621/// \endcode
622///
623/// If you have an ESP32 (we tested with the Geekworm EASY-KIT ESP32-B1 which has a ESP-WROOM-32 chip)
624/// \code
625/// ESP32 RFM-22B
626/// GND----------GND-\ (ground in)
627/// SDN-/ (shutdown in)
628/// 3V3----------VCC (3.3V in)
629/// interrupt pin GPIO15-------NIRQ (interrupt request out)
630/// SS pin GPIO13-------NSEL (chip select in)
631/// SCK pin GPIO18-------SCK (SPI clock in)
632/// MOSI pin GPIO23-------SDI (SPI Data in)
633/// MISO pin GPIO19-------SDO (SPI data out)
634/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
635/// \--TX_ANT (TX antenna control in) RFM22B only
636/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
637/// \--RX_ANT (RX antenna control in) RFM22B only
638/// \endcode
639/// and initialise like this:
640/// \code
641/// RH_RF22 driver(13, 15);
642/// \endcode
643/// You can of course use other pins for NSEL and NIRQ if you prefer.
644///
645/// To connect an STM32 F4 Discovery board to RF22 using Arduino and Arduino_STM32
646/// connect the pins like this:
647/// \code
648/// STM32 RFM-22B
649/// GND----------GND-\ (ground in)
650/// SDN-/ (shutdown in)
651/// VDD----------VCC (3.3V in)
652/// interrupt pin PB1----------NIRQ (interrupt request out)
653/// SS pin PB0----------NSEL (chip select in)
654/// SCK pin PB3----------SCK (SPI clock in)
655/// MOSI pin PB5----------SDI (SPI Data in)
656/// MISO pin PB4----------SDO (SPI data out)
657/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
658/// \--TX_ANT (TX antenna control in) RFM22B only
659/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
660/// \--RX_ANT (RX antenna control in) RFM22B only
661/// \endcode
662/// and initialise like this:
663/// \code
664/// RH_RF22 driver(PB0, PB1);
665/// \endcode
666/// You can of use other pins for NSEL and NIRQ if you prefer.
667///
668/// To connect an ATTiny Mega x16 such as AtTiny 3216 etc
669/// (running at 5V) etc RF22 using Arduino using Spencer Kondes
670/// megaTinyCore https://github.com/SpenceKonde/megaTinyCore connect the pins like this:
671/// (pin numbering based on https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x16.md)
672/// \code
673/// AtTiny x16 RFM-22B
674/// GND----------GND-\ (ground in)
675/// SDN-/ (shutdown in)
676/// VDD----------VCC (5V in)
677/// interrupt pin PA6----------NIRQ (interrupt request out)
678/// SS pin PC0----------NSEL (chip select in)
679/// SCK pin PA3----------SCK (SPI clock in)
680/// MOSI pin PA1----------SDI (SPI Data in)
681/// MISO pin PA2----------SDO (SPI data out)
682/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
683/// \--TX_ANT (TX antenna control in) RFM22B only
684/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
685/// \--RX_ANT (RX antenna control in) RFM22B only
686/// \endcode
687/// and initialise like this:
688/// \code
689/// RH_RF22 driver(10, 2);
690/// \endcode
691/// You can of use other pins for NSEL and NIRQ if you prefer.
692///
693/// For ESP8266-based ESP-12 modules. Caution: on some breakout boards we have seen
694/// labels for D4 and D5 reversed.
695/// \code
696/// ESP-12 RFM-22B
697/// GND----------GND-\ (ground in)
698/// SDN-/ (shutdown in)
699/// 3V3----------VCC (3.3V in)
700/// interrupt 0 pin D4-----------NIRQ (interrupt request out)
701/// SS pin D5-----------NSEL (chip select in)
702/// SCK pin D14----------SCK (SPI clock in)
703/// MOSI pin D13----------SDI (SPI Data in)
704/// MISO pin D12----------SDO (SPI data out)
705/// /--GPIO0 (GPIO0 out to control transmitter antenna TX_ANT)
706/// \--TX_ANT (TX antenna control in) RFM22B only
707/// /--GPIO1 (GPIO1 out to control receiver antenna RX_ANT)
708/// \--RX_ANT (RX antenna control in) RFM22B only
709/// \endcode
710/// and initialise like this:
711/// \code
712/// RH_RF22 driver(5, 4);
713/// \endcode
714///
715/// Note: It is possible to have 2 radios connected to one Arduino, provided each radio has its own
716/// SS and interrupt line (SCK, SDI and SDO are common to both radios)
717///
718/// Caution: on some Arduinos such as the Mega 2560, if you set the slave select pin to be other than the usual SS
719/// pin (D53 on Mega 2560), you may need to set the usual SS pin to be an output to force the Arduino into SPI
720/// master mode.
721///
722/// Caution: Power supply requirements of the RF22 module may be relevant in some circumstances:
723/// RF22 modules are capable of pulling 80mA+ at full power, where Arduino's 3.3V line can
724/// give 50mA. You may need to make provision for alternate power supply for
725/// the RF22, especially if you wish to use full transmit power, and/or you have
726/// other shields demanding power. Inadequate power for the RF22 is reported to cause symptoms such as:
727/// - reset's/bootups terminate with "init failed" messages
728/// -random termination of communication after 5-30 packets sent/received
729/// -"fake ok" state, where initialization passes fluently, but communication doesn't happen
730/// -shields hang Arduino boards, especially during the flashing
731///
732/// Caution: some RF22 breakout boards (such as the HAB-RFM22B-BOA HAB-RFM22B-BO) reportedly
733/// have the TX_ANT and RX_ANT pre-connected to GPIO0 and GPIO1 round the wrong way. You can work with this
734/// if you use setGpioReversed().
735///
736/// Caution: If you are using a bare RF22 module without IO level shifters, you may have difficulty connecting
737/// to a 5V arduino. The RF22 module is 3.3V and its IO pins are 3.3V not 5V. Some Arduinos (Diecimila and
738/// Uno) seem to work OK with this, and some (Mega) do not always work reliably. Your Mileage May Vary.
739/// For best result, use level shifters, or use a RF22 shield or board with level shifters built in,
740/// such as the Sparkfun RFM22 shield http://www.sparkfun.com/products/11018.
741/// You could also use a 3.3V IO Arduino such as a Pro.
742/// It is recognised that it is difficult to connect
743/// the Sparkfun RFM22 shield to a Mega, since the SPI pins on the Mega are different to other Arduinos,
744/// But it is possible, by bending the SPI pins (D10, D11, D12, D13) on the
745/// shield out of the way before plugging it in to the Mega and jumpering the shield pins to the Mega like this:
746/// \code
747/// RF22 Shield Mega
748/// D10 D53
749/// D13 D52
750/// D11 D51
751/// D12 D50
752/// \endcode
753///
754/// \par Interrupts
755///
756/// The Driver uses interrupts to react to events in the RF22 module,
757/// such as the reception of a new packet, or the completion of transmission of a packet.
758/// The RH_RF22 interrupt service routine reads status from and writes data
759/// to the the RF22 module via the SPI interface. It is very important therefore,
760/// that if you are using the RF22 library with another SPI based deviced, that you
761/// disable interrupts while you transfer data to and from that other device.
762/// Use cli() to disable interrupts and sei() to reenable them.
763///
764/// \par SPI Interface
765///
766/// The RF22 module uses the SPI bus to communicate with the Arduino. Arduino
767/// IDE includes a hardware SPI class to communicate with SPI devices using
768/// the SPI facilities built into the Atmel chips, over the standard designated
769/// SPI pins MOSI, MISO, SCK, which are usually on Arduino pins 11, 12 and 13
770/// respectively (or 51, 50, 52 on a Mega).
771///
772/// By default, the RH_RF22 Driver uses the Hardware SPI interface to
773/// communicate with the RF22 module. However, if your RF22 SPI is connected to
774/// the Arduino through non-standard pins, or the standard Hardware SPI
775/// interface will not work for you, you can instead use a bit-banged Software
776/// SPI class RHSoftwareSPI, which can be configured to work on any Arduino digital IO pins.
777/// See the documentation of RHSoftwareSPI for details.
778///
779/// The advantages of the Software SPI interface are that it can be used on
780/// any Arduino pins, not just the usual dedicated hardware pins. The
781/// disadvantage is that it is significantly slower then hardware.
782/// If you observe reliable behaviour with the default hardware SPI RHHardwareSPI, but unreliable behaviour
783/// with Software SPI RHSoftwareSPI, it may be due to slow CPU performance.
784///
785/// Initialisation example with hardware SPI
786/// \code
787/// #include <RH_RF22.h>
788/// RH_RF22 driver;
789/// RHReliableDatagram manager(driver, CLIENT_ADDRESS);
790/// \endcode
791///
792/// Initialisation example with software SPI
793/// \code
794/// #include <RH_RF22.h>
795/// #include <RHSoftwareSPI.h>
796/// RHSoftwareSPI spi;
797/// RH_RF22 driver(10, 2, spi);
798/// RHReliableDatagram manager(driver, CLIENT_ADDRESS);
799/// \endcode
800///
801/// \par Memory
802///
803/// The RH_RF22 Driver requires non-trivial amounts of memory. The sample programs all compile to
804/// about 9 to 14kbytes each on Arduino, which will fit in the flash proram memory of most Arduinos. However,
805/// the RAM requirements are more critical. Most sample programs above will run on Duemilanova,
806/// but not on Diecimila. Even on Duemilanova, the RAM requirements are very close to the
807/// available memory of 2kbytes. Therefore, you should be vary sparing with RAM use in programs that use
808/// the RH_RF22 Driver on Duemilanova.
809///
810/// The sample RHRouter and RHMesh programs compile to about 14kbytes,
811/// and require more RAM than the others.
812/// They will not run on Duemilanova or Diecimila, but will run on Arduino Mega.
813///
814/// It is often hard to accurately identify when you are hitting RAM limits on Arduino.
815/// The symptoms can include:
816/// - Mysterious crashes and restarts
817/// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements)
818/// - Hanging
819/// - Output from Serial.print() not appearing
820///
821/// With an Arduino Mega, with 8 kbytes of SRAM, there is much more RAM headroom for
822/// your own elaborate programs.
823/// This library is reported to work with Arduino Pro Mini, but that has not been tested by me.
824///
825/// The RF22M modules use an inexpensive crystal to control the frequency synthesizer, and therfore you can expect
826/// the transmitter and receiver frequencies to be subject to the usual inaccuracies of such crystals. The RF22
827/// contains an AFC circuit to compensate for differences in transmitter and receiver frequencies.
828/// It does this by altering the receiver frequency during reception by up to the pull-in frequency range.
829/// This RF22 library enables the AFC and by default sets the pull-in frequency range to
830/// 0.05MHz, which should be sufficient to handle most situations. However, if you observe unexplained packet losses
831/// or failure to operate correctly all the time it may be because your modules have a wider frequency difference, and
832/// you may need to set the afcPullInRange to a different value, using setFrequency();
833///
834/// \par Transmitter Power
835///
836/// You can control the transmitter power on the RF22 and RF23 transceivers
837/// with the RH_RF22::setTxPower() function. The argument can be any of the
838/// RH_RF22_TXPOW_* (for RFM22) or RH_RF22_RF23B_TXPOW_* (for RFM23) values.
839/// The default is RH_RF22_TXPOW_8DBM/RH_RF22_RF23B_TXPOW_1DBM . Eg:
840/// \code
841/// driver.setTxPower(RH_RF22_TXPOW_2DBM);
842/// \endcode
843///
844/// The RF23BP has higher power capability, there are
845/// several power settings that are specific to the RF23BP only:
846///
847/// - RH_RF22_RF23BP_TXPOW_28DBM
848/// - RH_RF22_RF23BP_TXPOW_29DBM
849/// - RH_RF22_RF23BP_TXPOW_30DBM
850///
851/// CAUTION: the high power settings available on the RFM23BP require
852/// significant power supply current. For example at +30dBm, the typical chip
853/// supply current is 550mA. This will overwhelm some small CPU board power
854/// regulators and USB supplies. If you use this chip at high power make sure
855/// you have an adequate supply current providing full 5V to the RFM23BP (and
856/// the CPU if required), otherwise you can expect strange behaviour like
857/// hanging, stopping, incorrect power levels, RF power amp overheating etc.
858/// You must also ensure that the RFM23BP GPIO pins are connected to the
859/// antenna switch control pins like so:
860////
861/// \code
862/// GPIO0 <-> RXON
863/// GPIO1 <-> TXON
864/// \endcode
865///
866/// The RF output impedance of the RFM22BP module is 50 ohms. In our
867/// experiments we found that the most critical issue (besides a suitable
868/// power supply) is to ensure that the antenna impedance is also near 50
869/// ohms. Connecting a simple 1/4 wavelength (ie a 17.3cm single wire)
870/// directly to the antenna output <b>will not work at full 30dBm power</b>,
871/// and will result in the transmitter hanging and/or the power amp
872/// overheating. Connect a proper 50 ohm impedance transmission line or
873/// antenna, and prevent RF radiation into the radio and arduino modules,
874/// in order to get full, reliable power. Our tests show that a 433MHz
875/// RFM23BP feeding a 50 ohm transmission line with a VHF discone antenna at
876/// the end results in full power output and the power amp transistor on the
877/// RFM22BP module runnning slightly warm but not hot. We recommend you use
878/// the services of a competent RF engineer when trying to use this high power
879/// module.
880///
881/// Note: with RFM23BP, the reported maximum possible power when operating on 3.3V is 27dBm.
882/// The BP version is an RFM23 with a PA
883/// external to the Silicon Labs radio chip.
884/// The RFM23BP only supports the top three power settings because those three
885/// output levels from the RFM23 provide enough drive to the PA to make it
886/// saturate. Less drive and the PA will dissipate more heat. However, those
887/// three levels don't change the output power from the PA.
888///
889/// We have made some actual power measurements against
890/// programmed power for Sparkfun RFM22 wireless module under the following conditions:
891/// - Sparkfun RFM22 wireless module, Duemilanove, USB power
892/// - 10cm RG58C/U soldered direct to RFM22 module ANT and GND
893/// - bnc connecteor
894/// - 12dB attenuator
895/// - BNC-SMA adapter
896/// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
897/// - Tektronix TDS220 scope to measure the Vout from power head
898/// \code
899/// Program power Measured Power
900/// dBm dBm
901/// 1 -5.6
902/// 2 -3.8
903/// 5 -2.2
904/// 8 -0.6
905/// 11 1.2
906/// 14 11.6
907/// 17 14.4
908/// 20 18.0
909/// \endcode
910/// (Caution: we dont claim laboratory accuracy for these measurements)
911/// You would not expect to get anywhere near these powers to air with a simple 1/4 wavelength wire antenna.
912///
913/// \par Performance
914///
915/// Some simple speed performance tests have been conducted.
916/// In general packet transmission rate will be limited by the modulation scheme.
917/// Also, if your code does any slow operations like Serial printing it will also limit performance.
918/// We disabled any printing in the tests below.
919/// We tested with RH_RF22::GFSK_Rb125Fd125, which is probably the fastest scheme available.
920/// We tested with a 13 octet message length, over a very short distance of 10cm.
921///
922/// Transmission (no reply) tests with modulation RH_RF22::GFSK_Rb125Fd125 and a
923/// 13 octet message show about 330 messages per second transmitted.
924///
925/// Transmit-and-wait-for-a-reply tests with modulation RH_RF22::GFSK_Rb125Fd125 and a
926/// 13 octet message (send and receive) show about 160 round trips per second.
927///
928/// \par Compatibility with RF22 library
929/// The RH_RF22 driver is based on our earlier RF22 library http://www.airspayce.com/mikem/arduino/RF22
930/// We have tried hard to be as compatible as possible with the earlier RF22 library, but there are some differences:
931/// - Different constructor.
932/// - Indexes for some modem configurations have changed (we recommend you use the symbolic names, not integer indexes).
933///
934/// The major difference is that under RadioHead, you are
935/// required to create 2 objects (ie RH_RF22 and a manager) instead of just one object under RF22
936/// (ie RHMesh, RHRouter, RHReliableDatagram or RHDatagram).
937/// It may be sufficient or you to change for example:
938/// \code
939/// RF22ReliableDatagram rf22(CLIENT_ADDRESS);
940/// \endcode
941/// to:
942/// \code
943/// RH_RF22 driver;
944/// RHReliableDatagram rf22(driver, CLIENT_ADDRESS);
945/// \endcode
946/// and any instance of RF22_MAX_MESSAGE_LEN to RH_RF22_MAX_MESSAGE_LEN
947///
948/// RadioHead version 1.6 changed the way the interrupt pin number is
949/// specified on Arduino and Uno32 platforms. If your code previously
950/// specifed a non-default interrupt pin number in the RH_RF22 constructor,
951/// you may need to review your code to specify the correct interrrupt pin
952/// (and not the interrupt number as before).
953class RH_RF22 : public RHSPIDriver
954{
955public:
956 /// \brief Defines register values for a set of modem configuration registers
957 ///
958 /// Defines register values for a set of modem configuration registers
959 /// that can be passed to setModemConfig()
960 /// if none of the choices in ModemConfigChoice suit your need
961 /// setModemConfig() writes the register values to the appropriate RH_RF22 registers
962 /// to set the desired modulation type, data rate and deviation/bandwidth.
963 /// Suitable values for these registers can be computed using the register calculator at
964 /// http://www.hoperf.com/upload/rf/RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls
965 typedef struct
966 {
967 uint8_t reg_1c; ///< Value for register RH_RF22_REG_1C_IF_FILTER_BANDWIDTH
968 uint8_t reg_1f; ///< Value for register RH_RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE
969 uint8_t reg_20; ///< Value for register RH_RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE
970 uint8_t reg_21; ///< Value for register RH_RF22_REG_21_CLOCK_RECOVERY_OFFSET2
971 uint8_t reg_22; ///< Value for register RH_RF22_REG_22_CLOCK_RECOVERY_OFFSET1
972 uint8_t reg_23; ///< Value for register RH_RF22_REG_23_CLOCK_RECOVERY_OFFSET0
973 uint8_t reg_24; ///< Value for register RH_RF22_REG_24_CLOCK_RECOVERY_TIMING_LOOP_GAIN1
974 uint8_t reg_25; ///< Value for register RH_RF22_REG_25_CLOCK_RECOVERY_TIMING_LOOP_GAIN0
975 uint8_t reg_2c; ///< Value for register RH_RF22_REG_2C_OOK_COUNTER_VALUE_1
976 uint8_t reg_2d; ///< Value for register RH_RF22_REG_2D_OOK_COUNTER_VALUE_2
977 uint8_t reg_2e; ///< Value for register RH_RF22_REG_2E_SLICER_PEAK_HOLD
978 uint8_t reg_58; ///< Value for register RH_RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING
979 uint8_t reg_69; ///< Value for register RH_RF22_REG_69_AGC_OVERRIDE1
980 uint8_t reg_6e; ///< Value for register RH_RF22_REG_6E_TX_DATA_RATE1
981 uint8_t reg_6f; ///< Value for register RH_RF22_REG_6F_TX_DATA_RATE0
982 uint8_t reg_70; ///< Value for register RH_RF22_REG_70_MODULATION_CONTROL1
983 uint8_t reg_71; ///< Value for register RH_RF22_REG_71_MODULATION_CONTROL2
984 uint8_t reg_72; ///< Value for register RH_RF22_REG_72_FREQUENCY_DEVIATION
985 } ModemConfig;
986
987 /// Choices for setModemConfig() for a selected subset of common modulation types,
988 /// and data rates. If you need another configuration, use the register calculator.
989 /// and call setModemRegisters() with your desired settings.
990 /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
991 /// definitions and not their integer equivalents: its possible that new values will be
992 /// introduced in later versions (though we will try to avoid it).
993 typedef enum
994 {
995 UnmodulatedCarrier = 0, ///< Unmodulated carrier for testing
996 FSK_PN9_Rb2Fd5, ///< FSK, No Manchester, Rb = 2kbs, Fd = 5kHz, PN9 random modulation for testing
997
998 FSK_Rb2Fd5, ///< FSK, No Manchester, Rb = 2kbs, Fd = 5kHz
999 FSK_Rb2_4Fd36, ///< FSK, No Manchester, Rb = 2.4kbs, Fd = 36kHz
1000 FSK_Rb4_8Fd45, ///< FSK, No Manchester, Rb = 4.8kbs, Fd = 45kHz
1001 FSK_Rb9_6Fd45, ///< FSK, No Manchester, Rb = 9.6kbs, Fd = 45kHz
1002 FSK_Rb19_2Fd9_6, ///< FSK, No Manchester, Rb = 19.2kbs, Fd = 9.6kHz
1003 FSK_Rb38_4Fd19_6, ///< FSK, No Manchester, Rb = 38.4kbs, Fd = 19.6kHz
1004 FSK_Rb57_6Fd28_8, ///< FSK, No Manchester, Rb = 57.6kbs, Fd = 28.8kHz
1005 FSK_Rb125Fd125, ///< FSK, No Manchester, Rb = 125kbs, Fd = 125kHz
1006 FSK_Rb_512Fd2_5, ///< FSK, No Manchester, Rb = 512bs, Fd = 2.5kHz, for POCSAG compatibility
1007 FSK_Rb_512Fd4_5, ///< FSK, No Manchester, Rb = 512bs, Fd = 4.5kHz, for POCSAG compatibility
1008
1009 GFSK_Rb2Fd5, ///< GFSK, No Manchester, Rb = 2kbs, Fd = 5kHz
1010 GFSK_Rb2_4Fd36, ///< GFSK, No Manchester, Rb = 2.4kbs, Fd = 36kHz
1011 GFSK_Rb4_8Fd45, ///< GFSK, No Manchester, Rb = 4.8kbs, Fd = 45kHz
1012 GFSK_Rb9_6Fd45, ///< GFSK, No Manchester, Rb = 9.6kbs, Fd = 45kHz
1013 GFSK_Rb19_2Fd9_6, ///< GFSK, No Manchester, Rb = 19.2kbs, Fd = 9.6kHz
1014 GFSK_Rb38_4Fd19_6, ///< GFSK, No Manchester, Rb = 38.4kbs, Fd = 19.6kHz
1015 GFSK_Rb57_6Fd28_8, ///< GFSK, No Manchester, Rb = 57.6kbs, Fd = 28.8kHz
1016 GFSK_Rb125Fd125, ///< GFSK, No Manchester, Rb = 125kbs, Fd = 125kHz
1017
1018 OOK_Rb1_2Bw75, ///< OOK, No Manchester, Rb = 1.2kbs, Rx Bandwidth = 75kHz
1019 OOK_Rb2_4Bw335, ///< OOK, No Manchester, Rb = 2.4kbs, Rx Bandwidth = 335kHz
1020 OOK_Rb4_8Bw335, ///< OOK, No Manchester, Rb = 4.8kbs, Rx Bandwidth = 335kHz
1021 OOK_Rb9_6Bw335, ///< OOK, No Manchester, Rb = 9.6kbs, Rx Bandwidth = 335kHz
1022 OOK_Rb19_2Bw335, ///< OOK, No Manchester, Rb = 19.2kbs, Rx Bandwidth = 335kHz
1023 OOK_Rb38_4Bw335, ///< OOK, No Manchester, Rb = 38.4kbs, Rx Bandwidth = 335kHz
1024 OOK_Rb40Bw335 ///< OOK, No Manchester, Rb = 40kbs, Rx Bandwidth = 335kHz
1025
1027
1028 /// \brief Defines the available choices for CRC
1029 /// Types of permitted CRC polynomials, to be passed to setCRCPolynomial()
1030 /// They deliberately have the same numeric values as the crc[1:0] field of Register
1031 /// RH_RF22_REG_30_DATA_ACCESS_CONTROL
1032 typedef enum
1033 {
1034 CRC_CCITT = 0, ///< CCITT
1035 CRC_16_IBM = 1, ///< CRC-16 (IBM) The default used by RH_RF22 driver
1036 CRC_IEC_16 = 2, ///< IEC-16
1037 CRC_Biacheva = 3 ///< Biacheva
1039
1040 /// Constructor. You can have multiple instances, but each instance must have its own
1041 /// interrupt and slave select pin. After constructing, you must call init() to initialise the interface
1042 /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
1043 /// distinct interrupt lines, one for each instance.
1044 /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RH_RF22 before
1045 /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
1046 /// \param[in] interruptPin The interrupt Pin number that is connected to the RF22 NIRQ interrupt line.
1047 /// Defaults to pin 2, as required by sparkfun RFM22 module shields.
1048 /// Caution: You must specify an interrupt capable pin.
1049 /// On many Arduino boards, there are limitations as to which pins may be used as interrupts.
1050 /// On Leonardo pins 0, 1, 2 or 3. On Mega2560 pins 2, 3, 18, 19, 20, 21. On Due and Teensy, any digital pin.
1051 /// On other Arduinos pins 2 or 3.
1052 /// See http://arduino.cc/en/Reference/attachInterrupt for more details.
1053 /// On Chipkit Uno32, pins 38, 2, 7, 8, 35.
1054 /// On other boards, any digital pin may be used.
1055 /// \param[in] spi Pointer to the SPI interface object to use.
1056 /// Defaults to the standard Arduino hardware SPI interface
1057 RH_RF22(uint8_t slaveSelectPin = SS, uint8_t interruptPin = 2, RHGenericSPI& spi = hardware_spi);
1058
1059 /// Initialises this instance and the radio module connected to it.
1060 /// The following steps are taken:
1061 /// - Initialise the slave select pin and the SPI interface library
1062 /// - Software reset the RH_RF22 module
1063 /// - Checks the connected RH_RF22 module is either a RH_RF22_DEVICE_TYPE_RX_TRX or a RH_RF22_DEVICE_TYPE_TX
1064 /// - Attaches an interrupt handler
1065 /// - Configures the RH_RF22 module
1066 /// - Sets the frequency to 434.0 MHz
1067 /// - Sets the modem data rate to FSK_Rb2_4Fd36
1068 /// \return true if everything was successful
1069 bool init();
1070
1071 /// Issues a software reset to the
1072 /// RH_RF22 module. Blocks for 1ms to ensure the reset is complete.
1073 void reset();
1074
1075 /// Reads and returns the device status register RH_RF22_REG_02_DEVICE_STATUS
1076 /// \return The value of the device status register
1077 uint8_t statusRead();
1078
1079 /// Reads a value from the on-chip analog-digital converter
1080 /// \param[in] adcsel Selects the ADC input to measure. One of RH_RF22_ADCSEL_*. Defaults to the
1081 /// internal temperature sensor
1082 /// \param[in] adcref Specifies the refernce voltage to use. One of RH_RF22_ADCREF_*.
1083 /// Defaults to the internal bandgap voltage.
1084 /// \param[in] adcgain Amplifier gain selection.
1085 /// \param[in] adcoffs Amplifier offseet (0 to 15).
1086 /// \return The analog value. 0 to 255.
1087 uint8_t adcRead(uint8_t adcsel = RH_RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR,
1088 uint8_t adcref = RH_RF22_ADCREF_BANDGAP_VOLTAGE,
1089 uint8_t adcgain = 0,
1090 uint8_t adcoffs = 0);
1091
1092 /// Reads the on-chip temperature sensor
1093 /// \param[in] tsrange Specifies the temperature range to use. One of RH_RF22_TSRANGE_*
1094 /// \param[in] tvoffs Specifies the temperature value offset. This is actually signed value
1095 /// added to the measured temperature value
1096 /// \return The measured temperature.
1097 uint8_t temperatureRead(uint8_t tsrange = RH_RF22_TSRANGE_M64_64C, uint8_t tvoffs = 0);
1098
1099 /// Reads the wakeup timer value in registers RH_RF22_REG_17_WAKEUP_TIMER_VALUE1
1100 /// and RH_RF22_REG_18_WAKEUP_TIMER_VALUE2
1101 /// \return The wakeup timer value
1102 uint16_t wutRead();
1103
1104 /// Sets the wakeup timer period registers RH_RF22_REG_14_WAKEUP_TIMER_PERIOD1,
1105 /// RH_RF22_REG_15_WAKEUP_TIMER_PERIOD2 and RH_RF22_R<EG_16_WAKEUP_TIMER_PERIOD3
1106 /// \param[in] wtm Wakeup timer mantissa value
1107 /// \param[in] wtr Wakeup timer exponent R value
1108 /// \param[in] wtd Wakeup timer exponent D value
1109 void setWutPeriod(uint16_t wtm, uint8_t wtr = 0, uint8_t wtd = 0);
1110
1111 /// Sets the transmitter and receiver centre frequency
1112 /// \param[in] centre Frequency in MHz. 240.0 to 960.0. Caution, some versions of RH_RF22 and derivatives
1113 /// implemented more restricted frequency ranges.
1114 /// \param[in] afcPullInRange Sets the AF Pull In Range in MHz. Defaults to 0.05MHz (50kHz).
1115 /// Range is 0.0 to 0.159375
1116 /// for frequencies 240.0 to 480MHz, and 0.0 to 0.318750MHz for frequencies 480.0 to 960MHz,
1117 /// \return true if the selected frquency centre + (fhch * fhs) is within range and the afcPullInRange
1118 /// is within range
1119 bool setFrequency(float centre, float afcPullInRange = 0.05);
1120
1121 /// Sets the frequency hopping step size.
1122 /// \param[in] fhs Frequency Hopping step size in 10kHz increments
1123 /// \return true if centre + (fhch * fhs) is within limits
1124 bool setFHStepSize(uint8_t fhs);
1125
1126 /// Sets the frequncy hopping channel. Adds fhch * fhs to centre frequency
1127 /// \param[in] fhch The channel number
1128 /// \return true if the selected frquency centre + (fhch * fhs) is within range
1129 bool setFHChannel(uint8_t fhch);
1130
1131 /// Reads and returns the current RSSI value from register RH_RF22_REG_26_RSSI. Caution: this is
1132 /// in internal units (see figure 31 of RFM22B/23B documentation), not in dBm. If you want to find the RSSI in dBm
1133 /// of the last received message, use lastRssi() instead.
1134 /// \return The current RSSI value
1135 uint8_t rssiRead();
1136
1137 /// Reads and returns the current EZMAC value from register RH_RF22_REG_31_EZMAC_STATUS
1138 /// \return The current EZMAC value
1139 uint8_t ezmacStatusRead();
1140
1141 /// Sets the parameters for the RH_RF22 Idle mode in register RH_RF22_REG_07_OPERATING_MODE.
1142 /// Idle mode is the mode the RH_RF22 will be in when not transmitting or receiving. The default idle mode
1143 /// is RH_RF22_XTON ie READY mode.
1144 /// \param[in] mode Mask of mode bits, using RH_RF22_SWRES, RH_RF22_ENLBD, RH_RF22_ENWT,
1145 /// RH_RF22_X32KSEL, RH_RF22_PLLON, RH_RF22_XTON.
1146 void setOpMode(uint8_t mode);
1147
1148 /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
1149 /// disables them.
1150 void setModeIdle();
1151
1152 /// If current mode is Tx or Idle, changes it to Rx.
1153 /// Starts the receiver in the RH_RF22.
1154 void setModeRx();
1155
1156 /// If current mode is Rx or Idle, changes it to Rx.
1157 /// Starts the transmitter in the RH_RF22.
1158 void setModeTx();
1159
1160 /// Sets the transmitter power output level in register RH_RF22_REG_6D_TX_POWER.
1161 /// Be a good neighbour and set the lowest power level you need.
1162 /// After init(), the power will be set to RH_RF22::RH_RF22_TXPOW_8DBM on RF22B
1163 /// or RH_RF22_RF23B_TXPOW_1DBM on an RF23B.
1164 /// The highest power available on RF22B is RH_RF22::RH_RF22_TXPOW_20DBM (20dBm).
1165 /// The highest power available on RF23B is RH_RF22::RH_RF22_RF23B_TXPOW_13DBM (13dBm).
1166 /// Higher powers are available on RF23BP (using RH_RF22_RF23BP_TXPOW_*),
1167 /// and then only with an adequate power supply. See comments above.
1168 /// Caution: In some countries you may only select certain higher power levels if you
1169 /// are also using frequency hopping. Make sure you are aware of the legal
1170 /// limitations and regulations in your region.
1171 /// \param[in] power Transmitter power level, one of RH_RF22_*TXPOW_*
1172 void setTxPower(uint8_t power);
1173
1174 /// Sets all the registered required to configure the data modem in the RH_RF22, including the data rate,
1175 /// bandwidths etc. You cas use this to configure the modem with custom configuraitons if none of the
1176 /// canned configurations in ModemConfigChoice suit you.
1177 /// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
1178 void setModemRegisters(const ModemConfig* config);
1179
1180 /// Select one of the predefined modem configurations. If you need a modem configuration not provided
1181 /// here, use setModemRegisters() with your own ModemConfig.
1182 /// \param[in] index The configuration choice.
1183 /// \return true if index is a valid choice.
1185
1186 /// Starts the receiver and checks whether a received message is available.
1187 /// This can be called multiple times in a timeout loop
1188 /// \return true if a complete, valid message has been received and is able to be retrieved by
1189 /// recv()
1190 bool available();
1191
1192#if RH_PLATFORM == RH_PLATFORM_ESP8266
1193 /// Reimplementation of virtual waitPacketSent method only for ESP8266. This method calls
1194 /// the loopIsr method to check when a new interrupt is asserted and handles the interrupt
1195 /// service routine.
1196 bool waitPacketSent();
1197#endif
1198
1199 /// Turns the receiver on if it not already on.
1200 /// If there is a valid message available, copy it to buf and return true
1201 /// else return false.
1202 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
1203 /// You should be sure to call this function frequently enough to not miss any messages
1204 /// It is recommended that you call it in your main loop.
1205 /// \param[in] buf Location to copy the received message
1206 /// \param[in,out] len Pointer to the number of octets available in buf. The number be reset to the actual number of octets copied.
1207 /// \return true if a valid message was copied to buf
1208 bool recv(uint8_t* buf, uint8_t* len);
1209
1210 /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
1211 /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
1212 /// of 0 is NOT permitted.
1213 /// \param[in] data Array of data to be sent
1214 /// \param[in] len Number of bytes of data to send (> 0)
1215 /// \return true if the message length was valid and it was correctly queued for transmit
1216 bool send(const uint8_t* data, uint8_t len);
1217
1218 /// Sets the length of the preamble
1219 /// in 4-bit nibbles.
1220 /// Caution: this should be set to the same
1221 /// value on all nodes in your network. Default is 8.
1222 /// Sets the message preamble length in RH_RF22_REG_34_PREAMBLE_LENGTH
1223 /// \param[in] nibbles Preamble length in nibbles of 4 bits each.
1224 void setPreambleLength(uint8_t nibbles);
1225
1226 /// Sets the sync words for transmit and receive in registers RH_RF22_REG_36_SYNC_WORD3
1227 /// to RH_RF22_REG_39_SYNC_WORD0
1228 /// Caution: SyncWords should be set to the same
1229 /// value on all nodes in your network. Nodes with different SyncWords set will never receive
1230 /// each others messages, so different SyncWords can be used to isolate different
1231 /// networks from each other. Default is { 0x2d, 0xd4 }.
1232 /// \param[in] syncWords Array of sync words, 1 to 4 octets long
1233 /// \param[in] len Number of sync words to set, 1 to 4.
1234 void setSyncWords(const uint8_t* syncWords, uint8_t len);
1235
1236 /// Tells the receiver to accept messages with any TO address, not just messages
1237 /// addressed to thisAddress or the broadcast address
1238 /// \param[in] promiscuous true if you wish to receive messages with any TO address
1239 virtual void setPromiscuous(bool promiscuous);
1240
1241 /// Sets the CRC polynomial to be used to generate the CRC for both receive and transmit
1242 /// otherwise the default of CRC_16_IBM will be used.
1243 /// \param[in] polynomial One of RH_RF22::CRCPolynomial choices CRC_*
1244 /// \return true if polynomial is a valid option for this radio.
1245 bool setCRCPolynomial(CRCPolynomial polynomial);
1246
1247 /// Configures GPIO pins for reversed GPIO connections to the antenna switch.
1248 /// Normally on RF22 modules, GPIO0(out) is connected to TX_ANT(in) to enable tx antenna during transmit
1249 /// and GPIO1(out) is connected to RX_ANT(in) to enable rx antenna during receive. The RH_RF22 driver
1250 /// configures the GPIO pins during init() so the antenna switch works as expected.
1251 /// However, some RF22 modules, such as HAB-RFM22B-BOA HAB-RFM22B-BO, also Si4432 sold by Dorji.com via Tindie.com
1252 /// have these GPIO pins reversed, so that GPIO0 is connected to RX_ANT.
1253 /// Call this function with a true argument after init() and before transmitting
1254 /// in order to configure the module for reversed GPIO pins.
1255 /// \param[in] gpioReversed Set to true if your RF22 module has reversed GPIO antenna switch connections.
1256 void setGpioReversed(bool gpioReversed = false);
1257
1258 /// Returns the time in millis since the last preamble was received, and when the last
1259 /// RSSI measurement was made.
1260 uint32_t getLastPreambleTime();
1261
1262 /// The maximum message length supported by this driver
1263 /// \return The maximum message length supported by this driver
1264 uint8_t maxMessageLength();
1265
1266 /// Sets the radio into low-power sleep mode.
1267 /// If successful, the transport will stay in sleep mode until woken by
1268 /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
1269 /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
1270 /// \return true if sleep mode was successfully entered.
1271 virtual bool sleep();
1272
1273protected:
1274 /// This is a low level function to handle the interrupts for one instance of RH_RF22.
1275 /// Called automatically by isr*()
1276 /// Should not need to be called.
1277 void handleInterrupt();
1278
1279 /// Clears the receiver buffer.
1280 /// Internal use only
1281 void clearRxBuf();
1282
1283 /// Clears the transmitter buffer
1284 /// Internal use only
1285 void clearTxBuf();
1286
1287 /// Fills the transmitter buffer with the data of a mesage to be sent
1288 /// \param[in] data Array of data bytes to be sent (1 to 255)
1289 /// \param[in] len Number of data bytes in data (> 0)
1290 /// \return true if the message length is valid
1291 bool fillTxBuf(const uint8_t* data, uint8_t len);
1292
1293 /// Appends the transmitter buffer with the data of a mesage to be sent
1294 /// \param[in] data Array of data bytes to be sent (0 to 255)
1295 /// \param[in] len Number of data bytes in data
1296 /// \return false if the resulting message would exceed RH_RF22_MAX_MESSAGE_LEN, else true
1297 bool appendTxBuf(const uint8_t* data, uint8_t len);
1298
1299 /// Internal function to load the next fragment of
1300 /// the current message into the transmitter FIFO
1301 /// Internal use only
1302 void sendNextFragment();
1303
1304 /// function to copy the next fragment from
1305 /// the receiver FIF) into the receiver buffer
1306 void readNextFragment();
1307
1308 /// Clears the RF22 Rx and Tx FIFOs
1309 /// Internal use only
1310 void resetFifos();
1311
1312 /// Clears the RF22 Rx FIFO
1313 /// Internal use only
1314 void resetRxFifo();
1315
1316 /// Clears the RF22 Tx FIFO
1317 /// Internal use only
1318 void resetTxFifo();
1319
1320 /// This function will be called by handleInterrupt() if an RF22 external interrupt occurs.
1321 /// This can only happen if external interrupts are enabled in the RF22
1322 /// (which they are not by default).
1323 /// Subclasses may override this function to get control when an RF22 external interrupt occurs.
1324 virtual void handleExternalInterrupt();
1325
1326 /// This function will be called by handleInterrupt() if an RF22 wakeup timer interrupt occurs.
1327 /// This can only happen if wakeup timer interrupts are enabled in theRF22
1328 /// (which they are not by default).
1329 /// Subclasses may override this function to get control when an RF22 wakeup timer interrupt occurs.
1330 virtual void handleWakeupTimerInterrupt();
1331
1332 /// Start the transmission of the contents
1333 /// of the Tx buffer
1334 void startTransmit();
1335
1336 /// ReStart the transmission of the contents
1337 /// of the Tx buffer after a atransmission failure
1338 void restartTransmit();
1339
1340 void setThisAddress(uint8_t thisAddress);
1341
1342 /// Sets the radio operating mode for the case when the driver is idle (ie not
1343 /// transmitting or receiving), allowing you to control the idle mode power requirements
1344 /// at the expense of slower transitions to transmit and receive modes.
1345 /// By default, the idle mode is RH_RF22_XTON,
1346 /// but eg setIdleMode(RH_RF22_PLL) will provide a much lower
1347 /// idle current but slower transitions. Call this function after init().
1348 /// \param[in] idleMode The chip operating mode to use when the driver is idle. One of the valid definitions for RH_RF22_REG_07_OPERATING_MODE
1349 void setIdleMode(uint8_t idleMode);
1350
1351#if RH_PLATFORM == RH_PLATFORM_ESP8266
1352 /// \brief Method only for ESP8266 to avoid SPI calls from the ISRs
1353 ///
1354 /// This method is used only with ESP8266 platform and must be called from
1355 /// the main loop. It checks if the Isr flags have been asserted and calls,
1356 /// from the main loop, the interrupt handler methods (where SPI calls are
1357 /// needed to process the communication).
1358 void loopIsr();
1359#endif
1360
1361protected:
1362 /// Low level interrupt service routine for RF22 connected to interrupt 0
1363 static void isr0();
1364
1365 /// Low level interrupt service routine for RF22 connected to interrupt 1
1366 static void isr1();
1367
1368 /// Low level interrupt service routine for RF22 connected to interrupt 1
1369 static void isr2();
1370
1371 /// Array of instances connected to interrupts 0 and 1
1373
1374 /// Index of next interrupt number to use in _deviceForInterrupt
1375 static uint8_t _interruptCount;
1376
1377 /// The configured interrupt pin connected to this instance
1379
1380 /// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
1381 /// else 0xff
1383
1384 /// The radio mode to use when mode is idle
1385 uint8_t _idleMode;
1386
1387 /// The device type reported by the RF22
1389
1390 /// The selected CRC polynomial
1392
1393 // These volatile members may get changed in the interrupt service routine
1394 /// Number of octets in the receiver buffer
1395 volatile uint8_t _bufLen;
1396
1397 /// The receiver buffer
1398 uint8_t _buf[RH_RF22_MAX_MESSAGE_LEN];
1399
1400 /// True when there is a valid message in the Rx buffer
1401 volatile bool _rxBufValid;
1402
1403 /// Index into TX buffer of the next to send chunk
1404 volatile uint8_t _txBufSentIndex;
1405
1406 /// Time in millis since the last preamble was received (and the last time the RSSI was measured)
1408};
1409
1410/// @example rf22_client.ino
1411/// @example rf22_server.ino
1412/// @example rf22_cw.ino
1413
1414#endif
virtual bool waitPacketSent()
Definition: RHGenericDriver.cpp:58
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 RF22 and compatible radio transce...
Definition: RH_RF22.h:954
volatile uint8_t _bufLen
Number of octets in the receiver buffer.
Definition: RH_RF22.h:1395
uint32_t getLastPreambleTime()
Definition: RH_RF22.cpp:792
RH_RF22(uint8_t slaveSelectPin=SS, uint8_t interruptPin=2, RHGenericSPI &spi=hardware_spi)
Definition: RH_RF22.cpp:65
void setPreambleLength(uint8_t nibbles)
Definition: RH_RF22.cpp:573
static uint8_t _interruptCount
Index of next interrupt number to use in _deviceForInterrupt.
Definition: RH_RF22.h:1375
bool recv(uint8_t *buf, uint8_t *len)
Definition: RH_RF22.cpp:619
virtual void handleExternalInterrupt()
Definition: RH_RF22.cpp:754
void restartTransmit()
Definition: RH_RF22.cpp:653
uint16_t wutRead()
Definition: RH_RF22.cpp:412
uint8_t _deviceType
The device type reported by the RF22.
Definition: RH_RF22.h:1388
volatile uint8_t _txBufSentIndex
Index into TX buffer of the next to send chunk.
Definition: RH_RF22.h:1404
void resetFifos()
Definition: RH_RF22.cpp:732
void clearTxBuf()
Definition: RH_RF22.cpp:637
bool available()
Definition: RH_RF22.cpp:592
bool init()
Definition: RH_RF22.cpp:80
bool setFHChannel(uint8_t fhch)
Definition: RH_RF22.cpp:479
void setIdleMode(uint8_t idleMode)
Definition: RH_RF22.cpp:75
static void isr2()
Low level interrupt service routine for RF22 connected to interrupt 1.
Definition: RH_RF22.cpp:366
void reset()
Definition: RH_RF22.cpp:376
void resetTxFifo()
Definition: RH_RF22.cpp:747
uint8_t adcRead(uint8_t adcsel=RH_RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR, uint8_t adcref=RH_RF22_ADCREF_BANDGAP_VOLTAGE, uint8_t adcgain=0, uint8_t adcoffs=0)
Definition: RH_RF22.cpp:388
virtual void setPromiscuous(bool promiscuous)
Definition: RH_RF22.cpp:763
bool setFrequency(float centre, float afcPullInRange=0.05)
Definition: RH_RF22.cpp:433
uint8_t ezmacStatusRead()
Definition: RH_RF22.cpp:490
uint8_t _interruptPin
The configured interrupt pin connected to this instance.
Definition: RH_RF22.h:1378
uint8_t temperatureRead(uint8_t tsrange=RH_RF22_TSRANGE_M64_64C, uint8_t tvoffs=0)
Definition: RH_RF22.cpp:405
void resetRxFifo()
Definition: RH_RF22.cpp:739
static void isr0()
Low level interrupt service routine for RF22 connected to interrupt 0.
Definition: RH_RF22.cpp:348
bool setCRCPolynomial(CRCPolynomial polynomial)
Definition: RH_RF22.cpp:769
void handleInterrupt()
Definition: RH_RF22.cpp:202
CRCPolynomial _polynomial
The selected CRC polynomial.
Definition: RH_RF22.h:1391
bool setFHStepSize(uint8_t fhs)
Definition: RH_RF22.cpp:471
static void isr1()
Low level interrupt service routine for RF22 connected to interrupt 1.
Definition: RH_RF22.cpp:357
void setSyncWords(const uint8_t *syncWords, uint8_t len)
Definition: RH_RF22.cpp:579
void setGpioReversed(bool gpioReversed=false)
Definition: RH_RF22.cpp:797
ModemConfigChoice
Definition: RH_RF22.h:994
@ GFSK_Rb57_6Fd28_8
GFSK, No Manchester, Rb = 57.6kbs, Fd = 28.8kHz.
Definition: RH_RF22.h:1015
@ OOK_Rb40Bw335
OOK, No Manchester, Rb = 40kbs, Rx Bandwidth = 335kHz.
Definition: RH_RF22.h:1024
@ GFSK_Rb9_6Fd45
GFSK, No Manchester, Rb = 9.6kbs, Fd = 45kHz.
Definition: RH_RF22.h:1012
@ OOK_Rb2_4Bw335
OOK, No Manchester, Rb = 2.4kbs, Rx Bandwidth = 335kHz.
Definition: RH_RF22.h:1019
@ GFSK_Rb2_4Fd36
GFSK, No Manchester, Rb = 2.4kbs, Fd = 36kHz.
Definition: RH_RF22.h:1010
@ OOK_Rb38_4Bw335
OOK, No Manchester, Rb = 38.4kbs, Rx Bandwidth = 335kHz.
Definition: RH_RF22.h:1023
@ FSK_Rb57_6Fd28_8
FSK, No Manchester, Rb = 57.6kbs, Fd = 28.8kHz.
Definition: RH_RF22.h:1004
@ FSK_Rb9_6Fd45
FSK, No Manchester, Rb = 9.6kbs, Fd = 45kHz.
Definition: RH_RF22.h:1001
@ FSK_Rb4_8Fd45
FSK, No Manchester, Rb = 4.8kbs, Fd = 45kHz.
Definition: RH_RF22.h:1000
@ FSK_Rb_512Fd2_5
FSK, No Manchester, Rb = 512bs, Fd = 2.5kHz, for POCSAG compatibility.
Definition: RH_RF22.h:1006
@ OOK_Rb9_6Bw335
OOK, No Manchester, Rb = 9.6kbs, Rx Bandwidth = 335kHz.
Definition: RH_RF22.h:1021
@ GFSK_Rb2Fd5
GFSK, No Manchester, Rb = 2kbs, Fd = 5kHz.
Definition: RH_RF22.h:1009
@ FSK_Rb38_4Fd19_6
FSK, No Manchester, Rb = 38.4kbs, Fd = 19.6kHz.
Definition: RH_RF22.h:1003
@ OOK_Rb19_2Bw335
OOK, No Manchester, Rb = 19.2kbs, Rx Bandwidth = 335kHz.
Definition: RH_RF22.h:1022
@ OOK_Rb4_8Bw335
OOK, No Manchester, Rb = 4.8kbs, Rx Bandwidth = 335kHz.
Definition: RH_RF22.h:1020
@ FSK_PN9_Rb2Fd5
FSK, No Manchester, Rb = 2kbs, Fd = 5kHz, PN9 random modulation for testing.
Definition: RH_RF22.h:996
@ FSK_Rb125Fd125
FSK, No Manchester, Rb = 125kbs, Fd = 125kHz.
Definition: RH_RF22.h:1005
@ GFSK_Rb4_8Fd45
GFSK, No Manchester, Rb = 4.8kbs, Fd = 45kHz.
Definition: RH_RF22.h:1011
@ FSK_Rb2Fd5
FSK, No Manchester, Rb = 2kbs, Fd = 5kHz.
Definition: RH_RF22.h:998
@ GFSK_Rb125Fd125
GFSK, No Manchester, Rb = 125kbs, Fd = 125kHz.
Definition: RH_RF22.h:1016
@ FSK_Rb19_2Fd9_6
FSK, No Manchester, Rb = 19.2kbs, Fd = 9.6kHz.
Definition: RH_RF22.h:1002
@ GFSK_Rb38_4Fd19_6
GFSK, No Manchester, Rb = 38.4kbs, Fd = 19.6kHz.
Definition: RH_RF22.h:1014
@ FSK_Rb2_4Fd36
FSK, No Manchester, Rb = 2.4kbs, Fd = 36kHz.
Definition: RH_RF22.h:999
@ FSK_Rb_512Fd4_5
FSK, No Manchester, Rb = 512bs, Fd = 4.5kHz, for POCSAG compatibility.
Definition: RH_RF22.h:1007
@ UnmodulatedCarrier
Unmodulated carrier for testing.
Definition: RH_RF22.h:995
@ GFSK_Rb19_2Fd9_6
GFSK, No Manchester, Rb = 19.2kbs, Fd = 9.6kHz.
Definition: RH_RF22.h:1013
@ OOK_Rb1_2Bw75
OOK, No Manchester, Rb = 1.2kbs, Rx Bandwidth = 75kHz.
Definition: RH_RF22.h:1018
static RH_RF22 * _deviceForInterrupt[]
Array of instances connected to interrupts 0 and 1.
Definition: RH_RF22.h:1372
bool fillTxBuf(const uint8_t *data, uint8_t len)
Definition: RH_RF22.cpp:683
void sendNextFragment()
Definition: RH_RF22.cpp:704
void setThisAddress(uint8_t thisAddress)
Definition: RH_RF22.cpp:786
void setOpMode(uint8_t mode)
Definition: RH_RF22.cpp:495
void setModeTx()
Definition: RH_RF22.cpp:528
virtual void handleWakeupTimerInterrupt()
Definition: RH_RF22.cpp:759
void startTransmit()
Definition: RH_RF22.cpp:645
void readNextFragment()
Definition: RH_RF22.cpp:721
uint32_t _lastPreambleTime
Time in millis since the last preamble was received (and the last time the RSSI was measured)
Definition: RH_RF22.h:1407
uint8_t maxMessageLength()
Definition: RH_RF22.cpp:781
volatile bool _rxBufValid
True when there is a valid message in the Rx buffer.
Definition: RH_RF22.h:1401
void setModeIdle()
Definition: RH_RF22.cpp:500
uint8_t _buf[RH_RF22_MAX_MESSAGE_LEN]
The receiver buffer.
Definition: RH_RF22.h:1398
void setTxPower(uint8_t power)
Definition: RH_RF22.cpp:541
void setWutPeriod(uint16_t wtm, uint8_t wtr=0, uint8_t wtd=0)
Definition: RH_RF22.cpp:420
uint8_t _myInterruptIndex
Definition: RH_RF22.h:1382
CRCPolynomial
Defines the available choices for CRC Types of permitted CRC polynomials, to be passed to setCRCPolyn...
Definition: RH_RF22.h:1033
@ CRC_CCITT
CCITT.
Definition: RH_RF22.h:1034
@ CRC_IEC_16
IEC-16.
Definition: RH_RF22.h:1036
@ CRC_Biacheva
Biacheva.
Definition: RH_RF22.h:1037
@ CRC_16_IBM
CRC-16 (IBM) The default used by RH_RF22 driver.
Definition: RH_RF22.h:1035
uint8_t statusRead()
Definition: RH_RF22.cpp:383
virtual bool sleep()
Definition: RH_RF22.cpp:509
uint8_t _idleMode
The radio mode to use when mode is idle.
Definition: RH_RF22.h:1385
void setModeRx()
Definition: RH_RF22.cpp:519
bool send(const uint8_t *data, uint8_t len)
Definition: RH_RF22.cpp:661
void clearRxBuf()
Definition: RH_RF22.cpp:584
bool appendTxBuf(const uint8_t *data, uint8_t len)
Definition: RH_RF22.cpp:691
uint8_t rssiRead()
Definition: RH_RF22.cpp:485
bool setModemConfig(ModemConfigChoice index)
Definition: RH_RF22.cpp:560
void setModemRegisters(const ModemConfig *config)
Definition: RH_RF22.cpp:547
Defines register values for a set of modem configuration registers.
Definition: RH_RF22.h:966
uint8_t reg_24
Value for register RH_RF22_REG_24_CLOCK_RECOVERY_TIMING_LOOP_GAIN1.
Definition: RH_RF22.h:973
uint8_t reg_70
Value for register RH_RF22_REG_70_MODULATION_CONTROL1.
Definition: RH_RF22.h:982
uint8_t reg_22
Value for register RH_RF22_REG_22_CLOCK_RECOVERY_OFFSET1.
Definition: RH_RF22.h:971
uint8_t reg_2c
Value for register RH_RF22_REG_2C_OOK_COUNTER_VALUE_1.
Definition: RH_RF22.h:975
uint8_t reg_2d
Value for register RH_RF22_REG_2D_OOK_COUNTER_VALUE_2.
Definition: RH_RF22.h:976
uint8_t reg_20
Value for register RH_RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE.
Definition: RH_RF22.h:969
uint8_t reg_21
Value for register RH_RF22_REG_21_CLOCK_RECOVERY_OFFSET2.
Definition: RH_RF22.h:970
uint8_t reg_1c
Value for register RH_RF22_REG_1C_IF_FILTER_BANDWIDTH.
Definition: RH_RF22.h:967
uint8_t reg_69
Value for register RH_RF22_REG_69_AGC_OVERRIDE1.
Definition: RH_RF22.h:979
uint8_t reg_72
Value for register RH_RF22_REG_72_FREQUENCY_DEVIATION.
Definition: RH_RF22.h:984
uint8_t reg_6e
Value for register RH_RF22_REG_6E_TX_DATA_RATE1.
Definition: RH_RF22.h:980
uint8_t reg_58
Value for register RH_RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING.
Definition: RH_RF22.h:978
uint8_t reg_2e
Value for register RH_RF22_REG_2E_SLICER_PEAK_HOLD.
Definition: RH_RF22.h:977
uint8_t reg_71
Value for register RH_RF22_REG_71_MODULATION_CONTROL2.
Definition: RH_RF22.h:983
uint8_t reg_6f
Value for register RH_RF22_REG_6F_TX_DATA_RATE0.
Definition: RH_RF22.h:981
uint8_t reg_1f
Value for register RH_RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE.
Definition: RH_RF22.h:968
uint8_t reg_25
Value for register RH_RF22_REG_25_CLOCK_RECOVERY_TIMING_LOOP_GAIN0.
Definition: RH_RF22.h:974
uint8_t reg_23
Value for register RH_RF22_REG_23_CLOCK_RECOVERY_OFFSET0.
Definition: RH_RF22.h:972