PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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