2013-07-14 04:49:26 +01:00
// **********************************************************************************
2014-08-13 03:03:19 +01:00
// Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech SX1231/1231H
2013-07-14 04:49:26 +01:00
// **********************************************************************************
2014-08-13 03:03:19 +01:00
// Copyright Felix Rusu (2014), felix@lowpowerlab.com
// http://lowpowerlab.com/
// **********************************************************************************
// License
// **********************************************************************************
// This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU General
// Public License as published by the Free Software
2014-11-14 20:25:45 +00:00
// Foundation; either version 3 of the License, or
2014-08-13 03:03:19 +01:00
// (at your option) any later version.
//
// This program is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A
2014-11-14 20:25:45 +00:00
// PARTICULAR PURPOSE. See the GNU General Public
2014-08-13 03:03:19 +01:00
// License for more details.
//
// You should have received a copy of the GNU General
2014-11-14 20:25:45 +00:00
// Public License along with this program.
// If not, see <http://www.gnu.org/licenses/>.
2014-08-13 03:03:19 +01:00
//
// Licence can be viewed at
2014-11-14 20:25:45 +00:00
// http://www.gnu.org/licenses/gpl-3.0.txt
2014-08-13 03:03:19 +01:00
//
// Please maintain this license information along with authorship
// and copyright notices in any redistribution of this code
2013-07-14 04:49:26 +01:00
// **********************************************************************************
2013-06-20 22:06:39 +01:00
# include <RFM69.h>
# include <RFM69registers.h>
# include <SPI.h>
2015-01-12 10:34:16 +00:00
volatile uint8_t RFM69 : : DATA [ RF69_MAX_DATA_LEN ] ;
volatile uint8_t RFM69 : : _mode ; // current transceiver state
volatile uint8_t RFM69 : : DATALEN ;
volatile uint8_t RFM69 : : SENDERID ;
volatile uint8_t RFM69 : : TARGETID ; // should match _address
volatile uint8_t RFM69 : : PAYLOADLEN ;
volatile uint8_t RFM69 : : ACK_REQUESTED ;
volatile uint8_t RFM69 : : ACK_RECEIVED ; // should be polled immediately after sending a packet with ACK request
volatile int16_t RFM69 : : RSSI ; // most accurate RSSI during reception (closest to the reception)
2013-06-20 22:06:39 +01:00
RFM69 * RFM69 : : selfPointer ;
2015-01-12 10:34:16 +00:00
bool RFM69 : : initialize ( uint8_t freqBand , uint8_t nodeID , uint8_t networkID )
2013-06-20 22:06:39 +01:00
{
2015-01-12 10:34:16 +00:00
const uint8_t CONFIG [ ] [ 2 ] =
2013-06-20 22:06:39 +01:00
{
2013-07-14 04:49:26 +01:00
/* 0x01 */ { REG_OPMODE , RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY } ,
2015-01-06 14:25:29 +00:00
/* 0x02 */ { REG_DATAMODUL , RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 } , // no shaping
2015-01-12 10:00:43 +00:00
/* 0x03 */ { REG_BITRATEMSB , RF_BITRATEMSB_55555 } , // default: 4.8 KBPS
2013-06-28 21:13:38 +01:00
/* 0x04 */ { REG_BITRATELSB , RF_BITRATELSB_55555 } ,
2015-01-12 10:00:43 +00:00
/* 0x05 */ { REG_FDEVMSB , RF_FDEVMSB_50000 } , // default: 5KHz, (FDEV + BitRate / 2 <= 500KHz)
2013-06-20 22:06:39 +01:00
/* 0x06 */ { REG_FDEVLSB , RF_FDEVLSB_50000 } ,
2015-01-12 14:09:49 +00:00
/* 0x07 */ { REG_FRFMSB , ( uint8_t ) ( freqBand = = RF69_315MHZ ? RF_FRFMSB_315 : ( freqBand = = RF69_433MHZ ? RF_FRFMSB_433 : ( freqBand = = RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915 ) ) ) } ,
/* 0x08 */ { REG_FRFMID , ( uint8_t ) ( freqBand = = RF69_315MHZ ? RF_FRFMID_315 : ( freqBand = = RF69_433MHZ ? RF_FRFMID_433 : ( freqBand = = RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915 ) ) ) } ,
/* 0x09 */ { REG_FRFLSB , ( uint8_t ) ( freqBand = = RF69_315MHZ ? RF_FRFLSB_315 : ( freqBand = = RF69_433MHZ ? RF_FRFLSB_433 : ( freqBand = = RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915 ) ) ) } ,
2015-01-06 13:46:04 +00:00
2013-06-20 22:06:39 +01:00
// looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm
// +17dBm and +20dBm are possible on RFM69HW
2015-01-12 10:00:43 +00:00
// +13dBm formula: Pout = -18 + OutputPower (with PA0 or PA1**)
// +17dBm formula: Pout = -14 + OutputPower (with PA1 and PA2)**
// +20dBm formula: Pout = -11 + OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet)
2013-06-20 22:06:39 +01:00
///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111},
2015-01-06 14:25:29 +00:00
///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, // over current protection (default is 95mA)
2015-01-06 13:46:04 +00:00
2015-01-12 10:00:43 +00:00
// RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4KHz)
2015-01-06 14:25:29 +00:00
/* 0x19 */ { REG_RXBW , RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 } , // (BitRate < 2 * RxBw)
//for BR-19200: /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 },
/* 0x25 */ { REG_DIOMAPPING1 , RF_DIOMAPPING1_DIO0_01 } , // DIO0 is the only IRQ we're using
2015-01-24 14:10:52 +00:00
/* 0x26 */ { REG_DIOMAPPING2 , RF_DIOMAPPING2_CLKOUT_OFF } , // DIO5 ClkOut disable for power saving
2015-01-18 11:09:08 +00:00
/* 0x28 */ { REG_IRQFLAGS2 , RF_IRQFLAGS2_FIFOOVERRUN } , // writing to this bit ensures that the FIFO & status flags are reset
2015-01-12 10:00:43 +00:00
/* 0x29 */ { REG_RSSITHRESH , 220 } , // must be set to dBm = (-Sensitivity / 2), default is 0xE4 = 228 so -114dBm
///* 0x2D */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA
/* 0x2E */ { REG_SYNCCONFIG , RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 } ,
/* 0x2F */ { REG_SYNCVALUE1 , 0x2D } , // attempt to make this compatible with sync1 byte of RFM12B lib
2015-01-06 14:25:29 +00:00
/* 0x30 */ { REG_SYNCVALUE2 , networkID } , // NETWORK ID
2013-06-20 22:06:39 +01:00
/* 0x37 */ { REG_PACKETCONFIG1 , RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF } ,
2015-01-06 14:25:29 +00:00
/* 0x38 */ { REG_PAYLOADLENGTH , 66 } , // in variable length mode: the max frame size, not used in TX
///* 0x39 */ { REG_NODEADRS, nodeID }, // turned off because we're not using address filtering
/* 0x3C */ { REG_FIFOTHRESH , RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE } , // TX on FIFO not empty
2015-01-12 10:00:43 +00:00
/* 0x3D */ { REG_PACKETCONFIG2 , RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF } , // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
//for BR-19200: /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
2015-01-24 13:13:15 +00:00
/* 0x6F */ { REG_TESTDAGC , RF_DAGC_IMPROVED_LOWBETA0 } , // run DAGC continuously in RX mode for Fading Margin Improvement, recommended default for AfcLowBetaOn=0
2013-06-20 22:06:39 +01:00
{ 255 , 0 }
} ;
2013-07-14 04:49:26 +01:00
2015-01-18 11:31:16 +00:00
digitalWrite ( _slaveSelectPin , HIGH ) ;
2013-06-20 22:06:39 +01:00
pinMode ( _slaveSelectPin , OUTPUT ) ;
SPI . begin ( ) ;
2014-08-13 03:03:19 +01:00
2015-01-12 10:00:43 +00:00
do writeReg ( REG_SYNCVALUE1 , 0xAA ) ; while ( readReg ( REG_SYNCVALUE1 ) ! = 0xAA ) ;
2015-01-06 13:46:04 +00:00
do writeReg ( REG_SYNCVALUE1 , 0x55 ) ; while ( readReg ( REG_SYNCVALUE1 ) ! = 0x55 ) ;
2014-08-13 03:03:19 +01:00
2015-01-12 10:34:16 +00:00
for ( uint8_t i = 0 ; CONFIG [ i ] [ 0 ] ! = 255 ; i + + )
2013-06-20 22:06:39 +01:00
writeReg ( CONFIG [ i ] [ 0 ] , CONFIG [ i ] [ 1 ] ) ;
2014-01-02 21:57:18 +00:00
// Encryption is persistent between resets and can trip you up during debugging.
// Disable it during initialization so we always start from a known state.
encrypt ( 0 ) ;
2015-01-06 14:25:29 +00:00
setHighPower ( _isRFM69HW ) ; // called regardless if it's a RFM69W or RFM69HW
2013-06-20 22:06:39 +01:00
setMode ( RF69_MODE_STANDBY ) ;
2015-01-06 14:25:29 +00:00
while ( ( readReg ( REG_IRQFLAGS1 ) & RF_IRQFLAGS1_MODEREADY ) = = 0x00 ) ; // wait for ModeReady
2014-08-13 03:03:19 +01:00
attachInterrupt ( _interruptNum , RFM69 : : isr0 , RISING ) ;
2013-06-20 22:06:39 +01:00
selfPointer = this ;
_address = nodeID ;
2013-10-27 23:53:02 +00:00
return true ;
2013-06-20 22:06:39 +01:00
}
2015-01-06 14:25:29 +00:00
// return the frequency (in Hz)
2014-11-14 20:25:45 +00:00
uint32_t RFM69 : : getFrequency ( )
2013-06-20 22:06:39 +01:00
{
2015-01-12 10:00:43 +00:00
return RF69_FSTEP * ( ( ( uint32_t ) readReg ( REG_FRFMSB ) < < 16 ) + ( ( uint16_t ) readReg ( REG_FRFMID ) < < 8 ) + readReg ( REG_FRFLSB ) ) ;
2014-11-14 20:25:45 +00:00
}
2015-01-06 14:25:29 +00:00
// set the frequency (in Hz)
2014-11-14 20:25:45 +00:00
void RFM69 : : setFrequency ( uint32_t freqHz )
2013-06-20 22:06:39 +01:00
{
2015-01-18 11:22:43 +00:00
uint8_t oldMode = _mode ;
if ( oldMode = = RF69_MODE_TX ) {
setMode ( RF69_MODE_RX ) ;
}
2015-01-06 14:25:29 +00:00
freqHz / = RF69_FSTEP ; // divide down by FSTEP to get FRF
2014-11-14 20:25:45 +00:00
writeReg ( REG_FRFMSB , freqHz > > 16 ) ;
writeReg ( REG_FRFMID , freqHz > > 8 ) ;
writeReg ( REG_FRFLSB , freqHz ) ;
2015-01-18 11:22:43 +00:00
if ( oldMode = = RF69_MODE_RX ) {
setMode ( RF69_MODE_SYNTH ) ;
}
setMode ( oldMode ) ;
2013-06-20 22:06:39 +01:00
}
2015-01-12 10:34:16 +00:00
void RFM69 : : setMode ( uint8_t newMode )
2013-06-20 22:06:39 +01:00
{
2015-01-18 11:22:43 +00:00
if ( newMode = = _mode )
return ;
2013-06-20 22:06:39 +01:00
2015-01-06 13:46:04 +00:00
switch ( newMode ) {
case RF69_MODE_TX :
writeReg ( REG_OPMODE , ( readReg ( REG_OPMODE ) & 0xE3 ) | RF_OPMODE_TRANSMITTER ) ;
2013-06-20 22:06:39 +01:00
if ( _isRFM69HW ) setHighPowerRegs ( true ) ;
2015-01-06 13:46:04 +00:00
break ;
case RF69_MODE_RX :
writeReg ( REG_OPMODE , ( readReg ( REG_OPMODE ) & 0xE3 ) | RF_OPMODE_RECEIVER ) ;
2013-06-20 22:06:39 +01:00
if ( _isRFM69HW ) setHighPowerRegs ( false ) ;
2015-01-06 13:46:04 +00:00
break ;
case RF69_MODE_SYNTH :
writeReg ( REG_OPMODE , ( readReg ( REG_OPMODE ) & 0xE3 ) | RF_OPMODE_SYNTHESIZER ) ;
break ;
case RF69_MODE_STANDBY :
writeReg ( REG_OPMODE , ( readReg ( REG_OPMODE ) & 0xE3 ) | RF_OPMODE_STANDBY ) ;
break ;
case RF69_MODE_SLEEP :
writeReg ( REG_OPMODE , ( readReg ( REG_OPMODE ) & 0xE3 ) | RF_OPMODE_SLEEP ) ;
break ;
2015-01-18 11:22:43 +00:00
default :
return ;
2015-01-06 13:46:04 +00:00
}
// we are using packet mode, so this check is not really needed
2013-07-14 04:49:26 +01:00
// but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode
2015-01-06 14:25:29 +00:00
while ( _mode = = RF69_MODE_SLEEP & & ( readReg ( REG_IRQFLAGS1 ) & RF_IRQFLAGS1_MODEREADY ) = = 0x00 ) ; // wait for ModeReady
2013-06-20 22:06:39 +01:00
2015-01-06 13:46:04 +00:00
_mode = newMode ;
2013-06-20 22:06:39 +01:00
}
2015-05-19 20:08:41 +01:00
//put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone()
2013-06-20 22:06:39 +01:00
void RFM69 : : sleep ( ) {
setMode ( RF69_MODE_SLEEP ) ;
}
2015-05-19 20:08:41 +01:00
//set this node's address
2015-01-12 10:34:16 +00:00
void RFM69 : : setAddress ( uint8_t addr )
2013-06-20 22:06:39 +01:00
{
2013-07-14 04:49:26 +01:00
_address = addr ;
2015-01-06 13:46:04 +00:00
writeReg ( REG_NODEADRS , _address ) ;
2013-06-20 22:06:39 +01:00
}
2015-05-19 20:08:41 +01:00
//set this node's network id
2015-01-12 10:34:16 +00:00
void RFM69 : : setNetwork ( uint8_t networkID )
2014-11-14 20:25:45 +00:00
{
2015-01-06 13:46:04 +00:00
writeReg ( REG_SYNCVALUE2 , networkID ) ;
2013-06-20 22:06:39 +01:00
}
2015-04-01 21:26:47 +01:00
// set *transmit/TX* output power: 0=min, 31=max
2013-08-17 02:35:34 +01:00
// this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver
2015-04-01 21:26:47 +01:00
// the power configurations are explained in the SX1231H datasheet (Table 10 on p21; RegPaLevel p66): http://www.semtech.com/images/datasheet/sx1231h.pdf
// valid powerLevel parameter values are 0-31 and result in a directly proportional effect on the output/transmission power
// this function implements 2 modes as follows:
// - for RFM69W the range is from 0-31 [-18dBm to 13dBm] (PA0 only on RFIO pin)
// - for RFM69HW the range is from 0-31 [5dBm to 20dBm] (PA1 & PA2 on PA_BOOST pin & high Power PA settings - see section 3.3.7 in datasheet, p22)
2015-01-12 10:34:16 +00:00
void RFM69 : : setPowerLevel ( uint8_t powerLevel )
2013-06-20 22:06:39 +01:00
{
2015-04-01 21:26:47 +01:00
_powerLevel = ( powerLevel > 31 ? 31 : powerLevel ) ;
if ( _isRFM69HW ) _powerLevel / = 2 ;
writeReg ( REG_PALEVEL , ( readReg ( REG_PALEVEL ) & 0xE0 ) | _powerLevel ) ;
2013-06-20 22:06:39 +01:00
}
bool RFM69 : : canSend ( )
{
2015-01-06 14:25:29 +00:00
if ( _mode = = RF69_MODE_RX & & PAYLOADLEN = = 0 & & readRSSI ( ) < CSMA_LIMIT ) // if signal stronger than -100dBm is detected assume channel activity
2013-06-20 22:06:39 +01:00
{
setMode ( RF69_MODE_STANDBY ) ;
return true ;
}
return false ;
}
2015-01-12 10:34:16 +00:00
void RFM69 : : send ( uint8_t toAddress , const void * buffer , uint8_t bufferSize , bool requestACK )
2013-06-20 22:06:39 +01:00
{
2013-07-14 04:49:26 +01:00
writeReg ( REG_PACKETCONFIG2 , ( readReg ( REG_PACKETCONFIG2 ) & 0xFB ) | RF_PACKET2_RXRESTART ) ; // avoid RX deadlocks
2015-01-12 10:34:16 +00:00
uint32_t now = millis ( ) ;
2015-01-12 10:00:43 +00:00
while ( ! canSend ( ) & & millis ( ) - now < RF69_CSMA_LIMIT_MS ) receiveDone ( ) ;
2013-06-20 22:06:39 +01:00
sendFrame ( toAddress , buffer , bufferSize , requestACK , false ) ;
}
2013-07-14 04:49:26 +01:00
// to increase the chance of getting a packet across, call this function instead of send
2013-06-20 22:06:39 +01:00
// and it handles all the ACK requesting/retrying for you :)
// The only twist is that you have to manually listen to ACK requests on the other side and send back the ACKs
2015-01-06 14:25:29 +00:00
// The reason for the semi-automaton is that the lib is interrupt driven and
2013-06-20 22:06:39 +01:00
// requires user action to read the received data and decide what to do with it
2015-01-12 10:00:43 +00:00
// replies usually take only 5..8ms at 50kbps@915MHz
2015-01-12 10:34:16 +00:00
bool RFM69 : : sendWithRetry ( uint8_t toAddress , const void * buffer , uint8_t bufferSize , uint8_t retries , uint8_t retryWaitTime ) {
uint32_t sentTime ;
for ( uint8_t i = 0 ; i < = retries ; i + + )
2013-06-20 22:06:39 +01:00
{
send ( toAddress , buffer , bufferSize , true ) ;
sentTime = millis ( ) ;
2015-01-12 10:00:43 +00:00
while ( millis ( ) - sentTime < retryWaitTime )
2013-06-20 22:06:39 +01:00
{
if ( ACKReceived ( toAddress ) )
{
2015-01-12 10:00:43 +00:00
//Serial.print(" ~ms:"); Serial.print(millis() - sentTime);
2013-06-20 22:06:39 +01:00
return true ;
}
}
2015-01-12 10:00:43 +00:00
//Serial.print(" RETRY#"); Serial.println(i + 1);
2013-06-20 22:06:39 +01:00
}
return false ;
}
2015-01-06 14:25:29 +00:00
// should be polled immediately after sending a packet with ACK request
2015-01-12 10:34:16 +00:00
bool RFM69 : : ACKReceived ( uint8_t fromNodeID ) {
2013-06-20 22:06:39 +01:00
if ( receiveDone ( ) )
2014-02-02 02:13:40 +00:00
return ( SENDERID = = fromNodeID | | fromNodeID = = RF69_BROADCAST_ADDR ) & & ACK_RECEIVED ;
2013-06-20 22:06:39 +01:00
return false ;
}
2015-01-06 14:25:29 +00:00
// check whether an ACK was requested in the last received packet (non-broadcasted packet)
2014-08-13 03:03:19 +01:00
bool RFM69 : : ACKRequested ( ) {
return ACK_REQUESTED & & ( TARGETID ! = RF69_BROADCAST_ADDR ) ;
}
2015-01-06 14:25:29 +00:00
// should be called immediately after reception in case sender wants ACK
2015-01-12 10:34:16 +00:00
void RFM69 : : sendACK ( const void * buffer , uint8_t bufferSize ) {
uint8_t sender = SENDERID ;
int16_t _RSSI = RSSI ; // save payload received RSSI value
2014-11-17 19:58:00 +00:00
writeReg ( REG_PACKETCONFIG2 , ( readReg ( REG_PACKETCONFIG2 ) & 0xFB ) | RF_PACKET2_RXRESTART ) ; // avoid RX deadlocks
2015-01-12 10:34:16 +00:00
uint32_t now = millis ( ) ;
2015-01-12 10:00:43 +00:00
while ( ! canSend ( ) & & millis ( ) - now < RF69_CSMA_LIMIT_MS ) receiveDone ( ) ;
2013-07-14 04:49:26 +01:00
sendFrame ( sender , buffer , bufferSize , false , true ) ;
2015-01-06 14:25:29 +00:00
RSSI = _RSSI ; // restore payload RSSI
2013-06-20 22:06:39 +01:00
}
2015-05-19 20:08:41 +01:00
// internal function
2015-01-12 10:34:16 +00:00
void RFM69 : : sendFrame ( uint8_t toAddress , const void * buffer , uint8_t bufferSize , bool requestACK , bool sendACK )
2013-06-20 22:06:39 +01:00
{
2015-01-06 14:25:29 +00:00
setMode ( RF69_MODE_STANDBY ) ; // turn off receiver to prevent reception while filling fifo
while ( ( readReg ( REG_IRQFLAGS1 ) & RF_IRQFLAGS1_MODEREADY ) = = 0x00 ) ; // wait for ModeReady
2013-07-14 04:49:26 +01:00
writeReg ( REG_DIOMAPPING1 , RF_DIOMAPPING1_DIO0_00 ) ; // DIO0 is "Packet Sent"
2014-08-13 03:03:19 +01:00
if ( bufferSize > RF69_MAX_DATA_LEN ) bufferSize = RF69_MAX_DATA_LEN ;
2013-06-20 22:06:39 +01:00
2015-02-06 11:21:13 +00:00
// control byte
uint8_t CTLbyte = 0x00 ;
2013-06-20 22:06:39 +01:00
if ( sendACK )
2015-02-06 11:21:13 +00:00
CTLbyte = 0x80 ;
2013-06-20 22:06:39 +01:00
else if ( requestACK )
2015-02-06 11:21:13 +00:00
CTLbyte = 0x40 ;
2015-01-06 14:25:29 +00:00
// write to FIFO
2015-01-06 13:46:04 +00:00
select ( ) ;
SPI . transfer ( REG_FIFO | 0x80 ) ;
SPI . transfer ( bufferSize + 3 ) ;
SPI . transfer ( toAddress ) ;
2013-06-20 22:06:39 +01:00
SPI . transfer ( _address ) ;
2015-02-06 11:21:13 +00:00
SPI . transfer ( CTLbyte ) ;
2015-01-06 13:46:04 +00:00
2015-01-12 10:34:16 +00:00
for ( uint8_t i = 0 ; i < bufferSize ; i + + )
SPI . transfer ( ( ( uint8_t * ) buffer ) [ i ] ) ;
2015-01-06 13:46:04 +00:00
unselect ( ) ;
2013-06-20 22:06:39 +01:00
2015-01-12 10:00:43 +00:00
// no need to wait for transmit mode to be ready since its handled by the radio
2015-01-06 13:46:04 +00:00
setMode ( RF69_MODE_TX ) ;
2015-01-12 10:34:16 +00:00
uint32_t txStart = millis ( ) ;
2015-01-12 10:00:43 +00:00
while ( digitalRead ( _interruptPin ) = = 0 & & millis ( ) - txStart < RF69_TX_LIMIT_MS ) ; // wait for DIO0 to turn HIGH signalling transmission finish
2015-01-06 14:25:29 +00:00
//while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // wait for ModeReady
2013-06-20 22:06:39 +01:00
setMode ( RF69_MODE_STANDBY ) ;
}
2015-05-19 20:08:41 +01:00
// internal function - interrupt gets called when a packet is received
2013-06-20 22:06:39 +01:00
void RFM69 : : interruptHandler ( ) {
2013-07-14 04:49:26 +01:00
//pinMode(4, OUTPUT);
//digitalWrite(4, 1);
2013-06-20 22:06:39 +01:00
if ( _mode = = RF69_MODE_RX & & ( readReg ( REG_IRQFLAGS2 ) & RF_IRQFLAGS2_PAYLOADREADY ) )
{
2014-08-13 03:03:19 +01:00
//RSSI = readRSSI();
2013-06-20 22:06:39 +01:00
setMode ( RF69_MODE_STANDBY ) ;
select ( ) ;
2015-01-12 10:00:43 +00:00
SPI . transfer ( REG_FIFO & 0x7F ) ;
2013-06-20 22:06:39 +01:00
PAYLOADLEN = SPI . transfer ( 0 ) ;
2015-01-06 14:25:29 +00:00
PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN ; // precaution
2013-06-20 22:06:39 +01:00
TARGETID = SPI . transfer ( 0 ) ;
2015-01-06 14:25:29 +00:00
if ( ! ( _promiscuousMode | | TARGETID = = _address | | TARGETID = = RF69_BROADCAST_ADDR ) // match this node's address, or broadcast address or anything in promiscuous mode
| | PAYLOADLEN < 3 ) // address situation could receive packets that are malformed and don't fit this libraries extra fields
2013-06-20 22:06:39 +01:00
{
PAYLOADLEN = 0 ;
unselect ( ) ;
2014-11-17 19:58:00 +00:00
receiveBegin ( ) ;
2013-07-14 04:49:26 +01:00
//digitalWrite(4, 0);
2013-06-20 22:06:39 +01:00
return ;
}
2014-11-17 19:58:00 +00:00
2013-09-06 00:32:11 +01:00
DATALEN = PAYLOADLEN - 3 ;
2013-07-14 04:49:26 +01:00
SENDERID = SPI . transfer ( 0 ) ;
2015-01-12 10:34:16 +00:00
uint8_t CTLbyte = SPI . transfer ( 0 ) ;
2015-01-06 13:46:04 +00:00
2015-01-06 14:25:29 +00:00
ACK_RECEIVED = CTLbyte & 0x80 ; // extract ACK-received flag
ACK_REQUESTED = CTLbyte & 0x40 ; // extract ACK-requested flag
2015-01-06 13:46:04 +00:00
2015-01-12 10:34:16 +00:00
for ( uint8_t i = 0 ; i < DATALEN ; i + + )
2013-06-20 22:06:39 +01:00
{
DATA [ i ] = SPI . transfer ( 0 ) ;
}
2015-01-12 10:00:43 +00:00
if ( DATALEN < RF69_MAX_DATA_LEN ) DATA [ DATALEN ] = 0 ; // add null at end of string
2013-06-20 22:06:39 +01:00
unselect ( ) ;
setMode ( RF69_MODE_RX ) ;
}
2013-11-07 04:15:51 +00:00
RSSI = readRSSI ( ) ;
2013-09-06 00:32:11 +01:00
//digitalWrite(4, 0);
2013-06-20 22:06:39 +01:00
}
2015-05-19 20:08:41 +01:00
// internal function
2013-06-20 22:06:39 +01:00
void RFM69 : : isr0 ( ) { selfPointer - > interruptHandler ( ) ; }
2015-05-19 20:08:41 +01:00
// internal function
2013-06-20 22:06:39 +01:00
void RFM69 : : receiveBegin ( ) {
2013-07-14 04:49:26 +01:00
DATALEN = 0 ;
SENDERID = 0 ;
TARGETID = 0 ;
PAYLOADLEN = 0 ;
ACK_REQUESTED = 0 ;
ACK_RECEIVED = 0 ;
2013-11-07 04:15:51 +00:00
RSSI = 0 ;
2013-07-14 04:49:26 +01:00
if ( readReg ( REG_IRQFLAGS2 ) & RF_IRQFLAGS2_PAYLOADREADY )
writeReg ( REG_PACKETCONFIG2 , ( readReg ( REG_PACKETCONFIG2 ) & 0xFB ) | RF_PACKET2_RXRESTART ) ; // avoid RX deadlocks
2015-01-06 14:25:29 +00:00
writeReg ( REG_DIOMAPPING1 , RF_DIOMAPPING1_DIO0_01 ) ; // set DIO0 to "PAYLOADREADY" in receive mode
2013-06-20 22:06:39 +01:00
setMode ( RF69_MODE_RX ) ;
}
2015-05-19 20:08:41 +01:00
// checks if a packet was received and/or puts transceiver in receive (ie RX or listen) mode
2013-06-20 22:06:39 +01:00
bool RFM69 : : receiveDone ( ) {
2015-01-06 14:25:29 +00:00
//ATOMIC_BLOCK(ATOMIC_FORCEON)
//{
noInterrupts ( ) ; // re-enabled in unselect() via setMode() or via receiveBegin()
2015-01-12 10:00:43 +00:00
if ( _mode = = RF69_MODE_RX & & PAYLOADLEN > 0 )
2013-06-20 22:06:39 +01:00
{
2015-01-06 14:25:29 +00:00
setMode ( RF69_MODE_STANDBY ) ; // enables interrupts
2013-06-20 22:06:39 +01:00
return true ;
}
2015-01-12 10:00:43 +00:00
else if ( _mode = = RF69_MODE_RX ) // already in RX no payload yet
2014-02-02 02:13:40 +00:00
{
2015-01-06 14:25:29 +00:00
interrupts ( ) ; // explicitly re-enable interrupts
2014-02-02 02:13:40 +00:00
return false ;
}
2013-06-20 22:06:39 +01:00
receiveBegin ( ) ;
return false ;
2013-07-14 04:49:26 +01:00
//}
2013-06-20 22:06:39 +01:00
}
// To enable encryption: radio.encrypt("ABCDEFGHIJKLMNOP");
// To disable encryption: radio.encrypt(null) or radio.encrypt(0)
// KEY HAS TO BE 16 bytes !!!
void RFM69 : : encrypt ( const char * key ) {
setMode ( RF69_MODE_STANDBY ) ;
2015-01-06 14:25:29 +00:00
if ( key ! = 0 )
2013-06-20 22:06:39 +01:00
{
select ( ) ;
SPI . transfer ( REG_AESKEY1 | 0x80 ) ;
2015-01-12 10:34:16 +00:00
for ( uint8_t i = 0 ; i < 16 ; i + + )
2013-06-20 22:06:39 +01:00
SPI . transfer ( key [ i ] ) ;
unselect ( ) ;
}
writeReg ( REG_PACKETCONFIG2 , ( readReg ( REG_PACKETCONFIG2 ) & 0xFE ) | ( key ? 1 : 0 ) ) ;
}
2015-05-19 20:08:41 +01:00
// get the received signal strength indicator (RSSI)
2015-01-12 10:34:16 +00:00
int16_t RFM69 : : readRSSI ( bool forceTrigger ) {
int16_t rssi = 0 ;
2013-06-20 22:06:39 +01:00
if ( forceTrigger )
{
2015-01-06 14:25:29 +00:00
// RSSI trigger not needed if DAGC is in continuous mode
2013-06-20 22:06:39 +01:00
writeReg ( REG_RSSICONFIG , RF_RSSI_START ) ;
2015-01-06 14:25:29 +00:00
while ( ( readReg ( REG_RSSICONFIG ) & RF_RSSI_DONE ) = = 0x00 ) ; // wait for RSSI_Ready
2013-06-20 22:06:39 +01:00
}
rssi = - readReg ( REG_RSSIVALUE ) ;
rssi > > = 1 ;
return rssi ;
}
2015-01-12 10:34:16 +00:00
uint8_t RFM69 : : readReg ( uint8_t addr )
2013-06-20 22:06:39 +01:00
{
select ( ) ;
SPI . transfer ( addr & 0x7F ) ;
2015-01-12 10:34:16 +00:00
uint8_t regval = SPI . transfer ( 0 ) ;
2013-06-20 22:06:39 +01:00
unselect ( ) ;
return regval ;
}
2015-01-12 10:34:16 +00:00
void RFM69 : : writeReg ( uint8_t addr , uint8_t value )
2013-06-20 22:06:39 +01:00
{
select ( ) ;
SPI . transfer ( addr | 0x80 ) ;
2013-10-27 23:53:02 +00:00
SPI . transfer ( value ) ;
2013-06-20 22:06:39 +01:00
unselect ( ) ;
}
2015-05-19 20:08:41 +01:00
// select the RFM69 transceiver (save SPI settings, set CS low)
2013-06-20 22:06:39 +01:00
void RFM69 : : select ( ) {
noInterrupts ( ) ;
2015-01-06 14:25:29 +00:00
// save current SPI settings
2014-08-13 03:03:19 +01:00
_SPCR = SPCR ;
_SPSR = SPSR ;
2015-01-06 14:25:29 +00:00
// set RFM69 SPI settings
2014-08-13 03:03:19 +01:00
SPI . setDataMode ( SPI_MODE0 ) ;
SPI . setBitOrder ( MSBFIRST ) ;
2015-01-06 14:25:29 +00:00
SPI . setClockDivider ( SPI_CLOCK_DIV4 ) ; // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
2013-06-20 22:06:39 +01:00
digitalWrite ( _slaveSelectPin , LOW ) ;
}
2015-05-19 20:08:41 +01:00
// unselect the RFM69 transceiver (set CS high, restore SPI settings)
2013-06-20 22:06:39 +01:00
void RFM69 : : unselect ( ) {
digitalWrite ( _slaveSelectPin , HIGH ) ;
2015-01-06 14:25:29 +00:00
// restore SPI settings to what they were before talking to RFM69
2014-08-13 03:03:19 +01:00
SPCR = _SPCR ;
SPSR = _SPSR ;
2013-06-20 22:06:39 +01:00
interrupts ( ) ;
}
2015-05-19 20:08:41 +01:00
// true = disable filtering to capture all frames on network
// false = enable node/broadcast filtering to capture only frames sent to this/broadcast address
2013-06-20 22:06:39 +01:00
void RFM69 : : promiscuous ( bool onOff ) {
2015-01-06 14:25:29 +00:00
_promiscuousMode = onOff ;
2013-06-20 22:06:39 +01:00
//writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST));
}
2015-05-19 20:08:41 +01:00
// for RFM69HW only: you must call setHighPower(true) after initialize() or else transmission won't work
2013-06-20 22:06:39 +01:00
void RFM69 : : setHighPower ( bool onOff ) {
_isRFM69HW = onOff ;
writeReg ( REG_OCP , _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON ) ;
2015-01-06 14:25:29 +00:00
if ( _isRFM69HW ) // turning ON
writeReg ( REG_PALEVEL , ( readReg ( REG_PALEVEL ) & 0x1F ) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON ) ; // enable P1 & P2 amplifier stages
2013-06-20 22:06:39 +01:00
else
2015-01-06 14:25:29 +00:00
writeReg ( REG_PALEVEL , RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel ) ; // enable P0 only
2013-06-20 22:06:39 +01:00
}
2015-05-19 20:08:41 +01:00
// internal function
2013-06-20 22:06:39 +01:00
void RFM69 : : setHighPowerRegs ( bool onOff ) {
writeReg ( REG_TESTPA1 , onOff ? 0x5D : 0x55 ) ;
writeReg ( REG_TESTPA2 , onOff ? 0x7C : 0x70 ) ;
}
2015-05-19 20:08:41 +01:00
// set the slave select (CS) pin
2015-01-12 10:34:16 +00:00
void RFM69 : : setCS ( uint8_t newSPISlaveSelect ) {
2013-06-20 22:06:39 +01:00
_slaveSelectPin = newSPISlaveSelect ;
2015-01-18 11:31:16 +00:00
digitalWrite ( _slaveSelectPin , HIGH ) ;
2013-06-20 22:06:39 +01:00
pinMode ( _slaveSelectPin , OUTPUT ) ;
}
//for debugging
2015-08-23 03:13:20 +01:00
# define REGISTER_DETAIL 0
2014-11-12 04:05:36 +00:00
# if REGISTER_DETAIL
// SERIAL PRINT
// replace Serial.print("string") with SerialPrint("string")
# define SerialPrint(x) SerialPrint_P(PSTR(x))
void SerialWrite ( uint8_t c ) {
Serial . write ( c ) ;
}
void SerialPrint_P ( PGM_P str , void ( * f ) ( uint8_t ) = SerialWrite ) {
for ( uint8_t c ; ( c = pgm_read_byte ( str ) ) ; str + + ) ( * f ) ( c ) ;
}
# endif
2013-06-20 22:06:39 +01:00
void RFM69 : : readAllRegs ( )
{
2015-01-12 10:34:16 +00:00
uint8_t regVal ;
2014-11-12 04:05:36 +00:00
# if REGISTER_DETAIL
2014-11-11 05:02:52 +00:00
int capVal ;
2014-11-10 00:01:51 +00:00
2014-11-12 04:05:36 +00:00
//... State Variables for intelligent decoding
2015-08-23 02:03:51 +01:00
uint8_t modeFSK = 0 ;
2014-11-12 04:05:36 +00:00
int bitRate = 0 ;
int freqDev = 0 ;
long freqCenter = 0 ;
# endif
2015-08-23 03:13:20 +01:00
Serial . println ( " Address - HEX - BIN " ) ;
2015-01-12 10:34:16 +00:00
for ( uint8_t regAddr = 1 ; regAddr < = 0x4F ; regAddr + + )
2015-01-06 13:46:04 +00:00
{
2013-06-20 22:06:39 +01:00
select ( ) ;
2015-01-12 10:00:43 +00:00
SPI . transfer ( regAddr & 0x7F ) ; // send address + r/w bit
2013-06-20 22:06:39 +01:00
regVal = SPI . transfer ( 0 ) ;
unselect ( ) ;
Serial . print ( regAddr , HEX ) ;
Serial . print ( " - " ) ;
Serial . print ( regVal , HEX ) ;
Serial . print ( " - " ) ;
Serial . println ( regVal , BIN ) ;
2014-11-11 05:02:52 +00:00
2014-11-12 04:05:36 +00:00
# if REGISTER_DETAIL
2015-08-23 02:03:51 +01:00
switch ( regAddr )
{
2014-11-12 04:05:36 +00:00
case 0x1 : {
SerialPrint ( " Controls the automatic Sequencer ( see section 4.2 ) \n SequencerOff : " ) ;
2014-11-11 05:02:52 +00:00
if ( 0x80 & regVal ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 1 -> Mode is forced by the user \n " ) ;
2014-11-11 05:02:52 +00:00
} else {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 0 -> Operating mode as selected with Mode bits in RegOpMode is automatically reached with the Sequencer \n " ) ;
2014-11-11 05:02:52 +00:00
}
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n Enables Listen mode, should be enabled whilst in Standby mode: \n ListenOn : " ) ;
2014-11-11 05:02:52 +00:00
if ( 0x40 & regVal ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 1 -> On \n " ) ;
2014-11-11 05:02:52 +00:00
} else {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 0 -> Off ( see section 4.3) \n " ) ;
2014-11-11 05:02:52 +00:00
}
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n Aborts Listen mode when set together with ListenOn=0 See section 4.3.4 for details (Always reads 0.) \n " ) ;
2014-11-11 05:02:52 +00:00
if ( 0x20 & regVal ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " ERROR - ListenAbort should NEVER return 1 this is a write only register \n " ) ;
2014-11-11 05:02:52 +00:00
}
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n Transceiver's operating modes: \n Mode : " ) ;
2014-11-11 05:02:52 +00:00
capVal = ( regVal > > 2 ) & 0x7 ;
if ( capVal = = 0b000 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 000 -> Sleep mode (SLEEP) \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = 0b001 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 001 -> Standby mode (STDBY) \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = 0b010 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 010 -> Frequency Synthesizer mode (FS) \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = 0b011 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 011 -> Transmitter mode (TX) \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = 0b100 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 100 -> Receiver Mode (RX) \n " ) ;
2014-11-11 05:02:52 +00:00
} else {
Serial . print ( capVal , BIN ) ;
2014-11-12 04:05:36 +00:00
SerialPrint ( " -> RESERVED \n " ) ;
2014-11-11 05:02:52 +00:00
}
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n " ) ;
2014-11-11 05:02:52 +00:00
break ;
}
case 0x2 : {
2014-11-12 04:05:36 +00:00
SerialPrint ( " Data Processing mode: \n DataMode : " ) ;
2014-11-11 05:02:52 +00:00
capVal = ( regVal > > 5 ) & 0x3 ;
if ( capVal = = 0b00 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 00 -> Packet mode \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = = 0b01 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 01 -> reserved \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = = 0b10 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 10 -> Continuous mode with bit synchronizer \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = = 0b11 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 11 -> Continuous mode without bit synchronizer \n " ) ;
2014-11-11 05:02:52 +00:00
}
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n Modulation scheme: \n Modulation Type : " ) ;
2014-11-11 05:02:52 +00:00
capVal = ( regVal > > 3 ) & 0x3 ;
if ( capVal = = 0b00 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 00 -> FSK \n " ) ;
modeFSK = 1 ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = = 0b01 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 01 -> OOK \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = = 0b10 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 10 -> reserved \n " ) ;
2014-11-11 05:02:52 +00:00
} else if ( capVal = = 0b11 ) {
2014-11-12 04:05:36 +00:00
SerialPrint ( " 11 -> reserved \n " ) ;
2014-11-11 05:02:52 +00:00
}
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n Data shaping: " ) ;
if ( modeFSK ) {
SerialPrint ( " in FSK: \n " ) ;
} else {
SerialPrint ( " in OOK: \n " ) ;
}
SerialPrint ( " ModulationShaping : " ) ;
capVal = regVal & 0x3 ;
if ( modeFSK ) {
if ( capVal = = 0b00 ) {
SerialPrint ( " 00 -> no shaping \n " ) ;
} else if ( capVal = = 0b01 ) {
SerialPrint ( " 01 -> Gaussian filter, BT = 1.0 \n " ) ;
} else if ( capVal = = 0b10 ) {
SerialPrint ( " 10 -> Gaussian filter, BT = 0.5 \n " ) ;
} else if ( capVal = = 0b11 ) {
SerialPrint ( " 11 -> Gaussian filter, BT = 0.3 \n " ) ;
}
} else {
if ( capVal = = 0b00 ) {
SerialPrint ( " 00 -> no shaping \n " ) ;
} else if ( capVal = = 0b01 ) {
SerialPrint ( " 01 -> filtering with f(cutoff) = BR \n " ) ;
} else if ( capVal = = 0b10 ) {
SerialPrint ( " 10 -> filtering with f(cutoff) = 2*BR \n " ) ;
} else if ( capVal = = 0b11 ) {
SerialPrint ( " ERROR - 11 is reserved \n " ) ;
}
}
2014-11-11 05:02:52 +00:00
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n " ) ;
2014-11-11 05:02:52 +00:00
break ;
}
2014-11-12 04:05:36 +00:00
case 0x3 : {
bitRate = ( regVal < < 8 ) ;
break ;
}
case 0x4 : {
bitRate | = regVal ;
SerialPrint ( " Bit Rate (Chip Rate when Manchester encoding is enabled) \n BitRate : " ) ;
unsigned long val = 32UL * 1000UL * 1000UL / bitRate ;
Serial . println ( val ) ;
SerialPrint ( " \n " ) ;
break ;
}
case 0x5 : {
freqDev = ( ( regVal & 0x3f ) < < 8 ) ;
break ;
}
case 0x6 : {
freqDev | = regVal ;
SerialPrint ( " Frequency deviation \n Fdev : " ) ;
unsigned long val = 61UL * freqDev ;
Serial . println ( val ) ;
SerialPrint ( " \n " ) ;
break ;
}
case 0x7 : {
unsigned long tempVal = regVal ;
freqCenter = ( tempVal < < 16 ) ;
break ;
}
case 0x8 : {
unsigned long tempVal = regVal ;
freqCenter = freqCenter | ( tempVal < < 8 ) ;
break ;
}
case 0x9 : {
freqCenter = freqCenter | regVal ;
SerialPrint ( " RF Carrier frequency \n FRF : " ) ;
unsigned long val = 61UL * freqCenter ;
Serial . println ( val ) ;
SerialPrint ( " \n " ) ;
break ;
}
case 0xa : {
SerialPrint ( " RC calibration control & status \n RcCalDone : " ) ;
if ( 0x40 & regVal ) {
SerialPrint ( " 1 -> RC calibration is over \n " ) ;
} else {
SerialPrint ( " 0 -> RC calibration is in progress \n " ) ;
}
SerialPrint ( " \n " ) ;
break ;
2014-11-11 05:02:52 +00:00
}
2014-11-12 04:05:36 +00:00
case 0xb : {
SerialPrint ( " Improved AFC routine for signals with modulation index lower than 2. Refer to section 3.4.16 for details \n AfcLowBetaOn : " ) ;
if ( 0x20 & regVal ) {
SerialPrint ( " 1 -> Improved AFC routine \n " ) ;
} else {
SerialPrint ( " 0 -> Standard AFC routine \n " ) ;
}
SerialPrint ( " \n " ) ;
break ;
}
case 0xc : {
SerialPrint ( " Reserved \n \n " ) ;
break ;
}
case 0xd : {
byte val ;
SerialPrint ( " Resolution of Listen mode Idle time (calibrated RC osc): \n ListenResolIdle : " ) ;
val = regVal > > 6 ;
if ( val = = 0b00 ) {
SerialPrint ( " 00 -> reserved \n " ) ;
} else if ( val = = 0b01 ) {
SerialPrint ( " 01 -> 64 us \n " ) ;
} else if ( val = = 0b10 ) {
SerialPrint ( " 10 -> 4.1 ms \n " ) ;
} else if ( val = = 0b11 ) {
SerialPrint ( " 11 -> 262 ms \n " ) ;
}
2014-11-11 05:02:52 +00:00
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n Resolution of Listen mode Rx time (calibrated RC osc): \n ListenResolRx : " ) ;
val = ( regVal > > 4 ) & 0x3 ;
if ( val = = 0b00 ) {
SerialPrint ( " 00 -> reserved \n " ) ;
} else if ( val = = 0b01 ) {
SerialPrint ( " 01 -> 64 us \n " ) ;
} else if ( val = = 0b10 ) {
SerialPrint ( " 10 -> 4.1 ms \n " ) ;
} else if ( val = = 0b11 ) {
SerialPrint ( " 11 -> 262 ms \n " ) ;
}
SerialPrint ( " \n Criteria for packet acceptance in Listen mode: \n ListenCriteria : " ) ;
if ( 0x8 & regVal ) {
SerialPrint ( " 1 -> signal strength is above RssiThreshold and SyncAddress matched \n " ) ;
} else {
SerialPrint ( " 0 -> signal strength is above RssiThreshold \n " ) ;
}
2014-11-11 05:02:52 +00:00
2014-11-12 04:05:36 +00:00
SerialPrint ( " \n Action taken after acceptance of a packet in Listen mode: \n ListenEnd : " ) ;
val = ( regVal > > 1 ) & 0x3 ;
if ( val = = 0b00 ) {
SerialPrint ( " 00 -> chip stays in Rx mode. Listen mode stops and must be disabled (see section 4.3) \n " ) ;
} else if ( val = = 0b01 ) {
SerialPrint ( " 01 -> chip stays in Rx mode until PayloadReady or Timeout interrupt occurs. It then goes to the mode defined by Mode. Listen mode stops and must be disabled (see section 4.3) \n " ) ;
} else if ( val = = 0b10 ) {
SerialPrint ( " 10 -> chip stays in Rx mode until PayloadReady or Timeout occurs. Listen mode then resumes in Idle state. FIFO content is lost at next Rx wakeup. \n " ) ;
} else if ( val = = 0b11 ) {
SerialPrint ( " 11 -> Reserved \n " ) ;
}
SerialPrint ( " \n " ) ;
break ;
}
2014-11-11 05:02:52 +00:00
2014-11-12 04:05:36 +00:00
default : {
}
2014-11-11 05:02:52 +00:00
}
# endif
2015-01-06 13:46:04 +00:00
}
2013-06-20 22:06:39 +01:00
unselect ( ) ;
}
2015-01-12 10:34:16 +00:00
uint8_t RFM69 : : readTemperature ( uint8_t calFactor ) // returns centigrade
2013-09-06 00:32:11 +01:00
{
setMode ( RF69_MODE_STANDBY ) ;
writeReg ( REG_TEMP1 , RF_TEMP1_MEAS_START ) ;
2015-01-03 01:24:25 +00:00
while ( ( readReg ( REG_TEMP1 ) & RF_TEMP1_MEAS_RUNNING ) ) ;
2015-01-12 10:00:43 +00:00
return ~ readReg ( REG_TEMP2 ) + COURSE_TEMP_COEF + calFactor ; // 'complement' corrects the slope, rising temp = rising val
2015-01-06 13:46:04 +00:00
} // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction
2013-09-06 00:32:11 +01:00
void RFM69 : : rcCalibration ( )
{
writeReg ( REG_OSC1 , RF_OSC1_RCCAL_START ) ;
while ( ( readReg ( REG_OSC1 ) & RF_OSC1_RCCAL_DONE ) = = 0x00 ) ;
2015-01-03 01:24:25 +00:00
}