Line data Source code
1 : #include "PhysicalLayer.h"
2 :
3 : #include <string.h>
4 :
5 50 : PhysicalLayer::PhysicalLayer() {
6 50 : this->freqStep = 1;
7 50 : this->maxPacketLength = 1;
8 : #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
9 50 : this->bufferBitPos = 0;
10 50 : this->bufferWritePos = 0;
11 : #endif
12 50 : }
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 0 : 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 0 : };
144 :
145 0 : int16_t state = this->stageMode(RADIOLIB_RADIO_MODE_RX, &cfg);
146 0 : 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 0 : 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 0 : };
168 :
169 0 : int16_t state = this->stageMode(RADIOLIB_RADIO_MODE_TX, &cfg);
170 0 : 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 0 : return(0);
307 : }
308 :
309 0 : float PhysicalLayer::getRSSI() {
310 0 : return(RADIOLIB_ERR_UNSUPPORTED);
311 : }
312 :
313 0 : float PhysicalLayer::getSNR() {
314 0 : return(RADIOLIB_ERR_UNSUPPORTED);
315 : }
316 :
317 0 : RadioLibTime_t PhysicalLayer::calculateTimeOnAir(ModemType_t modem, DataRate_t dr, PacketConfig_t pc, size_t len) {
318 : (void)modem;
319 : (void)dr;
320 : (void)pc;
321 : (void)len;
322 0 : return(0);
323 : }
324 :
325 0 : RadioLibTime_t PhysicalLayer::getTimeOnAir(size_t len) {
326 : (void)len;
327 0 : return(0);
328 : }
329 :
330 0 : RadioLibTime_t PhysicalLayer::calculateRxTimeout(RadioLibTime_t timeoutUs) {
331 : (void)timeoutUs;
332 0 : return(0);
333 : }
334 :
335 0 : uint32_t PhysicalLayer::getIrqMapped(RadioLibIrqFlags_t irq) {
336 : // iterate over all set bits and build the module-specific flags
337 0 : uint32_t irqRaw = 0;
338 0 : for(uint8_t i = 0; i < 8*(sizeof(RadioLibIrqFlags_t)); i++) {
339 0 : if((irq & (uint32_t)(1UL << i)) && (this->irqMap[i] != RADIOLIB_IRQ_NOT_SUPPORTED)) {
340 0 : irqRaw |= this->irqMap[i];
341 : }
342 : }
343 :
344 0 : return(irqRaw);
345 : }
346 :
347 0 : int16_t PhysicalLayer::checkIrq(RadioLibIrqType_t irq) {
348 0 : if((irq > RADIOLIB_IRQ_TIMEOUT) || (this->irqMap[irq] == RADIOLIB_IRQ_NOT_SUPPORTED)) {
349 0 : return(RADIOLIB_ERR_UNSUPPORTED);
350 : }
351 :
352 0 : return(getIrqFlags() & this->irqMap[irq]);
353 : }
354 :
355 0 : int16_t PhysicalLayer::setIrq(RadioLibIrqFlags_t irq) {
356 0 : return(setIrqFlags(getIrqMapped(irq)));
357 : }
358 :
359 0 : int16_t PhysicalLayer::clearIrq(RadioLibIrqFlags_t irq) {
360 0 : return(clearIrqFlags(getIrqMapped(irq)));
361 : }
362 :
363 0 : uint32_t PhysicalLayer::getIrqFlags() {
364 0 : return(RADIOLIB_ERR_UNSUPPORTED);
365 : }
366 :
367 0 : int16_t PhysicalLayer::setIrqFlags(uint32_t irq) {
368 : (void)irq;
369 0 : return(RADIOLIB_ERR_UNSUPPORTED);
370 : }
371 :
372 0 : int16_t PhysicalLayer::clearIrqFlags(uint32_t irq) {
373 : (void)irq;
374 0 : return(RADIOLIB_ERR_UNSUPPORTED);
375 : }
376 :
377 0 : int16_t PhysicalLayer::startChannelScan() {
378 0 : return(RADIOLIB_ERR_UNSUPPORTED);
379 : }
380 :
381 0 : int16_t PhysicalLayer::startChannelScan(const ChannelScanConfig_t &config) {
382 : (void)config;
383 0 : return(RADIOLIB_ERR_UNSUPPORTED);
384 : }
385 :
386 0 : int16_t PhysicalLayer::getChannelScanResult() {
387 0 : return(RADIOLIB_ERR_UNSUPPORTED);
388 : }
389 :
390 0 : int16_t PhysicalLayer::scanChannel() {
391 0 : return(RADIOLIB_ERR_UNSUPPORTED);
392 : }
393 :
394 0 : int16_t PhysicalLayer::scanChannel(const ChannelScanConfig_t &config) {
395 : (void)config;
396 0 : return(RADIOLIB_ERR_UNSUPPORTED);
397 : }
398 :
399 0 : int32_t PhysicalLayer::random(int32_t max) {
400 0 : if(max == 0) {
401 0 : return(0);
402 : }
403 :
404 : // get random bytes from the radio
405 : uint8_t randBuff[4];
406 0 : for(uint8_t i = 0; i < 4; i++) {
407 0 : randBuff[i] = randomByte();
408 : }
409 :
410 : // create 32-bit TRNG number
411 0 : int32_t randNum = ((int32_t)randBuff[0] << 24) | ((int32_t)randBuff[1] << 16) | ((int32_t)randBuff[2] << 8) | ((int32_t)randBuff[3]);
412 0 : if(randNum < 0) {
413 0 : randNum *= -1;
414 : }
415 0 : return(randNum % max);
416 : }
417 :
418 0 : int32_t PhysicalLayer::random(int32_t min, int32_t max) {
419 0 : if(min >= max) {
420 0 : return(min);
421 : }
422 :
423 0 : return(PhysicalLayer::random(max - min) + min);
424 : }
425 :
426 0 : uint8_t PhysicalLayer::randomByte() {
427 0 : return(0);
428 : }
429 :
430 0 : int16_t PhysicalLayer::startDirect() {
431 : // disable encodings
432 0 : int16_t state = setEncoding(RADIOLIB_ENCODING_NRZ);
433 0 : RADIOLIB_ASSERT(state);
434 :
435 : // disable shaping
436 0 : state = setDataShaping(RADIOLIB_SHAPING_NONE);
437 0 : RADIOLIB_ASSERT(state);
438 :
439 : // set frequency deviation to the lowest possible value
440 0 : state = setFrequencyDeviation(-1);
441 0 : return(state);
442 : }
443 :
444 : #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
445 0 : int16_t PhysicalLayer::available() {
446 0 : return(this->bufferWritePos);
447 : }
448 :
449 0 : void PhysicalLayer::dropSync() {
450 0 : if(this->directSyncWordLen > 0) {
451 0 : this->gotSync = false;
452 0 : this->syncBuffer = 0;
453 : }
454 0 : }
455 :
456 0 : uint8_t PhysicalLayer::read(bool drop) {
457 0 : if(drop) {
458 0 : dropSync();
459 : }
460 0 : this->bufferWritePos--;
461 0 : return(this->buffer[this->bufferReadPos++]);
462 : }
463 :
464 0 : int16_t PhysicalLayer::setDirectSyncWord(uint32_t syncWord, uint8_t len) {
465 0 : if(len > 32) {
466 0 : return(RADIOLIB_ERR_INVALID_SYNC_WORD);
467 : }
468 0 : this->directSyncWordMask = 0xFFFFFFFF >> (32 - len);
469 0 : this->directSyncWordLen = len;
470 0 : this->directSyncWord = syncWord;
471 :
472 : // override sync word matching when length is set to 0
473 0 : if(this->directSyncWordLen == 0) {
474 0 : this->gotSync = true;
475 : }
476 :
477 0 : return(RADIOLIB_ERR_NONE);
478 : }
479 :
480 0 : void PhysicalLayer::updateDirectBuffer(uint8_t bit) {
481 : // check sync word
482 0 : if(!this->gotSync) {
483 0 : this->syncBuffer <<= 1;
484 0 : this->syncBuffer |= bit;
485 :
486 : RADIOLIB_DEBUG_PROTOCOL_PRINTLN("S\t%lu", (long unsigned int)this->syncBuffer);
487 :
488 0 : if((this->syncBuffer & this->directSyncWordMask) == this->directSyncWord) {
489 0 : this->gotSync = true;
490 0 : this->bufferWritePos = 0;
491 0 : this->bufferReadPos = 0;
492 0 : this->bufferBitPos = 0;
493 : }
494 :
495 : } else {
496 : // save the bit
497 0 : if(bit) {
498 0 : this->buffer[this->bufferWritePos] |= 0x01 << this->bufferBitPos;
499 : } else {
500 0 : this->buffer[this->bufferWritePos] &= ~(0x01 << this->bufferBitPos);
501 : }
502 0 : this->bufferBitPos++;
503 :
504 : // check complete byte
505 0 : if(this->bufferBitPos == 8) {
506 0 : this->buffer[this->bufferWritePos] = rlb_reflect(this->buffer[this->bufferWritePos], 8);
507 : RADIOLIB_DEBUG_PROTOCOL_PRINTLN("R\t%X", this->buffer[this->bufferWritePos]);
508 :
509 0 : this->bufferWritePos++;
510 0 : this->bufferBitPos = 0;
511 : }
512 : }
513 0 : }
514 :
515 0 : void PhysicalLayer::setDirectAction(void (*func)(void)) {
516 : (void)func;
517 0 : }
518 :
519 0 : void PhysicalLayer::readBit(uint32_t pin) {
520 : (void)pin;
521 0 : }
522 :
523 : #endif
524 :
525 0 : int16_t PhysicalLayer::setDIOMapping(uint32_t pin, uint32_t value) {
526 : (void)pin;
527 : (void)value;
528 0 : return(RADIOLIB_ERR_UNSUPPORTED);
529 : }
530 :
531 0 : void PhysicalLayer::setPacketReceivedAction(void (*func)(void)) {
532 : (void)func;
533 0 : }
534 :
535 0 : void PhysicalLayer::clearPacketReceivedAction() {
536 :
537 0 : }
538 :
539 0 : void PhysicalLayer::setPacketSentAction(void (*func)(void)) {
540 : (void)func;
541 0 : }
542 :
543 0 : void PhysicalLayer::clearPacketSentAction() {
544 :
545 0 : }
546 :
547 0 : void PhysicalLayer::setChannelScanAction(void (*func)(void)) {
548 : (void)func;
549 0 : }
550 :
551 0 : void PhysicalLayer::clearChannelScanAction() {
552 :
553 0 : }
554 :
555 0 : int16_t PhysicalLayer::setModem(ModemType_t modem) {
556 : (void)modem;
557 0 : return(RADIOLIB_ERR_UNSUPPORTED);
558 : }
559 :
560 0 : int16_t PhysicalLayer::getModem(ModemType_t* modem) {
561 : (void)modem;
562 0 : return(RADIOLIB_ERR_UNSUPPORTED);
563 : }
564 :
565 0 : int16_t PhysicalLayer::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
566 : (void)mode;
567 : (void)cfg;
568 0 : return(RADIOLIB_ERR_UNSUPPORTED);
569 : }
570 :
571 0 : int16_t PhysicalLayer::launchMode() {
572 0 : return(RADIOLIB_ERR_UNSUPPORTED);
573 : }
574 :
575 : #if RADIOLIB_INTERRUPT_TIMING
576 : void PhysicalLayer::setInterruptSetup(void (*func)(uint32_t)) {
577 : Module* mod = getMod();
578 : mod->TimerSetupCb = func;
579 : }
580 :
581 : void PhysicalLayer::setTimerFlag() {
582 : Module* mod = getMod();
583 : mod->TimerFlag = true;
584 : }
585 : #endif
|