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