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