930 lines
45 KiB
C
930 lines
45 KiB
C
|
// RH_RF69.h
|
||
|
// Author: Mike McCauley (mikem@airspayce.com)
|
||
|
// Copyright (C) 2014 Mike McCauley
|
||
|
// $Id: RH_RF69.h,v 1.32 2016/07/07 00:02:53 mikem Exp mikem $
|
||
|
//
|
||
|
///
|
||
|
|
||
|
|
||
|
#ifndef RH_RF69_h
|
||
|
#define RH_RF69_h
|
||
|
|
||
|
#include <RHGenericSPI.h>
|
||
|
#include <RHSPIDriver.h>
|
||
|
|
||
|
// The crystal oscillator frequency of the RF69 module
|
||
|
#define RH_RF69_FXOSC 32000000.0
|
||
|
|
||
|
// The Frequency Synthesizer step = RH_RF69_FXOSC / 2^^19
|
||
|
#define RH_RF69_FSTEP (RH_RF69_FXOSC / 524288)
|
||
|
|
||
|
// This is the maximum number of interrupts the driver can support
|
||
|
// Most Arduinos can handle 2, Megas can handle more
|
||
|
#define RH_RF69_NUM_INTERRUPTS 3
|
||
|
|
||
|
// This is the bit in the SPI address that marks it as a write
|
||
|
#define RH_RF69_SPI_WRITE_MASK 0x80
|
||
|
|
||
|
// Max number of octets the RH_RF69 Rx and Tx FIFOs can hold
|
||
|
#define RH_RF69_FIFO_SIZE 66
|
||
|
|
||
|
// Maximum encryptable payload length the RF69 can support
|
||
|
#define RH_RF69_MAX_ENCRYPTABLE_PAYLOAD_LEN 64
|
||
|
|
||
|
// The length of the headers we add.
|
||
|
// The headers are inside the RF69's payload and are therefore encrypted if encryption is enabled
|
||
|
#define RH_RF69_HEADER_LEN 4
|
||
|
|
||
|
// This is the maximum message length that can be supported by this driver. Limited by
|
||
|
// the size of the FIFO, since we are unable to support on-the-fly filling and emptying
|
||
|
// of the FIFO.
|
||
|
// Can be pre-defined to a smaller size (to save SRAM) prior to including this header
|
||
|
// Here we allow for 4 bytes of address and header and payload to be included in the 64 byte encryption limit.
|
||
|
// the one byte payload length is not encrpyted
|
||
|
#ifndef RH_RF69_MAX_MESSAGE_LEN
|
||
|
#define RH_RF69_MAX_MESSAGE_LEN (RH_RF69_MAX_ENCRYPTABLE_PAYLOAD_LEN - RH_RF69_HEADER_LEN)
|
||
|
#endif
|
||
|
|
||
|
// Keep track of the mode the RF69 is in
|
||
|
#define RH_RF69_MODE_IDLE 0
|
||
|
#define RH_RF69_MODE_RX 1
|
||
|
#define RH_RF69_MODE_TX 2
|
||
|
|
||
|
// This is the default node address,
|
||
|
#define RH_RF69_DEFAULT_NODE_ADDRESS 0
|
||
|
|
||
|
// Register names
|
||
|
#define RH_RF69_REG_00_FIFO 0x00
|
||
|
#define RH_RF69_REG_01_OPMODE 0x01
|
||
|
#define RH_RF69_REG_02_DATAMODUL 0x02
|
||
|
#define RH_RF69_REG_03_BITRATEMSB 0x03
|
||
|
#define RH_RF69_REG_04_BITRATELSB 0x04
|
||
|
#define RH_RF69_REG_05_FDEVMSB 0x05
|
||
|
#define RH_RF69_REG_06_FDEVLSB 0x06
|
||
|
#define RH_RF69_REG_07_FRFMSB 0x07
|
||
|
#define RH_RF69_REG_08_FRFMID 0x08
|
||
|
#define RH_RF69_REG_09_FRFLSB 0x09
|
||
|
#define RH_RF69_REG_0A_OSC1 0x0a
|
||
|
#define RH_RF69_REG_0B_AFCCTRL 0x0b
|
||
|
#define RH_RF69_REG_0C_RESERVED 0x0c
|
||
|
#define RH_RF69_REG_0D_LISTEN1 0x0d
|
||
|
#define RH_RF69_REG_0E_LISTEN2 0x0e
|
||
|
#define RH_RF69_REG_0F_LISTEN3 0x0f
|
||
|
#define RH_RF69_REG_10_VERSION 0x10
|
||
|
#define RH_RF69_REG_11_PALEVEL 0x11
|
||
|
#define RH_RF69_REG_12_PARAMP 0x12
|
||
|
#define RH_RF69_REG_13_OCP 0x13
|
||
|
#define RH_RF69_REG_14_RESERVED 0x14
|
||
|
#define RH_RF69_REG_15_RESERVED 0x15
|
||
|
#define RH_RF69_REG_16_RESERVED 0x16
|
||
|
#define RH_RF69_REG_17_RESERVED 0x17
|
||
|
#define RH_RF69_REG_18_LNA 0x18
|
||
|
#define RH_RF69_REG_19_RXBW 0x19
|
||
|
#define RH_RF69_REG_1A_AFCBW 0x1a
|
||
|
#define RH_RF69_REG_1B_OOKPEAK 0x1b
|
||
|
#define RH_RF69_REG_1C_OOKAVG 0x1c
|
||
|
#define RH_RF69_REG_1D_OOKFIX 0x1d
|
||
|
#define RH_RF69_REG_1E_AFCFEI 0x1e
|
||
|
#define RH_RF69_REG_1F_AFCMSB 0x1f
|
||
|
#define RH_RF69_REG_20_AFCLSB 0x20
|
||
|
#define RH_RF69_REG_21_FEIMSB 0x21
|
||
|
#define RH_RF69_REG_22_FEILSB 0x22
|
||
|
#define RH_RF69_REG_23_RSSICONFIG 0x23
|
||
|
#define RH_RF69_REG_24_RSSIVALUE 0x24
|
||
|
#define RH_RF69_REG_25_DIOMAPPING1 0x25
|
||
|
#define RH_RF69_REG_26_DIOMAPPING2 0x26
|
||
|
#define RH_RF69_REG_27_IRQFLAGS1 0x27
|
||
|
#define RH_RF69_REG_28_IRQFLAGS2 0x28
|
||
|
#define RH_RF69_REG_29_RSSITHRESH 0x29
|
||
|
#define RH_RF69_REG_2A_RXTIMEOUT1 0x2a
|
||
|
#define RH_RF69_REG_2B_RXTIMEOUT2 0x2b
|
||
|
#define RH_RF69_REG_2C_PREAMBLEMSB 0x2c
|
||
|
#define RH_RF69_REG_2D_PREAMBLELSB 0x2d
|
||
|
#define RH_RF69_REG_2E_SYNCCONFIG 0x2e
|
||
|
#define RH_RF69_REG_2F_SYNCVALUE1 0x2f
|
||
|
// another 7 sync word bytes follow, 30 through 36 inclusive
|
||
|
#define RH_RF69_REG_37_PACKETCONFIG1 0x37
|
||
|
#define RH_RF69_REG_38_PAYLOADLENGTH 0x38
|
||
|
#define RH_RF69_REG_39_NODEADRS 0x39
|
||
|
#define RH_RF69_REG_3A_BROADCASTADRS 0x3a
|
||
|
#define RH_RF69_REG_3B_AUTOMODES 0x3b
|
||
|
#define RH_RF69_REG_3C_FIFOTHRESH 0x3c
|
||
|
#define RH_RF69_REG_3D_PACKETCONFIG2 0x3d
|
||
|
#define RH_RF69_REG_3E_AESKEY1 0x3e
|
||
|
// Another 15 AES key bytes follow
|
||
|
#define RH_RF69_REG_4E_TEMP1 0x4e
|
||
|
#define RH_RF69_REG_4F_TEMP2 0x4f
|
||
|
#define RH_RF69_REG_58_TESTLNA 0x58
|
||
|
#define RH_RF69_REG_5A_TESTPA1 0x5a
|
||
|
#define RH_RF69_REG_5C_TESTPA2 0x5c
|
||
|
#define RH_RF69_REG_6F_TESTDAGC 0x6f
|
||
|
#define RH_RF69_REG_71_TESTAFC 0x71
|
||
|
|
||
|
// These register masks etc are named wherever possible
|
||
|
// corresponding to the bit and field names in the RFM69 Manual
|
||
|
|
||
|
// RH_RF69_REG_01_OPMODE
|
||
|
#define RH_RF69_OPMODE_SEQUENCEROFF 0x80
|
||
|
#define RH_RF69_OPMODE_LISTENON 0x40
|
||
|
#define RH_RF69_OPMODE_LISTENABORT 0x20
|
||
|
#define RH_RF69_OPMODE_MODE 0x1c
|
||
|
#define RH_RF69_OPMODE_MODE_SLEEP 0x00
|
||
|
#define RH_RF69_OPMODE_MODE_STDBY 0x04
|
||
|
#define RH_RF69_OPMODE_MODE_FS 0x08
|
||
|
#define RH_RF69_OPMODE_MODE_TX 0x0c
|
||
|
#define RH_RF69_OPMODE_MODE_RX 0x10
|
||
|
|
||
|
// RH_RF69_REG_02_DATAMODUL
|
||
|
#define RH_RF69_DATAMODUL_DATAMODE 0x60
|
||
|
#define RH_RF69_DATAMODUL_DATAMODE_PACKET 0x00
|
||
|
#define RH_RF69_DATAMODUL_DATAMODE_CONT_WITH_SYNC 0x40
|
||
|
#define RH_RF69_DATAMODUL_DATAMODE_CONT_WITHOUT_SYNC 0x60
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONTYPE 0x18
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONTYPE_FSK 0x00
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONTYPE_OOK 0x08
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONSHAPING 0x03
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_NONE 0x00
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT1_0 0x01
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT0_5 0x02
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT0_3 0x03
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_NONE 0x00
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_BR 0x01
|
||
|
#define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_2BR 0x02
|
||
|
|
||
|
// RH_RF69_REG_11_PALEVEL
|
||
|
#define RH_RF69_PALEVEL_PA0ON 0x80
|
||
|
#define RH_RF69_PALEVEL_PA1ON 0x40
|
||
|
#define RH_RF69_PALEVEL_PA2ON 0x20
|
||
|
#define RH_RF69_PALEVEL_OUTPUTPOWER 0x1f
|
||
|
|
||
|
// RH_RF69_REG_23_RSSICONFIG
|
||
|
#define RH_RF69_RSSICONFIG_RSSIDONE 0x02
|
||
|
#define RH_RF69_RSSICONFIG_RSSISTART 0x01
|
||
|
|
||
|
// RH_RF69_REG_25_DIOMAPPING1
|
||
|
#define RH_RF69_DIOMAPPING1_DIO0MAPPING 0xc0
|
||
|
#define RH_RF69_DIOMAPPING1_DIO0MAPPING_00 0x00
|
||
|
#define RH_RF69_DIOMAPPING1_DIO0MAPPING_01 0x40
|
||
|
#define RH_RF69_DIOMAPPING1_DIO0MAPPING_10 0x80
|
||
|
#define RH_RF69_DIOMAPPING1_DIO0MAPPING_11 0xc0
|
||
|
|
||
|
#define RH_RF69_DIOMAPPING1_DIO1MAPPING 0x30
|
||
|
#define RH_RF69_DIOMAPPING1_DIO1MAPPING_00 0x00
|
||
|
#define RH_RF69_DIOMAPPING1_DIO1MAPPING_01 0x10
|
||
|
#define RH_RF69_DIOMAPPING1_DIO1MAPPING_10 0x20
|
||
|
#define RH_RF69_DIOMAPPING1_DIO1MAPPING_11 0x30
|
||
|
|
||
|
#define RH_RF69_DIOMAPPING1_DIO2MAPPING 0x0c
|
||
|
#define RH_RF69_DIOMAPPING1_DIO2MAPPING_00 0x00
|
||
|
#define RH_RF69_DIOMAPPING1_DIO2MAPPING_01 0x04
|
||
|
#define RH_RF69_DIOMAPPING1_DIO2MAPPING_10 0x08
|
||
|
#define RH_RF69_DIOMAPPING1_DIO2MAPPING_11 0x0c
|
||
|
|
||
|
#define RH_RF69_DIOMAPPING1_DIO3MAPPING 0x03
|
||
|
#define RH_RF69_DIOMAPPING1_DIO3MAPPING_00 0x00
|
||
|
#define RH_RF69_DIOMAPPING1_DIO3MAPPING_01 0x01
|
||
|
#define RH_RF69_DIOMAPPING1_DIO3MAPPING_10 0x02
|
||
|
#define RH_RF69_DIOMAPPING1_DIO3MAPPING_11 0x03
|
||
|
|
||
|
// RH_RF69_REG_26_DIOMAPPING2
|
||
|
#define RH_RF69_DIOMAPPING2_DIO4MAPPING 0xc0
|
||
|
#define RH_RF69_DIOMAPPING2_DIO4MAPPING_00 0x00
|
||
|
#define RH_RF69_DIOMAPPING2_DIO4MAPPING_01 0x40
|
||
|
#define RH_RF69_DIOMAPPING2_DIO4MAPPING_10 0x80
|
||
|
#define RH_RF69_DIOMAPPING2_DIO4MAPPING_11 0xc0
|
||
|
|
||
|
#define RH_RF69_DIOMAPPING2_DIO5MAPPING 0x30
|
||
|
#define RH_RF69_DIOMAPPING2_DIO5MAPPING_00 0x00
|
||
|
#define RH_RF69_DIOMAPPING2_DIO5MAPPING_01 0x10
|
||
|
#define RH_RF69_DIOMAPPING2_DIO5MAPPING_10 0x20
|
||
|
#define RH_RF69_DIOMAPPING2_DIO5MAPPING_11 0x30
|
||
|
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT 0x07
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_ 0x00
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_2 0x01
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_4 0x02
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_8 0x03
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_16 0x04
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_32 0x05
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_RC 0x06
|
||
|
#define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_OFF 0x07
|
||
|
|
||
|
// RH_RF69_REG_27_IRQFLAGS1
|
||
|
#define RH_RF69_IRQFLAGS1_MODEREADY 0x80
|
||
|
#define RH_RF69_IRQFLAGS1_RXREADY 0x40
|
||
|
#define RH_RF69_IRQFLAGS1_TXREADY 0x20
|
||
|
#define RH_RF69_IRQFLAGS1_PLLLOCK 0x10
|
||
|
#define RH_RF69_IRQFLAGS1_RSSI 0x08
|
||
|
#define RH_RF69_IRQFLAGS1_TIMEOUT 0x04
|
||
|
#define RH_RF69_IRQFLAGS1_AUTOMODE 0x02
|
||
|
#define RH_RF69_IRQFLAGS1_SYNADDRESSMATCH 0x01
|
||
|
|
||
|
// RH_RF69_REG_28_IRQFLAGS2
|
||
|
#define RH_RF69_IRQFLAGS2_FIFOFULL 0x80
|
||
|
#define RH_RF69_IRQFLAGS2_FIFONOTEMPTY 0x40
|
||
|
#define RH_RF69_IRQFLAGS2_FIFOLEVEL 0x20
|
||
|
#define RH_RF69_IRQFLAGS2_FIFOOVERRUN 0x10
|
||
|
#define RH_RF69_IRQFLAGS2_PACKETSENT 0x08
|
||
|
#define RH_RF69_IRQFLAGS2_PAYLOADREADY 0x04
|
||
|
#define RH_RF69_IRQFLAGS2_CRCOK 0x02
|
||
|
|
||
|
// RH_RF69_REG_2E_SYNCCONFIG
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCON 0x80
|
||
|
#define RH_RF69_SYNCCONFIG_FIFOFILLCONDITION_MANUAL 0x40
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE 0x38
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_1 0x00
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_2 0x08
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_3 0x10
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_4 0x18
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_5 0x20
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_6 0x28
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_7 0x30
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_8 0x38
|
||
|
#define RH_RF69_SYNCCONFIG_SYNCSIZE_SYNCTOL 0x07
|
||
|
|
||
|
// RH_RF69_REG_37_PACKETCONFIG1
|
||
|
#define RH_RF69_PACKETCONFIG1_PACKETFORMAT_VARIABLE 0x80
|
||
|
#define RH_RF69_PACKETCONFIG1_DCFREE 0x60
|
||
|
#define RH_RF69_PACKETCONFIG1_DCFREE_NONE 0x00
|
||
|
#define RH_RF69_PACKETCONFIG1_DCFREE_MANCHESTER 0x20
|
||
|
#define RH_RF69_PACKETCONFIG1_DCFREE_WHITENING 0x40
|
||
|
#define RH_RF69_PACKETCONFIG1_DCFREE_RESERVED 0x60
|
||
|
#define RH_RF69_PACKETCONFIG1_CRC_ON 0x10
|
||
|
#define RH_RF69_PACKETCONFIG1_CRCAUTOCLEAROFF 0x08
|
||
|
#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING 0x06
|
||
|
#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NONE 0x00
|
||
|
#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NODE 0x02
|
||
|
#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NODE_BC 0x04
|
||
|
#define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_RESERVED 0x06
|
||
|
|
||
|
// RH_RF69_REG_3C_FIFOTHRESH
|
||
|
#define RH_RF69_FIFOTHRESH_TXSTARTCONDITION_NOTEMPTY 0x80
|
||
|
#define RH_RF69_FIFOTHRESH_FIFOTHRESHOLD 0x7f
|
||
|
|
||
|
// RH_RF69_REG_3D_PACKETCONFIG2
|
||
|
#define RH_RF69_PACKETCONFIG2_INTERPACKETRXDELAY 0xf0
|
||
|
#define RH_RF69_PACKETCONFIG2_RESTARTRX 0x04
|
||
|
#define RH_RF69_PACKETCONFIG2_AUTORXRESTARTON 0x02
|
||
|
#define RH_RF69_PACKETCONFIG2_AESON 0x01
|
||
|
|
||
|
// RH_RF69_REG_4E_TEMP1
|
||
|
#define RH_RF69_TEMP1_TEMPMEASSTART 0x08
|
||
|
#define RH_RF69_TEMP1_TEMPMEASRUNNING 0x04
|
||
|
|
||
|
// RH_RF69_REG_5A_TESTPA1
|
||
|
#define RH_RF69_TESTPA1_NORMAL 0x55
|
||
|
#define RH_RF69_TESTPA1_BOOST 0x5d
|
||
|
|
||
|
// RH_RF69_REG_5C_TESTPA2
|
||
|
#define RH_RF69_TESTPA2_NORMAL 0x70
|
||
|
#define RH_RF69_TESTPA2_BOOST 0x7c
|
||
|
|
||
|
// RH_RF69_REG_6F_TESTDAGC
|
||
|
#define RH_RF69_TESTDAGC_CONTINUOUSDAGC_NORMAL 0x00
|
||
|
#define RH_RF69_TESTDAGC_CONTINUOUSDAGC_IMPROVED_LOWBETAON 0x20
|
||
|
#define RH_RF69_TESTDAGC_CONTINUOUSDAGC_IMPROVED_LOWBETAOFF 0x30
|
||
|
|
||
|
// Define this to include Serial printing in diagnostic routines
|
||
|
#define RH_RF69_HAVE_SERIAL
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
/// \class RH_RF69 RH_RF69.h <RH_RF69.h>
|
||
|
/// \brief Driver to send and receive unaddressed, unreliable datagrams via an RF69 and compatible radio transceiver.
|
||
|
///
|
||
|
/// Works with
|
||
|
/// - the excellent Moteino and Moteino-USB
|
||
|
/// boards from LowPowerLab http://lowpowerlab.com/moteino/
|
||
|
/// - compatible chips and modules such as RFM69W, RFM69HW, RFM69CW, RFM69HCW (Semtech SX1231, SX1231H),
|
||
|
/// - RFM69 modules from http://www.hoperfusa.com such as http://www.hoperfusa.com/details.jsp?pid=145
|
||
|
/// - Anarduino MiniWireless -CW and -HW boards http://www.anarduino.com/miniwireless/ including
|
||
|
/// the marvellous high powered MinWireless-HW (with 20dBm output for excellent range)
|
||
|
/// - the excellent Rocket Scream Mini Ultra Pro with the RFM69HCW
|
||
|
/// http://www.rocketscream.com/blog/product/mini-ultra-pro-with-radio/
|
||
|
/// - The excellent talk2 Whisper Node boards
|
||
|
/// (https://talk2.wisen.com.au/ and https://bitbucket.org/talk2/),
|
||
|
/// an Arduino Nano compatible board, which include an on-board RF69 radio, external antenna,
|
||
|
/// run on 2xAA batteries and support low power operations. RF69 examples work without modification.
|
||
|
///
|
||
|
/// \par Overview
|
||
|
///
|
||
|
/// This class provides basic functions for sending and receiving unaddressed,
|
||
|
/// unreliable datagrams of arbitrary length to 64 octets per packet.
|
||
|
///
|
||
|
/// Manager classes may use this class to implement reliable, addressed datagrams and streams,
|
||
|
/// mesh routers, repeaters, translators etc.
|
||
|
///
|
||
|
/// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
|
||
|
/// modulation scheme.
|
||
|
///
|
||
|
/// This Driver provides an object-oriented interface for sending and receiving data messages with Hope-RF
|
||
|
/// RF69B and compatible radio modules, such as the RFM69 module.
|
||
|
///
|
||
|
/// The Hope-RF (http://www.hoperf.com) RF69 is a low-cost ISM transceiver
|
||
|
/// chip. It supports FSK, GFSK, OOK over a wide range of frequencies and
|
||
|
/// programmable data rates. It also suports AES encryption of up to 64 octets
|
||
|
/// of payload It is available prepackaged on modules such as the RFM69W. And
|
||
|
/// such modules can be prepacked on processor boards such as the Moteino from
|
||
|
/// LowPowerLabs (which is what we used to develop the RH_RF69 driver)
|
||
|
///
|
||
|
/// This Driver provides functions for sending and receiving messages of up
|
||
|
/// to 60 octets on any frequency supported by the RF69, in a range of
|
||
|
/// predefined data rates and frequency deviations. Frequency can be set with
|
||
|
/// 61Hz precision to any frequency from 240.0MHz to 960.0MHz. Caution: most modules only support a more limited
|
||
|
/// range of frequencies due to antenna tuning.
|
||
|
///
|
||
|
/// Up to 2 RF69B modules can be connected to an Arduino (3 on a Mega),
|
||
|
/// permitting the construction of translators and frequency changers, etc.
|
||
|
///
|
||
|
/// The following modulation types are suppported with a range of modem configurations for
|
||
|
/// common data rates and frequency deviations:
|
||
|
/// - GFSK Gaussian Frequency Shift Keying
|
||
|
/// - FSK Frequency Shift Keying
|
||
|
///
|
||
|
/// Support for other RF69 features such as on-chip temperature measurement,
|
||
|
/// transmitter power control etc is also provided.
|
||
|
///
|
||
|
/// Tested on USB-Moteino with arduino-1.0.5
|
||
|
/// on OpenSuSE 13.1
|
||
|
///
|
||
|
/// \par Packet Format
|
||
|
///
|
||
|
/// All messages sent and received by this RH_RF69 Driver conform to this packet format:
|
||
|
///
|
||
|
/// - 4 octets PREAMBLE
|
||
|
/// - 2 octets SYNC 0x2d, 0xd4 (configurable, so you can use this as a network filter)
|
||
|
/// - 1 octet RH_RF69 payload length
|
||
|
/// - 4 octets HEADER: (TO, FROM, ID, FLAGS)
|
||
|
/// - 0 to 60 octets DATA
|
||
|
/// - 2 octets CRC computed with CRC16(IBM), computed on HEADER and DATA
|
||
|
///
|
||
|
/// For technical reasons, the message format is not protocol compatible with the
|
||
|
/// 'HopeRF Radio Transceiver Message Library for Arduino'
|
||
|
/// http://www.airspayce.com/mikem/arduino/HopeRF from the same author. Nor is
|
||
|
/// it compatible with messages sent by 'Virtual Wire'
|
||
|
/// http://www.airspayce.com/mikem/arduino/VirtualWire.pdf also from the same
|
||
|
/// author. Nor is it compatible with messages sent by 'RF22'
|
||
|
/// http://www.airspayce.com/mikem/arduino/RF22 also from the same author.
|
||
|
///
|
||
|
/// \par Connecting RFM-69 to Arduino
|
||
|
///
|
||
|
/// We tested with Moteino, which is an Arduino Uno compatible with the RFM69W
|
||
|
/// module on-board. Therefore it needs no connections other than the USB
|
||
|
/// programming connection and an antenna to make it work.
|
||
|
///
|
||
|
/// If you have a bare RFM69W that you want to connect to an Arduino, you
|
||
|
/// might use these connections: CAUTION: you must use a 3.3V type
|
||
|
/// Arduino, otherwise you will also need voltage level shifters between the
|
||
|
/// Arduino and the RFM69. CAUTION, you must also ensure you connect an
|
||
|
/// antenna
|
||
|
///
|
||
|
/// \code
|
||
|
/// Arduino RFM69W
|
||
|
/// GND----------GND (ground in)
|
||
|
/// 3V3----------3.3V (3.3V in)
|
||
|
/// interrupt 0 pin D2-----------DIO0 (interrupt request out)
|
||
|
/// SS pin D10----------NSS (chip select in)
|
||
|
/// SCK pin D13----------SCK (SPI clock in)
|
||
|
/// MOSI pin D11----------MOSI (SPI Data in)
|
||
|
/// MISO pin D12----------MISO (SPI Data out)
|
||
|
/// \endcode
|
||
|
///
|
||
|
/// For Arduino Due, use these connections:
|
||
|
/// \code
|
||
|
/// Arduino RFM69W
|
||
|
/// GND----------GND (ground in)
|
||
|
/// 3V3----------3.3V (3.3V in)
|
||
|
/// interrupt 0 pin D2-----------DIO0 (interrupt request out)
|
||
|
/// SS pin D10----------NSS (chip select in)
|
||
|
/// SCK SPI pin 3----------SCK (SPI clock in)
|
||
|
/// MOSI SPI pin 4----------MOSI (SPI Data in)
|
||
|
/// MISO SPI pin 1----------MISO (SPI Data out)
|
||
|
/// \endcode
|
||
|
///
|
||
|
/// With these connections, you can then use the default constructor RH_RF69().
|
||
|
/// You can override the default settings for the SS pin and the interrupt in
|
||
|
/// the RH_RF69 constructor if you wish to connect the slave select SS to other
|
||
|
/// than the normal one for your Arduino (D10 for Diecimila, Uno etc and D53
|
||
|
/// for Mega) or the interrupt request to other than pin D2 (Caution,
|
||
|
/// different processors have different constraints as to the pins available
|
||
|
/// for interrupts).
|
||
|
///
|
||
|
/// If you have a Teensy 3.1 and a compatible RFM69 breakout board, you will need to
|
||
|
/// construct the RH_RF69 instance like this:
|
||
|
/// \code
|
||
|
/// RH_RF69 driver(15, 16);
|
||
|
/// \endcode
|
||
|
///
|
||
|
/// If you have a MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
|
||
|
/// with RFM69 on board, you dont need to make any wiring connections
|
||
|
/// (the RFM69 module is soldered onto the MotienoMEGA), but you must initialise the RH_RF69
|
||
|
/// constructor like this:
|
||
|
/// \code
|
||
|
/// RH_RF69 driver(4, 2);
|
||
|
/// \endcode
|
||
|
/// Make sure you have the MoteinoMEGA core installed in your Arduino hardware folder as described in the
|
||
|
/// documentation for the MoteinoMEGA.
|
||
|
///
|
||
|
/// If you have an Arduino M0 Pro from arduino.org,
|
||
|
/// you should note that you cannot use Pin 2 for the interrupt line
|
||
|
/// (Pin 2 is for the NMI only). The same comments apply to Pin 4 on Arduino Zero from arduino.cc.
|
||
|
/// Instead you can use any other pin (we use Pin 3) and initialise RH_RF69 like this:
|
||
|
/// \code
|
||
|
/// // Slave Select is pin 10, interrupt is Pin 3
|
||
|
/// RH_RF69 driver(10, 3);
|
||
|
/// \endcode
|
||
|
///
|
||
|
/// If you have a Rocket Scream Mini Ultra Pro with the RFM69HCW
|
||
|
/// - Ensure you have Arduino SAMD board support 1.6.5 or later in Arduino IDE 1.6.8 or later.
|
||
|
/// - The radio SS is hardwired to pin D5 and the DIO0 interrupt to pin D2,
|
||
|
/// so you need to initialise the radio like this:
|
||
|
/// \code
|
||
|
/// RH_RF69 driver(5, 2);
|
||
|
/// \endcode
|
||
|
/// - The name of the serial port on that board is 'SerialUSB', not 'Serial', so this may be helpful at the top of our
|
||
|
/// sample sketches:
|
||
|
/// \code
|
||
|
/// #define Serial SerialUSB
|
||
|
/// \endcode
|
||
|
/// - You also need this in setup before radio initialisation
|
||
|
/// \code
|
||
|
/// // Ensure serial flash is not interfering with radio communication on SPI bus
|
||
|
/// pinMode(4, OUTPUT);
|
||
|
/// digitalWrite(4, HIGH);
|
||
|
/// \endcode
|
||
|
/// - and if you have a 915MHz part, you need this after driver/manager intitalisation:
|
||
|
/// \code
|
||
|
/// rf69.setFrequency(915.0);
|
||
|
/// rf69.setTxPower(20);
|
||
|
/// \endcode
|
||
|
/// which adds up to modifying sample sketches something like:
|
||
|
/// \code
|
||
|
/// #include <SPI.h>
|
||
|
/// #include <RH_RF69.h>
|
||
|
/// RH_RF69 rf69(5, 2); // Rocket Scream Mini Ultra Pro with the RFM69HCW
|
||
|
/// #define Serial SerialUSB
|
||
|
///
|
||
|
/// void setup()
|
||
|
/// {
|
||
|
/// // Ensure serial flash is not interfering with radio communication on SPI bus
|
||
|
/// pinMode(4, OUTPUT);
|
||
|
/// digitalWrite(4, HIGH);
|
||
|
///
|
||
|
/// Serial.begin(9600);
|
||
|
/// while (!Serial) ; // Wait for serial port to be available
|
||
|
/// if (!rf69.init())
|
||
|
/// Serial.println("init failed");
|
||
|
/// rf69.setFrequency(915.0);
|
||
|
/// rf69.setTxPower(20);
|
||
|
/// }
|
||
|
/// ...
|
||
|
/// \endcode
|
||
|
///
|
||
|
/// If you have a talk2 Whisper Node board with on-board RF69 radio,
|
||
|
/// the example rf69_* sketches work without modifications. Initialise the radio like
|
||
|
/// with the default constructor:
|
||
|
/// \code
|
||
|
/// RH_RF69 driver;
|
||
|
/// \endcode
|
||
|
///
|
||
|
/// It is possible to have 2 or more radios connected to one Arduino, provided
|
||
|
/// each radio has its own SS and interrupt line (SCK, SDI and SDO are common
|
||
|
/// to all radios)
|
||
|
///
|
||
|
/// Caution: on some Arduinos such as the Mega 2560, if you set the slave
|
||
|
/// select pin to be other than the usual SS pin (D53 on Mega 2560), you may
|
||
|
/// need to set the usual SS pin to be an output to force the Arduino into SPI
|
||
|
/// master mode.
|
||
|
///
|
||
|
/// Caution: Power supply requirements of the RF69 module may be relevant in some circumstances:
|
||
|
/// RF69 modules are capable of pulling 45mA+ at full power, where Arduino's 3.3V line can
|
||
|
/// give 50mA. You may need to make provision for alternate power supply for
|
||
|
/// the RF69, especially if you wish to use full transmit power, and/or you have
|
||
|
/// other shields demanding power. Inadequate power for the RF69 is likely to cause symptoms such as:
|
||
|
/// -reset's/bootups terminate with "init failed" messages
|
||
|
/// -random termination of communication after 5-30 packets sent/received
|
||
|
/// -"fake ok" state, where initialization passes fluently, but communication doesn't happen
|
||
|
/// -shields hang Arduino boards, especially during the flashing
|
||
|
/// \par Interrupts
|
||
|
///
|
||
|
/// The RH_RF69 driver uses interrupts to react to events in the RF69 module,
|
||
|
/// such as the reception of a new packet, or the completion of transmission
|
||
|
/// of a packet. The RH_RF69 driver interrupt service routine reads status from
|
||
|
/// and writes data to the the RF69 module via the SPI interface. It is very
|
||
|
/// important therefore, that if you are using the RH_RF69 driver with another
|
||
|
/// SPI based deviced, that you disable interrupts while you transfer data to
|
||
|
/// and from that other device. Use cli() to disable interrupts and sei() to
|
||
|
/// reenable them.
|
||
|
///
|
||
|
/// \par Memory
|
||
|
///
|
||
|
/// The RH_RF69 driver requires non-trivial amounts of memory. The sample
|
||
|
/// programs above all compile to about 8kbytes each, which will fit in the
|
||
|
/// flash proram memory of most Arduinos. However, the RAM requirements are
|
||
|
/// more critical. Therefore, you should be vary sparing with RAM use in
|
||
|
/// programs that use the RH_RF69 driver.
|
||
|
///
|
||
|
/// It is often hard to accurately identify when you are hitting RAM limits on Arduino.
|
||
|
/// The symptoms can include:
|
||
|
/// - Mysterious crashes and restarts
|
||
|
/// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements)
|
||
|
/// - Hanging
|
||
|
/// - Output from Serial.print() not appearing
|
||
|
///
|
||
|
/// \par Automatic Frequency Control (AFC)
|
||
|
///
|
||
|
/// The RF69 module is configured by the RH_RF69 driver to always use AFC.
|
||
|
///
|
||
|
/// \par Transmitter Power
|
||
|
///
|
||
|
/// You can control the transmitter power on the RF69 transceiver
|
||
|
/// with the RH_RF69::setTxPower() function. The argument can be any of
|
||
|
/// -18 to +13 (for RF69W) or -14 to 20 (for RF69HW)
|
||
|
/// The default is 13. Eg:
|
||
|
/// \code
|
||
|
/// driver.setTxPower(-5);
|
||
|
/// \endcode
|
||
|
///
|
||
|
/// We have made some actual power measurements against
|
||
|
/// programmed power for Moteino (with RF69W)
|
||
|
/// - Moteino (with RF69W), USB power
|
||
|
/// - 10cm RG58C/U soldered direct to RFM69 module ANT and GND
|
||
|
/// - bnc connecteor
|
||
|
/// - 12dB attenuator
|
||
|
/// - BNC-SMA adapter
|
||
|
/// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
|
||
|
/// - Tektronix TDS220 scope to measure the Vout from power head
|
||
|
/// \code
|
||
|
/// Program power Measured Power
|
||
|
/// dBm dBm
|
||
|
/// -18 -17
|
||
|
/// -16 -16
|
||
|
/// -14 -14
|
||
|
/// -12 -12
|
||
|
/// -10 -9
|
||
|
/// -8 -7
|
||
|
/// -6 -4
|
||
|
/// -4 -3
|
||
|
/// -2 -2
|
||
|
/// 0 0.2
|
||
|
/// 2 3
|
||
|
/// 4 5
|
||
|
/// 6 7
|
||
|
/// 8 10
|
||
|
/// 10 13
|
||
|
/// 12 14
|
||
|
/// 13 15
|
||
|
/// 14 -51
|
||
|
/// 20 -51
|
||
|
/// \endcode
|
||
|
/// We have also made some actual power measurements against
|
||
|
/// programmed power for Anarduino MiniWireless with RFM69-HW
|
||
|
/// Anarduino MiniWireless (with RFM69-HW), USB power
|
||
|
/// - 10cm RG58C/U soldered direct to RFM69 module ANT and GND
|
||
|
/// - bnc connecteor
|
||
|
/// - 2x12dB attenuators
|
||
|
/// - BNC-SMA adapter
|
||
|
/// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
|
||
|
/// - Tektronix TDS220 scope to measure the Vout from power head
|
||
|
/// \code
|
||
|
/// Program power Measured Power
|
||
|
/// dBm dBm
|
||
|
/// -18 no measurable output
|
||
|
/// 0 no measurable output
|
||
|
/// 13 no measurable output
|
||
|
/// 14 11
|
||
|
/// 15 12
|
||
|
/// 16 12.4
|
||
|
/// 17 14
|
||
|
/// 18 15
|
||
|
/// 19 15.8
|
||
|
/// 20 17
|
||
|
/// \endcode
|
||
|
/// (Caution: we dont claim laboratory accuracy for these measurements)
|
||
|
/// You would not expect to get anywhere near these powers to air with a simple 1/4 wavelength wire antenna.
|
||
|
/// Caution: although the RFM69 appears to have a PC antenna on board, you will get much better power and range even
|
||
|
/// with just a 1/4 wave wire antenna.
|
||
|
///
|
||
|
/// \par Performance
|
||
|
///
|
||
|
/// Some simple speed performance tests have been conducted.
|
||
|
/// In general packet transmission rate will be limited by the modulation scheme.
|
||
|
/// Also, if your code does any slow operations like Serial printing it will also limit performance.
|
||
|
/// We disabled any printing in the tests below.
|
||
|
/// We tested with RH_RF69::GFSK_Rb250Fd250, which is probably the fastest scheme available.
|
||
|
/// We tested with a 13 octet message length, over a very short distance of 10cm.
|
||
|
///
|
||
|
/// Transmission (no reply) tests with modulation RH_RF69::GFSK_Rb250Fd250 and a
|
||
|
/// 13 octet message show about 152 messages per second transmitted and received.
|
||
|
///
|
||
|
/// Transmit-and-wait-for-a-reply tests with modulation RH_RF69::GFSK_Rb250Fd250 and a
|
||
|
/// 13 octet message (send and receive) show about 68 round trips per second.
|
||
|
///
|
||
|
class RH_RF69 : public RHSPIDriver
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
/// \brief Defines register values for a set of modem configuration registers
|
||
|
///
|
||
|
/// Defines register values for a set of modem configuration registers
|
||
|
/// that can be passed to setModemRegisters() if none of the choices in
|
||
|
/// ModemConfigChoice suit your need setModemRegisters() writes the
|
||
|
/// register values from this structure to the appropriate RF69 registers
|
||
|
/// to set the desired modulation type, data rate and deviation/bandwidth.
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t reg_02; ///< Value for register RH_RF69_REG_02_DATAMODUL
|
||
|
uint8_t reg_03; ///< Value for register RH_RF69_REG_03_BITRATEMSB
|
||
|
uint8_t reg_04; ///< Value for register RH_RF69_REG_04_BITRATELSB
|
||
|
uint8_t reg_05; ///< Value for register RH_RF69_REG_05_FDEVMSB
|
||
|
uint8_t reg_06; ///< Value for register RH_RF69_REG_06_FDEVLSB
|
||
|
uint8_t reg_19; ///< Value for register RH_RF69_REG_19_RXBW
|
||
|
uint8_t reg_1a; ///< Value for register RH_RF69_REG_1A_AFCBW
|
||
|
uint8_t reg_37; ///< Value for register RH_RF69_REG_37_PACKETCONFIG1
|
||
|
} ModemConfig;
|
||
|
|
||
|
/// Choices for setModemConfig() for a selected subset of common
|
||
|
/// modulation types, and data rates. If you need another configuration,
|
||
|
/// use the register calculator. and call setModemRegisters() with your
|
||
|
/// desired settings.
|
||
|
/// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
|
||
|
/// definitions and not their integer equivalents: its possible that new values will be
|
||
|
/// introduced in later versions (though we will try to avoid it).
|
||
|
/// CAUTION: some of these configurations do not work corectly and are marked as such.
|
||
|
typedef enum
|
||
|
{
|
||
|
FSK_Rb2Fd5 = 0, ///< FSK, Whitening, Rb = 2kbs, Fd = 5kHz
|
||
|
FSK_Rb2_4Fd4_8, ///< FSK, Whitening, Rb = 2.4kbs, Fd = 4.8kHz
|
||
|
FSK_Rb4_8Fd9_6, ///< FSK, Whitening, Rb = 4.8kbs, Fd = 9.6kHz
|
||
|
FSK_Rb9_6Fd19_2, ///< FSK, Whitening, Rb = 9.6kbs, Fd = 19.2kHz
|
||
|
FSK_Rb19_2Fd38_4, ///< FSK, Whitening, Rb = 19.2kbs, Fd = 38.4kHz
|
||
|
FSK_Rb38_4Fd76_8, ///< FSK, Whitening, Rb = 38.4kbs, Fd = 76.8kHz
|
||
|
FSK_Rb57_6Fd120, ///< FSK, Whitening, Rb = 57.6kbs, Fd = 120kHz
|
||
|
FSK_Rb125Fd125, ///< FSK, Whitening, Rb = 125kbs, Fd = 125kHz
|
||
|
FSK_Rb250Fd250, ///< FSK, Whitening, Rb = 250kbs, Fd = 250kHz
|
||
|
FSK_Rb55555Fd50, ///< FSK, Whitening, Rb = 55555kbs,Fd = 50kHz for RFM69 lib compatibility
|
||
|
|
||
|
GFSK_Rb2Fd5, ///< GFSK, Whitening, Rb = 2kbs, Fd = 5kHz
|
||
|
GFSK_Rb2_4Fd4_8, ///< GFSK, Whitening, Rb = 2.4kbs, Fd = 4.8kHz
|
||
|
GFSK_Rb4_8Fd9_6, ///< GFSK, Whitening, Rb = 4.8kbs, Fd = 9.6kHz
|
||
|
GFSK_Rb9_6Fd19_2, ///< GFSK, Whitening, Rb = 9.6kbs, Fd = 19.2kHz
|
||
|
GFSK_Rb19_2Fd38_4, ///< GFSK, Whitening, Rb = 19.2kbs, Fd = 38.4kHz
|
||
|
GFSK_Rb38_4Fd76_8, ///< GFSK, Whitening, Rb = 38.4kbs, Fd = 76.8kHz
|
||
|
GFSK_Rb57_6Fd120, ///< GFSK, Whitening, Rb = 57.6kbs, Fd = 120kHz
|
||
|
GFSK_Rb125Fd125, ///< GFSK, Whitening, Rb = 125kbs, Fd = 125kHz
|
||
|
GFSK_Rb250Fd250, ///< GFSK, Whitening, Rb = 250kbs, Fd = 250kHz
|
||
|
GFSK_Rb55555Fd50, ///< GFSK, Whitening, Rb = 55555kbs,Fd = 50kHz
|
||
|
|
||
|
OOK_Rb1Bw1, ///< OOK, Whitening, Rb = 1kbs, Rx Bandwidth = 1kHz.
|
||
|
OOK_Rb1_2Bw75, ///< OOK, Whitening, Rb = 1.2kbs, Rx Bandwidth = 75kHz.
|
||
|
OOK_Rb2_4Bw4_8, ///< OOK, Whitening, Rb = 2.4kbs, Rx Bandwidth = 4.8kHz.
|
||
|
OOK_Rb4_8Bw9_6, ///< OOK, Whitening, Rb = 4.8kbs, Rx Bandwidth = 9.6kHz.
|
||
|
OOK_Rb9_6Bw19_2, ///< OOK, Whitening, Rb = 9.6kbs, Rx Bandwidth = 19.2kHz.
|
||
|
OOK_Rb19_2Bw38_4, ///< OOK, Whitening, Rb = 19.2kbs, Rx Bandwidth = 38.4kHz.
|
||
|
OOK_Rb32Bw64, ///< OOK, Whitening, Rb = 32kbs, Rx Bandwidth = 64kHz.
|
||
|
|
||
|
// Test,
|
||
|
} ModemConfigChoice;
|
||
|
|
||
|
/// Constructor. You can have multiple instances, but each instance must have its own
|
||
|
/// interrupt and slave select pin. After constructing, you must call init() to initialise the interface
|
||
|
/// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
|
||
|
/// distinct interrupt lines, one for each instance.
|
||
|
/// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF69 before
|
||
|
/// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
|
||
|
/// \param[in] interruptPin The interrupt Pin number that is connected to the RF69 DIO0 interrupt line.
|
||
|
/// Defaults to pin 2.
|
||
|
/// Caution: You must specify an interrupt capable pin.
|
||
|
/// On many Arduino boards, there are limitations as to which pins may be used as interrupts.
|
||
|
/// On Leonardo pins 0, 1, 2 or 3. On Mega2560 pins 2, 3, 18, 19, 20, 21. On Due and Teensy, any digital pin.
|
||
|
/// On Arduino Zero from arduino.cc, any digital pin other than 4.
|
||
|
/// On Arduino M0 Pro from arduino.org, any digital pin other than 2.
|
||
|
/// On other Arduinos pins 2 or 3.
|
||
|
/// See http://arduino.cc/en/Reference/attachInterrupt for more details.
|
||
|
/// On Chipkit Uno32, pins 38, 2, 7, 8, 35.
|
||
|
/// On other boards, any digital pin may be used.
|
||
|
/// \param[in] spi Pointer to the SPI interface object to use.
|
||
|
/// Defaults to the standard Arduino hardware SPI interface
|
||
|
RH_RF69(uint8_t slaveSelectPin = SS, uint8_t interruptPin = 2, RHGenericSPI& spi = hardware_spi);
|
||
|
|
||
|
/// Initialises this instance and the radio module connected to it.
|
||
|
/// The following steps are taken:
|
||
|
/// - Initialise the slave select pin and the SPI interface library
|
||
|
/// - Checks the connected RF69 module can be communicated
|
||
|
/// - Attaches an interrupt handler
|
||
|
/// - Configures the RF69 module
|
||
|
/// - Sets the frequency to 434.0 MHz
|
||
|
/// - Sets the modem data rate to FSK_Rb2Fd5
|
||
|
/// \return true if everything was successful
|
||
|
bool init();
|
||
|
|
||
|
/// Reads the on-chip temperature sensor.
|
||
|
/// The RF69 must be in Idle mode (= RF69 Standby) to measure temperature.
|
||
|
/// The measurement is uncalibrated and without calibration, you can expect it to be far from
|
||
|
/// correct.
|
||
|
/// \return The measured temperature, in degrees C from -40 to 85 (uncalibrated)
|
||
|
int8_t temperatureRead();
|
||
|
|
||
|
/// Sets the transmitter and receiver
|
||
|
/// centre frequency
|
||
|
/// \param[in] centre Frequency in MHz. 240.0 to 960.0. Caution, RF69 comes in several
|
||
|
/// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
|
||
|
/// \param[in] afcPullInRange Not used
|
||
|
/// \return true if the selected frquency centre is within range
|
||
|
bool setFrequency(float centre, float afcPullInRange = 0.05);
|
||
|
|
||
|
/// Reads and returns the current RSSI value.
|
||
|
/// Causes the current signal strength to be measured and returned
|
||
|
/// If you want to find the RSSI
|
||
|
/// of the last received message, use lastRssi() instead.
|
||
|
/// \return The current RSSI value on units of 0.5dB.
|
||
|
int8_t rssiRead();
|
||
|
|
||
|
/// Sets the parameters for the RF69 OPMODE.
|
||
|
/// This is a low level device access function, and should not normally ned to be used by user code.
|
||
|
/// Instead can use stModeRx(), setModeTx(), setModeIdle()
|
||
|
/// \param[in] mode RF69 OPMODE to set, one of RH_RF69_OPMODE_MODE_*.
|
||
|
void setOpMode(uint8_t mode);
|
||
|
|
||
|
/// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
|
||
|
/// disables them.
|
||
|
void setModeIdle();
|
||
|
|
||
|
/// If current mode is Tx or Idle, changes it to Rx.
|
||
|
/// Starts the receiver in the RF69.
|
||
|
void setModeRx();
|
||
|
|
||
|
/// If current mode is Rx or Idle, changes it to Rx. F
|
||
|
/// Starts the transmitter in the RF69.
|
||
|
void setModeTx();
|
||
|
|
||
|
/// Sets the transmitter power output level.
|
||
|
/// Be a good neighbour and set the lowest power level you need.
|
||
|
/// Caution: legal power limits may apply in certain countries.
|
||
|
/// After init(), the power will be set to 13dBm.
|
||
|
/// \param[in] power Transmitter power level in dBm. For RF69W, valid values are from -18 to +13
|
||
|
/// (higher power settings disable the transmitter).
|
||
|
/// For RF69HW, valid values are from +14 to +20. Caution: at +20dBm, duty cycle is limited to 1% and a
|
||
|
/// maximum VSWR of 3:1 at the antenna port.
|
||
|
void setTxPower(int8_t power);
|
||
|
|
||
|
/// Sets all the registers required to configure the data modem in the RF69, including the data rate,
|
||
|
/// bandwidths etc. You can use this to configure the modem with custom configurations if none of the
|
||
|
/// canned configurations in ModemConfigChoice suit you.
|
||
|
/// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
|
||
|
void setModemRegisters(const ModemConfig* config);
|
||
|
|
||
|
/// Select one of the predefined modem configurations. If you need a modem configuration not provided
|
||
|
/// here, use setModemRegisters() with your own ModemConfig. The default after init() is RH_RF69::GFSK_Rb250Fd250.
|
||
|
/// \param[in] index The configuration choice.
|
||
|
/// \return true if index is a valid choice.
|
||
|
bool setModemConfig(ModemConfigChoice index);
|
||
|
|
||
|
/// Starts the receiver and checks whether a received message is available.
|
||
|
/// This can be called multiple times in a timeout loop
|
||
|
/// \return true if a complete, valid message has been received and is able to be retrieved by
|
||
|
/// recv()
|
||
|
bool available();
|
||
|
|
||
|
/// Turns the receiver on if it not already on.
|
||
|
/// If there is a valid message available, copy it to buf and return true
|
||
|
/// else return false.
|
||
|
/// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
|
||
|
/// You should be sure to call this function frequently enough to not miss any messages
|
||
|
/// It is recommended that you call it in your main loop.
|
||
|
/// \param[in] buf Location to copy the received message
|
||
|
/// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
|
||
|
/// \return true if a valid message was copied to buf
|
||
|
bool recv(uint8_t* buf, uint8_t* len);
|
||
|
|
||
|
/// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
|
||
|
/// Then loads a message into the transmitter and starts the transmitter. Note that a message length
|
||
|
/// of 0 is NOT permitted.
|
||
|
/// \param[in] data Array of data to be sent
|
||
|
/// \param[in] len Number of bytes of data to send (> 0)
|
||
|
/// \return true if the message length was valid and it was correctly queued for transmit
|
||
|
bool send(const uint8_t* data, uint8_t len);
|
||
|
|
||
|
/// Sets the length of the preamble
|
||
|
/// in bytes.
|
||
|
/// Caution: this should be set to the same
|
||
|
/// value on all nodes in your network. Default is 4.
|
||
|
/// Sets the message preamble length in REG_0?_PREAMBLE?SB
|
||
|
/// \param[in] bytes Preamble length in bytes.
|
||
|
void setPreambleLength(uint16_t bytes);
|
||
|
|
||
|
/// Sets the sync words for transmit and receive
|
||
|
/// Caution: SyncWords should be set to the same
|
||
|
/// value on all nodes in your network. Nodes with different SyncWords set will never receive
|
||
|
/// each others messages, so different SyncWords can be used to isolate different
|
||
|
/// networks from each other. Default is { 0x2d, 0xd4 }.
|
||
|
/// \param[in] syncWords Array of sync words, 1 to 4 octets long. NULL if no sync words to be used.
|
||
|
/// \param[in] len Number of sync words to set, 1 to 4. 0 if no sync words to be used.
|
||
|
void setSyncWords(const uint8_t* syncWords = NULL, uint8_t len = 0);
|
||
|
|
||
|
/// Enables AES encryption and sets the AES encryption key, used
|
||
|
/// to encrypt and decrypt all messages. The default is disabled.
|
||
|
/// \param[in] key The key to use. Must be 16 bytes long. The same key must be installed
|
||
|
/// in other instances of RF69, otherwise communications will not work correctly. If key is NULL,
|
||
|
/// encryption is disabled.
|
||
|
void setEncryptionKey(uint8_t* key = NULL);
|
||
|
|
||
|
/// Returns the time in millis since the most recent preamble was received, and when the most recent
|
||
|
/// RSSI measurement was made.
|
||
|
uint32_t getLastPreambleTime();
|
||
|
|
||
|
/// The maximum message length supported by this driver
|
||
|
/// \return The maximum message length supported by this driver
|
||
|
uint8_t maxMessageLength();
|
||
|
|
||
|
/// Prints the value of a single register
|
||
|
/// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
|
||
|
/// For debugging/testing only
|
||
|
/// \return true if successful
|
||
|
bool printRegister(uint8_t reg);
|
||
|
|
||
|
/// Prints the value of all the RF69 registers
|
||
|
/// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
|
||
|
/// For debugging/testing only
|
||
|
/// \return true if successful
|
||
|
bool printRegisters();
|
||
|
|
||
|
/// Sets the radio operating mode for the case when the driver is idle (ie not
|
||
|
/// transmitting or receiving), allowing you to control the idle mode power requirements
|
||
|
/// at the expense of slower transitions to transmit and receive modes.
|
||
|
/// By default, the idle mode is RH_RF69_OPMODE_MODE_STDBY,
|
||
|
/// but eg setIdleMode(RH_RF69_OPMODE_MODE_SLEEP) will provide a much lower
|
||
|
/// idle current but slower transitions. Call this function after init().
|
||
|
/// \param[in] idleMode The chip operating mode to use when the driver is idle. One of RH_RF69_OPMODE_*
|
||
|
void setIdleMode(uint8_t idleMode);
|
||
|
|
||
|
/// Sets the radio into low-power sleep mode.
|
||
|
/// If successful, the transport will stay in sleep mode until woken by
|
||
|
/// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
|
||
|
/// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
|
||
|
/// \return true if sleep mode was successfully entered.
|
||
|
virtual bool sleep();
|
||
|
|
||
|
protected:
|
||
|
/// This is a low level function to handle the interrupts for one instance of RF69.
|
||
|
/// Called automatically by isr*()
|
||
|
/// Should not need to be called by user code.
|
||
|
void handleInterrupt();
|
||
|
|
||
|
/// Low level function to read the FIFO and put the received data into the receive buffer
|
||
|
/// Should not need to be called by user code.
|
||
|
void readFifo();
|
||
|
|
||
|
protected:
|
||
|
/// Low level interrupt service routine for RF69 connected to interrupt 0
|
||
|
static void isr0();
|
||
|
|
||
|
/// Low level interrupt service routine for RF69 connected to interrupt 1
|
||
|
static void isr1();
|
||
|
|
||
|
/// Low level interrupt service routine for RF69 connected to interrupt 1
|
||
|
static void isr2();
|
||
|
|
||
|
/// Array of instances connected to interrupts 0 and 1
|
||
|
static RH_RF69* _deviceForInterrupt[];
|
||
|
|
||
|
/// Index of next interrupt number to use in _deviceForInterrupt
|
||
|
static uint8_t _interruptCount;
|
||
|
|
||
|
/// The configured interrupt pin connected to this instance
|
||
|
uint8_t _interruptPin;
|
||
|
|
||
|
/// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
|
||
|
/// else 0xff
|
||
|
uint8_t _myInterruptIndex;
|
||
|
|
||
|
/// The radio OP mode to use when mode is RHModeIdle
|
||
|
uint8_t _idleMode;
|
||
|
|
||
|
/// The reported device type
|
||
|
uint8_t _deviceType;
|
||
|
|
||
|
/// The selected output power in dBm
|
||
|
int8_t _power;
|
||
|
|
||
|
/// The message length in _buf
|
||
|
volatile uint8_t _bufLen;
|
||
|
|
||
|
/// Array of octets of teh last received message or the next to transmit message
|
||
|
uint8_t _buf[RH_RF69_MAX_MESSAGE_LEN];
|
||
|
|
||
|
/// True when there is a valid message in the Rx buffer
|
||
|
volatile bool _rxBufValid;
|
||
|
|
||
|
/// Time in millis since the last preamble was received (and the last time the RSSI was measured)
|
||
|
uint32_t _lastPreambleTime;
|
||
|
};
|
||
|
|
||
|
/// @example rf69_client.pde
|
||
|
/// @example rf69_server.pde
|
||
|
/// @example rf69_reliable_datagram_client.pde
|
||
|
/// @example rf69_reliable_datagram_server.pde
|
||
|
|
||
|
|
||
|
#endif
|