This repository has been archived by the owner on Nov 7, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
RFM69.h
170 lines (154 loc) · 7.35 KB
/
RFM69.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// **********************************************************************************
// Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech SX1231/1231H
// **********************************************************************************
// 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
// Foundation; either version 3 of the License, or
// (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
// PARTICULAR PURPOSE. See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General
// Public License along with this program.
// If not, see <http://www.gnu.org/licenses/>.
//
// Licence can be viewed at
// http://www.gnu.org/licenses/gpl-3.0.txt
//
// Please maintain this license information along with authorship
// and copyright notices in any redistribution of this code
// **********************************************************************************
#ifndef RFM69_h
#define RFM69_h
#include <Arduino.h> // assumes Arduino IDE v1.0 or greater
#define RF69_MAX_DATA_LEN 61 // to take advantage of the built in AES/CRC we want to limit the frame size to the internal FIFO size (66 bytes - 3 bytes overhead - 2 bytes crc)
#define RF69_SPI_CS SS // SS is the SPI slave select pin, for instance D10 on ATmega328
// INT0 on AVRs should be connected to RFM69's DIO0 (ex on ATmega328 it's D2, on ATmega644/1284 it's D2)
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
#define RF69_IRQ_PIN 2
#define RF69_IRQ_NUM 0
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
#define RF69_IRQ_PIN 2
#define RF69_IRQ_NUM 2
#elif defined(__AVR_ATmega32U4__)
#define RF69_IRQ_PIN 3
#define RF69_IRQ_NUM 0
#elif defined(__arm__)//Use pin 10 or any pin you want
#define RF69_IRQ_PIN 10
#define RF69_IRQ_NUM 10
#else
#define RF69_IRQ_PIN 2
#define RF69_IRQ_NUM 0
#endif
#define Test_Pin PC13
#define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access
#define RF69_MODE_SLEEP 0 // XTAL OFF
#define RF69_MODE_STANDBY 1 // XTAL ON
#define RF69_MODE_SYNTH 2 // PLL ON
#define RF69_MODE_RX 3 // RX MODE
#define RF69_MODE_TX 4 // TX MODE
// available frequency bands
#define RF69_315MHZ 31 // non trivial values to avoid misconfiguration
#define RF69_433MHZ 43
#define RF69_868MHZ 86
#define RF69_915MHZ 91
#define null 0
#define COURSE_TEMP_COEF -90 // puts the temperature reading in the ballpark, user can fine tune the returned value
#define RF69_BROADCAST_ADDR 255
#define RF69_CSMA_LIMIT_MS 1000
#define RF69_TX_LIMIT_MS 1000
#define RF69_FSTEP 61.03515625 // == FXOSC / 2^19 = 32MHz / 2^19 (p13 in datasheet)
// TWS: define CTLbyte bits
#define RFM69_CTL_SENDACK 0x80
#define RFM69_CTL_REQACK 0x40
class RFM69 {
public:
static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; // recv/xmit buf, including header & crc bytes
static volatile uint8_t DATALEN;
static volatile uint8_t SENDERID;
static volatile uint8_t TARGETID; // should match _address
static volatile uint8_t PAYLOADLEN;
static volatile uint8_t ACK_REQUESTED;
static volatile uint8_t ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request
static volatile int16_t RSSI; // most accurate RSSI during reception (closest to the reception)
static volatile uint8_t _mode; // should be protected?
RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM) {
_slaveSelectPin = slaveSelectPin;
_interruptPin = interruptPin;
_interruptNum = interruptNum;
_mode = RF69_MODE_STANDBY;
_promiscuousMode = false;
_powerLevel = 31;
_isRFM69HW = isRFM69HW;
}
uint8_t getTestPin();
bool initialize(uint8_t freqBand, uint8_t ID, uint8_t networkID=1);
void setAddress(uint8_t addr);
uint8_t getAdress();
void setNetwork(uint8_t networkID);
uint8_t getNetwork();
void setSlaveSelectPin(uint8_t newSPISlaveSelect);
uint8_t getSlaveSelectPin();
void setInterruptPin(uint8_t newInterruptPin);
uint8_t getInterruptPin();
void setInterruptNumber(uint8_t newInterruptNumber);
uint8_t getInterruptNumber();
bool canSend();
virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false);
virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); // 40ms roundtrip req for 61byte packets
virtual bool receiveDone();
bool ACKReceived(uint8_t fromNodeID);
bool ACKRequested();
virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0);
uint32_t getFrequency();
void setFrequency(uint32_t freqHz);
void encrypt(const char* key);
int16_t readRSSI(bool forceTrigger=false);
void promiscuous(bool onOff=true);
virtual void setHighPower(bool onOFF=true); // has to be called after initialize() for RFM69HW
uint8_t getHighPower();
virtual void setPowerLevel(uint8_t level); // reduce/increase transmit power level
uint8_t getPowerLevel();
void sleep();
uint8_t readTemperature(uint8_t calFactor=0); // get CMOS temperature (8bit)
void rcCalibration(); // calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy]
// allow hacking registers by making these public
uint8_t readReg(uint8_t addr);
void writeReg(uint8_t addr, uint8_t val);
void readAllRegs();
protected:
static void isr0();
void virtual interruptHandler();
virtual void interruptHook(uint8_t CTLbyte) {};
static volatile bool _inISR;
virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false);
static RFM69* selfPointer;
uint8_t _slaveSelectPin;
uint8_t _interruptPin;
uint8_t _interruptNum;
uint8_t _address;
bool _promiscuousMode;
uint8_t _powerLevel;
bool _isRFM69HW;
#if defined (SPCR) && defined (SPSR)
uint8_t _SPCR;
uint8_t _SPSR;
#endif
virtual void receiveBegin();
virtual void setMode(uint8_t mode);
virtual void setHighPowerRegs(bool onOff);
virtual void select();
virtual void unselect();
inline void maybeInterrupts();
};
#endif