Line data Source code
1 : #include "LR2021.h"
2 :
3 : #include <string.h>
4 : #include <math.h>
5 :
6 : #if !RADIOLIB_EXCLUDE_LR2021
7 :
8 1 : LR2021::LR2021(Module* mod) : LRxxxx(mod) {
9 1 : this->freqStep = RADIOLIB_LR2021_FREQUENCY_STEP_SIZE;
10 1 : this->maxPacketLength = RADIOLIB_LR2021_MAX_PACKET_LENGTH;
11 1 : this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_LR2021_IRQ_TX_DONE;
12 1 : this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_LR2021_IRQ_RX_DONE;
13 1 : this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED;
14 1 : this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID;
15 1 : this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID;
16 1 : this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_LR2021_IRQ_LORA_HDR_CRC_ERROR;
17 1 : this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_LR2021_IRQ_CRC_ERROR;
18 1 : this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_LR2021_IRQ_CAD_DONE;
19 1 : this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_LR2021_IRQ_CAD_DETECTED;
20 1 : this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_LR2021_IRQ_TIMEOUT;
21 1 : }
22 :
23 0 : int16_t LR2021::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
24 : // set module properties and perform initial setup
25 0 : int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_LORA);
26 0 : RADIOLIB_ASSERT(state);
27 :
28 : // configure publicly accessible settings
29 0 : state = setBandwidth(bw);
30 0 : RADIOLIB_ASSERT(state);
31 :
32 0 : state = setSpreadingFactor(sf);
33 0 : RADIOLIB_ASSERT(state);
34 :
35 0 : state = setCodingRate(cr);
36 0 : RADIOLIB_ASSERT(state);
37 :
38 0 : state = setSyncWord(syncWord);
39 0 : RADIOLIB_ASSERT(state);
40 :
41 0 : state = setOutputPower(power);
42 0 : RADIOLIB_ASSERT(state);
43 :
44 0 : state = setPreambleLength(preambleLength);
45 0 : RADIOLIB_ASSERT(state);
46 :
47 : // set publicly accessible settings that are not a part of begin method
48 0 : state = setCRC(2);
49 0 : RADIOLIB_ASSERT(state);
50 :
51 0 : state = invertIQ(false);
52 0 : return(state);
53 : }
54 :
55 0 : int16_t LR2021::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
56 0 : this->rxBandwidth = RADIOLIB_LR2021_GFSK_OOK_RX_BW_153_8;
57 0 : this->frequencyDev = freqDev * 1000.0f;
58 :
59 : // set module properties and perform initial setup
60 0 : int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_GFSK);
61 0 : RADIOLIB_ASSERT(state);
62 :
63 : // configure publicly accessible settings
64 0 : state = setBitRate(br);
65 0 : RADIOLIB_ASSERT(state);
66 :
67 0 : state = setFrequencyDeviation(freqDev);
68 0 : RADIOLIB_ASSERT(state);
69 :
70 0 : state = setRxBandwidth(rxBw);
71 0 : RADIOLIB_ASSERT(state);
72 :
73 0 : state = setOutputPower(power);
74 0 : RADIOLIB_ASSERT(state);
75 :
76 0 : state = setPreambleLength(preambleLength);
77 0 : RADIOLIB_ASSERT(state);
78 :
79 : // set publicly accessible settings that are not a part of begin method
80 0 : uint8_t sync[] = { 0x12, 0xAD };
81 0 : state = setSyncWord(sync, 2);
82 0 : RADIOLIB_ASSERT(state);
83 :
84 0 : state = setDataShaping(RADIOLIB_SHAPING_NONE);
85 0 : RADIOLIB_ASSERT(state);
86 :
87 0 : state = setEncoding(RADIOLIB_ENCODING_NRZ);
88 0 : RADIOLIB_ASSERT(state);
89 :
90 0 : state = variablePacketLengthMode(RADIOLIB_LR2021_MAX_PACKET_LENGTH);
91 0 : RADIOLIB_ASSERT(state);
92 :
93 0 : state = setCRC(2);
94 0 : return(state);
95 : }
96 :
97 0 : int16_t LR2021::beginOOK(float freq, float br, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
98 0 : this->rxBandwidth = RADIOLIB_LR2021_GFSK_OOK_RX_BW_153_8;
99 :
100 : // set module properties and perform initial setup
101 0 : int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_OOK);
102 0 : RADIOLIB_ASSERT(state);
103 :
104 : // configure publicly accessible settings
105 0 : state = setBitRate(br);
106 0 : RADIOLIB_ASSERT(state);
107 :
108 0 : state = setRxBandwidth(rxBw);
109 0 : RADIOLIB_ASSERT(state);
110 :
111 0 : state = setOutputPower(power);
112 0 : RADIOLIB_ASSERT(state);
113 :
114 0 : state = setPreambleLength(preambleLength);
115 0 : RADIOLIB_ASSERT(state);
116 :
117 : // set publicly accessible settings that are not a part of begin method
118 0 : uint8_t sync[] = { 0x12, 0xAD };
119 0 : state = setSyncWord(sync, 2);
120 0 : RADIOLIB_ASSERT(state);
121 :
122 0 : state = setDataShaping(RADIOLIB_SHAPING_NONE);
123 0 : RADIOLIB_ASSERT(state);
124 :
125 0 : state = setEncoding(RADIOLIB_ENCODING_NRZ);
126 0 : RADIOLIB_ASSERT(state);
127 :
128 0 : state = variablePacketLengthMode(RADIOLIB_LR2021_MAX_PACKET_LENGTH);
129 0 : RADIOLIB_ASSERT(state);
130 :
131 0 : state = setCRC(2);
132 0 : return(state);
133 : }
134 :
135 0 : int16_t LR2021::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, int8_t power, float tcxoVoltage) {
136 : // set module properties and perform initial setup
137 0 : int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS);
138 0 : RADIOLIB_ASSERT(state);
139 :
140 : // set grid spacing
141 0 : this->lrFhssGrid = narrowGrid ? RADIOLIB_LRXXXX_LR_FHSS_GRID_STEP_NON_FCC : RADIOLIB_LRXXXX_LR_FHSS_GRID_STEP_FCC;
142 :
143 : // configure publicly accessible settings
144 0 : state = setLrFhssConfig(bw, cr);
145 0 : RADIOLIB_ASSERT(state);
146 :
147 0 : state = setOutputPower(power);
148 0 : RADIOLIB_ASSERT(state);
149 :
150 0 : uint8_t syncWord[] = { 0x12, 0xAD, 0x10, 0x1B };
151 0 : state = setSyncWord(syncWord, 4);
152 0 : return(state);
153 : }
154 :
155 0 : int16_t LR2021::beginFLRC(float freq, uint16_t br, uint8_t cr, int8_t pwr, uint16_t preambleLength, uint8_t dataShaping, float tcxoVoltage) {
156 : // initialize FLRC modulation variables
157 0 : this->bitRateFlrc = br;
158 0 : this->codingRateFlrc = RADIOLIB_LR2021_FLRC_CR_3_4;
159 0 : this->pulseShape = RADIOLIB_LR2021_GFSK_BPSK_FLRC_OOK_SHAPING_GAUSS_BT_0_5;
160 :
161 : // initialize FLRC packet variables
162 0 : this->preambleLengthGFSK = preambleLength;
163 0 : this->crcLenGFSK = 1;
164 :
165 : // set module properties and perform initial setup
166 0 : int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_FLRC);
167 0 : RADIOLIB_ASSERT(state);
168 :
169 : // configure publicly accessible settings
170 0 : state = setFrequency(freq);
171 0 : RADIOLIB_ASSERT(state);
172 :
173 0 : state = setBitRate(br);
174 0 : RADIOLIB_ASSERT(state);
175 :
176 0 : state = setCodingRate(cr);
177 0 : RADIOLIB_ASSERT(state);
178 :
179 0 : state = setOutputPower(pwr);
180 0 : RADIOLIB_ASSERT(state);
181 :
182 0 : state = setPreambleLength(preambleLength);
183 0 : RADIOLIB_ASSERT(state);
184 :
185 0 : state = setDataShaping(dataShaping);
186 0 : RADIOLIB_ASSERT(state);
187 :
188 : // set publicly accessible settings that are not a part of begin method
189 0 : uint8_t sync[] = { 0x2D, 0x01, 0x4B, 0x1D};
190 0 : state = setSyncWord(sync, 4);
191 0 : RADIOLIB_ASSERT(state);
192 :
193 0 : state = variablePacketLengthMode(RADIOLIB_LR2021_MAX_PACKET_LENGTH);
194 0 : RADIOLIB_ASSERT(state);
195 :
196 0 : state = setCRC(2);
197 0 : return(state);
198 : }
199 :
200 1 : int16_t LR2021::transmit(const uint8_t* data, size_t len, uint8_t addr) {
201 : // set mode to standby
202 1 : int16_t state = standby();
203 1 : RADIOLIB_ASSERT(state);
204 :
205 : // check packet length
206 0 : if (this->codingRate > RADIOLIB_LR2021_LORA_CR_4_8) {
207 : // Long Interleaver needs at least 8 bytes
208 0 : if(len < 8) {
209 0 : return(RADIOLIB_ERR_PACKET_TOO_SHORT);
210 : }
211 :
212 : // Long Interleaver supports up to 253 bytes if CRC is enabled
213 0 : if (this->crcTypeLoRa == RADIOLIB_LR2021_LORA_CRC_ENABLED && (len > RADIOLIB_LR2021_MAX_PACKET_LENGTH - 2)) {
214 0 : return(RADIOLIB_ERR_PACKET_TOO_LONG);
215 : }
216 : }
217 0 : if(len > RADIOLIB_LR2021_MAX_PACKET_LENGTH) {
218 0 : return(RADIOLIB_ERR_PACKET_TOO_LONG);
219 : }
220 :
221 : // get currently active modem
222 0 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
223 0 : state = getPacketType(&modem);
224 0 : RADIOLIB_ASSERT(state);
225 0 : RadioLibTime_t timeout = getTimeOnAir(len);
226 0 : if(modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) {
227 : // calculate timeout (150% of expected time-on-air)
228 0 : timeout = (timeout * 3) / 2;
229 :
230 0 : } else if((modem == RADIOLIB_LR2021_PACKET_TYPE_GFSK) ||
231 0 : (modem == RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS) ||
232 0 : (modem == RADIOLIB_LR2021_PACKET_TYPE_FLRC) ||
233 0 : (modem == RADIOLIB_LR2021_PACKET_TYPE_OOK)) {
234 : // calculate timeout (500% of expected time-on-air)
235 0 : timeout = timeout * 5;
236 :
237 : } else {
238 0 : return(RADIOLIB_ERR_WRONG_MODEM);
239 : }
240 :
241 : RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu us", timeout);
242 :
243 : // start transmission
244 0 : state = startTransmit(data, len, addr);
245 0 : RADIOLIB_ASSERT(state);
246 :
247 : // wait for packet transmission or timeout
248 0 : RadioLibTime_t start = this->mod->hal->micros();
249 0 : while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
250 0 : this->mod->hal->yield();
251 0 : if(this->mod->hal->micros() - start > timeout) {
252 0 : finishTransmit();
253 0 : return(RADIOLIB_ERR_TX_TIMEOUT);
254 : }
255 : }
256 :
257 0 : return(finishTransmit());
258 : }
259 :
260 1 : int16_t LR2021::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
261 : // set mode to standby
262 1 : int16_t state = standby();
263 1 : RADIOLIB_ASSERT(state);
264 :
265 : // calculate timeout based on the configured modem
266 0 : RadioLibTime_t timeoutInternal = timeout;
267 0 : if(!timeoutInternal) {
268 : // get currently active modem
269 0 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
270 0 : state = getPacketType(&modem);
271 0 : RADIOLIB_ASSERT(state);
272 0 : if((modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) ||
273 0 : (modem == RADIOLIB_LR2021_PACKET_TYPE_GFSK) ||
274 0 : (modem == RADIOLIB_LR2021_PACKET_TYPE_FLRC) ||
275 0 : (modem == RADIOLIB_LR2021_PACKET_TYPE_OOK)) {
276 : // calculate timeout (500 % of expected time-one-air)
277 0 : size_t maxLen = len;
278 0 : if(len == 0) { maxLen = RADIOLIB_LR2021_MAX_PACKET_LENGTH; }
279 0 : timeoutInternal = (getTimeOnAir(maxLen) * 5) / 1000;
280 :
281 0 : } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS) {
282 : // this modem cannot receive
283 0 : return(RADIOLIB_ERR_WRONG_MODEM);
284 :
285 : } else {
286 0 : return(RADIOLIB_ERR_UNKNOWN);
287 :
288 : }
289 : }
290 :
291 : RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeoutInternal);
292 :
293 : // start reception
294 0 : uint32_t timeoutValue = (uint32_t)(((float)timeoutInternal * 1000.0f) / 30.52f);
295 0 : state = startReceive(timeoutValue);
296 0 : RADIOLIB_ASSERT(state);
297 :
298 : // wait for packet reception or timeout
299 0 : bool softTimeout = false;
300 0 : RadioLibTime_t start = this->mod->hal->millis();
301 0 : while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
302 0 : this->mod->hal->yield();
303 : // safety check, the timeout should be done by the radio
304 0 : if(this->mod->hal->millis() - start > timeoutInternal) {
305 0 : softTimeout = true;
306 0 : break;
307 : }
308 : }
309 :
310 : // if it was a timeout, this will return an error code
311 : //! \TODO: [LR2021] taken from SX126x, does this really work?
312 0 : state = standby();
313 0 : if((state != RADIOLIB_ERR_NONE) && (state != RADIOLIB_ERR_SPI_CMD_TIMEOUT)) {
314 0 : return(state);
315 : }
316 :
317 : // check whether this was a timeout or not
318 0 : if(softTimeout || (getIrqFlags() & this->irqMap[RADIOLIB_IRQ_TIMEOUT])) {
319 0 : (void)finishReceive();
320 0 : return(RADIOLIB_ERR_RX_TIMEOUT);
321 : }
322 :
323 : // read the received data
324 0 : return(readData(data, len));
325 : }
326 :
327 1 : int16_t LR2021::transmitDirect(uint32_t frf) {
328 : // set RF switch (if present)
329 1 : this->mod->setRfSwitchState(Module::MODE_TX);
330 :
331 : // user requested to start transmitting immediately (required for RTTY)
332 1 : int16_t state = RADIOLIB_ERR_NONE;
333 1 : if(frf != 0) {
334 0 : state = setRfFrequency(frf);
335 : }
336 1 : RADIOLIB_ASSERT(state);
337 :
338 : // start transmitting
339 1 : return(setTxTestMode(RADIOLIB_LR2021_TX_TEST_MODE_CW));
340 : }
341 :
342 1 : int16_t LR2021::receiveDirect() {
343 : // set RF switch (if present)
344 1 : this->mod->setRfSwitchState(Module::MODE_RX);
345 :
346 : // LR2021 is unable to output received data directly
347 1 : return(RADIOLIB_ERR_UNKNOWN);
348 : }
349 :
350 1 : int16_t LR2021::scanChannel() {
351 1 : ChannelScanConfig_t cfg = {
352 : .cad = {
353 : .symNum = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
354 : .detPeak = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
355 : .detMin = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
356 : .exitMode = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
357 : .timeout = 0,
358 : .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
359 : .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
360 : },
361 : };
362 2 : return(this->scanChannel(cfg));
363 : }
364 :
365 2 : int16_t LR2021::scanChannel(const ChannelScanConfig_t &config) {
366 : // set mode to CAD
367 2 : int state = startChannelScan(config);
368 2 : RADIOLIB_ASSERT(state);
369 :
370 : // wait for channel activity detected or timeout
371 0 : while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
372 0 : this->mod->hal->yield();
373 : }
374 :
375 : // check CAD result
376 0 : return(getChannelScanResult());
377 : }
378 :
379 5 : int16_t LR2021::standby() {
380 5 : return(this->standby(RADIOLIB_LR2021_STANDBY_RC));
381 : }
382 :
383 6 : int16_t LR2021::standby(uint8_t mode) {
384 6 : return(this->standby(mode, true));
385 : }
386 :
387 6 : int16_t LR2021::standby(uint8_t mode, bool wakeup) {
388 : // set RF switch (if present)
389 6 : this->mod->setRfSwitchState(Module::MODE_IDLE);
390 :
391 6 : if(wakeup) {
392 : // send a NOP command - this pulls the NSS low to exit the sleep mode,
393 : // while preventing interference with possible other SPI transactions
394 6 : (void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_LR2021_CMD_NOP, NULL, 0, false, false);
395 : }
396 :
397 6 : uint8_t buff[] = { mode };
398 12 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_STANDBY, true, buff, sizeof(buff)));
399 : }
400 :
401 1 : int16_t LR2021::sleep() {
402 1 : return(this->sleep(true, 0));
403 : }
404 :
405 1 : int16_t LR2021::sleep(bool retainConfig, uint32_t sleepTime) {
406 : // set RF switch (if present)
407 1 : this->mod->setRfSwitchState(Module::MODE_IDLE);
408 :
409 : uint8_t buff[] = { (uint8_t)(retainConfig ? RADIOLIB_LR2021_SLEEP_RETENTION_ENABLED : RADIOLIB_LR2021_SLEEP_RETENTION_DISABLED),
410 1 : (uint8_t)((sleepTime >> 24) & 0xFF), (uint8_t)((sleepTime >> 16) & 0xFF),
411 1 : (uint8_t)((sleepTime >> 8) & 0xFF), (uint8_t)(sleepTime & 0xFF),
412 1 : };
413 :
414 : // in sleep, the busy line will remain high, so we have to use this method to disable waiting for it to go low
415 1 : int16_t state = this->mod->SPIwriteStream(RADIOLIB_LR2021_CMD_SET_SLEEP, buff, sizeof(buff), false, false);
416 :
417 : // wait for the module to safely enter sleep mode
418 1 : this->mod->hal->delay(1);
419 :
420 1 : return(state);
421 : }
422 :
423 1 : size_t LR2021::getPacketLength(bool update) {
424 : (void)update;
425 :
426 : // in implicit mode, return the cached value
427 1 : uint8_t type = RADIOLIB_LR2021_PACKET_TYPE_NONE;
428 1 : (void)getPacketType(&type);
429 1 : if((type == RADIOLIB_LR2021_PACKET_TYPE_LORA) && (this->headerType == RADIOLIB_LR2021_LORA_HEADER_IMPLICIT)) {
430 0 : return(this->implicitLen);
431 : }
432 :
433 1 : uint16_t len = 0;
434 1 : (void)getRxPktLength(&len);
435 1 : return((size_t)len);
436 : }
437 :
438 1 : int16_t LR2021::finishTransmit() {
439 : // clear interrupt flags
440 1 : clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
441 :
442 : // set mode to standby to disable transmitter/RF switch
443 1 : return(standby());
444 : }
445 :
446 1 : int16_t LR2021::startReceive() {
447 1 : return(this->startReceive(RADIOLIB_LR2021_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
448 : }
449 :
450 1 : int16_t LR2021::readData(uint8_t* data, size_t len) {
451 : // check active modem
452 1 : int16_t state = RADIOLIB_ERR_NONE;
453 1 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
454 1 : state = getPacketType(&modem);
455 1 : RADIOLIB_ASSERT(state);
456 0 : if((modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) &&
457 0 : (modem != RADIOLIB_LR2021_PACKET_TYPE_GFSK) &&
458 0 : (modem != RADIOLIB_LR2021_PACKET_TYPE_FLRC) &&
459 0 : (modem != RADIOLIB_LR2021_PACKET_TYPE_OOK)) {
460 0 : return(RADIOLIB_ERR_WRONG_MODEM);
461 : }
462 :
463 : // check integrity CRC
464 0 : uint32_t irq = getIrqStatus();
465 0 : int16_t crcState = RADIOLIB_ERR_NONE;
466 : // report CRC mismatch when there's a payload CRC error
467 0 : if(irq & RADIOLIB_LR2021_IRQ_CRC_ERROR) {
468 0 : crcState = RADIOLIB_ERR_CRC_MISMATCH;
469 : }
470 :
471 : // for LoRa modem and explicit header mode, check also also header valid flag
472 0 : if((modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) &&
473 0 : (this->headerType == RADIOLIB_LR2021_LORA_HEADER_EXPLICIT) &&
474 0 : (!(irq & RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID))) {
475 0 : crcState = RADIOLIB_ERR_LORA_HEADER_DAMAGED;
476 : }
477 :
478 : // get packet length
479 0 : size_t length = getPacketLength();
480 0 : if((len != 0) && (len < length)) {
481 : // user requested less data than we got, only return what was requested
482 0 : length = len;
483 : }
484 :
485 : // read packet data
486 0 : state = readRadioRxFifo(data, length);
487 0 : RADIOLIB_ASSERT(state);
488 :
489 : // clear the Rx buffer
490 0 : state = clearRxFifo();
491 0 : RADIOLIB_ASSERT(state);
492 :
493 : // clear interrupt flags
494 0 : state = clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
495 :
496 : // check if CRC failed - this is done after reading data to give user the option to keep them
497 0 : RADIOLIB_ASSERT(crcState);
498 :
499 0 : return(state);
500 : }
501 :
502 1 : int16_t LR2021::finishReceive() {
503 : // set mode to standby to disable RF switch
504 1 : int16_t state = standby();
505 1 : RADIOLIB_ASSERT(state);
506 :
507 : // clear interrupt flags
508 0 : return(clearIrqState(RADIOLIB_LR2021_IRQ_ALL));
509 : }
510 :
511 1 : int16_t LR2021::startChannelScan() {
512 1 : ChannelScanConfig_t cfg = {
513 : .cad = {
514 : .symNum = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
515 : .detPeak = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
516 : .detMin = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
517 : .exitMode = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
518 : .timeout = 0,
519 : .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
520 : .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
521 : },
522 : };
523 2 : return(this->startChannelScan(cfg));
524 : }
525 :
526 4 : int16_t LR2021::startChannelScan(const ChannelScanConfig_t &config) {
527 : // check active modem
528 4 : int16_t state = RADIOLIB_ERR_NONE;
529 4 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
530 4 : state = getPacketType(&modem);
531 4 : RADIOLIB_ASSERT(state);
532 0 : if(modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) {
533 0 : return(RADIOLIB_ERR_WRONG_MODEM);
534 : }
535 :
536 : // set mode to standby
537 0 : state = standby();
538 0 : RADIOLIB_ASSERT(state);
539 :
540 : // set RF switch (if present)
541 0 : this->mod->setRfSwitchState(Module::MODE_RX);
542 :
543 : // set DIO pin mapping
544 0 : uint32_t irqFlags = (config.cad.irqFlags == RADIOLIB_IRQ_NOT_SUPPORTED) ? RADIOLIB_LR2021_IRQ_CAD_DETECTED | RADIOLIB_LR2021_IRQ_CAD_DONE : config.cad.irqFlags;
545 0 : state = setDioIrqConfig(this->irqDioNum, getIrqMapped(irqFlags));
546 0 : RADIOLIB_ASSERT(state);
547 :
548 : // clear interrupt flags
549 0 : state = clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
550 0 : RADIOLIB_ASSERT(state);
551 :
552 : // set mode to CAD
553 0 : return(startCad(config.cad.symNum, config.cad.detPeak, config.cad.detMin, config.cad.exitMode, config.cad.timeout));
554 : }
555 :
556 1 : int16_t LR2021::getChannelScanResult() {
557 : // check active modem
558 1 : int16_t state = RADIOLIB_ERR_NONE;
559 1 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
560 1 : state = getPacketType(&modem);
561 1 : RADIOLIB_ASSERT(state);
562 0 : if(modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) {
563 0 : return(RADIOLIB_ERR_WRONG_MODEM);
564 : }
565 :
566 : // check CAD result
567 0 : uint32_t cadResult = getIrqStatus();
568 0 : if(cadResult & RADIOLIB_LR2021_IRQ_CAD_DETECTED) {
569 : // detected some LoRa activity
570 0 : return(RADIOLIB_LORA_DETECTED);
571 0 : } else if(cadResult & RADIOLIB_LR2021_IRQ_CAD_DONE) {
572 : // channel is free
573 0 : return(RADIOLIB_CHANNEL_FREE);
574 : }
575 :
576 0 : return(RADIOLIB_ERR_UNKNOWN);
577 : }
578 :
579 1 : uint32_t LR2021::getIrqFlags() {
580 1 : return(getIrqStatus());
581 : }
582 :
583 1 : int16_t LR2021::setIrqFlags(uint32_t irq) {
584 1 : return(this->setDioIrqConfig(this->irqDioNum, irq));
585 : }
586 :
587 1 : int16_t LR2021::clearIrqFlags(uint32_t irq) {
588 1 : return(this->clearIrqState(irq));
589 : }
590 :
591 1 : int16_t LR2021::setModem(ModemType_t modem) {
592 1 : switch(modem) {
593 0 : case(ModemType_t::RADIOLIB_MODEM_LORA): {
594 0 : return(this->begin());
595 : } break;
596 0 : case(ModemType_t::RADIOLIB_MODEM_FSK): {
597 0 : return(this->beginGFSK());
598 : } break;
599 0 : case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
600 0 : return(this->beginLRFHSS());
601 : } break;
602 1 : default:
603 1 : return(RADIOLIB_ERR_WRONG_MODEM);
604 : }
605 : }
606 :
607 0 : Module* LR2021::getMod() {
608 0 : return(this->mod);
609 : }
610 :
611 0 : int16_t LR2021::modSetup(float freq, float tcxoVoltage, uint8_t modem) {
612 0 : this->mod->init();
613 0 : this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
614 0 : this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
615 0 : this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_LR2021_CMD_READ_REG_MEM_32;
616 0 : this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_LR2021_CMD_WRITE_REG_MEM_32;
617 0 : this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_LR2021_CMD_NOP;
618 0 : this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_LR2021_CMD_GET_STATUS;
619 0 : this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_24;
620 0 : this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_16;
621 :
622 : // try to find the chip - this will also reset the module at least once
623 0 : if(!this->findChip()) {
624 : RADIOLIB_DEBUG_BASIC_PRINTLN("No LR2021 found!");
625 0 : this->mod->term();
626 0 : return(RADIOLIB_ERR_CHIP_NOT_FOUND);
627 : }
628 : RADIOLIB_DEBUG_BASIC_PRINTLN("M\tLR2021");
629 :
630 : // set mode to standby
631 0 : int16_t state = standby();
632 0 : RADIOLIB_ASSERT(state);
633 :
634 : // set TCXO control, if requested
635 0 : if(!this->XTAL && tcxoVoltage > 0.0f) {
636 0 : state = setTCXO(tcxoVoltage);
637 0 : RADIOLIB_ASSERT(state);
638 : }
639 :
640 : // configure settings not accessible by API
641 0 : state = config(modem);
642 0 : RADIOLIB_ASSERT(state);
643 :
644 0 : state = setFrequency(freq);
645 0 : return(state);
646 : }
647 :
648 0 : bool LR2021::findChip(void) {
649 : // this is the only version mentioned in datasheet
650 0 : const uint8_t expMajor = 0x01;
651 0 : const uint8_t expMinor = 0x18;
652 :
653 0 : uint8_t i = 0;
654 0 : bool flagFound = false;
655 0 : uint8_t fwMajor = 0, fwMinor = 0;
656 0 : while((i < 10) && !flagFound) {
657 : // reset the module
658 0 : reset();
659 :
660 : // read the version
661 0 : int16_t state = getVersion(&fwMajor, &fwMinor);
662 0 : RADIOLIB_ASSERT(state);
663 :
664 0 : if((fwMajor == expMajor) && (fwMinor == expMinor)) {
665 : RADIOLIB_DEBUG_BASIC_PRINTLN("Found LR2021");
666 : RADIOLIB_DEBUG_BASIC_PRINTLN("Base FW version: %d.%d", (int)fwMajor, (int)fwMinor);
667 0 : flagFound = true;
668 : } else {
669 : RADIOLIB_DEBUG_BASIC_PRINTLN("LR2021 not found! (%d of 10 tries) FW version: = %d.%d", (int)fwMajor, (int)fwMinor);
670 : RADIOLIB_DEBUG_BASIC_PRINTLN("Expected: %d.%d", (int)expMajor, (int)expMinor);
671 0 : this->mod->hal->delay(10);
672 0 : i++;
673 : }
674 : }
675 :
676 0 : return(flagFound);
677 : }
678 :
679 0 : int16_t LR2021::config(uint8_t modem) {
680 : // set Rx/Tx fallback mode to STDBY_RC
681 0 : int16_t state = this->setRxTxFallbackMode(RADIOLIB_LR2021_FALLBACK_MODE_STBY_RC);
682 0 : RADIOLIB_ASSERT(state);
683 :
684 : // clear IRQ
685 0 : state = this->clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
686 0 : RADIOLIB_ASSERT(state);
687 :
688 : // validate DIO pin number
689 0 : if((this->irqDioNum < 5) || (this->irqDioNum > 11)) {
690 0 : return(RADIOLIB_ERR_INVALID_DIO_PIN);
691 : }
692 :
693 : // set the DIO to IRQ
694 : // DIO5 can only be pull up
695 0 : uint8_t pull = this->irqDioNum == 5 ? RADIOLIB_LR2021_DIO_SLEEP_PULL_UP : RADIOLIB_LR2021_DIO_SLEEP_PULL_NONE;
696 0 : state = this->setDioFunction(this->irqDioNum, RADIOLIB_LR2021_DIO_FUNCTION_IRQ, pull);
697 0 : RADIOLIB_ASSERT(state);
698 :
699 : // calibrate all blocks
700 0 : state = this->calibrate(RADIOLIB_LR2021_CALIBRATE_ALL);
701 :
702 : // wait for calibration completion
703 0 : this->mod->hal->delay(5);
704 0 : while(this->mod->hal->digitalRead(this->mod->getGpio())) {
705 0 : this->mod->hal->yield();
706 : }
707 :
708 : // if something failed, show the device errors
709 : #if RADIOLIB_DEBUG_BASIC
710 : if(state != RADIOLIB_ERR_NONE) {
711 : uint16_t errors = 0;
712 : getErrors(&errors);
713 : RADIOLIB_DEBUG_BASIC_PRINTLN("Calibration failed, device errors: 0x%X", errors);
714 : }
715 : #else
716 0 : RADIOLIB_ASSERT(state);
717 : #endif
718 :
719 : // set modem
720 0 : state = this->setPacketType(modem);
721 0 : return(state);
722 : }
723 :
724 0 : int16_t LR2021::startCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin, uint8_t exitMode, RadioLibTime_t timeout) {
725 : // check active modem
726 0 : uint8_t type = RADIOLIB_LR2021_PACKET_TYPE_NONE;
727 0 : int16_t state = getPacketType(&type);
728 0 : RADIOLIB_ASSERT(state);
729 0 : if(type != RADIOLIB_LR2021_PACKET_TYPE_LORA) {
730 0 : return(RADIOLIB_ERR_WRONG_MODEM);
731 : }
732 :
733 : // select CAD parameters
734 : //! \TODO: [LR2021] the magic numbers for CAD are based on Semtech examples, this is probably suboptimal
735 0 : uint8_t num = symbolNum;
736 0 : if(num == RADIOLIB_LR2021_CAD_PARAM_DEFAULT) {
737 0 : num = 2;
738 : }
739 :
740 0 : const uint8_t detPeakValues[8] = { 48, 48, 50, 55, 55, 59, 61, 65 };
741 0 : uint8_t peak = detPeak;
742 0 : if(peak == RADIOLIB_LR2021_CAD_PARAM_DEFAULT) {
743 0 : peak = detPeakValues[this->spreadingFactor - 5];
744 : }
745 :
746 0 : uint8_t min = detMin;
747 0 : if(min == RADIOLIB_LR2021_CAD_PARAM_DEFAULT) {
748 0 : min = 10;
749 : }
750 :
751 0 : uint8_t mode = exitMode;
752 0 : if(mode == RADIOLIB_LR2021_CAD_PARAM_DEFAULT) {
753 0 : mode = RADIOLIB_LR2021_CAD_EXIT_MODE_FALLBACK;
754 : }
755 :
756 0 : uint32_t timeout_raw = (float)timeout / 30.52f;
757 :
758 : //! \TODO: [LR2021] The datasheet says this CAD is only based on RSSI, but the reference to the LoRa CAD is GetLoraRxStats ...?
759 : (void)peak;
760 : (void)min;
761 :
762 : // set CAD parameters
763 : //! \TODO: [LR2021] add configurable exit mode and timeout
764 0 : state = setCadParams(timeout_raw, num, mode, timeout_raw);
765 0 : RADIOLIB_ASSERT(state);
766 :
767 : // start CAD
768 0 : return(setCad());
769 : }
770 :
771 1 : RadioLibTime_t LR2021::getTimeOnAir(size_t len) {
772 1 : uint8_t type = RADIOLIB_LR2021_PACKET_TYPE_NONE;
773 1 : int16_t state = getPacketType(&type);
774 1 : RADIOLIB_ASSERT(state);
775 :
776 0 : switch(type) {
777 : // basic modems are supported by the LRxxxx base class
778 0 : case(RADIOLIB_LR2021_PACKET_TYPE_LORA):
779 0 : return(LRxxxx::getTimeOnAir(len, ModemType_t::RADIOLIB_MODEM_LORA));
780 0 : case(RADIOLIB_LR2021_PACKET_TYPE_GFSK):
781 0 : return(LRxxxx::getTimeOnAir(len, ModemType_t::RADIOLIB_MODEM_FSK));
782 0 : case(RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS):
783 0 : return(LRxxxx::getTimeOnAir(len, ModemType_t::RADIOLIB_MODEM_LRFHSS));
784 0 : case(RADIOLIB_LR2021_PACKET_TYPE_FLRC): {
785 : //! \todo [LR2021] Add FLRC to the modems supported in ModemType_t
786 :
787 : // calculate the bits of the uncoded part of the packet
788 0 : size_t n_uncoded_bits = (this->preambleLengthGFSK + 1)*4 + 21 + this->syncWordLength*8;
789 0 : if(this->packetType != RADIOLIB_LR2021_GFSK_OOK_PACKET_FORMAT_FIXED) { n_uncoded_bits+= 16; }
790 :
791 : // calculate bits in the coded part
792 0 : size_t n_coded_bits = len*8;
793 0 : if(this->crcLenGFSK != 0) { n_coded_bits += (this->crcLenGFSK + 1)*8; }
794 0 : if(this->codingRateFlrc <= RADIOLIB_LR2021_FLRC_CR_3_4) { n_coded_bits += 6; }
795 0 : float n_coded_bits_flt = n_coded_bits;
796 0 : switch(this->codingRateFlrc) {
797 0 : case(RADIOLIB_LR2021_FLRC_CR_1_2):
798 0 : n_coded_bits += 6;
799 0 : n_coded_bits_flt = (float)n_coded_bits*2.0f;
800 0 : break;
801 0 : case(RADIOLIB_LR2021_FLRC_CR_3_4):
802 0 : n_coded_bits += 6;
803 0 : n_coded_bits_flt = ((float)n_coded_bits*4.0f)/3.0f;
804 0 : break;
805 0 : case(RADIOLIB_LR2021_FLRC_CR_2_3):
806 0 : n_coded_bits_flt = ((float)n_coded_bits*3.0f)/2.0f;
807 0 : break;
808 : }
809 0 : n_coded_bits = n_coded_bits_flt + 0.5f;
810 :
811 : // now calculate the real time on air
812 0 : return((float)(n_uncoded_bits + n_coded_bits) / (float)(this->bitRate / 1000.0f));
813 : }
814 : }
815 :
816 : RADIOLIB_DEBUG_BASIC_PRINTLN("Called getTimeOnAir() for invalid modem (%02x)!", type);
817 0 : return(0);
818 : }
819 :
820 3 : int16_t LR2021::getModem(ModemType_t* modem) {
821 3 : RADIOLIB_ASSERT_PTR(modem);
822 :
823 3 : uint8_t type = RADIOLIB_LR2021_PACKET_TYPE_NONE;
824 3 : int16_t state = getPacketType(&type);
825 3 : RADIOLIB_ASSERT(state);
826 :
827 0 : switch(type) {
828 0 : case(RADIOLIB_LR2021_PACKET_TYPE_LORA):
829 0 : *modem = ModemType_t::RADIOLIB_MODEM_LORA;
830 0 : return(RADIOLIB_ERR_NONE);
831 0 : case(RADIOLIB_LR2021_PACKET_TYPE_GFSK):
832 0 : *modem = ModemType_t::RADIOLIB_MODEM_FSK;
833 0 : return(RADIOLIB_ERR_NONE);
834 0 : case(RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS):
835 0 : *modem = ModemType_t::RADIOLIB_MODEM_LRFHSS;
836 0 : return(RADIOLIB_ERR_NONE);
837 : }
838 :
839 0 : return(RADIOLIB_ERR_WRONG_MODEM);
840 : }
841 :
842 4 : int16_t LR2021::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
843 : int16_t state;
844 :
845 4 : switch(mode) {
846 3 : case(RADIOLIB_RADIO_MODE_RX): {
847 : // check active modem
848 3 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
849 3 : state = getPacketType(&modem);
850 3 : RADIOLIB_ASSERT(state);
851 0 : if((modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) &&
852 0 : (modem != RADIOLIB_LR2021_PACKET_TYPE_GFSK) &&
853 0 : (modem != RADIOLIB_LR2021_PACKET_TYPE_FLRC) &&
854 0 : (modem != RADIOLIB_LR2021_PACKET_TYPE_OOK)) {
855 0 : return(RADIOLIB_ERR_WRONG_MODEM);
856 : }
857 :
858 : // set the correct Rx path
859 0 : state = setRxPath(this->highFreq ? RADIOLIB_LR2021_RX_PATH_HF : RADIOLIB_LR2021_RX_PATH_LF, this->highFreq ? this->gainModeHf : this->gainModeLf);
860 0 : RADIOLIB_ASSERT(state);
861 :
862 : // set DIO mapping
863 0 : if(cfg->receive.timeout != RADIOLIB_LR2021_RX_TIMEOUT_INF) {
864 0 : cfg->receive.irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
865 : }
866 0 : state = setDioIrqConfig(this->irqDioNum, getIrqMapped(cfg->receive.irqFlags & cfg->receive.irqMask));
867 0 : RADIOLIB_ASSERT(state);
868 :
869 : // clear interrupt flags
870 0 : state = clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
871 0 : RADIOLIB_ASSERT(state);
872 :
873 : // set implicit mode and expected len if applicable
874 0 : if((this->headerType == RADIOLIB_LR2021_LORA_HEADER_IMPLICIT) && (modem == RADIOLIB_LR2021_PACKET_TYPE_LORA)) {
875 0 : state = setLoRaPacketParams(this->preambleLengthLoRa, this->headerType, this->implicitLen, this->crcTypeLoRa, this->invertIQEnabled);
876 0 : RADIOLIB_ASSERT(state);
877 : }
878 :
879 : // if max(uint32_t) is used, revert to RxContinuous
880 0 : if(cfg->receive.timeout == 0xFFFFFFFF) {
881 0 : cfg->receive.timeout = 0xFFFFFF;
882 : }
883 0 : this->rxTimeout = cfg->receive.timeout;
884 0 : } break;
885 :
886 1 : case(RADIOLIB_RADIO_MODE_TX): {
887 : // check packet length
888 1 : if(cfg->transmit.len > RADIOLIB_LR2021_MAX_PACKET_LENGTH) {
889 1 : return(RADIOLIB_ERR_PACKET_TOO_LONG);
890 : }
891 :
892 : // maximum packet length is decreased by 1 when address filtering is active
893 : //! \todo [LR2021] implement GFSK address filtering
894 :
895 : // set packet Length
896 1 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
897 1 : state = getPacketType(&modem);
898 1 : RADIOLIB_ASSERT(state);
899 0 : if(modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) {
900 0 : state = setLoRaPacketParams(this->preambleLengthLoRa, this->headerType, cfg->transmit.len, this->crcTypeLoRa, this->invertIQEnabled);
901 :
902 0 : } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_GFSK) {
903 0 : state = setGfskPacketParams(this->preambleLengthGFSK, this->preambleDetLength, false, false, this->addrComp, this->packetType, cfg->transmit.len, this->crcTypeGFSK, this->whitening);
904 :
905 0 : } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_OOK) {
906 0 : state = setOokPacketParams(this->preambleLengthGFSK, this->addrComp, this->packetType, cfg->transmit.len, this->crcTypeGFSK, this->whitening);
907 :
908 0 : } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_FLRC) {
909 0 : state = setFlrcPacketParams(this->preambleLengthGFSK, this->syncWordLength, 1, 0x01, this->packetType == RADIOLIB_LR2021_GFSK_OOK_PACKET_FORMAT_FIXED, this->crcLenGFSK, cfg->transmit.len);
910 :
911 : } else {
912 0 : return(RADIOLIB_ERR_WRONG_MODEM);
913 : }
914 :
915 0 : RADIOLIB_ASSERT(state);
916 :
917 : // set DIO mapping
918 0 : state = setDioIrqConfig(this->irqDioNum, RADIOLIB_LR2021_IRQ_TX_DONE | RADIOLIB_LR2021_IRQ_TIMEOUT);
919 0 : RADIOLIB_ASSERT(state);
920 :
921 0 : if(modem == RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS) {
922 : // in LR-FHSS mode, the packet is built by the device
923 : //! \todo [LR2021] add configurable LR-FHSS device offset
924 0 : state = LRxxxx::lrFhssBuildFrame(RADIOLIB_LR2021_CMD_LR_FHSS_BUILD_FRAME, this->lrFhssHdrCount, this->lrFhssCr, this->lrFhssGrid, true, this->lrFhssBw, this->lrFhssHopSeq, 0, cfg->transmit.data, cfg->transmit.len);
925 0 : RADIOLIB_ASSERT(state);
926 :
927 : } else {
928 : // write packet to buffer
929 0 : state = writeRadioTxFifo(cfg->transmit.data, cfg->transmit.len);
930 0 : RADIOLIB_ASSERT(state);
931 :
932 : }
933 :
934 : // clear interrupt flags
935 0 : state = clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
936 0 : RADIOLIB_ASSERT(state);
937 0 : } break;
938 :
939 0 : default:
940 0 : return(RADIOLIB_ERR_UNSUPPORTED);
941 : }
942 :
943 0 : this->stagedMode = mode;
944 0 : return(state);
945 : }
946 :
947 1 : int16_t LR2021::launchMode() {
948 : int16_t state;
949 1 : switch(this->stagedMode) {
950 1 : case(RADIOLIB_RADIO_MODE_RX): {
951 1 : this->mod->setRfSwitchState(Module::MODE_RX);
952 1 : state = setRx(this->rxTimeout);
953 1 : } break;
954 :
955 0 : case(RADIOLIB_RADIO_MODE_TX): {
956 0 : this->mod->setRfSwitchState(Module::MODE_TX);
957 0 : state = setTx(RADIOLIB_LR2021_TX_TIMEOUT_NONE);
958 0 : RADIOLIB_ASSERT(state);
959 :
960 : // wait for BUSY to go low (= PA ramp up done)
961 0 : while(this->mod->hal->digitalRead(this->mod->getGpio())) {
962 0 : this->mod->hal->yield();
963 : }
964 0 : } break;
965 :
966 0 : default:
967 0 : return(RADIOLIB_ERR_UNSUPPORTED);
968 : }
969 :
970 1 : this->stagedMode = RADIOLIB_RADIO_MODE_NONE;
971 1 : return(state);
972 : }
973 :
974 0 : float LR2021::getVoltage(uint8_t bits) {
975 0 : if((bits < 8) || (bits > 13)) {
976 0 : return(0);
977 : }
978 :
979 : uint16_t val;
980 0 : if(getVbat(bits, &val) != RADIOLIB_ERR_NONE) {
981 0 : return(0);
982 : }
983 :
984 0 : return((float)val / 1000.0f);
985 : }
986 :
987 0 : float LR2021::getTemperature(uint8_t source, uint8_t bits) {
988 0 : if((bits < 8) || (bits > 13)) {
989 0 : return(0);
990 : }
991 :
992 : float val;
993 0 : if(getTemp(source, bits, &val) != RADIOLIB_ERR_NONE) {
994 0 : return(0);
995 : }
996 :
997 0 : return(val);
998 : }
999 :
1000 1 : float LR2021::getRSSI() {
1001 1 : return(this->getRSSI(true));
1002 : }
1003 :
1004 1 : float LR2021::getRSSI(bool packet, bool skipReceive) {
1005 1 : float rssi = 0;
1006 : int16_t state;
1007 1 : if(!packet) {
1008 : // get instantaneous RSSI value
1009 0 : if(!skipReceive) { (void)startReceive(); }
1010 0 : state = this->getRssiInst(&rssi);
1011 0 : if(!skipReceive) { (void)standby(); }
1012 0 : if(state != RADIOLIB_ERR_NONE) { return(0); }
1013 0 : return(rssi);
1014 : }
1015 :
1016 : // check modem type
1017 1 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
1018 1 : state = this->getPacketType(&modem);
1019 1 : if(state != RADIOLIB_ERR_NONE) { return(0); }
1020 0 : if(modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) {
1021 0 : state = this->getLoRaPacketStatus(NULL, NULL, NULL, NULL, &rssi, NULL);
1022 0 : } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_GFSK) {
1023 0 : state = this->getGfskPacketStatus(NULL, &rssi, NULL, NULL, NULL, NULL);
1024 : } else {
1025 0 : return(0);
1026 : }
1027 :
1028 0 : if(state != RADIOLIB_ERR_NONE) { return(0); }
1029 0 : return(rssi);
1030 : }
1031 :
1032 1 : float LR2021::getSNR() {
1033 : float snr;
1034 1 : uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
1035 1 : int16_t state = this->getPacketType(&modem);
1036 1 : if(state != RADIOLIB_ERR_NONE) { return(0); }
1037 0 : if(modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) { return(0); }
1038 0 : state = this->getLoRaPacketStatus(NULL, NULL, NULL, &snr, NULL, NULL);
1039 0 : if(state != RADIOLIB_ERR_NONE) { return(0); }
1040 0 : return(snr);
1041 : }
1042 :
1043 1 : uint8_t LR2021::randomByte() {
1044 1 : uint32_t num = 0;
1045 1 : (void)getRandomNumber(&num);
1046 1 : return((uint8_t)num);
1047 : }
1048 :
1049 : #endif
|