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_or_863_870 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 Low Power Mode
374///
375/// Fernando Faria reports that:
376///
377/// In order for low power mode to work to achieve 1μA power consumption in this chip, you will need to do a few extra things:
378///
379/// 1. the datasheet states that IRQ0 and IRQ1 must have a valid logic state at
380/// all times, so you will need to apply pull-down resistors to those pins (if not already present).
381/// See the data sheet Table 2-4 Note 3
382///
383/// 2. You must also ensure the SPI pins are in a certain state after calling mrf89.sleep();
384/// This may be suitable for your electrical connections:
385/// \code
386/// digitalWrite(9, HIGH); // CSDAT
387/// digitalWrite(10, LOW); // SS
388/// digitalWrite(11, LOW); //MOSI
389/// digitalWrite(13, LOW); // MISO
390/// \endcode
391///
392/// \par Example programs
393///
394/// Several example programs are provided.
395///
397{
398public:
399
400 /// \brief Defines register configuration values for a desired modulation
401 ///
402 /// Defines values for various configuration fields and registers to
403 /// achieve a desired modulation speed and frequency deviation.
404 typedef struct
405 {
406 uint8_t MODSEL; ///< Value for MODSEL in RH_MRF89_REG_01_DMODREG
407 uint8_t FDVAL; ///< Value for FDVAL in RH_MRF89_REG_02_FDEVREG
408 uint8_t BRVAL; ///< Value for BRVAL RH_MRF89_REG_03_BRSREG
409 uint8_t FILCREG; ///< Value for PASFILV | BUTFILV in RH_MRF89_REG_10_FILCREG
410 uint8_t TXIPOLFV; ///< Value for TXIPOLFV in RH_MRF89_REG_1A_TXCONREG
411 } ModemConfig;
412
413 /// Choices for setModemConfig() for a selected subset of common
414 /// data rates and frequency deviations.
415 /// Rb is the data rate in kbps. Fd is the FSK Frequency deviation in kHz.
416 /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
417 /// definitions and not their integer equivalents: its possible that new values will be
418 /// introduced in later versions (though we will try to avoid it).
419 /// OOK is not yet supported.
420 /// Based on sample configs in MRF89XA.h from Microchip
421 typedef enum
422 {
423 FSK_Rb2Fd33 = 0, ///< FSK, No Manchester, Whitened, Rb = 2kbs, Fd = 33kHz
424 FSK_Rb5Fd33, ///< FSK, No Manchester, Whitened, Rb = 5kbs, Fd = 33kHz
425 FSK_Rb10Fd33, ///< FSK, No Manchester, Whitened, Rb = 10kbs, Fd = 33kHz
426 FSK_Rb20Fd40, ///< FSK, No Manchester, Whitened, Rb = 20kbs, Fd = 40kHz
427 FSK_Rb40Fd80, ///< FSK, No Manchester, Whitened, Rb = 40kbs, Fd = 80kHz
428 FSK_Rb50Fd100, ///< FSK, No Manchester, Whitened, Rb = 50kbs, Fd = 100kHz
429 FSK_Rb66Fd133, ///< FSK, No Manchester, Whitened, Rb = 66kbs, Fd = 133kHz
430 FSK_Rb100Fd200, ///< FSK, No Manchester, Whitened, Rb = 100kbs, Fd = 200kHz
431 FSK_Rb200Fd200 ///< FSK, No Manchester, Whitened, Rb = 200kbs, Fd = 200kHz
433
434 /// Constructor.
435 /// Constructor. You can have multiple instances, but each instance must have its own
436 /// interrupt and 2 slave select pins. After constructing, you must call init() to initialise the interface
437 /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
438 /// distinct interrupt lines, one for each instance.
439 /// \param[in] csconPin the Arduino pin number connected to the CSCON pin of the MRF89XA.
440 /// Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
441 /// \param[in] csdatPin the Arduino pin number connected to the CSDAT pin of the MRF89XA.
442 /// Defaults to 9.
443 /// \param[in] interruptPin The interrupt Pin number that is connected to the IRQ1 pin of the MRF89XA.
444 /// Defaults to pin 2. (IRQ0 pin of the MRF89XA does not need to be connected).
445 /// \param[in] spi Pointer to the SPI interface object to use.
446 /// Defaults to the standard Arduino hardware SPI interface
447 RH_MRF89(uint8_t csconPin = SS, uint8_t csdatPin = 9, uint8_t interruptPin = 2, RHGenericSPI& spi = hardware_spi);
448
449 /// Initialise the Driver transport hardware and software.
450 /// Make sure the Driver is properly configured before calling init().
451 /// \return true if initialisation succeeded.
452 virtual bool init();
453
454 /// Prints the value of all chip registers
455 /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
456 /// For debugging purposes only.
457 /// \return true on success
458 bool printRegisters();
459
460 /// Sets the radio into low-power sleep mode.
461 /// If successful, the transport will stay in sleep mode until woken by
462 /// changing mode to idle, transmit or receive (eg by calling send(), recv(), available() etc)
463 /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
464 /// \return true if sleep mode was successfully entered.
465 virtual bool sleep();
466
467 /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
468 /// disables them.
469 void setModeIdle();
470
471 /// If current mode is Tx or Idle, changes it to Rx.
472 /// Starts the receiver in the radio.
473 // the next valid packet received will cause available() to be true.
474 void setModeRx();
475
476 /// If current mode is Rx or Idle, changes it to Rx. F
477 /// Starts the transmitter in the radio.
478 void setModeTx();
479
480 /// Sets the transmitter power output level in register RH_MRF89_REG_1A_TXCONREG.
481 /// Be a good neighbour and set the lowest power level you need.
482 /// After init(), the power will be set to RH_MRF89_TXOPVAL_1DBM (1dBm)
483 /// The highest power available is RH_MRF89_TXOPVAL_13DBM (13dBm)
484 /// Caution: In some countries you may only select certain higher power levels if you
485 /// are also using frequency hopping. Make sure you are aware of the legal
486 /// limitations and regulations in your region.
487 /// Caution: in some countries the maximum permitted power level may depend on the Bit rate
488 /// \param[in] power Transmitter power level, one of RH_MRF89_TXOPVAL*
489 void setTxPower(uint8_t power);
490
491 /// Select one of the predefined modem configurations. If you need a modem configuration not provided
492 /// here, use setModemRegisters() with your own ModemConfig.
493 /// \param[in] index The configuration choice.
494 /// \return true if index is a valid choice.
496
497 /// Tests whether a new message is available
498 /// from the Driver.
499 /// On most drivers, this will also put the Driver into RHModeRx mode until
500 /// a message is actually received by the transport, when it will be returned to RHModeIdle.
501 /// This can be called multiple times in a timeout loop
502 /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
503 virtual bool available();
504
505 /// Turns the receiver on if it not already on.
506 /// If there is a valid message available, copy it to buf and return true
507 /// else return false.
508 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
509 /// You should be sure to call this function frequently enough to not miss any messages
510 /// It is recommended that you call it in your main loop.
511 /// \param[in] buf Location to copy the received message
512 /// \param[in,out] len Pointer to the number of octets available in buf. The number be reset to the actual number of octets copied.
513 /// \return true if a valid message was copied to buf
514 virtual bool recv(uint8_t* buf, uint8_t* len);
515
516 /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
517 /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
518 /// of 0 is permitted.
519 /// \param[in] data Array of data to be sent
520 /// \param[in] len Number of bytes of data to send
521 /// \return true if the message length was valid and it was correctly queued for transmit
522 virtual bool send(const uint8_t* data, uint8_t len);
523
524 /// Returns the maximum message length
525 /// available in this Driver.
526 /// \return The maximum legal message length
527 virtual uint8_t maxMessageLength();
528
529 /// Sets the centre frequency in MHz.
530 /// Permitted ranges are: 902.0 to 928.0 and 950.0 to 960.0 (inclusive)
531 /// Caution not all freqs are supported on all modules: check your module specifications
532 /// Caution: not all available and supported frequencies are legal in every country: check
533 /// Regulatory Approval eg for MRF89XAM9A (in 75015B.pdf)
534 /// Australia 915.0 to 928.0
535 bool setFrequency(float centre);
536
537 /// Sets the length of the preamble
538 /// in bytes.
539 /// Caution: this should be set to the same
540 /// value on all nodes in your network. Default is 4.
541 /// Sets the message preamble length in RH_MRF89_REG_1E_PKTCREG
542 /// \param[in] bytes Preamble length in bytes of 8 bits each.
543 void setPreambleLength(uint8_t bytes);
544
545 /// Sets the sync words for transmit and receive in registers RH_MRF89_REG_16_SYNCV31REG
546 /// et seq.
547 /// Caution: SyncWords should be set to the same
548 /// value on all nodes in your network. Nodes with different SyncWords set will never receive
549 /// each others messages, so different SyncWords can be used to isolate different
550 /// networks from each other. Default is { 0x69, 0x81, 0x7e, 0x96 }.
551 /// Caution, sync words of 2 bytes and less do not work well with this chip.
552 /// \param[in] syncWords Array of sync words, 1 to 4 octets long
553 /// \param[in] len Number of sync words to set, 1 to 4.
554 void setSyncWords(const uint8_t* syncWords = NULL, uint8_t len = 0);
555
556protected:
557
558 /// Called automatically when a CRCOK or TXDONE interrupt occurs.
559 /// Handles the interrupt.
560 void handleInterrupt();
561
562 /// Reads a single register from the MRF89XA
563 /// \param[in] reg Register number, one of RH_MRF89_REG
564 /// \return The value of the register
565 uint8_t spiReadRegister(uint8_t reg);
566
567 /// Writes to a single single register on the MRF89XA
568 /// \param[in] reg Register number, one of RH_MRF89_REG_*
569 /// \param[in] val The value to write
570 /// \return the current value of RH_MRF89_REG_00_GCONREG (read while the command is sent)
571 uint8_t spiWriteRegister(uint8_t reg, uint8_t val);
572
573 /// Writes a single byte to the MRF89XA data FIFO.
574 /// \param[in] data The data value to write
575 /// \return 0
576 uint8_t spiWriteData(uint8_t data);
577
578 /// Write a number of bytes from a buffer to the MRF89XA data FIFO.
579 /// \param[in] data Pointer to a buffer containing the len bytes to be written
580 /// \param[in] len The number of bytes to write to teh FIFO
581 /// \return 0;
582 uint8_t spiWriteData(const uint8_t* data, uint8_t len);
583
584 /// Reads a single byte from the MRF89XA data FIFO.
585 /// \return The next data byte in the FIFO
586 uint8_t spiReadData();
587
588 /// Sets the operating mode in the CMOD bits in RH_MRF89_REG_00_GCONREG
589 /// which controls what mode the MRF89XA is running in
590 /// \param[in] mode One of RH_MRF89_CMOD_*
591 void setOpMode(uint8_t mode);
592
593 /// Verifies that the MRF89XA PLL has locked on the slected frequency.
594 /// This needs to be called if the frequency is changed
595 bool verifyPLLLock();
596
597 /// Examine the revceive buffer to determine whether the message is for this node
598 void validateRxBuf();
599
600 /// Clear our local receive buffer
601 void clearRxBuf();
602
603
604private:
605 /// Low level interrupt service routine for device connected to interrupt 0
606 static void isr0();
607
608 /// Low level interrupt service routine for device connected to interrupt 1
609 static void isr1();
610
611 /// Low level interrupt service routine for device connected to interrupt 1
612 static void isr2();
613
614 /// Array of instances connected to interrupts 0 and 1
615 static RH_MRF89* _deviceForInterrupt[];
616
617 /// Index of next interrupt number to use in _deviceForInterrupt
618 static uint8_t _interruptCount;
619
620 // Sigh: this chip has 2 differnt chip selects.
621 // We have to set one or the other as the SPI slave select pin depending
622 // on which block of registers we are accessing
623 uint8_t _csconPin;
624 uint8_t _csdatPin;
625
626 /// The configured interrupt pin connected to this instance
627 uint8_t _interruptPin;
628
629 /// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
630 /// else 0xff
631 uint8_t _myInterruptIndex;
632
633 /// Number of octets in the buffer
634 volatile uint8_t _bufLen;
635
636 /// The receiver/transmitter buffer
637 uint8_t _buf[RH_MRF89_MAX_PAYLOAD_LEN];
638
639 /// True when there is a valid message in the buffer
640 volatile bool _rxBufValid;
641
642};
643
644/// @example mrf89_client.ino
645/// @example mrf89_server.ino
646
647#endif
virtual RHMode mode()
Definition: RHGenericDriver.cpp:165
Base class for SPI interfaces.
Definition: RHGenericSPI.h:31
Base class for RadioHead drivers that use the SPI bus to communicate with its NRF family transport ha...
Definition: RHNRFSPIDriver.h:34
Send and receive unaddressed, unreliable datagrams by Microchip MRF89XA and compatible transceivers....
Definition: RH_MRF89.h:397
uint8_t spiWriteRegister(uint8_t reg, uint8_t val)
Definition: RH_MRF89.cpp:267
void setPreambleLength(uint8_t bytes)
Definition: RH_MRF89.cpp:550
uint8_t spiReadRegister(uint8_t reg)
Definition: RH_MRF89.cpp:259
bool printRegisters()
Definition: RH_MRF89.cpp:176
virtual bool send(const uint8_t *data, uint8_t len)
Definition: RH_MRF89.cpp:393
bool verifyPLLLock()
Definition: RH_MRF89.cpp:449
void setModeIdle()
Definition: RH_MRF89.cpp:321
ModemConfigChoice
Definition: RH_MRF89.h:422
@ FSK_Rb200Fd200
FSK, No Manchester, Whitened, Rb = 200kbs, Fd = 200kHz.
Definition: RH_MRF89.h:431
@ FSK_Rb2Fd33
FSK, No Manchester, Whitened, Rb = 2kbs, Fd = 33kHz.
Definition: RH_MRF89.h:423
@ FSK_Rb5Fd33
FSK, No Manchester, Whitened, Rb = 5kbs, Fd = 33kHz.
Definition: RH_MRF89.h:424
@ FSK_Rb100Fd200
FSK, No Manchester, Whitened, Rb = 100kbs, Fd = 200kHz.
Definition: RH_MRF89.h:430
@ FSK_Rb10Fd33
FSK, No Manchester, Whitened, Rb = 10kbs, Fd = 33kHz.
Definition: RH_MRF89.h:425
@ FSK_Rb40Fd80
FSK, No Manchester, Whitened, Rb = 40kbs, Fd = 80kHz.
Definition: RH_MRF89.h:427
@ FSK_Rb50Fd100
FSK, No Manchester, Whitened, Rb = 50kbs, Fd = 100kHz.
Definition: RH_MRF89.h:428
@ FSK_Rb66Fd133
FSK, No Manchester, Whitened, Rb = 66kbs, Fd = 133kHz.
Definition: RH_MRF89.h:429
@ FSK_Rb20Fd40
FSK, No Manchester, Whitened, Rb = 20kbs, Fd = 40kHz.
Definition: RH_MRF89.h:426
void setModeTx()
Definition: RH_MRF89.cpp:349
bool setFrequency(float centre)
Definition: RH_MRF89.cpp:467
uint8_t spiReadData()
Definition: RH_MRF89.cpp:305
virtual bool sleep()
Definition: RH_MRF89.cpp:330
void setModeRx()
Definition: RH_MRF89.cpp:340
bool setModemConfig(ModemConfigChoice index)
Definition: RH_MRF89.cpp:525
virtual bool available()
Definition: RH_MRF89.cpp:365
RH_MRF89(uint8_t csconPin=SS, uint8_t csdatPin=9, uint8_t interruptPin=2, RHGenericSPI &spi=hardware_spi)
Definition: RH_MRF89.cpp:38
void handleInterrupt()
Definition: RH_MRF89.cpp:195
void setOpMode(uint8_t mode)
Definition: RH_MRF89.cpp:313
uint8_t spiWriteData(uint8_t data)
Definition: RH_MRF89.cpp:278
virtual uint8_t maxMessageLength()
Definition: RH_MRF89.cpp:417
void clearRxBuf()
Clear our local receive buffer.
Definition: RH_MRF89.cpp:441
virtual bool recv(uint8_t *buf, uint8_t *len)
Definition: RH_MRF89.cpp:374
void setTxPower(uint8_t power)
Definition: RH_MRF89.cpp:358
virtual bool init()
Definition: RH_MRF89.cpp:48
void setSyncWords(const uint8_t *syncWords=NULL, uint8_t len=0)
Definition: RH_MRF89.cpp:561
void validateRxBuf()
Examine the revceive buffer to determine whether the message is for this node.
Definition: RH_MRF89.cpp:423
Defines register configuration values for a desired modulation.
Definition: RH_MRF89.h:405
uint8_t BRVAL
Value for BRVAL RH_MRF89_REG_03_BRSREG.
Definition: RH_MRF89.h:408
uint8_t FDVAL
Value for FDVAL in RH_MRF89_REG_02_FDEVREG.
Definition: RH_MRF89.h:407
uint8_t MODSEL
Value for MODSEL in RH_MRF89_REG_01_DMODREG.
Definition: RH_MRF89.h:406
uint8_t FILCREG
Value for PASFILV | BUTFILV in RH_MRF89_REG_10_FILCREG.
Definition: RH_MRF89.h:409
uint8_t TXIPOLFV
Value for TXIPOLFV in RH_MRF89_REG_1A_TXCONREG.
Definition: RH_MRF89.h:410