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