Line data Source code
1 : #include "SX128x.h"
2 : #include <math.h>
3 : #include <string.h>
4 : #if !RADIOLIB_EXCLUDE_SX128X
5 :
6 13 : SX128x::SX128x(Module* mod) : PhysicalLayer() {
7 13 : this->freqStep = RADIOLIB_SX128X_FREQUENCY_STEP_SIZE;
8 13 : this->maxPacketLength = RADIOLIB_SX128X_MAX_PACKET_LENGTH;
9 13 : this->mod = mod;
10 13 : this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_SX128X_IRQ_TX_DONE;
11 13 : this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_SX128X_IRQ_RX_DONE;
12 13 : this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED;
13 13 : this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_SX128X_IRQ_SYNC_WORD_VALID;
14 13 : this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_SX128X_IRQ_HEADER_VALID;
15 13 : this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_SX128X_IRQ_HEADER_ERROR;
16 13 : this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_SX128X_IRQ_CRC_ERROR;
17 13 : this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_SX128X_IRQ_CAD_DONE;
18 13 : this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_SX128X_IRQ_CAD_DETECTED;
19 13 : this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT;
20 13 : }
21 :
22 0 : int16_t SX128x::begin(const ConfigLoRa_t& cfg) {
23 : // initialize LoRa modulation variables
24 0 : this->bandwidthKhz = cfg.bandwidth;
25 0 : this->spreadingFactor = RADIOLIB_SX128X_LORA_SF_9;
26 0 : this->codingRateLoRa = RADIOLIB_SX128X_LORA_CR_4_7;
27 :
28 : // initialize LoRa packet variables
29 0 : this->preambleLengthLoRa = cfg.preambleLength;
30 0 : this->headerType = RADIOLIB_SX128X_LORA_HEADER_EXPLICIT;
31 0 : this->payloadLen = 0xFF;
32 0 : this->crcLoRa = RADIOLIB_SX128X_LORA_CRC_ON;
33 :
34 : // set module properties and perform initial setup
35 0 : int16_t state = this->modSetup(RADIOLIB_SX128X_PACKET_TYPE_LORA);
36 0 : RADIOLIB_ASSERT(state);
37 :
38 : // configure publicly accessible settings
39 0 : state = setFrequency(cfg.frequency);
40 0 : RADIOLIB_ASSERT(state);
41 :
42 0 : state = setBandwidth(cfg.bandwidth);
43 0 : RADIOLIB_ASSERT(state);
44 :
45 0 : state = setSpreadingFactor(cfg.spreadingFactor);
46 0 : RADIOLIB_ASSERT(state);
47 :
48 0 : state = setCodingRate(cfg.codingRate);
49 0 : RADIOLIB_ASSERT(state);
50 :
51 0 : state = setSyncWord(cfg.syncWord);
52 0 : RADIOLIB_ASSERT(state);
53 :
54 0 : state = setPreambleLength(cfg.preambleLength);
55 0 : RADIOLIB_ASSERT(state);
56 :
57 0 : state = setOutputPower(cfg.power);
58 0 : return(state);
59 : }
60 :
61 0 : int16_t SX128x::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t pwr, uint16_t preambleLength) {
62 0 : ConfigLoRa_t cfg;
63 0 : cfg.frequency = freq;
64 0 : cfg.bandwidth = bw;
65 0 : cfg.spreadingFactor = sf;
66 0 : cfg.codingRate = cr;
67 0 : cfg.syncWord = syncWord;
68 0 : cfg.power = pwr;
69 0 : cfg.preambleLength = preambleLength;
70 0 : return(begin(cfg));
71 : }
72 :
73 0 : int16_t SX128x::beginGFSK(const ConfigFSK_t& cfg) {
74 : // initialize GFSK modulation variables
75 0 : this->bitRateKbps = cfg.bitRate;
76 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_800_BW_2_4;
77 0 : this->modIndexReal = 1.0;
78 0 : this->modIndex = RADIOLIB_SX128X_BLE_GFSK_MOD_IND_1_00;
79 0 : this->shaping = RADIOLIB_SX128X_BLE_GFSK_BT_0_5;
80 :
81 : // initialize GFSK packet variables
82 0 : this->preambleLengthGFSK = cfg.preambleLength;
83 0 : this->syncWordLen = 2;
84 0 : this->syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_1;
85 0 : this->crcGFSK = RADIOLIB_SX128X_GFSK_FLRC_CRC_2_BYTE;
86 0 : this->whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_ON;
87 :
88 : // set module properties and perform initial setup
89 0 : int16_t state = this->modSetup(RADIOLIB_SX128X_PACKET_TYPE_GFSK);
90 0 : RADIOLIB_ASSERT(state);
91 :
92 : // configure publicly accessible settings
93 0 : state = setFrequency(cfg.frequency);
94 0 : RADIOLIB_ASSERT(state);
95 :
96 0 : state = setBitRate(cfg.bitRate);
97 0 : RADIOLIB_ASSERT(state);
98 :
99 0 : state = setFrequencyDeviation(cfg.frequencyDeviation);
100 0 : RADIOLIB_ASSERT(state);
101 :
102 0 : state = setOutputPower(cfg.power);
103 0 : RADIOLIB_ASSERT(state);
104 :
105 0 : state = setPreambleLength(cfg.preambleLength);
106 0 : RADIOLIB_ASSERT(state);
107 :
108 0 : state = setDataShaping(RADIOLIB_SHAPING_0_5);
109 0 : RADIOLIB_ASSERT(state);
110 :
111 : // set publicly accessible settings that are not a part of begin method
112 0 : uint8_t sync[] = { 0x12, 0xAD };
113 0 : state = setSyncWord(sync, 2);
114 0 : RADIOLIB_ASSERT(state);
115 :
116 0 : state = setEncoding(RADIOLIB_ENCODING_NRZ);
117 0 : return(state);
118 : }
119 :
120 0 : int16_t SX128x::beginGFSK(float freq, uint16_t br, float freqDev, int8_t pwr, uint16_t preambleLength) {
121 0 : ConfigFSK_t cfg;
122 0 : cfg.frequency = freq;
123 0 : cfg.bitRate = br;
124 0 : cfg.frequencyDeviation = freqDev;
125 0 : cfg.power = pwr;
126 0 : cfg.preambleLength = preambleLength;
127 0 : return(beginGFSK(cfg));
128 : }
129 :
130 0 : int16_t SX128x::beginBLE(const ConfigBLE_t& cfg) {
131 : // initialize BLE modulation variables
132 0 : this->bitRateKbps = cfg.bitRate;
133 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_800_BW_2_4;
134 0 : this->modIndexReal = 1.0;
135 0 : this->modIndex = RADIOLIB_SX128X_BLE_GFSK_MOD_IND_1_00;
136 0 : this->shaping = RADIOLIB_SX128X_BLE_GFSK_BT_0_5;
137 :
138 : // initialize BLE packet variables
139 0 : this->crcGFSK = RADIOLIB_SX128X_BLE_CRC_3_BYTE;
140 0 : this->whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_ON;
141 :
142 : // set module properties and perform initial setup
143 0 : int16_t state = this->modSetup(RADIOLIB_SX128X_PACKET_TYPE_BLE);
144 0 : RADIOLIB_ASSERT(state);
145 :
146 : // configure publicly accessible settings
147 0 : state = setFrequency(cfg.frequency);
148 0 : RADIOLIB_ASSERT(state);
149 :
150 0 : state = setBitRate(cfg.bitRate);
151 0 : RADIOLIB_ASSERT(state);
152 :
153 0 : state = setFrequencyDeviation(cfg.frequencyDeviation);
154 0 : RADIOLIB_ASSERT(state);
155 :
156 0 : state = setOutputPower(cfg.power);
157 0 : RADIOLIB_ASSERT(state);
158 :
159 0 : state = setDataShaping(cfg.dataShaping);
160 0 : return(state);
161 : }
162 :
163 0 : int16_t SX128x::beginBLE(float freq, uint16_t br, float freqDev, int8_t pwr, uint8_t dataShaping) {
164 0 : ConfigBLE_t cfg;
165 0 : cfg.frequency = freq;
166 0 : cfg.bitRate = br;
167 0 : cfg.frequencyDeviation = freqDev;
168 0 : cfg.power = pwr;
169 0 : cfg.dataShaping = dataShaping;
170 0 : return(beginBLE(cfg));
171 : }
172 :
173 0 : int16_t SX128x::beginFLRC(const ConfigFLRC_t& cfg) {
174 : // initialize FLRC modulation variables
175 0 : this->bitRateKbps = cfg.bitRate;
176 0 : this->bitRate = RADIOLIB_SX128X_FLRC_BR_0_650_BW_0_6;
177 0 : this->codingRateFLRC = RADIOLIB_SX128X_FLRC_CR_3_4;
178 0 : this->shaping = RADIOLIB_SX128X_FLRC_BT_0_5;
179 :
180 : // initialize FLRC packet variables
181 0 : this->preambleLengthGFSK = cfg.preambleLength;
182 0 : this->syncWordLen = 2;
183 0 : this->syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_1;
184 0 : this->crcGFSK = RADIOLIB_SX128X_GFSK_FLRC_CRC_2_BYTE;
185 0 : this->whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_OFF;
186 :
187 : // set module properties and perform initial setup
188 0 : int16_t state = this->modSetup(RADIOLIB_SX128X_PACKET_TYPE_FLRC);
189 0 : RADIOLIB_ASSERT(state);
190 :
191 : // configure publicly accessible settings
192 0 : state = setFrequency(cfg.frequency);
193 0 : RADIOLIB_ASSERT(state);
194 :
195 0 : state = setBitRate(cfg.bitRate);
196 0 : RADIOLIB_ASSERT(state);
197 :
198 0 : state = setCodingRate(cfg.codingRate);
199 0 : RADIOLIB_ASSERT(state);
200 :
201 0 : state = setOutputPower(cfg.power);
202 0 : RADIOLIB_ASSERT(state);
203 :
204 0 : state = setPreambleLength(cfg.preambleLength);
205 0 : RADIOLIB_ASSERT(state);
206 :
207 0 : state = setDataShaping(cfg.dataShaping);
208 0 : RADIOLIB_ASSERT(state);
209 :
210 : // set publicly accessible settings that are not a part of begin method
211 0 : uint8_t sync[] = { 0x2D, 0x01, 0x4B, 0x1D };
212 0 : state = setSyncWord(sync, 4);
213 0 : return(state);
214 : }
215 :
216 0 : int16_t SX128x::beginFLRC(float freq, uint16_t br, uint8_t cr, int8_t pwr, uint16_t preambleLength, uint8_t dataShaping) {
217 0 : ConfigFLRC_t cfg;
218 0 : cfg.frequency = freq;
219 0 : cfg.bitRate = br;
220 0 : cfg.codingRate = cr;
221 0 : cfg.power = pwr;
222 0 : cfg.preambleLength = preambleLength;
223 0 : cfg.dataShaping = dataShaping;
224 0 : return(beginFLRC(cfg));
225 : }
226 :
227 0 : int16_t SX128x::reset(bool verify) {
228 : // run the reset sequence - same as SX126x, as SX128x docs don't seem to mention this
229 0 : this->mod->hal->pinMode(this->mod->getRst(), this->mod->hal->GpioModeOutput);
230 0 : this->mod->hal->digitalWrite(this->mod->getRst(), this->mod->hal->GpioLevelLow);
231 0 : this->mod->hal->delay(1);
232 0 : this->mod->hal->digitalWrite(this->mod->getRst(), this->mod->hal->GpioLevelHigh);
233 :
234 : // return immediately when verification is disabled
235 0 : if(!verify) {
236 0 : return(RADIOLIB_ERR_NONE);
237 : }
238 :
239 : // set mode to standby
240 0 : RadioLibTime_t start = this->mod->hal->millis();
241 : while(true) {
242 : // try to set mode to standby
243 0 : int16_t state = standby();
244 0 : if(state == RADIOLIB_ERR_NONE) {
245 : // standby command successful
246 0 : return(RADIOLIB_ERR_NONE);
247 : }
248 :
249 : // standby command failed, check timeout and try again
250 0 : if(this->mod->hal->millis() - start >= 3000) {
251 : // timed out, possibly incorrect wiring
252 0 : return(state);
253 : }
254 :
255 : // wait a bit to not spam the module
256 0 : this->mod->hal->delay(10);
257 0 : }
258 : }
259 :
260 3 : int16_t SX128x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
261 : // check packet length
262 3 : if(this->codingRateLoRa == RADIOLIB_SX128X_LORA_CR_4_8_LI && this->crcLoRa == RADIOLIB_SX128X_LORA_CRC_ON) {
263 : // Long Interleaver at CR 4/8 supports up to 253 bytes if CRC is enabled
264 0 : if(len > RADIOLIB_SX128X_MAX_PACKET_LENGTH - 2) {
265 0 : return(RADIOLIB_ERR_PACKET_TOO_LONG);
266 : }
267 3 : } else if(len > RADIOLIB_SX128X_MAX_PACKET_LENGTH) {
268 0 : return(RADIOLIB_ERR_PACKET_TOO_LONG);
269 : }
270 :
271 : // check active modem
272 3 : uint8_t modem = getPacketType();
273 3 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
274 0 : return(RADIOLIB_ERR_WRONG_MODEM);
275 : }
276 :
277 : // set mode to standby
278 3 : int16_t state = standby();
279 3 : RADIOLIB_ASSERT(state);
280 :
281 : // calculate timeout in ms (5ms + 500 % of expected time-on-air)
282 0 : RadioLibTime_t timeout = 5 + (getTimeOnAir(len) * 5) / 1000;
283 : RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
284 :
285 : // start transmission
286 0 : state = startTransmit(data, len, addr);
287 0 : RADIOLIB_ASSERT(state);
288 :
289 : // wait for packet transmission or timeout
290 0 : RadioLibTime_t start = this->mod->hal->millis();
291 0 : while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
292 0 : this->mod->hal->yield();
293 0 : if(this->mod->hal->millis() - start > timeout) {
294 0 : finishTransmit();
295 0 : return(RADIOLIB_ERR_TX_TIMEOUT);
296 : }
297 : }
298 :
299 0 : return(finishTransmit());
300 : }
301 :
302 3 : int16_t SX128x::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
303 : // check active modem
304 3 : uint8_t modem = getPacketType();
305 3 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
306 0 : return(RADIOLIB_ERR_WRONG_MODEM);
307 : }
308 :
309 : // set mode to standby
310 3 : int16_t state = standby();
311 3 : RADIOLIB_ASSERT(state);
312 :
313 : // calculate timeout (1000% of expected time-on-air)
314 : // for most other modules, it is 500%, however, the overall datarates of SX128x are higher
315 : // so we use higher value for the default timeout
316 0 : RadioLibTime_t timeoutInternal = timeout;
317 0 : if(!timeoutInternal) {
318 0 : timeoutInternal = getTimeOnAir(len) * 10;
319 : }
320 : RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", (uint32_t)((timeout + 999) / 1000));
321 :
322 : // start reception
323 0 : uint32_t timeoutValue = (uint32_t)((float)timeoutInternal / 15.625f);
324 0 : state = startReceive(timeoutValue);
325 0 : RADIOLIB_ASSERT(state);
326 :
327 : // wait for packet reception or timeout
328 0 : bool softTimeout = false;
329 0 : RadioLibTime_t start = this->mod->hal->micros();
330 0 : while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
331 0 : this->mod->hal->yield();
332 : // safety check, the timeout should be done by the radio
333 0 : if(this->mod->hal->micros() - start > timeout) {
334 0 : softTimeout = true;
335 0 : break;
336 : }
337 : }
338 :
339 : // if it was a timeout, this will return an error code
340 0 : state = standby();
341 0 : if((state != RADIOLIB_ERR_NONE) && (state != RADIOLIB_ERR_SPI_CMD_TIMEOUT)) {
342 0 : return(state);
343 : }
344 :
345 : // check whether this was a timeout or not
346 0 : if(softTimeout || (getIrqStatus() & this->irqMap[RADIOLIB_IRQ_TIMEOUT])) {
347 0 : (void)finishReceive();
348 0 : return(RADIOLIB_ERR_RX_TIMEOUT);
349 : }
350 :
351 : // read the received data
352 0 : return(readData(data, len));
353 : }
354 :
355 3 : int16_t SX128x::transmitDirect(uint32_t frf) {
356 : // set RF switch (if present)
357 3 : this->mod->setRfSwitchState(Module::MODE_TX);
358 :
359 : // user requested to start transmitting immediately (required for RTTY)
360 3 : int16_t state = RADIOLIB_ERR_NONE;
361 3 : if(frf != 0) {
362 0 : state = setRfFrequency(frf);
363 : }
364 3 : RADIOLIB_ASSERT(state);
365 :
366 : // start transmitting
367 3 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_TX_CONTINUOUS_WAVE, NULL, 0));
368 : }
369 :
370 3 : int16_t SX128x::receiveDirect() {
371 : // set RF switch (if present)
372 3 : this->mod->setRfSwitchState(Module::MODE_RX);
373 :
374 : // SX128x is unable to output received data directly
375 3 : return(RADIOLIB_ERR_UNKNOWN);
376 : }
377 :
378 3 : int16_t SX128x::scanChannel() {
379 3 : ChannelScanConfig_t cfg = {
380 : .cad = {
381 : .symNum = RADIOLIB_SX128X_CAD_PARAM_DEFAULT,
382 : .detPeak = 0,
383 : .detMin = 0,
384 : .exitMode = 0,
385 : .timeout = 0,
386 : .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
387 : .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
388 : },
389 : };
390 6 : return(this->scanChannel(cfg));
391 : }
392 :
393 6 : int16_t SX128x::scanChannel(const ChannelScanConfig_t &cfg) {
394 : // set mode to CAD
395 6 : int16_t state = startChannelScan(cfg);
396 6 : RADIOLIB_ASSERT(state);
397 :
398 : // wait for channel activity detected or timeout
399 0 : while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
400 0 : this->mod->hal->yield();
401 : }
402 :
403 : // check CAD result
404 0 : return(getChannelScanResult());
405 : }
406 :
407 3 : int16_t SX128x::sleep() {
408 3 : return(SX128x::sleep(true));
409 : }
410 :
411 3 : int16_t SX128x::sleep(bool retainConfig) {
412 : // set RF switch (if present)
413 3 : this->mod->setRfSwitchState(Module::MODE_IDLE);
414 :
415 3 : uint8_t sleepConfig = RADIOLIB_SX128X_SLEEP_DATA_BUFFER_RETAIN | RADIOLIB_SX128X_SLEEP_DATA_RAM_RETAIN;
416 3 : if(!retainConfig) {
417 0 : sleepConfig = RADIOLIB_SX128X_SLEEP_DATA_BUFFER_FLUSH | RADIOLIB_SX128X_SLEEP_DATA_RAM_FLUSH;
418 : }
419 3 : int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SAVE_CONTEXT, NULL, 0, false, false);
420 3 : RADIOLIB_ASSERT(state);
421 3 : state = this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_SLEEP, &sleepConfig, 1, false, false);
422 :
423 : // wait for SX128x to safely enter sleep mode
424 3 : this->mod->hal->delay(1);
425 :
426 3 : return(state);
427 : }
428 :
429 18 : int16_t SX128x::standby() {
430 18 : return(SX128x::standby(RADIOLIB_SX128X_STANDBY_RC));
431 : }
432 :
433 21 : int16_t SX128x::standby(uint8_t mode) {
434 21 : return(SX128x::standby(mode, true));
435 : }
436 :
437 21 : int16_t SX128x::standby(uint8_t mode, bool wakeup) {
438 : // set RF switch (if present)
439 21 : this->mod->setRfSwitchState(Module::MODE_IDLE);
440 :
441 21 : if(wakeup) {
442 : // send a NOP command - this pulls the NSS low to exit the sleep mode,
443 : // while preventing interference with possible other SPI transactions
444 21 : (void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_SX128X_CMD_NOP, NULL, 0, false, false);
445 : }
446 :
447 21 : const uint8_t data[] = { mode };
448 42 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_STANDBY, data, 1));
449 : }
450 :
451 0 : void SX128x::setDio1Action(void (*func)(void)) {
452 0 : this->mod->hal->attachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()), func, this->mod->hal->GpioInterruptRising);
453 0 : }
454 :
455 0 : void SX128x::clearDio1Action() {
456 0 : this->mod->hal->detachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()));
457 0 : }
458 :
459 0 : void SX128x::setPacketReceivedAction(void (*func)(void)) {
460 0 : this->setDio1Action(func);
461 0 : }
462 :
463 0 : void SX128x::clearPacketReceivedAction() {
464 0 : this->clearDio1Action();
465 0 : }
466 :
467 0 : void SX128x::setPacketSentAction(void (*func)(void)) {
468 0 : this->setDio1Action(func);
469 0 : }
470 :
471 0 : void SX128x::clearPacketSentAction() {
472 0 : this->clearDio1Action();
473 0 : }
474 :
475 3 : int16_t SX128x::finishTransmit() {
476 : // clear interrupt flags
477 3 : clearIrqStatus();
478 :
479 : // set mode to standby to disable transmitter/RF switch
480 3 : return(standby());
481 : }
482 :
483 3 : int16_t SX128x::startReceive() {
484 3 : return(this->startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
485 : }
486 :
487 3 : int16_t SX128x::readData(uint8_t* data, size_t len) {
488 : // check active modem
489 3 : if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
490 0 : return(RADIOLIB_ERR_WRONG_MODEM);
491 : }
492 :
493 : // set mode to standby
494 3 : int16_t state = standby();
495 3 : RADIOLIB_ASSERT(state);
496 :
497 : // check integrity CRC
498 0 : uint16_t irq = getIrqStatus();
499 0 : int16_t crcState = RADIOLIB_ERR_NONE;
500 : // Report CRC mismatch when there's a payload CRC error, or a header error and no valid header (to avoid false alarm from previous packet)
501 0 : if((irq & RADIOLIB_SX128X_IRQ_CRC_ERROR) || ((irq & RADIOLIB_SX128X_IRQ_HEADER_ERROR) && !(irq & RADIOLIB_SX128X_IRQ_HEADER_VALID))) {
502 0 : crcState = RADIOLIB_ERR_CRC_MISMATCH;
503 : }
504 :
505 : // get packet length and Rx buffer offset
506 0 : uint8_t offset = 0;
507 0 : size_t length = getPacketLength(true, &offset);
508 0 : if((len != 0) && (len < length)) {
509 : // user requested less data than we got, only return what was requested
510 0 : length = len;
511 : }
512 :
513 : // read packet data starting at offset
514 0 : state = readBuffer(data, length, offset);
515 0 : RADIOLIB_ASSERT(state);
516 :
517 : // clear interrupt flags
518 0 : state = clearIrqStatus();
519 :
520 : // check if CRC failed - this is done after reading data to give user the option to keep them
521 0 : RADIOLIB_ASSERT(crcState);
522 :
523 0 : return(state);
524 : }
525 :
526 3 : int16_t SX128x::finishReceive() {
527 : // set mode to standby to disable RF switch
528 3 : int16_t state = standby();
529 3 : RADIOLIB_ASSERT(state);
530 :
531 : // clear interrupt flags
532 0 : return(clearIrqStatus());
533 : }
534 :
535 3 : uint32_t SX128x::getIrqFlags() {
536 3 : return((uint32_t)this->getIrqStatus());
537 : }
538 :
539 3 : int16_t SX128x::setIrqFlags(uint32_t irq) {
540 3 : return(this->setDioIrqParams(irq, irq));
541 : }
542 :
543 3 : int16_t SX128x::clearIrqFlags(uint32_t irq) {
544 3 : return(this->clearIrqStatus(irq));
545 : }
546 :
547 3 : int16_t SX128x::startChannelScan() {
548 3 : ChannelScanConfig_t cfg = {
549 : .cad = {
550 : .symNum = RADIOLIB_SX128X_CAD_PARAM_DEFAULT,
551 : .detPeak = 0,
552 : .detMin = 0,
553 : .exitMode = 0,
554 : .timeout = 0,
555 : .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
556 : .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
557 : },
558 : };
559 6 : return(this->startChannelScan(cfg));
560 : }
561 :
562 12 : int16_t SX128x::startChannelScan(const ChannelScanConfig_t &cfg) {
563 : // check active modem
564 12 : if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) {
565 12 : return(RADIOLIB_ERR_WRONG_MODEM);
566 : }
567 :
568 : // set mode to standby
569 0 : int16_t state = standby();
570 0 : RADIOLIB_ASSERT(state);
571 :
572 : // set DIO pin mapping
573 0 : state = setDioIrqParams(getIrqMapped(cfg.cad.irqFlags), getIrqMapped(cfg.cad.irqMask));
574 0 : RADIOLIB_ASSERT(state);
575 :
576 : // clear interrupt flags
577 0 : state = clearIrqStatus();
578 0 : RADIOLIB_ASSERT(state);
579 :
580 : // set RF switch (if present)
581 0 : this->mod->setRfSwitchState(Module::MODE_RX);
582 :
583 : // set mode to CAD
584 0 : return(setCad(cfg.cad.symNum));
585 : }
586 :
587 3 : int16_t SX128x::getChannelScanResult() {
588 : // check active modem
589 3 : if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) {
590 3 : return(RADIOLIB_ERR_WRONG_MODEM);
591 : }
592 :
593 : // check CAD result
594 0 : uint16_t cadResult = getIrqStatus();
595 0 : int16_t state = RADIOLIB_ERR_UNKNOWN;
596 0 : if(cadResult & RADIOLIB_SX128X_IRQ_CAD_DETECTED) {
597 : // detected some LoRa activity
598 0 : state = RADIOLIB_LORA_DETECTED;
599 0 : } else if(cadResult & RADIOLIB_SX128X_IRQ_CAD_DONE) {
600 : // channel is free
601 0 : state = RADIOLIB_CHANNEL_FREE;
602 : }
603 :
604 0 : clearIrqStatus();
605 0 : return(state);
606 : }
607 :
608 3 : int16_t SX128x::setFrequency(float freq) {
609 3 : RADIOLIB_CHECK_RANGE(freq, 2400.0f, 2500.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
610 :
611 : // calculate raw value
612 0 : uint32_t frf = (freq * (uint32_t(1) << RADIOLIB_SX128X_DIV_EXPONENT)) / RADIOLIB_SX128X_CRYSTAL_FREQ;
613 0 : return(setRfFrequency(frf));
614 : }
615 :
616 0 : int16_t SX128x::setBandwidth(float bw) {
617 : // check active modem
618 0 : uint8_t modem = getPacketType();
619 0 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
620 : // check range for LoRa
621 0 : RADIOLIB_CHECK_RANGE(bw, 203.125f, 1625.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
622 0 : } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
623 : // check range for ranging
624 0 : RADIOLIB_CHECK_RANGE(bw, 406.25f, 1625.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
625 : } else {
626 0 : return(RADIOLIB_ERR_WRONG_MODEM);
627 : }
628 :
629 0 : if(fabsf(bw - 203.125f) <= 0.001f) {
630 0 : this->bandwidth = RADIOLIB_SX128X_LORA_BW_203_125;
631 0 : } else if(fabsf(bw - 406.25f) <= 0.001f) {
632 0 : this->bandwidth = RADIOLIB_SX128X_LORA_BW_406_25;
633 0 : } else if(fabsf(bw - 812.5f) <= 0.001f) {
634 0 : this->bandwidth = RADIOLIB_SX128X_LORA_BW_812_50;
635 0 : } else if(fabsf(bw - 1625.0f) <= 0.001f) {
636 0 : this->bandwidth = RADIOLIB_SX128X_LORA_BW_1625_00;
637 : } else {
638 0 : return(RADIOLIB_ERR_INVALID_BANDWIDTH);
639 : }
640 :
641 : // update modulation parameters
642 0 : this->bandwidthKhz = bw;
643 0 : return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRateLoRa));
644 : }
645 :
646 0 : int16_t SX128x::setSpreadingFactor(uint8_t sf) {
647 : // check active modem
648 0 : uint8_t modem = getPacketType();
649 0 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
650 : // check range for LoRa
651 0 : RADIOLIB_CHECK_RANGE(sf, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
652 0 : } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
653 : // check range for ranging
654 0 : RADIOLIB_CHECK_RANGE(sf, 5, 10, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
655 : } else {
656 0 : return(RADIOLIB_ERR_WRONG_MODEM);
657 : }
658 :
659 : // update modulation parameters
660 0 : this->spreadingFactor = sf << 4;
661 0 : int16_t state = setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRateLoRa);
662 0 : RADIOLIB_ASSERT(state);
663 :
664 : // update mystery register in LoRa mode - SX1280 datasheet rev 3.2 section 14.4.1
665 0 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
666 0 : uint8_t data = 0;
667 0 : if((this->spreadingFactor == RADIOLIB_SX128X_LORA_SF_5) || (this->spreadingFactor == RADIOLIB_SX128X_LORA_SF_6)) {
668 0 : data = 0x1E;
669 0 : } else if((this->spreadingFactor == RADIOLIB_SX128X_LORA_SF_7) || (this->spreadingFactor == RADIOLIB_SX128X_LORA_SF_8)) {
670 0 : data = 0x37;
671 : } else {
672 0 : data = 0x32;
673 : }
674 0 : state = SX128x::writeRegister(RADIOLIB_SX128X_REG_LORA_SF_CONFIG, &data, 1);
675 0 : RADIOLIB_ASSERT(state);
676 :
677 : // this register must also be updated for some reason
678 0 : state = SX128x::readRegister(RADIOLIB_SX128X_REG_FREQ_ERROR_CORRECTION, &data, 1);
679 0 : RADIOLIB_ASSERT(state);
680 :
681 0 : data |= 0x01;
682 0 : state = SX128x::writeRegister(RADIOLIB_SX128X_REG_FREQ_ERROR_CORRECTION, &data, 1);
683 0 : RADIOLIB_ASSERT(state);
684 : }
685 :
686 0 : return(state);
687 : }
688 :
689 0 : int16_t SX128x::setCodingRate(uint8_t cr, bool longInterleaving) {
690 : // check active modem
691 0 : uint8_t modem = getPacketType();
692 :
693 : // LoRa/ranging
694 0 : if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) {
695 0 : RADIOLIB_CHECK_RANGE(cr, 4, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
696 :
697 : // update modulation parameters
698 0 : if(longInterleaving && (modem == RADIOLIB_SX128X_PACKET_TYPE_LORA)) {
699 0 : switch(cr) {
700 0 : case 4:
701 0 : this->codingRateLoRa = 0;
702 0 : break;
703 0 : case 5:
704 : case 6:
705 0 : this->codingRateLoRa = cr;
706 0 : break;
707 0 : case 8:
708 0 : this->codingRateLoRa = cr - 1;
709 0 : break;
710 0 : default:
711 0 : return(RADIOLIB_ERR_INVALID_CODING_RATE);
712 : }
713 : } else {
714 0 : this->codingRateLoRa = cr - 4;
715 : }
716 0 : return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRateLoRa));
717 :
718 : // FLRC
719 0 : } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC) {
720 0 : RADIOLIB_CHECK_RANGE(cr, 2, 4, RADIOLIB_ERR_INVALID_CODING_RATE);
721 :
722 : // update modulation parameters
723 0 : this->codingRateFLRC = (cr - 2) * 2;
724 0 : return(setModulationParams(this->bitRate, this->codingRateFLRC, this->shaping));
725 : }
726 :
727 0 : return(RADIOLIB_ERR_WRONG_MODEM);
728 : }
729 :
730 3 : int16_t SX128x::setOutputPower(int8_t pwr) {
731 : // check if power value is configurable
732 3 : int16_t state = checkOutputPower(pwr, NULL);
733 3 : RADIOLIB_ASSERT(state);
734 :
735 3 : this->power = pwr + 18;
736 3 : return(setTxParams(this->power));
737 : }
738 :
739 6 : int16_t SX128x::checkOutputPower(int8_t pwr, int8_t* clipped) {
740 6 : if(clipped) {
741 0 : *clipped = RADIOLIB_MAX(-18, RADIOLIB_MIN(13, pwr));
742 : }
743 6 : RADIOLIB_CHECK_RANGE(pwr, -18, 13, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
744 6 : return(RADIOLIB_ERR_NONE);
745 : }
746 :
747 3 : int16_t SX128x::setModem(ModemType_t modem) {
748 3 : switch(modem) {
749 0 : case(ModemType_t::RADIOLIB_MODEM_LORA): {
750 0 : return(this->begin());
751 : } break;
752 0 : case(ModemType_t::RADIOLIB_MODEM_FSK): {
753 0 : return(this->beginGFSK());
754 : } break;
755 3 : default:
756 3 : return(RADIOLIB_ERR_WRONG_MODEM);
757 : }
758 : }
759 :
760 9 : int16_t SX128x::getModem(ModemType_t* modem) {
761 9 : RADIOLIB_ASSERT_PTR(modem);
762 :
763 9 : switch(getPacketType()) {
764 0 : case(RADIOLIB_SX128X_PACKET_TYPE_LORA):
765 0 : *modem = ModemType_t::RADIOLIB_MODEM_LORA;
766 0 : return(RADIOLIB_ERR_NONE);
767 0 : case(RADIOLIB_SX128X_PACKET_TYPE_GFSK):
768 0 : *modem = ModemType_t::RADIOLIB_MODEM_FSK;
769 0 : return(RADIOLIB_ERR_NONE);
770 : }
771 :
772 9 : return(RADIOLIB_ERR_WRONG_MODEM);
773 : }
774 :
775 3 : int16_t SX128x::setPreambleLength(size_t preambleLength) {
776 3 : uint8_t modem = getPacketType();
777 3 : if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) {
778 : // LoRa or ranging
779 : // the actual limit is 491520, however, some platforms (notably AVR) limit size_t to 16 bits
780 0 : RADIOLIB_CHECK_RANGE(preambleLength, 2, 65534, RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH);
781 :
782 : // check preamble length is even - no point even trying odd numbers
783 0 : if(preambleLength % 2 != 0) {
784 0 : return(RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH);
785 : }
786 :
787 : // calculate exponent and mantissa values (use the next longer preamble if there's no exact match)
788 0 : uint8_t e = 1;
789 0 : uint8_t m = 1;
790 0 : uint32_t len = 0;
791 0 : for(; e <= 15; e++) {
792 0 : for(m = 1; m <= 15; m++) {
793 0 : len = m * (uint32_t(1) << e);
794 0 : if(len >= preambleLength) {
795 0 : break;
796 : }
797 : }
798 0 : if(len >= preambleLength) {
799 0 : break;
800 : }
801 : }
802 :
803 : // update packet parameters
804 0 : this->preambleLengthLoRa = (e << 4) | m;
805 0 : return(setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled));
806 :
807 3 : } else if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) {
808 : // GFSK or FLRC
809 0 : RADIOLIB_CHECK_RANGE(preambleLength, 4, 32, RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH);
810 :
811 : // check preamble length is multiple of 4
812 0 : if(preambleLength % 4 != 0) {
813 0 : return(RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH);
814 : }
815 :
816 : // update packet parameters
817 0 : this->preambleLengthGFSK = ((preambleLength / 4) - 1) << 4;
818 0 : return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType));
819 : }
820 :
821 3 : return(RADIOLIB_ERR_WRONG_MODEM);
822 : }
823 :
824 3 : int16_t SX128x::setDataRate(DataRate_t dr, ModemType_t modem) {
825 : // get the current modem
826 : ModemType_t currentModem;
827 3 : int16_t state = this->getModem(¤tModem);
828 3 : RADIOLIB_ASSERT(state);
829 :
830 : // switch over if the requested modem is different
831 0 : if(modem != RADIOLIB_MODEM_NONE && modem != currentModem) {
832 0 : state = this->standby();
833 0 : RADIOLIB_ASSERT(state);
834 0 : state = this->setModem(modem);
835 0 : RADIOLIB_ASSERT(state);
836 : }
837 :
838 0 : if(modem == RADIOLIB_MODEM_NONE) {
839 0 : modem = currentModem;
840 : }
841 :
842 : // select interpretation based on modem
843 0 : if (modem == RADIOLIB_MODEM_LORA) {
844 0 : state = this->setBandwidth(dr.lora.bandwidth);
845 0 : RADIOLIB_ASSERT(state);
846 0 : state = this->setSpreadingFactor(dr.lora.spreadingFactor);
847 0 : RADIOLIB_ASSERT(state);
848 0 : state = this->setCodingRate(dr.lora.codingRate);
849 : } else {
850 0 : return(RADIOLIB_ERR_WRONG_MODEM);
851 : }
852 0 : return(state);
853 : }
854 :
855 3 : int16_t SX128x::checkDataRate(DataRate_t dr, ModemType_t modem) {
856 3 : int16_t state = RADIOLIB_ERR_UNKNOWN;
857 :
858 : // retrieve modem if not supplied
859 3 : if(modem == RADIOLIB_MODEM_NONE) {
860 3 : state = this->getModem(&modem);
861 3 : RADIOLIB_ASSERT(state);
862 : }
863 :
864 : // select interpretation based on modem
865 0 : if(modem == RADIOLIB_MODEM_FSK) {
866 0 : RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 125.0f, 2000.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
867 0 : RADIOLIB_CHECK_RANGE(dr.fsk.freqDev, 62.5f, 1000.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
868 0 : return(RADIOLIB_ERR_NONE);
869 :
870 0 : } else if(modem == RADIOLIB_MODEM_LORA) {
871 0 : RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
872 0 : RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 203.0f, 1625.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
873 0 : RADIOLIB_CHECK_RANGE(dr.lora.codingRate, 4, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
874 0 : return(RADIOLIB_ERR_NONE);
875 :
876 : }
877 :
878 0 : return(state);
879 : }
880 :
881 3 : int16_t SX128x::setBitRate(float br) {
882 : // check active modem
883 3 : uint8_t modem = getPacketType();
884 :
885 : // GFSK/BLE
886 3 : if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE)) {
887 0 : if((uint16_t)br == 125) {
888 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_125_BW_0_3;
889 0 : } else if((uint16_t)br == 250) {
890 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_250_BW_0_6;
891 0 : } else if((uint16_t)br == 400) {
892 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_400_BW_1_2;
893 0 : } else if((uint16_t)br == 500) {
894 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_500_BW_1_2;
895 0 : } else if((uint16_t)br == 800) {
896 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_800_BW_2_4;
897 0 : } else if((uint16_t)br == 1000) {
898 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_1_000_BW_2_4;
899 0 : } else if((uint16_t)br == 1600) {
900 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_1_600_BW_2_4;
901 0 : } else if((uint16_t)br == 2000) {
902 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_2_000_BW_2_4;
903 : } else {
904 0 : return(RADIOLIB_ERR_INVALID_BIT_RATE);
905 : }
906 :
907 : // update modulation parameters
908 0 : this->bitRateKbps = (uint16_t)br;
909 0 : return(setModulationParams(this->bitRate, this->modIndex, this->shaping));
910 :
911 : // FLRC
912 3 : } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC) {
913 0 : if((uint16_t)br == 260) {
914 0 : this->bitRate = RADIOLIB_SX128X_FLRC_BR_0_260_BW_0_3;
915 0 : } else if((uint16_t)br == 325) {
916 0 : this->bitRate = RADIOLIB_SX128X_FLRC_BR_0_325_BW_0_3;
917 0 : } else if((uint16_t)br == 520) {
918 0 : this->bitRate = RADIOLIB_SX128X_FLRC_BR_0_520_BW_0_6;
919 0 : } else if((uint16_t)br == 650) {
920 0 : this->bitRate = RADIOLIB_SX128X_FLRC_BR_0_650_BW_0_6;
921 0 : } else if((uint16_t)br == 1000) {
922 0 : this->bitRate = RADIOLIB_SX128X_FLRC_BR_1_000_BW_1_2;
923 0 : } else if((uint16_t)br == 1300) {
924 0 : this->bitRate = RADIOLIB_SX128X_FLRC_BR_1_300_BW_1_2;
925 : } else {
926 0 : return(RADIOLIB_ERR_INVALID_BIT_RATE);
927 : }
928 :
929 : // update modulation parameters
930 0 : this->bitRateKbps = (uint16_t)br;
931 0 : return(setModulationParams(this->bitRate, this->codingRateFLRC, this->shaping));
932 :
933 : }
934 :
935 3 : return(RADIOLIB_ERR_WRONG_MODEM);
936 : }
937 :
938 3 : int16_t SX128x::setFrequencyDeviation(float freqDev) {
939 : // check active modem
940 3 : uint8_t modem = getPacketType();
941 3 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE))) {
942 3 : return(RADIOLIB_ERR_WRONG_MODEM);
943 : }
944 :
945 : // set frequency deviation to lowest available setting (required for digimodes)
946 0 : float newFreqDev = freqDev;
947 0 : if(freqDev < 0.0f) {
948 0 : newFreqDev = 62.5f;
949 : }
950 :
951 0 : RADIOLIB_CHECK_RANGE(newFreqDev, 62.5f, 1000.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
952 :
953 : // override for the lowest possible frequency deviation - required for some PhysicalLayer protocols
954 0 : if(newFreqDev == 0.0f) {
955 0 : this->modIndex = RADIOLIB_SX128X_BLE_GFSK_MOD_IND_0_35;
956 0 : this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_125_BW_0_3;
957 0 : return(setModulationParams(this->bitRate, this->modIndex, this->shaping));
958 : }
959 :
960 : // update modulation parameters
961 0 : uint8_t modInd = (uint8_t)((8.0f * (newFreqDev / (float)this->bitRateKbps)) - 1.0f);
962 0 : if(modInd > RADIOLIB_SX128X_BLE_GFSK_MOD_IND_4_00) {
963 0 : return(RADIOLIB_ERR_INVALID_MODULATION_PARAMETERS);
964 : }
965 :
966 : // update modulation parameters
967 0 : this->frequencyDev = newFreqDev;
968 0 : this->modIndex = modInd;
969 0 : return(setModulationParams(this->bitRate, this->modIndex, this->shaping));
970 : }
971 :
972 3 : int16_t SX128x::setDataShaping(uint8_t sh) {
973 : // check active modem
974 3 : uint8_t modem = getPacketType();
975 3 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC))) {
976 3 : return(RADIOLIB_ERR_WRONG_MODEM);
977 : }
978 :
979 : // set data this->shaping
980 0 : switch(sh) {
981 0 : case RADIOLIB_SHAPING_NONE:
982 0 : this->shaping = RADIOLIB_SX128X_BLE_GFSK_BT_OFF;
983 0 : break;
984 0 : case RADIOLIB_SHAPING_0_5:
985 0 : this->shaping = RADIOLIB_SX128X_BLE_GFSK_BT_0_5;
986 0 : break;
987 0 : case RADIOLIB_SHAPING_1_0:
988 0 : this->shaping = RADIOLIB_SX128X_BLE_GFSK_BT_1_0;
989 0 : break;
990 0 : default:
991 0 : return(RADIOLIB_ERR_INVALID_DATA_SHAPING);
992 : }
993 :
994 : // update modulation parameters
995 0 : if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE)) {
996 0 : return(setModulationParams(this->bitRate, this->modIndex, this->shaping));
997 : } else {
998 0 : return(setModulationParams(this->bitRate, this->codingRateFLRC, this->shaping));
999 : }
1000 : }
1001 :
1002 3 : int16_t SX128x::setSyncWord(uint8_t* sync, size_t len) {
1003 : // check active modem
1004 3 : uint8_t modem = getPacketType();
1005 3 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC))) {
1006 3 : return(RADIOLIB_ERR_WRONG_MODEM);
1007 : }
1008 :
1009 0 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) {
1010 : // GFSK can use up to 5 bytes as sync word
1011 0 : if(len > 5) {
1012 0 : return(RADIOLIB_ERR_INVALID_SYNC_WORD);
1013 : }
1014 :
1015 : // calculate sync word length parameter value
1016 0 : if(len > 0) {
1017 0 : this->syncWordLen = (len - 1)*2;
1018 : }
1019 :
1020 : } else {
1021 : // FLRC requires 32-bit sync word
1022 0 : if(!((len == 0) || (len == 4))) {
1023 0 : return(RADIOLIB_ERR_INVALID_SYNC_WORD);
1024 : }
1025 :
1026 : // save sync word length parameter value
1027 0 : this->syncWordLen = len;
1028 : }
1029 :
1030 : // update sync word
1031 0 : int16_t state = SX128x::writeRegister(RADIOLIB_SX128X_REG_SYNC_WORD_1_BYTE_4 + (5 - len), sync, len);
1032 0 : RADIOLIB_ASSERT(state);
1033 :
1034 : // update packet parameters
1035 0 : if(this->syncWordLen == 0) {
1036 0 : this->syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_OFF;
1037 : } else {
1038 : /// \todo add support for multiple sync words
1039 0 : this->syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_1;
1040 : }
1041 0 : return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType));
1042 : }
1043 :
1044 0 : int16_t SX128x::setSyncWord(uint8_t syncWord, uint8_t controlBits) {
1045 : // check active modem
1046 0 : if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) {
1047 0 : return(RADIOLIB_ERR_WRONG_MODEM);
1048 : }
1049 :
1050 : // update register
1051 0 : const uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))};
1052 0 : return(writeRegister(RADIOLIB_SX128X_REG_LORA_SYNC_WORD_MSB, data, 2));
1053 : }
1054 :
1055 0 : int16_t SX128x::setCRC(uint8_t len, uint32_t initial, uint16_t polynomial) {
1056 : // check active modem
1057 0 : uint8_t modem = getPacketType();
1058 :
1059 : int16_t state;
1060 0 : if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) {
1061 : // update packet parameters
1062 0 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) {
1063 0 : if(len > 2) {
1064 0 : return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION);
1065 : }
1066 : } else {
1067 0 : if(len > 3) {
1068 0 : return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION);
1069 : }
1070 : }
1071 0 : this->crcGFSK = len << 4;
1072 0 : state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType);
1073 0 : RADIOLIB_ASSERT(state);
1074 :
1075 : // set initial CRC value
1076 0 : uint8_t data[] = { (uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF) };
1077 0 : state = writeRegister(RADIOLIB_SX128X_REG_CRC_INITIAL_MSB, data, 2);
1078 0 : RADIOLIB_ASSERT(state);
1079 :
1080 : // set CRC polynomial
1081 0 : data[0] = (uint8_t)((polynomial >> 8) & 0xFF);
1082 0 : data[1] = (uint8_t)(polynomial & 0xFF);
1083 0 : state = writeRegister(RADIOLIB_SX128X_REG_CRC_POLYNOMIAL_MSB, data, 2);
1084 0 : return(state);
1085 :
1086 0 : } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
1087 : // update packet parameters
1088 0 : if(len == 0) {
1089 0 : this->crcBLE = RADIOLIB_SX128X_BLE_CRC_OFF;
1090 0 : } else if(len == 3) {
1091 0 : this->crcBLE = RADIOLIB_SX128X_BLE_CRC_3_BYTE;
1092 : } else {
1093 0 : return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION);
1094 : }
1095 0 : state = setPacketParamsBLE(this->connectionState, this->crcBLE, this->bleTestPayload, this->whitening);
1096 0 : RADIOLIB_ASSERT(state);
1097 :
1098 : // set initial CRC value
1099 0 : const uint8_t data[] = { (uint8_t)((initial >> 16) & 0xFF), (uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF) };
1100 0 : state = writeRegister(RADIOLIB_SX128X_REG_BLE_CRC_INITIAL_MSB, data, 3);
1101 0 : return(state);
1102 :
1103 0 : } else if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) {
1104 : // update packet parameters
1105 0 : if(len == 0) {
1106 0 : this->crcLoRa = RADIOLIB_SX128X_LORA_CRC_OFF;
1107 0 : } else if(len == 2) {
1108 0 : this->crcLoRa = RADIOLIB_SX128X_LORA_CRC_ON;
1109 : } else {
1110 0 : return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION);
1111 : }
1112 0 : state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled);
1113 0 : return(state);
1114 : }
1115 :
1116 0 : return(RADIOLIB_ERR_UNKNOWN);
1117 : }
1118 :
1119 3 : int16_t SX128x::setWhitening(bool enabled) {
1120 : // check active modem
1121 3 : uint8_t modem = getPacketType();
1122 3 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE))) {
1123 3 : return(RADIOLIB_ERR_WRONG_MODEM);
1124 : }
1125 :
1126 : // update packet parameters
1127 0 : if(enabled) {
1128 0 : this->whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_ON;
1129 : } else {
1130 0 : this->whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_OFF;
1131 : }
1132 :
1133 0 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) {
1134 0 : return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType));
1135 : }
1136 0 : return(setPacketParamsBLE(this->connectionState, this->crcBLE, this->bleTestPayload, this->whitening));
1137 : }
1138 :
1139 0 : int16_t SX128x::setAccessAddress(uint32_t addr) {
1140 : // check active modem
1141 0 : if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_BLE) {
1142 0 : return(RADIOLIB_ERR_WRONG_MODEM);
1143 : }
1144 :
1145 : // set the address
1146 0 : const uint8_t addrBuff[] = { (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
1147 0 : return(SX128x::writeRegister(RADIOLIB_SX128X_REG_ACCESS_ADDRESS_BYTE_3, addrBuff, 4));
1148 : }
1149 :
1150 0 : int16_t SX128x::setHighSensitivityMode(bool enable) {
1151 : // read the current registers
1152 0 : uint8_t RxGain = 0;
1153 0 : int16_t state = readRegister(RADIOLIB_SX128X_REG_GAIN_MODE, &RxGain, 1);
1154 0 : RADIOLIB_ASSERT(state);
1155 :
1156 0 : if(enable) {
1157 0 : RxGain |= 0xC0; // Set bits 6 and 7
1158 : } else {
1159 0 : RxGain &= ~0xC0; // Unset bits 6 and 7
1160 : }
1161 :
1162 : // update all values
1163 0 : state = writeRegister(RADIOLIB_SX128X_REG_GAIN_MODE, &RxGain, 1);
1164 0 : return(state);
1165 : }
1166 :
1167 0 : int16_t SX128x::setGainControl(uint8_t gain) {
1168 : // read the current registers
1169 0 : uint8_t ManualGainSetting = 0;
1170 0 : int16_t state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_2, &ManualGainSetting, 1);
1171 0 : RADIOLIB_ASSERT(state);
1172 0 : uint8_t LNAGainValue = 0;
1173 0 : state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_SETTING, &LNAGainValue, 1);
1174 0 : RADIOLIB_ASSERT(state);
1175 0 : uint8_t LNAGainControl = 0;
1176 0 : state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_1, &LNAGainControl, 1);
1177 0 : RADIOLIB_ASSERT(state);
1178 :
1179 : // set the gain
1180 0 : if (gain > 0 && gain < 14) {
1181 : // Set manual gain
1182 0 : ManualGainSetting &= ~0x01; // Set bit 0 to 0 (Enable Manual Gain Control)
1183 0 : LNAGainValue &= 0xF0; // Bits 0, 1, 2 and 3 to 0
1184 0 : LNAGainValue |= gain; // Set bits 0, 1, 2 and 3 to Manual Gain Setting (1-13)
1185 0 : LNAGainControl |= 0x80; // Set bit 7 to 1 (Enable Manual Gain Control)
1186 : } else {
1187 : // Set automatic gain if 0 or out of range
1188 0 : ManualGainSetting |= 0x01; // Set bit 0 to 1 (Enable Automatic Gain Control)
1189 0 : LNAGainValue &= 0xF0; // Bits 0, 1, 2 and 3 to 0
1190 0 : LNAGainValue |= 0x0A; // Set bits 0, 1, 2 and 3 to Manual Gain Setting (1-13)
1191 0 : LNAGainControl &= ~0x80; // Set bit 7 to 0 (Enable Automatic Gain Control)
1192 : }
1193 :
1194 : // update all values
1195 0 : state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_2, &ManualGainSetting, 1);
1196 0 : RADIOLIB_ASSERT(state);
1197 0 : state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_SETTING, &LNAGainValue, 1);
1198 0 : RADIOLIB_ASSERT(state);
1199 0 : state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_1, &LNAGainControl, 1);
1200 0 : return(state);
1201 : }
1202 :
1203 3 : float SX128x::getRSSI() {
1204 : // get packet status
1205 : uint8_t packetStatus[5];
1206 3 : this->mod->SPIreadStream(RADIOLIB_SX128X_CMD_GET_PACKET_STATUS, packetStatus, 5);
1207 :
1208 : // check active modem
1209 3 : uint8_t modem = getPacketType();
1210 3 : if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) {
1211 : // LoRa or ranging
1212 0 : uint8_t rssiSync = packetStatus[0];
1213 0 : float rssiMeasured = -1.0 * rssiSync/2.0;
1214 0 : float snr = getSNR();
1215 0 : if(snr <= 0.0f) {
1216 0 : return(rssiMeasured - snr);
1217 : } else {
1218 0 : return(rssiMeasured);
1219 : }
1220 : } else {
1221 : // GFSK, BLE or FLRC
1222 3 : uint8_t rssiSync = packetStatus[1];
1223 3 : return(-1.0 * rssiSync/2.0);
1224 : }
1225 : }
1226 :
1227 0 : float SX128x::getRSSI(bool packet) {
1228 0 : if (!packet) {
1229 : // get instantaneous RSSI value
1230 0 : uint8_t data[3] = {0, 0, 0}; // RssiInst, Status, RFU
1231 0 : this->mod->SPIreadStream(RADIOLIB_SX128X_CMD_GET_RSSI_INST, data, 3);
1232 0 : return ((float)data[0] / (-2.0f));
1233 : } else {
1234 0 : return this->getRSSI();
1235 : }
1236 : }
1237 :
1238 3 : float SX128x::getSNR() {
1239 : // check active modem
1240 3 : uint8_t modem = getPacketType();
1241 3 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) {
1242 3 : return(0.0);
1243 : }
1244 :
1245 : // get packet status
1246 : uint8_t packetStatus[5];
1247 0 : this->mod->SPIreadStream(RADIOLIB_SX128X_CMD_GET_PACKET_STATUS, packetStatus, 5);
1248 :
1249 : // calculate real SNR
1250 0 : uint8_t snr = packetStatus[1];
1251 0 : if(snr < 128) {
1252 0 : return(snr/4.0);
1253 : } else {
1254 0 : return((snr - 256)/4.0f);
1255 : }
1256 : }
1257 :
1258 0 : float SX128x::getFrequencyError() {
1259 : // check active modem
1260 0 : uint8_t modem = getPacketType();
1261 0 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) {
1262 0 : return(0.0);
1263 : }
1264 :
1265 : // read the raw frequency error register values
1266 0 : uint8_t efeRaw[3] = {0};
1267 0 : int16_t state = readRegister(RADIOLIB_SX128X_REG_FEI_MSB, &efeRaw[0], 1);
1268 0 : RADIOLIB_ASSERT(state);
1269 0 : state = readRegister(RADIOLIB_SX128X_REG_FEI_MID, &efeRaw[1], 1);
1270 0 : RADIOLIB_ASSERT(state);
1271 0 : state = readRegister(RADIOLIB_SX128X_REG_FEI_LSB, &efeRaw[2], 1);
1272 0 : RADIOLIB_ASSERT(state);
1273 0 : uint32_t efe = ((uint32_t) efeRaw[0] << 16) | ((uint32_t) efeRaw[1] << 8) | efeRaw[2];
1274 0 : efe &= 0x0FFFFF;
1275 :
1276 0 : float error = 0;
1277 :
1278 : // check the first bit
1279 0 : if (efe & 0x80000) {
1280 : // frequency error is negative
1281 0 : efe |= (uint32_t) 0xFFF00000;
1282 0 : efe = ~efe + 1;
1283 0 : error = 1.55f * (float) efe / (1600.0f / this->bandwidthKhz) * -1.0f;
1284 : } else {
1285 0 : error = 1.55f * (float) efe / (1600.0f / this->bandwidthKhz);
1286 : }
1287 :
1288 0 : return(error);
1289 : }
1290 :
1291 3 : size_t SX128x::getPacketLength(bool update) {
1292 3 : return(this->getPacketLength(update, NULL));
1293 : }
1294 :
1295 3 : size_t SX128x::getPacketLength(bool update, uint8_t* offset) {
1296 : (void)update;
1297 :
1298 : // in implicit mode, return the cached value
1299 3 : if((getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_LORA) && (this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT)) {
1300 0 : return(this->payloadLen);
1301 : }
1302 :
1303 3 : uint8_t rxBufStatus[2] = {0, 0};
1304 3 : this->mod->SPIreadStream(RADIOLIB_SX128X_CMD_GET_RX_BUFFER_STATUS, rxBufStatus, 2);
1305 :
1306 3 : if(offset) { *offset = rxBufStatus[1]; }
1307 :
1308 3 : return((size_t)rxBufStatus[0]);
1309 : }
1310 :
1311 0 : int16_t SX128x::getLoRaRxHeaderInfo(uint8_t* cr, bool* hasCRC) {
1312 0 : int16_t state = RADIOLIB_ERR_NONE;
1313 :
1314 : // check if in explicit header mode
1315 0 : if(this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) {
1316 0 : return(RADIOLIB_ERR_WRONG_MODEM);
1317 : }
1318 :
1319 0 : if(cr) { *cr = this->mod->SPIgetRegValue(RADIOLIB_SX128X_REG_LORA_RX_CODING_RATE, 6, 4) >> 4; }
1320 0 : if(hasCRC) { *hasCRC = (this->mod->SPIgetRegValue(RADIOLIB_SX128X_REG_FEI_MSB, 4, 4) != 0); }
1321 :
1322 0 : return(state);
1323 : }
1324 :
1325 0 : int16_t SX128x::fixedPacketLengthMode(uint8_t len) {
1326 0 : return(setPacketMode(RADIOLIB_SX128X_GFSK_FLRC_PACKET_FIXED, len));
1327 : }
1328 :
1329 0 : int16_t SX128x::variablePacketLengthMode(uint8_t maxLen) {
1330 0 : return(setPacketMode(RADIOLIB_SX128X_GFSK_FLRC_PACKET_VARIABLE, maxLen));
1331 : }
1332 :
1333 13 : RadioLibTime_t SX128x::calculateTimeOnAir(ModemType_t modem, DataRate_t dr, PacketConfig_t pc, size_t len) {
1334 13 : switch(modem) {
1335 6 : case (ModemType_t::RADIOLIB_MODEM_LORA): {
1336 : // calculate number of symbols
1337 6 : float N_symbol = 0;
1338 6 : uint8_t sf = dr.lora.spreadingFactor;
1339 6 : float cr = (float)dr.lora.codingRate;
1340 :
1341 : // get SF coefficients
1342 6 : float coeff1 = 0;
1343 6 : int16_t coeff2 = 0;
1344 6 : int16_t coeff3 = 0;
1345 6 : if(sf < 7) {
1346 : // SF5, SF6
1347 3 : coeff1 = 6.25;
1348 3 : coeff2 = 4*sf;
1349 3 : coeff3 = 4*sf;
1350 3 : } else if(sf < 11) {
1351 : // SF7. SF8, SF9, SF10
1352 0 : coeff1 = 4.25;
1353 0 : coeff2 = 4*sf + 8;
1354 0 : coeff3 = 4*sf;
1355 : } else {
1356 : // SF11, SF12
1357 3 : coeff1 = 4.25;
1358 3 : coeff2 = 4*sf + 8;
1359 3 : coeff3 = 4*(sf - 2);
1360 : }
1361 :
1362 : // get CRC length
1363 6 : int16_t N_bitCRC = 16;
1364 6 : if(!pc.lora.crcEnabled) {
1365 0 : N_bitCRC = 0;
1366 : }
1367 :
1368 : // get header length
1369 6 : int16_t N_symbolHeader = 20;
1370 6 : if(pc.lora.implicitHeader) {
1371 0 : N_symbolHeader = 0;
1372 : }
1373 :
1374 : // calculate number of LoRa preamble symbols
1375 6 : uint32_t N_symbolPreamble = pc.lora.preambleLength;
1376 :
1377 : // calculate the number of symbols
1378 6 : N_symbol = (float)N_symbolPreamble + coeff1 + 8.0f + ceilf((float)RADIOLIB_MAX((int16_t)(8 * len + N_bitCRC - coeff2 + N_symbolHeader), (int16_t)0) / (float)coeff3) * cr;
1379 :
1380 : // get time-on-air in us
1381 6 : return(((uint32_t(1) << sf) / dr.lora.bandwidth) * N_symbol * 1000.0f);
1382 : }
1383 4 : case (ModemType_t::RADIOLIB_MODEM_FSK):
1384 4 : return((((float)(pc.fsk.crcLength * 8) + pc.fsk.syncWordLength + pc.fsk.preambleLength + (uint32_t)len * 8) / (dr.fsk.bitRate / 1000.0f)));
1385 :
1386 3 : default:
1387 3 : return(RADIOLIB_ERR_WRONG_MODEM);
1388 : }
1389 :
1390 : }
1391 :
1392 3 : RadioLibTime_t SX128x::getTimeOnAir(size_t len) {
1393 : // check active modem
1394 3 : uint8_t modem = getPacketType();
1395 3 : DataRate_t dr = {};
1396 3 : PacketConfig_t pc = {};
1397 :
1398 3 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
1399 0 : uint8_t sf = this->spreadingFactor >> 4;
1400 0 : uint8_t cr = this->codingRateLoRa;
1401 : // We assume same calculation for short and long interleaving, so map CR values 0-4 and 5-7 to the same values
1402 0 : if (cr < 5) {
1403 0 : cr = cr + 4;
1404 0 : } else if (cr == 7) {
1405 0 : cr = cr + 1;
1406 : }
1407 :
1408 0 : dr.lora.spreadingFactor = sf;
1409 0 : dr.lora.codingRate = cr;
1410 0 : dr.lora.bandwidth = this->bandwidthKhz;
1411 :
1412 0 : uint16_t preambleLength = (this->preambleLengthLoRa & 0x0F) * (uint32_t(1) << ((this->preambleLengthLoRa & 0xF0) >> 4));
1413 :
1414 0 : pc.lora.preambleLength = preambleLength;
1415 0 : pc.lora.implicitHeader = this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT;
1416 0 : pc.lora.crcEnabled = this->crcLoRa == RADIOLIB_SX128X_LORA_CRC_ON;
1417 0 : pc.lora.ldrOptimize = false;
1418 :
1419 0 : return(calculateTimeOnAir(ModemType_t::RADIOLIB_MODEM_LORA, dr, pc, len));
1420 3 : } else if (modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) {
1421 0 : dr.fsk.bitRate = (float)this->bitRateKbps;
1422 0 : dr.fsk.freqDev = this->frequencyDev;
1423 :
1424 0 : pc.fsk.preambleLength = ((uint16_t)this->preambleLengthGFSK >> 2) + 4;
1425 0 : pc.fsk.syncWordLength = ((this->syncWordLen >> 1) + 1) * 8;
1426 0 : pc.fsk.crcLength = this->crcGFSK >> 4;
1427 :
1428 0 : return(calculateTimeOnAir(ModemType_t::RADIOLIB_MODEM_FSK, dr, pc, len));
1429 : } else {
1430 3 : return(RADIOLIB_ERR_WRONG_MODEM);
1431 : }
1432 :
1433 : }
1434 :
1435 3 : RadioLibTime_t SX128x::calculateRxTimeout(RadioLibTime_t timeoutUs) {
1436 : // the timeout value is given in units of 15.625 microseconds
1437 : // the calling function should provide some extra width, as this number of units is truncated to integer
1438 3 : RadioLibTime_t timeout = timeoutUs / 15.625f;
1439 3 : return(timeout);
1440 : }
1441 :
1442 0 : int16_t SX128x::implicitHeader(size_t len) {
1443 0 : return(setHeaderType(RADIOLIB_SX128X_LORA_HEADER_IMPLICIT, len));
1444 : }
1445 :
1446 0 : int16_t SX128x::explicitHeader() {
1447 0 : return(setHeaderType(RADIOLIB_SX128X_LORA_HEADER_EXPLICIT));
1448 : }
1449 :
1450 3 : int16_t SX128x::setEncoding(uint8_t encoding) {
1451 3 : return(setWhitening(encoding));
1452 : }
1453 :
1454 0 : void SX128x::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
1455 0 : this->mod->setRfSwitchPins(rxEn, txEn);
1456 0 : }
1457 :
1458 0 : void SX128x::setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
1459 0 : this->mod->setRfSwitchTable(pins, table);
1460 0 : }
1461 :
1462 3 : uint8_t SX128x::randomByte() {
1463 : // it's unclear whether SX128x can measure RSSI while not receiving a packet
1464 : // this method is implemented only for PhysicalLayer compatibility
1465 3 : return(0);
1466 : }
1467 :
1468 3 : int16_t SX128x::invertIQ(bool enable) {
1469 3 : if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) {
1470 3 : return(RADIOLIB_ERR_WRONG_MODEM);
1471 : }
1472 :
1473 0 : if(enable) {
1474 0 : this->invertIQEnabled = RADIOLIB_SX128X_LORA_IQ_INVERTED;
1475 : } else {
1476 0 : this->invertIQEnabled = RADIOLIB_SX128X_LORA_IQ_STANDARD;
1477 : }
1478 :
1479 0 : return(setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled));
1480 : }
1481 :
1482 12 : int16_t SX128x::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
1483 : int16_t state;
1484 :
1485 12 : switch(mode) {
1486 9 : case(RADIOLIB_RADIO_MODE_RX): {
1487 : // in implicit header mode, use the provided length if it is nonzero
1488 : // otherwise we trust the user has previously set the payload length manually
1489 9 : if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (cfg->receive.len != 0)) {
1490 0 : this->payloadLen = cfg->receive.len;
1491 : }
1492 :
1493 : // check active modem
1494 9 : if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
1495 0 : return(RADIOLIB_ERR_WRONG_MODEM);
1496 : }
1497 :
1498 : // set DIO mapping
1499 9 : if(cfg->receive.timeout != RADIOLIB_SX128X_RX_TIMEOUT_INF) {
1500 6 : cfg->receive.irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
1501 : }
1502 :
1503 9 : state = setDioIrqParams(getIrqMapped(cfg->receive.irqFlags), getIrqMapped(cfg->receive.irqMask));
1504 9 : RADIOLIB_ASSERT(state);
1505 :
1506 : // set buffer pointers
1507 0 : state = setBufferBaseAddress();
1508 0 : RADIOLIB_ASSERT(state);
1509 :
1510 : // clear interrupt flags
1511 0 : state = clearIrqStatus();
1512 0 : RADIOLIB_ASSERT(state);
1513 :
1514 : // set implicit mode and expected len if applicable
1515 0 : if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_LORA)) {
1516 0 : state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled);
1517 0 : RADIOLIB_ASSERT(state);
1518 : }
1519 : // if max(uint32_t) is used, revert to RxContinuous
1520 0 : if(cfg->receive.timeout == 0xFFFFFFFF) {
1521 0 : cfg->receive.timeout = 0xFFFF;
1522 : }
1523 0 : this->rxTimeout = cfg->receive.timeout;
1524 0 : } break;
1525 :
1526 3 : case(RADIOLIB_RADIO_MODE_TX): {
1527 : // check packet length
1528 3 : if(cfg->transmit.len > RADIOLIB_SX128X_MAX_PACKET_LENGTH) {
1529 0 : return(RADIOLIB_ERR_PACKET_TOO_LONG);
1530 : }
1531 :
1532 : // set packet Length
1533 3 : uint8_t modem = getPacketType();
1534 3 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
1535 0 : state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, cfg->transmit.len, this->crcLoRa, this->invertIQEnabled);
1536 3 : } else if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) {
1537 0 : state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType, cfg->transmit.len);
1538 3 : } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
1539 0 : state = setPacketParamsBLE(this->connectionState, this->crcBLE, this->bleTestPayload, this->whitening);
1540 : } else {
1541 3 : return(RADIOLIB_ERR_WRONG_MODEM);
1542 : }
1543 0 : RADIOLIB_ASSERT(state);
1544 :
1545 : // update output power
1546 0 : state = setTxParams(this->power);
1547 0 : RADIOLIB_ASSERT(state);
1548 :
1549 : // set buffer pointers
1550 0 : state = setBufferBaseAddress();
1551 0 : RADIOLIB_ASSERT(state);
1552 :
1553 : // write packet to buffer
1554 0 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
1555 : // first 2 bytes of BLE payload are PDU header
1556 0 : state = writeBuffer(cfg->transmit.data, cfg->transmit.len, 2);
1557 0 : RADIOLIB_ASSERT(state);
1558 : } else {
1559 0 : state = writeBuffer(cfg->transmit.data, cfg->transmit.len);
1560 0 : RADIOLIB_ASSERT(state);
1561 : }
1562 :
1563 : // set DIO mapping
1564 0 : state = setDioIrqParams(RADIOLIB_SX128X_IRQ_TX_DONE | RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT, RADIOLIB_SX128X_IRQ_TX_DONE);
1565 0 : RADIOLIB_ASSERT(state);
1566 :
1567 : // clear interrupt flags
1568 0 : state = clearIrqStatus();
1569 0 : RADIOLIB_ASSERT(state);
1570 0 : } break;
1571 :
1572 0 : default:
1573 0 : return(RADIOLIB_ERR_UNSUPPORTED);
1574 : }
1575 :
1576 0 : this->stagedMode = mode;
1577 0 : return(state);
1578 : }
1579 :
1580 3 : int16_t SX128x::launchMode() {
1581 : int16_t state;
1582 3 : switch(this->stagedMode) {
1583 3 : case(RADIOLIB_RADIO_MODE_RX): {
1584 3 : this->mod->setRfSwitchState(Module::MODE_RX);
1585 3 : state = setRx(this->rxTimeout);
1586 3 : RADIOLIB_ASSERT(state);
1587 0 : } break;
1588 :
1589 0 : case(RADIOLIB_RADIO_MODE_TX): {
1590 0 : this->mod->setRfSwitchState(Module::MODE_TX);
1591 0 : state = setTx(RADIOLIB_SX128X_TX_TIMEOUT_NONE);
1592 0 : RADIOLIB_ASSERT(state);
1593 :
1594 : // wait for BUSY to go low (= PA ramp up done)
1595 0 : while(this->mod->hal->digitalRead(this->mod->getGpio())) {
1596 0 : this->mod->hal->yield();
1597 : }
1598 0 : } break;
1599 :
1600 0 : default:
1601 0 : return(RADIOLIB_ERR_UNSUPPORTED);
1602 : }
1603 :
1604 0 : this->stagedMode = RADIOLIB_RADIO_MODE_NONE;
1605 0 : return(state);
1606 : }
1607 :
1608 : #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
1609 0 : void SX128x::setDirectAction(void (*func)(void)) {
1610 : // SX128x is unable to perform direct mode reception
1611 : // this method is implemented only for PhysicalLayer compatibility
1612 : (void)func;
1613 0 : }
1614 :
1615 0 : void SX128x::readBit(uint32_t pin) {
1616 : // SX128x is unable to perform direct mode reception
1617 : // this method is implemented only for PhysicalLayer compatibility
1618 : (void)pin;
1619 0 : }
1620 : #endif
1621 :
1622 0 : Module* SX128x::getMod() {
1623 0 : return(this->mod);
1624 : }
1625 :
1626 0 : int16_t SX128x::modSetup(uint8_t modem) {
1627 : // set module properties
1628 0 : this->mod->init();
1629 0 : this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
1630 0 : this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
1631 0 : this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
1632 0 : this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
1633 0 : this->mod->spiConfig.statusPos = 1;
1634 0 : this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX128X_CMD_READ_REGISTER;
1635 0 : this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
1636 0 : this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX128X_CMD_NOP;
1637 0 : this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX128X_CMD_GET_STATUS;
1638 0 : this->mod->spiConfig.stream = true;
1639 0 : this->mod->spiConfig.parseStatusCb = SPIparseStatus;
1640 :
1641 : // find the chip - this will also reset the module and verify the module
1642 0 : if(!SX128x::findChip(this->chipType)) {
1643 : RADIOLIB_DEBUG_BASIC_PRINTLN("No SX128x found!");
1644 0 : this->mod->term();
1645 0 : return(RADIOLIB_ERR_CHIP_NOT_FOUND);
1646 : }
1647 : RADIOLIB_DEBUG_BASIC_PRINTLN("M\tSX128x");
1648 :
1649 : // configure settings not accessible by API
1650 0 : return(config(modem));
1651 : }
1652 :
1653 0 : uint8_t SX128x::getStatus() {
1654 0 : uint8_t data = 0;
1655 0 : this->mod->SPIreadStream(RADIOLIB_SX128X_CMD_GET_STATUS, &data, 0);
1656 0 : return(data);
1657 : }
1658 :
1659 0 : int16_t SX128x::writeRegister(uint16_t addr, const uint8_t* data, uint8_t numBytes) {
1660 0 : this->mod->SPIwriteRegisterBurst(addr, data, numBytes);
1661 0 : return(RADIOLIB_ERR_NONE);
1662 : }
1663 :
1664 0 : int16_t SX128x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
1665 : // send the command
1666 0 : this->mod->SPIreadRegisterBurst(addr, numBytes, data);
1667 :
1668 : // check the status
1669 0 : int16_t state = this->mod->SPIcheckStream();
1670 0 : return(state);
1671 : }
1672 :
1673 0 : int16_t SX128x::writeBuffer(const uint8_t* data, uint8_t numBytes, uint8_t offset) {
1674 0 : const uint8_t cmd[] = { RADIOLIB_SX128X_CMD_WRITE_BUFFER, offset };
1675 0 : return(this->mod->SPIwriteStream(cmd, 2, data, numBytes));
1676 : }
1677 :
1678 0 : int16_t SX128x::readBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) {
1679 0 : const uint8_t cmd[] = { RADIOLIB_SX128X_CMD_READ_BUFFER, offset };
1680 0 : return(this->mod->SPIreadStream(cmd, 2, data, numBytes));
1681 : }
1682 :
1683 0 : int16_t SX128x::setTx(uint16_t periodBaseCount, uint8_t periodBase) {
1684 0 : const uint8_t data[] = { periodBase, (uint8_t)((periodBaseCount >> 8) & 0xFF), (uint8_t)(periodBaseCount & 0xFF) };
1685 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_TX, data, 3));
1686 : }
1687 :
1688 3 : int16_t SX128x::setRx(uint16_t periodBaseCount, uint8_t periodBase) {
1689 3 : const uint8_t data[] = { periodBase, (uint8_t)((periodBaseCount >> 8) & 0xFF), (uint8_t)(periodBaseCount & 0xFF) };
1690 6 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_RX, data, 3));
1691 : }
1692 :
1693 0 : int16_t SX128x::setCad(uint8_t symbolNum) {
1694 : // configure parameters
1695 0 : int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_CAD_PARAMS, &symbolNum, 1);
1696 0 : RADIOLIB_ASSERT(state);
1697 :
1698 : // start CAD
1699 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_CAD, NULL, 0));
1700 : }
1701 :
1702 78 : uint8_t SX128x::getPacketType() {
1703 78 : uint8_t data = 0xFF;
1704 78 : this->mod->SPIreadStream(RADIOLIB_SX128X_CMD_GET_PACKET_TYPE, &data, 1);
1705 78 : return(data);
1706 : }
1707 :
1708 0 : int16_t SX128x::setRfFrequency(uint32_t frf) {
1709 0 : const uint8_t data[] = { (uint8_t)((frf >> 16) & 0xFF), (uint8_t)((frf >> 8) & 0xFF), (uint8_t)(frf & 0xFF) };
1710 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_RF_FREQUENCY, data, 3));
1711 : }
1712 :
1713 3 : int16_t SX128x::setTxParams(uint8_t pwr, uint8_t rampTime) {
1714 3 : const uint8_t data[] = { pwr, rampTime };
1715 6 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_TX_PARAMS, data, 2));
1716 : }
1717 :
1718 0 : int16_t SX128x::setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) {
1719 0 : const uint8_t data[] = { txBaseAddress, rxBaseAddress };
1720 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_BUFFER_BASE_ADDRESS, data, 2));
1721 : }
1722 :
1723 0 : int16_t SX128x::setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3) {
1724 0 : const uint8_t data[] = { modParam1, modParam2, modParam3 };
1725 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_MODULATION_PARAMS, data, 3));
1726 : }
1727 :
1728 0 : int16_t SX128x::setPacketParamsGFSK(uint8_t preambleLen, uint8_t syncLen, uint8_t syncMatch, uint8_t crcLen, uint8_t whiten, uint8_t hdrType, uint8_t payLen) {
1729 0 : const uint8_t data[] = { preambleLen, syncLen, syncMatch, hdrType, payLen, crcLen, whiten };
1730 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7));
1731 : }
1732 :
1733 0 : int16_t SX128x::setPacketParamsBLE(uint8_t connState, uint8_t crcLen, uint8_t bleTest, uint8_t whiten) {
1734 0 : const uint8_t data[] = { connState, crcLen, bleTest, whiten, 0x00, 0x00, 0x00 };
1735 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7));
1736 : }
1737 :
1738 0 : int16_t SX128x::setPacketParamsLoRa(uint8_t preambleLen, uint8_t hdrType, uint8_t payLen, uint8_t crc, uint8_t invIQ) {
1739 0 : const uint8_t data[] = { preambleLen, hdrType, payLen, crc, invIQ, 0x00, 0x00 };
1740 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7));
1741 : }
1742 :
1743 12 : int16_t SX128x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) {
1744 12 : const uint8_t data[] = { (uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
1745 12 : (uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
1746 12 : (uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
1747 12 : (uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF) };
1748 24 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_DIO_IRQ_PARAMS, data, 8));
1749 : }
1750 :
1751 3 : uint16_t SX128x::getIrqStatus() {
1752 3 : uint8_t data[] = { 0x00, 0x00 };
1753 3 : this->mod->SPIreadStream(RADIOLIB_SX128X_CMD_GET_IRQ_STATUS, data, 2);
1754 3 : return(((uint16_t)(data[0]) << 8) | data[1]);
1755 : }
1756 :
1757 6 : int16_t SX128x::clearIrqStatus(uint16_t clearIrqParams) {
1758 6 : const uint8_t data[] = { (uint8_t)((clearIrqParams >> 8) & 0xFF), (uint8_t)(clearIrqParams & 0xFF) };
1759 12 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_CLEAR_IRQ_STATUS, data, 2));
1760 : }
1761 :
1762 0 : int16_t SX128x::setRangingRole(uint8_t role) {
1763 0 : const uint8_t data[] = { role };
1764 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_RANGING_ROLE, data, 1));
1765 : }
1766 :
1767 0 : int16_t SX128x::setPacketType(uint8_t type) {
1768 0 : const uint8_t data[] = { type };
1769 0 : return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_TYPE, data, 1));
1770 : }
1771 :
1772 0 : int16_t SX128x::setPacketMode(uint8_t mode, uint8_t len) {
1773 : // check active modem
1774 0 : uint8_t modem = getPacketType();
1775 0 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC))) {
1776 0 : return(RADIOLIB_ERR_WRONG_MODEM);
1777 : }
1778 :
1779 : // set requested packet mode
1780 0 : int16_t state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, mode, len);
1781 0 : RADIOLIB_ASSERT(state);
1782 :
1783 : // update cached value
1784 0 : this->packetType = mode;
1785 0 : return(state);
1786 : }
1787 :
1788 0 : int16_t SX128x::setHeaderType(uint8_t hdrType, size_t len) {
1789 : // check active modem
1790 0 : uint8_t modem = getPacketType();
1791 0 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) {
1792 0 : return(RADIOLIB_ERR_WRONG_MODEM);
1793 : }
1794 :
1795 : // update packet parameters
1796 0 : this->headerType = hdrType;
1797 0 : this->payloadLen = len;
1798 0 : return(setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled));
1799 : }
1800 :
1801 0 : int16_t SX128x::config(uint8_t modem) {
1802 : // reset buffer base address
1803 0 : int16_t state = setBufferBaseAddress();
1804 0 : RADIOLIB_ASSERT(state);
1805 :
1806 : // set modem
1807 : uint8_t data[1];
1808 0 : data[0] = modem;
1809 0 : state = this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_TYPE, data, 1);
1810 0 : RADIOLIB_ASSERT(state);
1811 :
1812 : // set CAD parameters
1813 0 : data[0] = RADIOLIB_SX128X_CAD_ON_8_SYMB;
1814 0 : state = this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_CAD_PARAMS, data, 1);
1815 0 : RADIOLIB_ASSERT(state);
1816 :
1817 : // set regulator mode to DC-DC
1818 0 : data[0] = RADIOLIB_SX128X_REGULATOR_DC_DC;
1819 0 : state = this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_REGULATOR_MODE, data, 1);
1820 0 : RADIOLIB_ASSERT(state);
1821 :
1822 0 : return(RADIOLIB_ERR_NONE);
1823 : }
1824 :
1825 0 : int16_t SX128x::SPIparseStatus(uint8_t in) {
1826 0 : if((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_TIMEOUT) {
1827 0 : return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
1828 0 : } else if((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_ERROR) {
1829 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
1830 0 : } else if((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_FAILED) {
1831 0 : return(RADIOLIB_ERR_SPI_CMD_FAILED);
1832 0 : } else if((in == 0x00) || (in == 0xFF)) {
1833 0 : return(RADIOLIB_ERR_CHIP_NOT_FOUND);
1834 : }
1835 0 : return(RADIOLIB_ERR_NONE);
1836 : }
1837 :
1838 0 : bool SX128x::findChip(const char* verStr) {
1839 0 : uint8_t i = 0;
1840 0 : bool flagFound = false;
1841 0 : while((i < 10) && !flagFound) {
1842 : // reset the module
1843 0 : reset(true);
1844 :
1845 : // read the version string
1846 0 : char version[16] = { 0 };
1847 0 : this->mod->SPIreadRegisterBurst(RADIOLIB_SX128X_REG_VERSION_STRING, 16, reinterpret_cast<uint8_t*>(version));
1848 :
1849 : // check version register
1850 0 : if(strncmp(verStr, version, 6) == 0) {
1851 : RADIOLIB_DEBUG_BASIC_PRINTLN("Found SX128x: RADIOLIB_SX128X_REG_VERSION_STRING:");
1852 : RADIOLIB_DEBUG_BASIC_HEXDUMP(reinterpret_cast<uint8_t*>(version), 16, RADIOLIB_SX128X_REG_VERSION_STRING);
1853 : RADIOLIB_DEBUG_BASIC_PRINTLN();
1854 0 : flagFound = true;
1855 : } else {
1856 : #if RADIOLIB_DEBUG_BASIC
1857 : RADIOLIB_DEBUG_BASIC_PRINTLN("SX128x not found! (%d of 10 tries) RADIOLIB_SX128X_REG_VERSION_STRING:", i + 1);
1858 : RADIOLIB_DEBUG_BASIC_HEXDUMP(reinterpret_cast<uint8_t*>(version), 16, RADIOLIB_SX128X_REG_VERSION_STRING);
1859 : RADIOLIB_DEBUG_BASIC_PRINTLN("Expected string: %s", verStr);
1860 : #endif
1861 0 : this->mod->hal->delay(10);
1862 0 : i++;
1863 : }
1864 : }
1865 :
1866 0 : return(flagFound);
1867 : }
1868 :
1869 : #endif
|