Line data Source code
1 : #include "PhysicalLayer.h"
2 :
3 : #include <string.h>
4 :
5 70 : PhysicalLayer::PhysicalLayer() {
6 70 : this->freqStep = 1;
7 70 : this->maxPacketLength = 1;
8 : #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
9 70 : this->bufferBitPos = 0;
10 70 : this->bufferWritePos = 0;
11 : #endif
12 70 : }
13 :
14 : #if defined(RADIOLIB_BUILD_ARDUINO)
15 : int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) {
16 : // read flash string length
17 : size_t len = 0;
18 : PGM_P p = reinterpret_cast<PGM_P>(fstr);
19 : while(true) {
20 : char c = RADIOLIB_NONVOLATILE_READ_BYTE(p++);
21 : len++;
22 : if(c == '\0') {
23 : break;
24 : }
25 : }
26 :
27 : // dynamically allocate memory
28 : #if RADIOLIB_STATIC_ONLY
29 : char str[RADIOLIB_STATIC_ARRAY_SIZE];
30 : #else
31 : char* str = new char[len];
32 : #endif
33 :
34 : // copy string from flash
35 : p = reinterpret_cast<PGM_P>(fstr);
36 : for(size_t i = 0; i < len; i++) {
37 : str[i] = RADIOLIB_NONVOLATILE_READ_BYTE(p + i);
38 : }
39 :
40 : // transmit string
41 : int16_t state = transmit(str, addr);
42 : #if !RADIOLIB_STATIC_ONLY
43 : delete[] str;
44 : #endif
45 : return(state);
46 : }
47 :
48 : int16_t PhysicalLayer::transmit(String& str, uint8_t addr) {
49 : return(transmit(str.c_str(), addr));
50 : }
51 : #endif
52 :
53 0 : int16_t PhysicalLayer::transmit(const char* str, uint8_t addr) {
54 0 : return(transmit(reinterpret_cast<uint8_t*>(const_cast<char*>(str)), strlen(str), addr));
55 : }
56 :
57 0 : int16_t PhysicalLayer::transmit(const uint8_t* data, size_t len, uint8_t addr) {
58 : (void)data;
59 : (void)len;
60 : (void)addr;
61 0 : return(RADIOLIB_ERR_UNSUPPORTED);
62 : }
63 :
64 : #if defined(RADIOLIB_BUILD_ARDUINO)
65 : int16_t PhysicalLayer::receive(String& str, size_t len, RadioLibTime_t timeout) {
66 : int16_t state = RADIOLIB_ERR_NONE;
67 :
68 : // user can override the length of data to read
69 : size_t length = len;
70 :
71 : // build a temporary buffer
72 : #if RADIOLIB_STATIC_ONLY
73 : uint8_t data[RADIOLIB_STATIC_ARRAY_SIZE + 1];
74 : #else
75 : uint8_t* data = NULL;
76 : if(length == 0) {
77 : data = new uint8_t[this->maxPacketLength + 1];
78 : } else {
79 : data = new uint8_t[length + 1];
80 : }
81 : RADIOLIB_ASSERT_PTR(data);
82 : #endif
83 :
84 : // attempt packet reception
85 : state = receive(data, length, timeout);
86 :
87 : // any of the following leads to at least some data being available
88 : // let's leave the decision of whether to keep it or not up to the user
89 : if((state == RADIOLIB_ERR_NONE) || (state == RADIOLIB_ERR_CRC_MISMATCH) || (state == RADIOLIB_ERR_LORA_HEADER_DAMAGED)) {
90 : // read the number of actually received bytes (for unknown packets)
91 : if(len == 0) {
92 : length = getPacketLength(false);
93 : }
94 :
95 : // add null terminator
96 : data[length] = 0;
97 :
98 : // initialize Arduino String class
99 : str = String(reinterpret_cast<char*>(data));
100 : }
101 :
102 : // deallocate temporary buffer
103 : #if !RADIOLIB_STATIC_ONLY
104 : delete[] data;
105 : #endif
106 :
107 : return(state);
108 : }
109 : #endif
110 :
111 0 : int16_t PhysicalLayer::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
112 : (void)data;
113 : (void)len;
114 : (void)timeout;
115 0 : return(RADIOLIB_ERR_UNSUPPORTED);
116 : }
117 :
118 0 : int16_t PhysicalLayer::sleep() {
119 0 : return(RADIOLIB_ERR_UNSUPPORTED);
120 : }
121 :
122 0 : int16_t PhysicalLayer::standby() {
123 0 : return(standby(RADIOLIB_STANDBY_DEFAULT));
124 : }
125 :
126 0 : int16_t PhysicalLayer::standby(uint8_t mode) {
127 : (void)mode;
128 0 : return(RADIOLIB_ERR_UNSUPPORTED);
129 : }
130 :
131 0 : int16_t PhysicalLayer::startReceive() {
132 0 : return(RADIOLIB_ERR_UNSUPPORTED);
133 : }
134 :
135 32 : int16_t PhysicalLayer::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
136 : RadioModeConfig_t cfg = {
137 : .receive = {
138 : .timeout = timeout,
139 : .irqFlags = irqFlags,
140 : .irqMask = irqMask,
141 : .len = len,
142 : }
143 32 : };
144 :
145 32 : int16_t state = this->stageMode(RADIOLIB_RADIO_MODE_RX, &cfg);
146 32 : RADIOLIB_ASSERT(state);
147 0 : return(this->launchMode());
148 : }
149 :
150 : #if defined(RADIOLIB_BUILD_ARDUINO)
151 : int16_t PhysicalLayer::startTransmit(String& str, uint8_t addr) {
152 : return(startTransmit(str.c_str(), addr));
153 : }
154 : #endif
155 :
156 0 : int16_t PhysicalLayer::startTransmit(const char* str, uint8_t addr) {
157 0 : return(startTransmit(reinterpret_cast<uint8_t*>(const_cast<char*>(str)), strlen(str), addr));
158 : }
159 :
160 16 : int16_t PhysicalLayer::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
161 : RadioModeConfig_t cfg = {
162 : .transmit = {
163 : .data = data,
164 : .len = len,
165 : .addr = addr,
166 : }
167 16 : };
168 :
169 16 : int16_t state = this->stageMode(RADIOLIB_RADIO_MODE_TX, &cfg);
170 16 : RADIOLIB_ASSERT(state);
171 0 : return(this->launchMode());
172 : }
173 :
174 0 : int16_t PhysicalLayer::finishTransmit() {
175 0 : return(RADIOLIB_ERR_UNSUPPORTED);
176 : }
177 :
178 0 : int16_t PhysicalLayer::finishReceive() {
179 0 : return(RADIOLIB_ERR_UNSUPPORTED);
180 : }
181 :
182 : #if defined(RADIOLIB_BUILD_ARDUINO)
183 : int16_t PhysicalLayer::readData(String& str, size_t len) {
184 : int16_t state = RADIOLIB_ERR_NONE;
185 :
186 : // read the number of actually received bytes
187 : size_t length = getPacketLength();
188 :
189 : if((len < length) && (len != 0)) {
190 : // user requested less bytes than were received, this is allowed (but frowned upon)
191 : // requests for more data than were received will only return the number of actually received bytes (unlike PhysicalLayer::receive())
192 : length = len;
193 : }
194 :
195 : // build a temporary buffer
196 : #if RADIOLIB_STATIC_ONLY
197 : uint8_t data[RADIOLIB_STATIC_ARRAY_SIZE + 1];
198 : #else
199 : uint8_t* data = new uint8_t[length + 1];
200 : RADIOLIB_ASSERT_PTR(data);
201 : #endif
202 :
203 : // read the received data
204 : state = readData(data, length);
205 :
206 : // any of the following leads to at least some data being available
207 : // let's leave the decision of whether to keep it or not up to the user
208 : if((state == RADIOLIB_ERR_NONE) || (state == RADIOLIB_ERR_CRC_MISMATCH) || (state == RADIOLIB_ERR_LORA_HEADER_DAMAGED)) {
209 : // add null terminator
210 : data[length] = 0;
211 :
212 : // initialize Arduino String class
213 : str = String(reinterpret_cast<char*>(data));
214 : }
215 :
216 : // deallocate temporary buffer
217 : #if !RADIOLIB_STATIC_ONLY
218 : delete[] data;
219 : #endif
220 :
221 : return(state);
222 : }
223 : #endif
224 :
225 0 : int16_t PhysicalLayer::readData(uint8_t* data, size_t len) {
226 : (void)data;
227 : (void)len;
228 0 : return(RADIOLIB_ERR_UNSUPPORTED);
229 : }
230 :
231 0 : int16_t PhysicalLayer::transmitDirect(uint32_t frf) {
232 : (void)frf;
233 0 : return(RADIOLIB_ERR_UNSUPPORTED);
234 : }
235 :
236 0 : int16_t PhysicalLayer::receiveDirect() {
237 0 : return(RADIOLIB_ERR_UNSUPPORTED);
238 : }
239 :
240 0 : int16_t PhysicalLayer::setFrequency(float freq) {
241 : (void)freq;
242 0 : return(RADIOLIB_ERR_UNSUPPORTED);
243 : }
244 :
245 0 : int16_t PhysicalLayer::setBitRate(float br) {
246 : (void)br;
247 0 : return(RADIOLIB_ERR_UNSUPPORTED);
248 : }
249 :
250 0 : int16_t PhysicalLayer::setFrequencyDeviation(float freqDev) {
251 : (void)freqDev;
252 0 : return(RADIOLIB_ERR_UNSUPPORTED);
253 : }
254 :
255 0 : int16_t PhysicalLayer::setDataShaping(uint8_t sh) {
256 : (void)sh;
257 0 : return(RADIOLIB_ERR_UNSUPPORTED);
258 : }
259 :
260 0 : int16_t PhysicalLayer::setEncoding(uint8_t encoding) {
261 : (void)encoding;
262 0 : return(RADIOLIB_ERR_UNSUPPORTED);
263 : }
264 :
265 0 : int16_t PhysicalLayer::invertIQ(bool enable) {
266 : (void)enable;
267 0 : return(RADIOLIB_ERR_UNSUPPORTED);
268 : }
269 :
270 0 : int16_t PhysicalLayer::setOutputPower(int8_t power) {
271 : (void)power;
272 0 : return(RADIOLIB_ERR_UNSUPPORTED);
273 : }
274 :
275 0 : int16_t PhysicalLayer::checkOutputPower(int8_t power, int8_t* clipped) {
276 : (void)power;
277 : (void)clipped;
278 0 : return(RADIOLIB_ERR_UNSUPPORTED);
279 : }
280 :
281 0 : int16_t PhysicalLayer::setSyncWord(uint8_t* sync, size_t len) {
282 : (void)sync;
283 : (void)len;
284 0 : return(RADIOLIB_ERR_UNSUPPORTED);
285 : }
286 :
287 0 : int16_t PhysicalLayer::setPreambleLength(size_t len) {
288 : (void)len;
289 0 : return(RADIOLIB_ERR_UNSUPPORTED);
290 : }
291 :
292 0 : int16_t PhysicalLayer::setDataRate(DataRate_t dr, ModemType_t modem) {
293 : (void)dr;
294 : (void)modem;
295 0 : return(RADIOLIB_ERR_UNSUPPORTED);
296 : }
297 :
298 0 : int16_t PhysicalLayer::checkDataRate(DataRate_t dr, ModemType_t modem) {
299 : (void)dr;
300 : (void)modem;
301 0 : return(RADIOLIB_ERR_UNSUPPORTED);
302 : }
303 :
304 0 : size_t PhysicalLayer::getPacketLength(bool update) {
305 : (void)update;
306 : // technically this should be returning some unsigned value, not a negative status code
307 : // however, 0 could be misinterpreted in this case
308 : // the value of RADIOLIB_ERR_UNSUPPORTED (-25) when converted to 32-bit unsigned int is 4294967271
309 : // that is conmfortably out of range for any possible packet length
310 0 : return((size_t)RADIOLIB_ERR_UNSUPPORTED);
311 : }
312 :
313 0 : float PhysicalLayer::getRSSI() {
314 0 : return(RADIOLIB_ERR_UNSUPPORTED);
315 : }
316 :
317 0 : float PhysicalLayer::getSNR() {
318 0 : return(RADIOLIB_ERR_UNSUPPORTED);
319 : }
320 :
321 0 : RadioLibTime_t PhysicalLayer::calculateTimeOnAir(ModemType_t modem, DataRate_t dr, PacketConfig_t pc, size_t len) {
322 : (void)modem;
323 : (void)dr;
324 : (void)pc;
325 : (void)len;
326 0 : return(0);
327 : }
328 :
329 0 : RadioLibTime_t PhysicalLayer::getTimeOnAir(size_t len) {
330 : (void)len;
331 0 : return(0);
332 : }
333 :
334 0 : RadioLibTime_t PhysicalLayer::calculateRxTimeout(RadioLibTime_t timeoutUs) {
335 : (void)timeoutUs;
336 0 : return(0);
337 : }
338 :
339 18 : uint32_t PhysicalLayer::getIrqMapped(RadioLibIrqFlags_t irq) {
340 : // iterate over all set bits and build the module-specific flags
341 18 : uint32_t irqRaw = 0;
342 594 : for(uint8_t i = 0; i < 8*(sizeof(RadioLibIrqFlags_t)); i++) {
343 576 : if((irq & (uint32_t)(1UL << i)) && (this->irqMap[i] != RADIOLIB_IRQ_NOT_SUPPORTED)) {
344 60 : irqRaw |= this->irqMap[i];
345 : }
346 : }
347 :
348 18 : return(irqRaw);
349 : }
350 :
351 0 : int16_t PhysicalLayer::checkIrq(RadioLibIrqType_t irq) {
352 0 : if((irq > RADIOLIB_IRQ_TIMEOUT) || (this->irqMap[irq] == RADIOLIB_IRQ_NOT_SUPPORTED)) {
353 0 : return(RADIOLIB_ERR_UNSUPPORTED);
354 : }
355 :
356 0 : return((getIrqFlags() & this->irqMap[irq]) != 0);
357 : }
358 :
359 0 : int16_t PhysicalLayer::setIrq(RadioLibIrqFlags_t irq) {
360 0 : return(setIrqFlags(getIrqMapped(irq)));
361 : }
362 :
363 0 : int16_t PhysicalLayer::clearIrq(RadioLibIrqFlags_t irq) {
364 0 : return(clearIrqFlags(getIrqMapped(irq)));
365 : }
366 :
367 0 : uint32_t PhysicalLayer::getIrqFlags() {
368 0 : return(RADIOLIB_ERR_UNSUPPORTED);
369 : }
370 :
371 0 : int16_t PhysicalLayer::setIrqFlags(uint32_t irq) {
372 : (void)irq;
373 0 : return(RADIOLIB_ERR_UNSUPPORTED);
374 : }
375 :
376 0 : int16_t PhysicalLayer::clearIrqFlags(uint32_t irq) {
377 : (void)irq;
378 0 : return(RADIOLIB_ERR_UNSUPPORTED);
379 : }
380 :
381 0 : int16_t PhysicalLayer::startChannelScan() {
382 0 : return(RADIOLIB_ERR_UNSUPPORTED);
383 : }
384 :
385 0 : int16_t PhysicalLayer::startChannelScan(const ChannelScanConfig_t &config) {
386 : (void)config;
387 0 : return(RADIOLIB_ERR_UNSUPPORTED);
388 : }
389 :
390 0 : int16_t PhysicalLayer::getChannelScanResult() {
391 0 : return(RADIOLIB_ERR_UNSUPPORTED);
392 : }
393 :
394 0 : int16_t PhysicalLayer::scanChannel() {
395 0 : return(RADIOLIB_ERR_UNSUPPORTED);
396 : }
397 :
398 0 : int16_t PhysicalLayer::scanChannel(const ChannelScanConfig_t &config) {
399 : (void)config;
400 0 : return(RADIOLIB_ERR_UNSUPPORTED);
401 : }
402 :
403 0 : int32_t PhysicalLayer::random(int32_t max) {
404 0 : if(max == 0) {
405 0 : return(0);
406 : }
407 :
408 : // get random bytes from the radio
409 : uint8_t randBuff[4];
410 0 : for(uint8_t i = 0; i < 4; i++) {
411 0 : randBuff[i] = randomByte();
412 : }
413 :
414 : // create 32-bit TRNG number
415 0 : int32_t randNum = ((int32_t)randBuff[0] << 24) | ((int32_t)randBuff[1] << 16) | ((int32_t)randBuff[2] << 8) | ((int32_t)randBuff[3]);
416 0 : if(randNum < 0) {
417 0 : randNum *= -1;
418 : }
419 0 : return(randNum % max);
420 : }
421 :
422 0 : int32_t PhysicalLayer::random(int32_t min, int32_t max) {
423 0 : if(min >= max) {
424 0 : return(min);
425 : }
426 :
427 0 : return(PhysicalLayer::random(max - min) + min);
428 : }
429 :
430 0 : uint8_t PhysicalLayer::randomByte() {
431 0 : return(0);
432 : }
433 :
434 0 : int16_t PhysicalLayer::startDirect() {
435 : // disable encodings
436 0 : int16_t state = setEncoding(RADIOLIB_ENCODING_NRZ);
437 0 : RADIOLIB_ASSERT(state);
438 :
439 : // disable shaping
440 0 : state = setDataShaping(RADIOLIB_SHAPING_NONE);
441 0 : RADIOLIB_ASSERT(state);
442 :
443 : // set frequency deviation to the lowest possible value
444 0 : state = setFrequencyDeviation(-1);
445 0 : return(state);
446 : }
447 :
448 : #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
449 0 : int16_t PhysicalLayer::available() {
450 0 : return(this->bufferWritePos);
451 : }
452 :
453 0 : void PhysicalLayer::dropSync() {
454 0 : if(this->directSyncWordLen > 0) {
455 0 : this->gotSync = false;
456 0 : this->syncBuffer = 0;
457 : }
458 0 : }
459 :
460 0 : uint8_t PhysicalLayer::read(bool drop) {
461 0 : if(drop) {
462 0 : dropSync();
463 : }
464 0 : this->bufferWritePos--;
465 0 : return(this->buffer[this->bufferReadPos++]);
466 : }
467 :
468 0 : int16_t PhysicalLayer::setDirectSyncWord(uint32_t syncWord, uint8_t len) {
469 0 : if(len > 32) {
470 0 : return(RADIOLIB_ERR_INVALID_SYNC_WORD);
471 : }
472 0 : this->directSyncWordMask = 0xFFFFFFFF >> (32 - len);
473 0 : this->directSyncWordLen = len;
474 0 : this->directSyncWord = syncWord;
475 :
476 : // override sync word matching when length is set to 0
477 0 : if(this->directSyncWordLen == 0) {
478 0 : this->gotSync = true;
479 : }
480 :
481 0 : return(RADIOLIB_ERR_NONE);
482 : }
483 :
484 0 : void PhysicalLayer::updateDirectBuffer(uint8_t bit) {
485 : // check sync word
486 0 : if(!this->gotSync) {
487 0 : this->syncBuffer <<= 1;
488 0 : this->syncBuffer |= bit;
489 :
490 : RADIOLIB_DEBUG_PROTOCOL_PRINTLN("S\t%lu", (long unsigned int)this->syncBuffer);
491 :
492 0 : if((this->syncBuffer & this->directSyncWordMask) == this->directSyncWord) {
493 0 : this->gotSync = true;
494 0 : this->bufferWritePos = 0;
495 0 : this->bufferReadPos = 0;
496 0 : this->bufferBitPos = 0;
497 : }
498 :
499 : } else {
500 : // save the bit
501 0 : if(bit) {
502 0 : this->buffer[this->bufferWritePos] |= 0x01 << this->bufferBitPos;
503 : } else {
504 0 : this->buffer[this->bufferWritePos] &= ~(0x01 << this->bufferBitPos);
505 : }
506 0 : this->bufferBitPos++;
507 :
508 : // check complete byte
509 0 : if(this->bufferBitPos == 8) {
510 0 : this->buffer[this->bufferWritePos] = rlb_reflect(this->buffer[this->bufferWritePos], 8);
511 : RADIOLIB_DEBUG_PROTOCOL_PRINTLN("R\t%X", this->buffer[this->bufferWritePos]);
512 :
513 0 : this->bufferWritePos++;
514 0 : this->bufferBitPos = 0;
515 : }
516 : }
517 0 : }
518 :
519 0 : void PhysicalLayer::setDirectAction(void (*func)(void)) {
520 : (void)func;
521 0 : }
522 :
523 0 : void PhysicalLayer::readBit(uint32_t pin) {
524 : (void)pin;
525 0 : }
526 :
527 : #endif
528 :
529 0 : void PhysicalLayer::setIrqAction(void (*func)(void), bool rising) {
530 0 : Module* mod = getMod();
531 0 : mod->hal->attachInterrupt(mod->hal->pinToInterrupt(mod->getIrq()), func,
532 0 : rising ? mod->hal->GpioInterruptRising : mod->hal->GpioInterruptFalling);
533 0 : }
534 :
535 0 : void PhysicalLayer::clearIrqAction() {
536 0 : Module* mod = getMod();
537 0 : mod->hal->detachInterrupt(mod->hal->pinToInterrupt(mod->getIrq()));
538 0 : }
539 :
540 0 : void PhysicalLayer::setPacketReceivedAction(void (*func)(void)) {
541 : (void)func;
542 0 : }
543 :
544 0 : void PhysicalLayer::clearPacketReceivedAction() {
545 :
546 0 : }
547 :
548 0 : void PhysicalLayer::setPacketSentAction(void (*func)(void)) {
549 : (void)func;
550 0 : }
551 :
552 0 : void PhysicalLayer::clearPacketSentAction() {
553 :
554 0 : }
555 :
556 0 : void PhysicalLayer::setChannelScanAction(void (*func)(void)) {
557 : (void)func;
558 0 : }
559 :
560 0 : void PhysicalLayer::clearChannelScanAction() {
561 :
562 0 : }
563 :
564 0 : int16_t PhysicalLayer::setModem(ModemType_t modem) {
565 : (void)modem;
566 0 : return(RADIOLIB_ERR_UNSUPPORTED);
567 : }
568 :
569 0 : int16_t PhysicalLayer::getModem(ModemType_t* modem) {
570 : (void)modem;
571 0 : return(RADIOLIB_ERR_UNSUPPORTED);
572 : }
573 :
574 0 : int16_t PhysicalLayer::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
575 : (void)mode;
576 : (void)cfg;
577 0 : return(RADIOLIB_ERR_UNSUPPORTED);
578 : }
579 :
580 0 : int16_t PhysicalLayer::launchMode() {
581 0 : return(RADIOLIB_ERR_UNSUPPORTED);
582 : }
583 :
584 0 : int16_t PhysicalLayer::writeTxBuffer(const uint8_t* data, size_t len) {
585 : (void)data;
586 : (void)len;
587 0 : return(RADIOLIB_ERR_UNSUPPORTED);
588 : }
589 :
590 0 : int16_t PhysicalLayer::clearTxBuffer() {
591 0 : return(RADIOLIB_ERR_UNSUPPORTED);
592 : }
593 :
594 : #if RADIOLIB_INTERRUPT_TIMING
595 : void PhysicalLayer::setInterruptSetup(void (*func)(uint32_t)) {
596 : Module* mod = getMod();
597 : mod->TimerSetupCb = func;
598 : }
599 :
600 : void PhysicalLayer::setTimerFlag() {
601 : Module* mod = getMod();
602 : mod->TimerFlag = true;
603 : }
604 : #endif
605 :
606 0 : int16_t PhysicalLayer::calculateRxDutyCycle(size_t txPreLen, size_t rxPreLen, uint16_t minSymbols, DataRate_t* dr, uint32_t* wakePeriod, uint32_t* sleepPeriod) {
607 0 : RADIOLIB_ASSERT_PTR(dr);
608 0 : RADIOLIB_ASSERT_PTR(wakePeriod);
609 0 : RADIOLIB_ASSERT_PTR(sleepPeriod);
610 :
611 0 : uint16_t senderPreambleLength = txPreLen;
612 0 : if(senderPreambleLength == 0) {
613 0 : senderPreambleLength = rxPreLen;
614 0 : } else if(senderPreambleLength > rxPreLen) {
615 : // the unit must be configured to expect a preamble length at least as long as the sender is using
616 0 : return(RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH);
617 : }
618 0 : if(minSymbols == 0) {
619 0 : if(dr->lora.spreadingFactor <= 6) {
620 0 : minSymbols = 12;
621 : } else {
622 0 : minSymbols = 8;
623 : }
624 : }
625 :
626 : // if we're not to sleep at all, just use the standard startReceive
627 0 : if(2 * minSymbols > senderPreambleLength) {
628 0 : *sleepPeriod = 0;
629 : RADIOLIB_DEBUG_BASIC_PRINTLN("Auto sleep period too short");
630 0 : return(RADIOLIB_ERR_NONE);
631 : }
632 :
633 : // worst case is that the sender starts transmitting when we're just less than minSymbols from going back to sleep.
634 : // in this case, we don't catch minSymbols before going to sleep,
635 : // so we must be awake for at least that long before the sender stops transmitting.
636 0 : uint16_t sleepSymbols = senderPreambleLength - 2 * minSymbols;
637 :
638 0 : uint32_t symbolLength = ((uint32_t)(10 * 1000) << dr->lora.spreadingFactor) / (10 * dr->lora.bandwidth);
639 0 : *sleepPeriod = symbolLength * sleepSymbols;
640 : RADIOLIB_DEBUG_BASIC_PRINTLN("Auto sleep period: %lu", (long unsigned int)*sleepPeriod);
641 :
642 : // when the unit detects a preamble, it starts a timer that will timeout if it doesn't receive a header in time.
643 : // the duration is sleepPeriod + 2 * wakePeriod.
644 : // The sleepPeriod doesn't take into account shutdown and startup time for the unit (~1ms)
645 : // We need to ensure that the timeout is longer than senderPreambleLength.
646 : // So we must satisfy: wakePeriod > (preamblePeriod - (sleepPeriod - 1000)) / 2. (A)
647 : // we also need to ensure the unit is awake to see at least minSymbols. (B)
648 0 : *wakePeriod = RADIOLIB_MAX(
649 : (symbolLength * (senderPreambleLength + 1) - (*sleepPeriod - 1000)) / 2, // (A)
650 : symbolLength * (minSymbols + 1)); //(B)
651 : RADIOLIB_DEBUG_BASIC_PRINTLN("Auto wake period: %lu", (long unsigned int)*wakePeriod);
652 :
653 0 : return(RADIOLIB_ERR_NONE);
654 : }
|