PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 3 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. // RH_MRF89.h
  2. //
  3. // Definitions for Microchip MRF89XA family radios radios per:
  4. // http://ww1.microchip.com/downloads/en/DeviceDoc/70622C.pdf
  5. // http://ww1.microchip.com/downloads/en/DeviceDoc/75017B.pdf
  6. //
  7. // Author: Mike McCauley (mikem@airspayce.com)
  8. // Copyright (C) 2015 Mike McCauley
  9. // $Id: RH_MRF89.h,v 1.6 2015/12/17 10:58:13 mikem Exp $
  10. //
  11. #ifndef RH_RF95_h
  12. #define RH_RF95_h
  13. #include <RHNRFSPIDriver.h>
  14. // This is the maximum number of interrupts the driver can support
  15. // Most Arduinos can handle 2, Megas can handle more
  16. #define RH_MRF89_NUM_INTERRUPTS 3
  17. // Max number of octets the MRF89XA Rx/Tx FIFO can hold
  18. #define RH_MRF89_FIFO_SIZE 64
  19. // This is the maximum number of bytes that can be carried by the MRF89XA.
  20. // We use some for headers, keeping fewer for RadioHead messages
  21. #define RH_MRF89_MAX_PAYLOAD_LEN RH_MRF89_FIFO_SIZE
  22. // The length of the headers we add.
  23. // The headers are inside the MRF89XA payload
  24. #define RH_MRF89_HEADER_LEN 4
  25. // This is the maximum user message length that can be supported by this driver.
  26. // Can be pre-defined to a smaller size (to save SRAM) prior to including this header
  27. // Here we allow for 4 bytes headers, user data. Message length and CRC are automatically encoded and decoded by
  28. // the MRF89XA
  29. #ifndef RH_MRF89_MAX_MESSAGE_LEN
  30. #define RH_MRF89_MAX_MESSAGE_LEN (RH_MRF89_MAX_PAYLOAD_LEN - RH_MRF89_HEADER_LEN)
  31. #endif
  32. // Bits that must be set to do a SPI read
  33. #define RH_MRF89_SPI_READ_MASK 0x40
  34. // The MRF89XA crystal frequency in MHz
  35. #define RH_MRF89_XTAL_FREQ 12.8
  36. // Register names from Figure 2-18
  37. #define RH_MRF89_REG_00_GCONREG 0x00
  38. #define RH_MRF89_REG_01_DMODREG 0x01
  39. #define RH_MRF89_REG_02_FDEVREG 0x02
  40. #define RH_MRF89_REG_03_BRSREG 0x03
  41. #define RH_MRF89_REG_04_FLTHREG 0x04
  42. #define RH_MRF89_REG_05_FIFOCREG 0x05
  43. #define RH_MRF89_REG_06_R1CREG 0x06
  44. #define RH_MRF89_REG_07_P1CREG 0x07
  45. #define RH_MRF89_REG_08_S1CREG 0x08
  46. #define RH_MRF89_REG_09_R2CREG 0x09
  47. #define RH_MRF89_REG_0A_P2CREG 0x0a
  48. #define RH_MRF89_REG_0B_S2CREG 0x0b
  49. #define RH_MRF89_REG_0C_PACREG 0x0c
  50. #define RH_MRF89_REG_0D_FTXRXIREG 0x0d
  51. #define RH_MRF89_REG_0E_FTPRIREG 0x0e
  52. #define RH_MRF89_REG_0F_RSTHIREG 0x0f
  53. #define RH_MRF89_REG_10_FILCREG 0x10
  54. #define RH_MRF89_REG_11_PFCREG 0x11
  55. #define RH_MRF89_REG_12_SYNCREG 0x12
  56. // Hmm the addresses of the next 2 is ambiguous in the docs
  57. // this seems to agree with whats in the chip:
  58. #define RH_MRF89_REG_13_RSVREG 0x13
  59. #define RH_MRF89_REG_14_RSTSREG 0x14
  60. #define RH_MRF89_REG_15_OOKCREG 0x15
  61. #define RH_MRF89_REG_16_SYNCV31REG 0x16
  62. #define RH_MRF89_REG_17_SYNCV23REG 0x17
  63. #define RH_MRF89_REG_18_SYNCV15REG 0x18
  64. #define RH_MRF89_REG_19_SYNCV07REG 0x19
  65. #define RH_MRF89_REG_1A_TXCONREG 0x1a
  66. #define RH_MRF89_REG_1B_CLKOREG 0x1b
  67. #define RH_MRF89_REG_1C_PLOADREG 0x1c
  68. #define RH_MRF89_REG_1D_NADDSREG 0x1d
  69. #define RH_MRF89_REG_1E_PKTCREG 0x1e
  70. #define RH_MRF89_REG_1F_FCRCREG 0x1f
  71. // Register bitfield definitions
  72. //#define RH_MRF89_REG_00_GCONREG 0x00
  73. #define RH_MRF89_CMOD 0xe0
  74. #define RH_MRF89_CMOD_TRANSMIT 0x80
  75. #define RH_MRF89_CMOD_RECEIVE 0x60
  76. #define RH_MRF89_CMOD_FS 0x40
  77. #define RH_MRF89_CMOD_STANDBY 0x20
  78. #define RH_MRF89_CMOD_SLEEP 0x00
  79. #define RH_MRF89_FBS 0x18
  80. #define RH_MRF89_FBS_950_960 0x10
  81. #define RH_MRF89_FBS_915_928 0x08
  82. #define RH_MRF89_FBS_902_915 0x00
  83. #define RH_MRF89_VCOT 0x06
  84. #define RH_MRF89_VCOT_180MV 0x06
  85. #define RH_MRF89_VCOT_120MV 0x04
  86. #define RH_MRF89_VCOT_60MV 0x02
  87. #define RH_MRF89_VCOT_TANK 0x00
  88. #define RH_MRF89_RPS 0x01
  89. //#define RH_MRF89_REG_01_DMODREG 0x01
  90. #define RH_MRF89_MODSEL 0xc0
  91. #define RH_MRF89_MODSEL_FSK 0x80
  92. #define RH_MRF89_MODSEL_OOK 0x40
  93. #define RH_MRF89_DMODE0 0x20
  94. #define RH_MRF89_OOKTYP 0x18
  95. #define RH_MRF89_OOKTYP_AVERAGE 0x10
  96. #define RH_MRF89_OOKTYP_PEAK 0x08
  97. #define RH_MRF89_OOKTYP_FIXED 0x00
  98. #define RH_MRF89_DMODE1 0x04
  99. #define RH_MRF89_IFGAIN 0x03
  100. #define RH_MRF89_IFGAIN_M13P5 0x03
  101. #define RH_MRF89_IFGAIN_M9 0x02
  102. #define RH_MRF89_IFGAIN_M4P5 0x01
  103. #define RH_MRF89_IFGAIN_0 0x00
  104. // DMODE1 and DMODE1:
  105. #define RH_MRF89_OPMODE_CONTINUOUS 0x00
  106. #define RH_MRF89_OPMODE_BUFFER RH_MRF89_DMODE0
  107. #define RH_MRF89_OPMODE_PACKET RH_MRF89_DMODE1
  108. //#define RH_MRF89_REG_03_BRSREG 0x03
  109. #define RH_MRF89_BRVAL 0x7f
  110. //#define RH_MRF89_REG_05_FIFOCREG 0x05
  111. #define RH_MRF89_FSIZE 0xc0
  112. #define RH_MRF89_FSIZE_64 0xc0
  113. #define RH_MRF89_FSIZE_48 0x80
  114. #define RH_MRF89_FSIZE_32 0x40
  115. #define RH_MRF89_FSIZE_16 0x00
  116. #define RH_MRF89_FTINT 0x3f
  117. //#define RH_MRF89_REG_0C_PACREG 0x0c
  118. #define RH_MRF89_PARC 0x18
  119. #define RH_MRF89_PARC_23 0x18
  120. #define RH_MRF89_PARC_15 0x10
  121. #define RH_MRF89_PARC_8P5 0x08
  122. #define RH_MRF89_PARC_3 0x00
  123. //#define RH_MRF89_REG_0D_FTXRXIREG 0x0d
  124. #define RH_MRF89_IRQ0RXS 0xc0
  125. #define RH_MRF89_IRQ0RXS_CONT_RSSI 0x40
  126. #define RH_MRF89_IRQ0RXS_CONT_SYNC 0x00
  127. #define RH_MRF89_IRQ0RXS_BUFFER_SYNC 0xc0
  128. #define RH_MRF89_IRQ0RXS_BUFFER_FIFOEMPTY 0x80
  129. #define RH_MRF89_IRQ0RXS_BUFFER_WRITEBYTE 0x40
  130. #define RH_MRF89_IRQ0RXS_BUFFER_NONE 0x00
  131. #define RH_MRF89_IRQ0RXS_PACKET_SYNC 0xc0
  132. #define RH_MRF89_IRQ0RXS_PACKET_FIFOEMPTY 0x80
  133. #define RH_MRF89_IRQ0RXS_PACKET_WRITEBYTE 0x40
  134. #define RH_MRF89_IRQ0RXS_PACKET_PLREADY 0x00
  135. #define RH_MRF89_IRQ1RXS 0x30
  136. #define RH_MRF89_IRQ1RXS_CONT_DCLK 0x00
  137. #define RH_MRF89_IRQ1RXS_BUFFER_FIFO_THRESH 0x30
  138. #define RH_MRF89_IRQ1RXS_BUFFER_RSSI 0x20
  139. #define RH_MRF89_IRQ1RXS_BUFFER_FIFOFULL 0x10
  140. #define RH_MRF89_IRQ1RXS_BUFFER_NONE 0x00
  141. #define RH_MRF89_IRQ1RXS_PACKET_FIFO_THRESH 0x30
  142. #define RH_MRF89_IRQ1RXS_PACKET_RSSI 0x20
  143. #define RH_MRF89_IRQ1RXS_PACKET_FIFOFULL 0x10
  144. #define RH_MRF89_IRQ1RXS_PACKET_CRCOK 0x00
  145. #define RH_MRF89_IRQ1TX 0x08
  146. #define RH_MRF89_FIFOFULL 0x04
  147. #define RH_MRF89_FIFOEMPTY 0x02
  148. #define RH_MRF89_FOVRUN 0x01
  149. //#define RH_MRF89_REG_0E_FTPRIREG 0x0e
  150. #define RH_MRF89_FIFOFM 0x80
  151. #define RH_MRF89_FIFOFSC 0x40
  152. #define RH_MRF89_TXDONE 0x20
  153. #define RH_MRF89_IRQ0TXST 0x10
  154. #define RH_MRF89_RIRQS 0x04
  155. #define RH_MRF89_LSTSPLL 0x02
  156. #define RH_MRF89_LENPLL 0x01
  157. //#define RH_MRF89_REG_10_FILCREG 0x10
  158. #define RH_MRF89_PASFILV 0xf0
  159. #define RH_MRF89_PASFILV_987KHZ 0xf0
  160. #define RH_MRF89_PASFILV_676KHZ 0xe0
  161. #define RH_MRF89_PASFILV_514KHZ 0xd0
  162. #define RH_MRF89_PASFILV_458KHZ 0xc0
  163. #define RH_MRF89_PASFILV_414KHZ 0xb0
  164. #define RH_MRF89_PASFILV_378KHZ 0xa0
  165. #define RH_MRF89_PASFILV_321KHZ 0x90
  166. #define RH_MRF89_PASFILV_262KHZ 0x80
  167. #define RH_MRF89_PASFILV_234KHZ 0x70
  168. #define RH_MRF89_PASFILV_211KHZ 0x60
  169. #define RH_MRF89_PASFILV_184KHZ 0x50
  170. #define RH_MRF89_PASFILV_157KHZ 0x40
  171. #define RH_MRF89_PASFILV_137KHZ 0x30
  172. #define RH_MRF89_PASFILV_109KHZ 0x20
  173. #define RH_MRF89_PASFILV_82KHZ 0x10
  174. #define RH_MRF89_PASFILV_65KHZ 0x00
  175. #define RH_MRF89_BUTFILV 0x0f
  176. #define RH_MRF89_BUTFILV_25KHZ 0x00
  177. #define RH_MRF89_BUTFILV_50KHZ 0x01
  178. #define RH_MRF89_BUTFILV_75KHZ 0x02
  179. #define RH_MRF89_BUTFILV_100KHZ 0x03
  180. #define RH_MRF89_BUTFILV_125KHZ 0x04
  181. #define RH_MRF89_BUTFILV_150KHZ 0x05
  182. #define RH_MRF89_BUTFILV_175KHZ 0x06
  183. #define RH_MRF89_BUTFILV_200KHZ 0x07
  184. #define RH_MRF89_BUTFILV_225KHZ 0x08
  185. #define RH_MRF89_BUTFILV_250KHZ 0x09
  186. #define RH_MRF89_BUTFILV_275KHZ 0x0a
  187. #define RH_MRF89_BUTFILV_300KHZ 0x0b
  188. #define RH_MRF89_BUTFILV_325KHZ 0x0c
  189. #define RH_MRF89_BUTFILV_350KHZ 0x0d
  190. #define RH_MRF89_BUTFILV_375KHZ 0x0e
  191. #define RH_MRF89_BUTFILV_400KHZ 0x0f
  192. //#define RH_MRF89_REG_11_PFCREG 0x11
  193. #define RH_MRF89_POLCFV 0xf0
  194. //#define RH_MRF89_REG_12_SYNCREG 0x12
  195. #define RH_MRF89_POLFILEN 0x80
  196. #define RH_MRF89_BSYNCEN 0x40
  197. #define RH_MRF89_SYNCREN 0x20
  198. #define RH_MRF89_SYNCWSZ 0x18
  199. #define RH_MRF89_SYNCWSZ_32 0x18
  200. #define RH_MRF89_SYNCWSZ_24 0x10
  201. #define RH_MRF89_SYNCWSZ_16 0x08
  202. #define RH_MRF89_SYNCWSZ_8 0x00
  203. #define RH_MRF89_SYNCTEN 0x06
  204. #define RH_MRF89_SYNCTEN_3 0x06
  205. #define RH_MRF89_SYNCTEN_2 0x04
  206. #define RH_MRF89_SYNCTEN_1 0x02
  207. #define RH_MRF89_SYNCTEN_0 0x00
  208. //#define RH_MRF89_REG_15_OOKCREG 0x15
  209. #define RH_MRF89_OOTHSV 0xe0
  210. #define RH_MRF89_OOTHSV_6P0DB 0xe0
  211. #define RH_MRF89_OOTHSV_5P0DB 0xc0
  212. #define RH_MRF89_OOTHSV_4P0DB 0xa0
  213. #define RH_MRF89_OOTHSV_3P0DB 0x80
  214. #define RH_MRF89_OOTHSV_2P0DB 0x60
  215. #define RH_MRF89_OOTHSV_1P5DB 0x40
  216. #define RH_MRF89_OOTHSV_1P0DB 0x20
  217. #define RH_MRF89_OOTHSV_0P5DB 0x00
  218. #define RH_MRF89_OOKTHPV 0x1c
  219. #define RH_MRF89_OOKTHPV_16 0x1c
  220. #define RH_MRF89_OOKTHPV_8 0x18
  221. #define RH_MRF89_OOKTHPV_4 0x14
  222. #define RH_MRF89_OOKTHPV_2 0x10
  223. #define RH_MRF89_OOKTHPV_1_IN_8 0x0c
  224. #define RH_MRF89_OOKTHPV_1_IN_4 0x08
  225. #define RH_MRF89_OOKTHPV_1_IN_2 0x04
  226. #define RH_MRF89_OOKTHPV_1_IN_1 0x00
  227. #define RH_MRF89_OOKATHC 0x03
  228. #define RH_MRF89_OOKATHC_32PI 0x03
  229. #define RH_MRF89_OOKATHC_8PI 0x00
  230. //#define RH_MRF89_REG_1A_TXCONREG 0x1a
  231. #define RH_MRF89_TXIPOLFV 0xf0
  232. #define RH_MRF89_TXOPVAL 0x0e
  233. #define RH_MRF89_TXOPVAL_M8DBM 0x0e
  234. #define RH_MRF89_TXOPVAL_M5DBM 0x0c
  235. #define RH_MRF89_TXOPVAL_M2DBM 0x0a
  236. #define RH_MRF89_TXOPVAL_1DBM 0x08
  237. #define RH_MRF89_TXOPVAL_4DBM 0x06
  238. #define RH_MRF89_TXOPVAL_7DBM 0x04
  239. #define RH_MRF89_TXOPVAL_10DBM 0x02
  240. #define RH_MRF89_TXOPVAL_13DBM 0x00
  241. //#define RH_MRF89_REG_1B_CLKOREG 0x1b
  242. #define RH_MRF89_CLKOCNTRL 0x80
  243. #define RH_MRF89_CLKOFREQ 0x7c
  244. //#define RH_MRF89_REG_1C_PLOADREG 0x1c
  245. #define RH_MRF89_MCHSTREN 0x80
  246. #define RH_MRF89_PLDPLEN 0x7f
  247. //#define RH_MRF89_REG_1E_PKTCREG 0x1e
  248. #define RH_MRF89_PKTLENF 0x80
  249. #define RH_MRF89_PRESIZE 0x60
  250. #define RH_MRF89_PRESIZE_4 0x60
  251. #define RH_MRF89_PRESIZE_3 0x40
  252. #define RH_MRF89_PRESIZE_2 0x20
  253. #define RH_MRF89_PRESIZE_1 0x00
  254. #define RH_MRF89_WHITEON 0x10
  255. #define RH_MRF89_CHKCRCEN 0x08
  256. #define RH_MRF89_ADDFIL 0x06
  257. #define RH_MRF89_ADDFIL_NODEADDR_00_FF 0x06
  258. #define RH_MRF89_ADDFIL_NODEADDR_00 0x04
  259. #define RH_MRF89_ADDFIL_NODEADDR 0x02
  260. #define RH_MRF89_ADDFIL_OFF 0x00
  261. #define RH_MRF89_STSCRCEN 0x01
  262. //#define RH_MRF89_REG_1F_FCRCREG 0x1f
  263. #define RH_MRF89_ACFCRC 0x80
  264. #define RH_MRF89_FRWAXS 0x40
  265. /////////////////////////////////////////////////////////////////////
  266. /// \class RH_MRF89 RH_MRF89.h <RH_MRF89.h>
  267. /// \brief Send and receive addressed, reliable, acknowledged datagrams by Microchip MRF89XA and compatible transceivers.
  268. /// and modules.
  269. ///
  270. /// The Microchip MRF89XA http://ww1.microchip.com/downloads/en/DeviceDoc/70622C.pdf is a low cost 900MHz
  271. /// bancd transceiver chip.
  272. /// It is commonly used on preassembled modules with supporting circcuits and antennas, such as
  273. /// the MRF89XAM9A http://www.microchip.com/wwwproducts/Devices.aspx?product=MRF89XAM9A
  274. /// This class supports all such modules
  275. ///
  276. /// This base class provides basic functions for sending and receiving unaddressed, unreliable datagrams
  277. /// of arbitrary length to 59 octets per packet. Use one of the Manager classes to get addressing and
  278. /// acknowledgement reliability, routing, meshes etc.
  279. ///
  280. /// Several MRF89XA modules can be connected to an Arduino, permitting the construction of translators
  281. /// and frequency changers, etc. Each instance requires 2 chip select pins, and interrupt pin the standard 3 SPI pins.
  282. ///
  283. /// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
  284. /// data rate, and with identical network addresses.
  285. ///
  286. /// Example Arduino programs are included to show the main modes of use.
  287. ///
  288. /// All messages sent and received by this class conform to this packet format:
  289. ///
  290. /// - 3 octets PREAMBLE
  291. /// - 2 to 4 octets NETWORK ADDRESS (also call Sync Word)
  292. /// - 1 octet message length bits packet control field
  293. /// - 4 to 63 octets PAYLOAD, consisting of:
  294. /// - 1 octet TO header
  295. /// - 1 octet FROM header
  296. /// - 1 octet ID header
  297. /// - 1 octet FLAGS header
  298. /// - 0 to 59 octets of user message
  299. /// - 2 octets CRC
  300. ///
  301. /// The payload is whitened. No Manchester encoding is used.
  302. ///
  303. /// \par Connecting MRF89XA to Arduino
  304. ///
  305. /// The electrical connection between the MRF89XA and the Arduino require 3.3V, the 3 x SPI pins (SCK, SDI, SDO),
  306. /// a 2 Chip Select pins (/CSCON and /CSDAT) and an interrupt.
  307. ///
  308. /// Caution: the MRF89XA is a 3.3V part and is not tolerant of 5V inputs. Connecting MRF89XA directly to a 5V
  309. /// MCU such as most Arduinos will damage the MRF89XA.
  310. ///
  311. /// Connect the MRF89XA to most 3.3V Arduinos or Teensy 3.1 like this (use 3.3V not 5V).
  312. /// \code
  313. /// Teensy MRF89XAM9A
  314. /// 3.3V-----------VIN (3.3V in)
  315. /// pin D9-----------/CSDAT (data chip select in)
  316. /// SS pin D10----------/CSCON (configuration chip select in)
  317. /// SCK pin D13----------SCK (SPI clock in)
  318. /// MOSI pin D11----------SDI (SPI Data in)
  319. /// MISO pin D12----------SDO (SPI data out)
  320. /// D2-----------IRQ1 (Interrupt 1 output)
  321. /// IRQ0 (Interrupt 0 output, not connected)
  322. /// GND----------GND (ground in)
  323. /// \endcode
  324. /// You can use other pins for /CSDAT, /CSCON, IRQ1 by passing appropriate arguments to the constructor.
  325. ///
  326. /// \par Example programs
  327. ///
  328. /// Several example programs are provided.
  329. ///
  330. class RH_MRF89 : public RHNRFSPIDriver
  331. {
  332. public:
  333. /// \brief Defines register configuration values for a desired modulation
  334. ///
  335. /// Defines values for various configuration fields and registers to
  336. /// achieve a desired modulation speed and frequency deviation.
  337. typedef struct
  338. {
  339. uint8_t MODSEL; ///< Value for MODSEL in RH_MRF89_REG_01_DMODREG
  340. uint8_t FDVAL; ///< Value for FDVAL in RH_MRF89_REG_02_FDEVREG
  341. uint8_t BRVAL; ///< Value for BRVAL RH_MRF89_REG_03_BRSREG
  342. uint8_t FILCREG; ///< Value for PASFILV | BUTFILV in RH_MRF89_REG_10_FILCREG
  343. uint8_t TXIPOLFV; ///< Value for TXIPOLFV in RH_MRF89_REG_1A_TXCONREG
  344. } ModemConfig;
  345. /// Choices for setModemConfig() for a selected subset of common
  346. /// data rates and frequency deviations.
  347. /// Rb is the data rate in kbps. Fd is the FSK Frequency deviation in kHz.
  348. /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
  349. /// definitions and not their integer equivalents: its possible that new values will be
  350. /// introduced in later versions (though we will try to avoid it).
  351. /// OOK is not yet supported.
  352. /// Based on sample configs in MRF89XA.h from Microchip
  353. typedef enum
  354. {
  355. FSK_Rb2Fd33 = 0, ///< FSK, No Manchester, Whitened, Rb = 2kbs, Fd = 33kHz
  356. FSK_Rb5Fd33, ///< FSK, No Manchester, Whitened, Rb = 5kbs, Fd = 33kHz
  357. FSK_Rb10Fd33, ///< FSK, No Manchester, Whitened, Rb = 10kbs, Fd = 33kHz
  358. FSK_Rb20Fd40, ///< FSK, No Manchester, Whitened, Rb = 20kbs, Fd = 40kHz
  359. FSK_Rb40Fd80, ///< FSK, No Manchester, Whitened, Rb = 40kbs, Fd = 80kHz
  360. FSK_Rb50Fd100, ///< FSK, No Manchester, Whitened, Rb = 50kbs, Fd = 100kHz
  361. FSK_Rb66Fd133, ///< FSK, No Manchester, Whitened, Rb = 66kbs, Fd = 133kHz
  362. FSK_Rb100Fd200, ///< FSK, No Manchester, Whitened, Rb = 100kbs, Fd = 200kHz
  363. FSK_Rb200Fd200 ///< FSK, No Manchester, Whitened, Rb = 200kbs, Fd = 200kHz
  364. } ModemConfigChoice;
  365. /// Constructor.
  366. /// Constructor. You can have multiple instances, but each instance must have its own
  367. /// interrupt and 2 slave select pins. After constructing, you must call init() to initialise the interface
  368. /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
  369. /// distinct interrupt lines, one for each instance.
  370. /// \param[in] csconPin the Arduino pin number connected to the CSCON pin of the MRF89XA.
  371. /// Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
  372. /// \param[in] csdatPin the Arduino pin number connected to the CSDAT pin of the MRF89XA.
  373. /// Defaults to 9.
  374. /// \param[in] interruptPin The interrupt Pin number that is connected to the IRQ1 pin of the MRF89XA.
  375. /// Defaults to pin 2. (IRQ0 pin of the MRF89XA does not need to be connected).
  376. /// \param[in] spi Pointer to the SPI interface object to use.
  377. /// Defaults to the standard Arduino hardware SPI interface
  378. RH_MRF89(uint8_t csconPin = SS, uint8_t csdatPin = 9, uint8_t interruptPin = 2, RHGenericSPI& spi = hardware_spi);
  379. /// Initialise the Driver transport hardware and software.
  380. /// Make sure the Driver is properly configured before calling init().
  381. /// \return true if initialisation succeeded.
  382. virtual bool init();
  383. /// Prints the value of all chip registers
  384. /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
  385. /// For debugging purposes only.
  386. /// \return true on success
  387. bool printRegisters();
  388. /// Sets the radio into low-power sleep mode.
  389. /// If successful, the transport will stay in sleep mode until woken by
  390. /// changing mode to idle, transmit or receive (eg by calling send(), recv(), available() etc)
  391. /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
  392. /// \return true if sleep mode was successfully entered.
  393. virtual bool sleep();
  394. /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
  395. /// disables them.
  396. void setModeIdle();
  397. /// If current mode is Tx or Idle, changes it to Rx.
  398. /// Starts the receiver in the radio.
  399. // the next valid packet received will cause available() to be true.
  400. void setModeRx();
  401. /// If current mode is Rx or Idle, changes it to Rx. F
  402. /// Starts the transmitter in the radio.
  403. void setModeTx();
  404. /// Sets the transmitter power output level in register RH_MRF89_REG_1A_TXCONREG.
  405. /// Be a good neighbour and set the lowest power level you need.
  406. /// After init(), the power will be set to RH_MRF89_TXOPVAL_1DBM (1dBm)
  407. /// The highest power available is RH_MRF89_TXOPVAL_13DBM (13dBm)
  408. /// Caution: In some countries you may only select certain higher power levels if you
  409. /// are also using frequency hopping. Make sure you are aware of the legal
  410. /// limitations and regulations in your region.
  411. /// Caution: in some countries the maximum permitted power level may depend on the Bit rate
  412. /// \param[in] power Transmitter power level, one of RH_MRF89_TXOPVAL*
  413. void setTxPower(uint8_t power);
  414. /// Select one of the predefined modem configurations. If you need a modem configuration not provided
  415. /// here, use setModemRegisters() with your own ModemConfig.
  416. /// \param[in] index The configuration choice.
  417. /// \return true if index is a valid choice.
  418. bool setModemConfig(ModemConfigChoice index);
  419. /// Tests whether a new message is available
  420. /// from the Driver.
  421. /// On most drivers, this will also put the Driver into RHModeRx mode until
  422. /// a message is actually received by the transport, when it will be returned to RHModeIdle.
  423. /// This can be called multiple times in a timeout loop
  424. /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
  425. virtual bool available();
  426. /// Turns the receiver on if it not already on.
  427. /// If there is a valid message available, copy it to buf and return true
  428. /// else return false.
  429. /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
  430. /// You should be sure to call this function frequently enough to not miss any messages
  431. /// It is recommended that you call it in your main loop.
  432. /// \param[in] buf Location to copy the received message
  433. /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
  434. /// \return true if a valid message was copied to buf
  435. virtual bool recv(uint8_t* buf, uint8_t* len);
  436. /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
  437. /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
  438. /// of 0 is permitted.
  439. /// \param[in] data Array of data to be sent
  440. /// \param[in] len Number of bytes of data to send
  441. /// \return true if the message length was valid and it was correctly queued for transmit
  442. virtual bool send(const uint8_t* data, uint8_t len);
  443. /// Returns the maximum message length
  444. /// available in this Driver.
  445. /// \return The maximum legal message length
  446. virtual uint8_t maxMessageLength();
  447. /// Sets the centre frequency in MHz.
  448. /// Permitted ranges are: 902.0 to 928.0 and 950.0 to 960.0 (inclusive)
  449. /// Caution not all freqs are supported on all modules: check your module specifications
  450. /// Caution: not all available and supported frequencies are legal in every country: check
  451. /// Regulatory Approval eg for MRF89XAM9A (in 75015B.pdf)
  452. /// Australia 915.0 to 928.0
  453. bool setFrequency(float centre);
  454. /// Sets the length of the preamble
  455. /// in bytes.
  456. /// Caution: this should be set to the same
  457. /// value on all nodes in your network. Default is 4.
  458. /// Sets the message preamble length in RH_MRF89_REG_1E_PKTCREG
  459. /// \param[in] bytes Preamble length in bytes of 8 bits each.
  460. void setPreambleLength(uint8_t bytes);
  461. /// Sets the sync words for transmit and receive in registers RH_MRF89_REG_16_SYNCV31REG
  462. /// et seq.
  463. /// Caution: SyncWords should be set to the same
  464. /// value on all nodes in your network. Nodes with different SyncWords set will never receive
  465. /// each others messages, so different SyncWords can be used to isolate different
  466. /// networks from each other. Default is { 0x69, 0x81, 0x7e, 0x96 }.
  467. /// Caution, sync words of 2 bytes and less do not work well with this chip.
  468. /// \param[in] syncWords Array of sync words, 1 to 4 octets long
  469. /// \param[in] len Number of sync words to set, 1 to 4.
  470. void setSyncWords(const uint8_t* syncWords = NULL, uint8_t len = 0);
  471. protected:
  472. /// Called automatically when a CRCOK or TXDONE interrupt occurs.
  473. /// Handles the interrupt.
  474. void handleInterrupt();
  475. /// Reads a single register from the MRF89XA
  476. /// \param[in] reg Register number, one of RH_MRF89_REG
  477. /// \return The value of the register
  478. uint8_t spiReadRegister(uint8_t reg);
  479. /// Writes to a single single register on the MRF89XA
  480. /// \param[in] reg Register number, one of RH_MRF89_REG_*
  481. /// \param[in] val The value to write
  482. /// \return the current value of RH_MRF89_REG_00_GCONREG (read while the command is sent)
  483. uint8_t spiWriteRegister(uint8_t reg, uint8_t val);
  484. /// Writes a single byte to the MRF89XA data FIFO.
  485. /// \param[in] data The data value to write
  486. /// \return 0
  487. uint8_t spiWriteData(uint8_t data);
  488. /// Write a number of bytes from a buffer to the MRF89XA data FIFO.
  489. /// \param[in] data Pointer to a buffer containing the len bytes to be written
  490. /// \param[in] len The number of bytes to write to teh FIFO
  491. /// \return 0;
  492. uint8_t spiWriteData(const uint8_t* data, uint8_t len);
  493. /// Reads a single byte from the MRF89XA data FIFO.
  494. /// \return The next data byte in the FIFO
  495. uint8_t spiReadData();
  496. /// Sets the operating mode in the CMOD bits in RH_MRF89_REG_00_GCONREG
  497. /// which controls what mode the MRF89XA is running in
  498. /// \param[in] mode One of RH_MRF89_CMOD_*
  499. void setOpMode(uint8_t mode);
  500. /// Verifies that the MRF89XA PLL has locked on the slected frequency.
  501. /// This needs to be called if the frequency is changed
  502. bool verifyPLLLock();
  503. /// Examine the revceive buffer to determine whether the message is for this node
  504. void validateRxBuf();
  505. /// Clear our local receive buffer
  506. void clearRxBuf();
  507. private:
  508. /// Low level interrupt service routine for device connected to interrupt 0
  509. static void isr0();
  510. /// Low level interrupt service routine for device connected to interrupt 1
  511. static void isr1();
  512. /// Low level interrupt service routine for device connected to interrupt 1
  513. static void isr2();
  514. /// Array of instances connected to interrupts 0 and 1
  515. static RH_MRF89* _deviceForInterrupt[];
  516. /// Index of next interrupt number to use in _deviceForInterrupt
  517. static uint8_t _interruptCount;
  518. // Sigh: this chip has 2 differnt chip selects.
  519. // We have to set one or the other as the SPI slave select pin depending
  520. // on which block of registers we are accessing
  521. uint8_t _csconPin;
  522. uint8_t _csdatPin;
  523. /// The configured interrupt pin connected to this instance
  524. uint8_t _interruptPin;
  525. /// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
  526. /// else 0xff
  527. uint8_t _myInterruptIndex;
  528. /// Number of octets in the buffer
  529. volatile uint8_t _bufLen;
  530. /// The receiver/transmitter buffer
  531. uint8_t _buf[RH_MRF89_MAX_PAYLOAD_LEN];
  532. /// True when there is a valid message in the buffer
  533. volatile bool _rxBufValid;
  534. };
  535. /// @example mrf89_client.pde
  536. /// @example mrf89_server.pde
  537. #endif