-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathplainRFM69.h
315 lines (232 loc) · 10.6 KB
/
plainRFM69.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/*
* Copyright (c) 2014, Ivor Wanders
* MIT License, see the LICENSE.md file in the root folder.
*/
#include <Arduino.h>
#include <bareRFM69.h>
#include <bareRFM69_const.h>
#ifndef PLAIN_RFM69_H
#define PLAIN_RFM69_H
/*
The plainRFM69 object only provides the essential functions to receive and
sent packets using the RFM69 radio module. It builds on top of bareRFM69
to address the hardware.
The normal state of the radio is to listen to packets, the poll() method
should be called to obtain the packet from the radio hardare and place it
into the plainRFM69's buffer. From this buffer it can then be read.
The AutoModes of the radio module are used. This allows the most efficient
transmissions of data, only enabling the transmitter when the data is ready
to be sent. The AutoMode is also used for the receiving state, once a packet
is received the radio is put in standby mode until the packet is retreived
by the poll() method.
The poll() method can also be attached to an interrupt, allowing efficient
retrieval of packets from the FIFO and placing them in the buffer such that
they are available outside of the interrupt.
*/
#ifdef RFM69_PLAIN_DEBUG
// #if RFM69_PLAIN_DEBUG==1
#define debug_rfm(a) Serial.print(a);
#define debug_rfmln(a) Serial.println(a);
#else
#define debug_rfm(a)
#define debug_rfmln(a)
#endif
/*
Assumes we are little endian.
0A 0B 0C 0D; a=0D, a+1=0C, a+2=0B, a+3=0A
*/
#define RFM69_PLAIN_STATE_RECEIVING 0
#define RFM69_PLAIN_STATE_SENDING 1
class plainRFM69 : public bareRFM69{
protected:
bool use_variable_length;
bool use_addressing;
bool use_AES;
bool use_HP_module = false;
bool tx_power_boosted = false;
// state of the radio module.
volatile uint8_t state;
// Rx packet buffer.
uint8_t packet_length;
uint8_t** packet_buffer;
uint8_t buffer_size;
// Rx packet buffer write and read index.
volatile uint8_t buffer_read_index;
volatile uint8_t buffer_write_index;
// Temporary buffer to compose the message in before writing to FIFO
uint8_t* tx_buffer;
void sendPacket(void* buffer, uint8_t len);
/*
Set the radio to Tx automode and write buffer up to len to the fifo.
Sets the state to sending.
*/
virtual void readPacket();
/*
Read a packet from the hardware to the internal buffer.
*/
virtual void setRawPacketLength();
/*
Sets the real packetlength in the hardware.
*/
public:
plainRFM69(uint8_t cs_pin) : bareRFM69(cs_pin){
this->packet_buffer = 0;
this->buffer_size = 0;
this->buffer_read_index = 0;
this->buffer_write_index = 0;
this->state = RFM69_PLAIN_STATE_RECEIVING;
this->use_AES = false;
};
/*
Order of calling the methods is important.
rfm.setRecommended();
// rfm.setAES(false); // should come before setPacketType
rfm.setPacketType(false, false);
rfm.setBufferSize(10); // should come after setPacketType
rfm.setPacketLength(32);
// should come after setBufferSize, allocates the buffer
// Might have to change the fifo thresshold
// rfm.setFifoThreshold(RFM69_THRESHOLD_CONDITION_FIFOLEVEL,3); // bareRFM
// if we use filtering, set the node and or broadcast address here.
// rfm.setNodeAddress(0x01);
rfm.setFrequency(434*1000*1000); // set the frequency.
rfm.baud300000(); // set the modulation parameters.
rfm.receive(); // set the radio to receive.
*/
void setRecommended();
/*
Sets various parameters in the radio module to the recommended
values as in the datasheet.
*/
void setPacketType(bool use_variable_length, bool use_addressing);
/*
Sets message properties:
use_variable_length = true:
Uses variable length packets.
use_variable_length = false:
Fixed packet length.
use_addressing = false:
Disables filtering on address.
use_addressing = true:
Enables filtering on address.
Set addressses with:
void setNodeAddress(uint8_t address)
void setBroadcastAddress(uint8_t address)
This function sets:
setFifoThreshold(RFM69_THRESHOLD_CONDITION_NOT_EMPTY,0);
Such that transmissions start when the packetlength is below 15
packets, which is the recommended value. If a slow SPI bus is used,
it might be necessary to manually use setFifoThreshold().
*/
void setBufferSize(uint8_t length);
/*
Sets the number of buffers slots to buffer messages into.
Should at least two, otherwise there is no way to know whether the
message has been read from the buffer.
(That is the read and write index are always the same...)
*/
void setPacketLength(uint8_t length);
/*
With variable length, this sets the Rx maximum length.
With fixed length this sets the packet length for both Rx and Tx.
Should only be called once. And after SetBufferSize and
setPacketType.
The length should be between 0-64, 64 bytes length is the maximum.
If AES is enabled, any length below 16 results in zero padding by
the radio module. So shorter lengths than 16 bytes do not result in
more efficient transmissions.
The setPacketType() method sets the FIFO thresshold, to start trans-
mission, however, if a slow SPI is used, it might be necessary to
set an adequate transmission start thresshold using:
setFifoThreshold(RFM69_THRESHOLD_CONDITION_FIFOLEVEL, X);
Where X determines how many bytes must be available before the
transmission starts.
*/
void setFrequency(uint32_t freq);
/*
Sets the frequency to approximately Freq.
Uses 61 as Fstep instead of 61.03515625 which it actually is.
For more precise control, use void setFrf from bareRFM69.
Example:
setFrequency((uint32_t) 450*1000*1000); sets to ~450 MHz (actually 450.259)
setFrequency((uint32_t) 434*1000*1000); sets to ~434 MHz (actually 434.250)
*/
void setAES(bool use_AES);
/*
enable or disable AES.
use bareRFM69::setAesKey(void* buffer, uint8_t len); to set the key.
Cipher mode is ECB, so every 16 byte block is encrypted with this
key, identical plaintext results in identical ciphertexts.
Remember it does not provide security against replay attacks.
It does provide some sort of whitening filter.
*/
void setHighPowerModule(){this->use_HP_module = true;};
/*
Informs the library that a high-power module variant (RFM69HW or RFM69HCW) is present.
*/
void setTxPower(int8_t power_level_dBm, bool enable_boost = false);
/*
Accepts a decibel target output power between -18 and +20.
The requested power will be adjusted to be within the capability range
of the installed module.
*/
bool canSend();
/*
Returns whether the module can send, or if it is busy sending.
The current implementation is naive. This method can definitely be
improved by taking RSSI into acocunt.
If the interupt method is used, a missed interrupt currently causes
the object to become stuck in the sending state.
*/
virtual void sendAddressedVariable(uint8_t address, void* buffer, uint8_t len);
// send to specific address with variable length. Use with setPacketType(true, true).
// It's not possible to send anything with length zero.
virtual void sendVariable(void* buffer, uint8_t len);
// send without addressing with variable length; Use with setPacketType(true, false).
// It's not possible to send anything with length zero.
virtual void sendAddressed(uint8_t address, void* buffer);
// send with addressing and fixed length. Use with setPacketType(false, true).
virtual void send(void* buffer);
// send without addressing and fixed length. Use with setPacketType(false, false).
void receive();
// sets the radio into receiver mode.
// should be called after setup.
void poll();
/*
Polls the radio to check for packets in the fifo. If a packet is
received, it is written to the buffer, from which it can be
retreived with read(void* buffer).
When the radio has received a packet, it stops receiving and waits
for the packet to be removed from the FIFO.
This method also puts the radio back into receiving mode after a
packet has been completely sent.
It is recommended to to call this method from an interrupt attached
to the AutoMode indicator.
*/
bool available();
/*
Returns true when the read pointer is not aligned with the write
pointer, this means packets are available, returns false in case
they align and no new packets are available.
There is no method to detect overflows of the buffer.
*/
uint8_t read(void* buffer);
/*
Reads the next packet from the buffer to the pointer.
If the packetlength is set to 'size' with: setPacketLength(size):
Returns the number of bytes in the packet. For variable length
payloads, it writes up to size bytes.
For variable and addessing, it writes up to size+1 bytes.
The first byte being the address to which it was sent.
For addressing only, it writes up to size+1 bytes.
It returns the packetlength of the packet read from the buffer.
Returns zero in case no packet is available.
*/
void baud4800();
void baud9600();
void baud153600();
void baud300000();
void emitPreamble(); // continuously emit a preamble
};
//PLAIN_RFM69_H
#endif