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