rcProtocol  V.0.3.0
A protocol for diy transmitters/receivers
rcDeviceProtocol.cpp
Go to the documentation of this file.
1 #include <RF24.h>
2 
3 #include "rcDeviceProtocol.h"
4 #include "rcSettings.h"
5 
6 DeviceProtocol::DeviceProtocol(RF24* tranceiver, const uint8_t deviceId[]) {
7  _isConnected = false;
8 
9  for(uint8_t i = 0; i < 5; i++) {
10  _remoteId[i] = 0;
11  }
12 
13  _radio = tranceiver;
14  _deviceId = deviceId;
15 
16 }
17 
21  _settings.setSettings(settings->getSettings());
22 
23  _radio->begin();
24 
25  //If there was a previous connection, try to re-establish it.
26  if(checkConnected()) {
28 
29  //Load the Remote ID.
30  uint8_t id[5];
31  loadRemoteID(id);
32 
33  _radio->openWritingPipe(id);
34  _radio->openReadingPipe(1, _deviceId);
35 
36  _radio->startListening();
37 
38  /*If the remote is still connected, it should be sending regular data
39  _settings.getCommsFrequency() per second, so we will wait for 3 time
40  periods before giving up.*/
41  if(wait_till_available(round(3000.0 / _settings.getCommsFrequency())) == -1) {
42  return -1;
43  }
44 
45  for(uint8_t i = 0; i < 5; i++) {
46  _remoteId[i] = id[i];
47  }
48  _isConnected = true;
49 
50 
51  return 1;
52 
53  }
54 
55  return 0;
56 }
57 
59  if(isConnected()) {
61  }
62 
63  uint8_t radioId[5];
64  bool sent = false;
65 
66  //Set the PA level to low as the pairing devices are going to be fairly
67  //close to each other.
68  _radio->setPALevel(RF24_PA_LOW);
69 
71 
72  //Don't yet open a writing pipe as we don't know who we will write to
73  _radio->openReadingPipe(1, _PAIR_ADDRESS);
74 
75  _radio->startListening();
76 
77  //clear the buffer of any unread messages.
78  flush_buffer();
79 
80  //wait until data is available from the remote
82  return RC_ERROR_TIMEOUT;
83  }
84 
85  //Read the Radio's ID
86  _radio->read(&radioId, 5);
87 
88  //write to the remote the device id
89  saveRemoteID(radioId);
90 
91  _radio->stopListening();
92 
93  //Now that we know who we will write to, open the writing pipe
94  _radio->openWritingPipe(radioId);
95 
96  //Delay so that the remote has time to start listening
97  delay(200);
98 
99  //Send the device id to the remote
100  sent = _radio->write(const_cast<uint8_t*>(_deviceId), 5);
101  if(!sent) {
103  }
104 
105  delay(200);
106 
107  //Send the settings to the remote
108  sent = _radio->write(const_cast<uint8_t*>(_settings.getSettings()), 32);
109  if(!sent) {
111  }
112 
113  return 0;
114 }
115 
118  if(isConnected()) {
120  }
121 
122  uint8_t connectSuccess = 0;
123  uint8_t test = 0;
124 
125  uint8_t remoteId[5];
126  loadRemoteID(remoteId);
127 
128  //reset connected because if we fail connecting, we will not be connected
129  //to anything.
130  _isConnected = false;
131 
132  _radio->setPALevel(RF24_PA_LOW);
133 
135 
136  _radio->openWritingPipe(remoteId);
137  _radio->openReadingPipe(1, _deviceId);
138 
139  flush_buffer();
140 
141  //Start writing
142  _radio->stopListening();
143 
144  //send the device id to the remote, this announces who we are.
145  if(force_send(const_cast<uint8_t*>(_deviceId), 5, RC_TIMEOUT) != 0) {
146  return RC_ERROR_TIMEOUT;
147  }
148 
149  _radio->startListening();
150 
151  //Wait until a response is made
154  }
155 
156  _radio->read(&connectSuccess, 1);
157 
158  _radio->stopListening();
159 
160  //check if the connection was successful
161  if(connectSuccess == _NACK) {
163  } else if(connectSuccess != _ACK) {
164  return RC_ERROR_BAD_DATA;
165  }
166 
168 
169  _radio->setPALevel(RF24_PA_HIGH);
170 
171  _radio->startListening();
172 
173 
174  if(_settings.getEnableAck()) {
176  _radio->writeAckPayload(1, &_TEST, 1);
177 
179  _radio->stopListening();
181  }
182 
183  _radio->read(&test, 1);
184 
185  if(test != _TEST) {
186  _radio->stopListening();
187  return RC_ERROR_BAD_DATA;
188  }
189 
190  } else {
192  _radio->stopListening();
194  }
195 
196  _radio->read(&test, 1);
197 
198  if(test != _TEST) {
199  _radio->stopListening();
200  return RC_ERROR_BAD_DATA;
201  }
202  }
203  } else {
205  _radio->stopListening();
207  }
208 
209  _radio->read(&test, 1);
210 
211  if(test != _TEST) {
212  _radio->stopListening();
213  return RC_ERROR_BAD_DATA;
214  }
215 
216  _radio->stopListening();
217 
218  delay(200);
219 
220  _radio->write(&_TEST, 1);
221 
222  _radio->startListening();
223 
224  }
225 
226  //We passed all of the tests, so we are connected.
227  _isConnected = true;
228  setConnected(true);
229 
230  for(uint8_t i = 0; i < 5; i++) {
231  _remoteId[i] = remoteId[i];
232  }
233 
234  return 0;
235 }
236 
238  return _isConnected;
239 }
240 
241 int8_t DeviceProtocol::check_packet(void* returnData, uint8_t dataSize,
242  void* telemetry, uint8_t telemetrySize) {
243  if(!isConnected()) {
244  return RC_ERROR_NOT_CONNECTED;
245  }
246 
247  uint8_t pipe = 0;
248 
249  if(_radio->available(&pipe)) {
250  _radio->read(returnData, dataSize);
251 
252  //Check if the telemetry should be sent through the ackPayload
253  if(telemetry && _settings.getEnableAckPayload()) {
254  _radio->writeAckPayload(pipe, telemetry, telemetrySize);
255  }
256 
257  return 1;
258  }
259 
260  return 0;
261 }
262 
263 int8_t DeviceProtocol::check_packet(void* returnData, uint8_t dataSize) {
264  return check_packet(returnData, dataSize, NULL, 0);
265 }
266 
267 int8_t DeviceProtocol::update(uint16_t channels[], uint8_t telemetry[],
269  if(!isConnected()) {
270  return RC_ERROR_NOT_CONNECTED;
271  }
272 
273  uint8_t packet[_settings.getPayloadSize()];
274 
275  int8_t packetStatus = 0;
276  int8_t status = 0;
277 
278  //Load a transmission, and send an ack payload.
279  packetStatus = check_packet(packet,
280  _settings.getPayloadSize() * sizeof(uint8_t),
281  telemetry, _settings.getPayloadSize());
282 
283 
284  //read through each transmission we have gotten since the last update
285  while(packetStatus == 1) {
286 
287  //Covert packet to channels
288 
289  //Check if the packet is a channel packet
290  if((packet[0] & 0xF0) == _PACKET_CHANNELS) {
291 
292  status = 1;
293 
294  for(uint8_t i = 0; i < _settings.getNumChannels(); i++) {
295  channels[i] = ((packet[i * 2 + 1] << 8)) | (packet[i * 2 + 2]);
296  }
297 
298  //If the packet is a Disconnect Packet
299  } else if(packet[0] == _PACKET_DISCONNECT) {
300  if(!_settings.getEnableAck()) {
301  _radio->stopListening();
302  delay(50);
303  _radio->write(const_cast<uint8_t*>(&_ACK), 1);
304  _radio->startListening();
305  }
306 
307  _isConnected = false;
308  setConnected(false);
309 
310  //If the packet is a Reconnect Packet
311  } else if(packet[0] == _PACKET_RECONNECT) {
312  if(!_settings.getEnableAck()) {
313  _radio->stopListening();
314  delay(20);
315  _radio->write(const_cast<uint8_t*>(&_ACK), 1);
316  _radio->startListening();
317  }
318  }
319 
320  //Load a transmission.
321  packetStatus = check_packet(packet,
322  _settings.getPayloadSize() * sizeof(uint8_t));
323  }
324 
325  if(packetStatus < 0) {
326  status = packetStatus;
327  }
328 
329  return status;
330 }
331 
333  return &_settings;
334 }
DeviceProtocol(RF24 *tranceiver, const uint8_t deviceId[])
#define RC_CONNECT_TIMEOUT
Definition: rcGlobal.h:15
int8_t connect(loadRemoteID loadRemoteID, setConnected setConnected)
#define RC_ERROR_BAD_DATA
Definition: rcGlobal.h:31
const uint8_t _PAIR_ADDRESS[5]
Definition: rcGlobal.h:59
#define RC_ERROR_TIMEOUT
Definition: rcGlobal.h:27
const uint8_t _PACKET_CHANNELS
Definition: rcGlobal.h:65
const uint8_t _TEST
Definition: rcGlobal.h:63
RF24 * _radio
Definition: rcGlobal.h:74
void apply_settings(RCSettings *settings)
Definition: rcGlobal.cpp:40
const uint8_t _ACK
Definition: rcGlobal.h:61
void setSettings(const uint8_t *settings)
Definition: rcSettings.cpp:17
int8_t pair(saveRemoteID saveRemoteID)
#define RC_TIMEOUT
Definition: rcGlobal.h:11
void() setConnected(bool connected)
void flush_buffer()
Definition: rcGlobal.cpp:65
const uint8_t _PACKET_DISCONNECT
Definition: rcGlobal.h:68
int8_t wait_till_available(unsigned long timeout)
Definition: rcGlobal.cpp:28
void() loadRemoteID(uint8_t *id)
#define RC_ERROR_LOST_CONNECTION
Definition: rcGlobal.h:23
RCSettings _pairSettings
Definition: rcGlobal.h:72
RCSettings * getSettings()
int8_t update(uint16_t channels[], uint8_t telemetry[], setConnected setConnected)
uint8_t getCommsFrequency()
Definition: rcSettings.cpp:96
uint8_t * getSettings()
Definition: rcSettings.cpp:23
uint8_t getPayloadSize()
Definition: rcSettings.cpp:88
void() saveRemoteID(const uint8_t *id)
int8_t force_send(void *buf, uint8_t size, unsigned long timeout)
Definition: rcGlobal.cpp:15
#define RC_ERROR_ALREADY_CONNECTED
Definition: rcGlobal.h:43
bool() checkConnected()
#define RC_ERROR_NOT_CONNECTED
Definition: rcGlobal.h:39
RCSettings _settings
Definition: rcGlobal.h:71
int8_t begin(RCSettings *settings, checkConnected checkConnected, loadRemoteID loadRemoteID)
bool getEnableAck()
Definition: rcSettings.cpp:43
bool getEnableAckPayload()
Definition: rcSettings.cpp:53
#define RC_ERROR_CONNECTION_REFUSED
Definition: rcGlobal.h:35
const uint8_t _NACK
Definition: rcGlobal.h:62
uint8_t getNumChannels()
Definition: rcSettings.cpp:114
const uint8_t _PACKET_RECONNECT
Definition: rcGlobal.h:69