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