Line data Source code
1 : #include "LR11x0.h"
2 :
3 : #include "../../utils/CRC.h"
4 : #include "../../utils/Cryptography.h"
5 :
6 : #include <string.h>
7 : #include <math.h>
8 :
9 : #if !RADIOLIB_EXCLUDE_LR11X0
10 :
11 0 : int16_t LR11x0::writeRegMem32(uint32_t addr, const uint32_t* data, size_t len) {
12 : // check maximum size
13 0 : if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
14 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
15 : }
16 0 : return(this->writeCommon(RADIOLIB_LR11X0_CMD_WRITE_REG_MEM, addr, data, len, false));
17 : }
18 :
19 0 : int16_t LR11x0::readRegMem32(uint32_t addr, uint32_t* data, size_t len) {
20 : // check maximum size
21 0 : if(len >= (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
22 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
23 : }
24 :
25 : // the request contains the address and length
26 : uint8_t reqBuff[5] = {
27 0 : (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF),
28 0 : (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF),
29 : (uint8_t)len,
30 0 : };
31 :
32 : // build buffers - later we need to ensure endians are correct,
33 : // so there is probably no way to do this without copying buffers and iterating
34 : #if RADIOLIB_STATIC_ONLY
35 : uint8_t rplBuff[RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
36 : #else
37 0 : uint8_t* rplBuff = new uint8_t[len*sizeof(uint32_t)];
38 : #endif
39 :
40 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_READ_REG_MEM, false, rplBuff, len*sizeof(uint32_t), reqBuff, sizeof(reqBuff));
41 :
42 : // convert endians
43 0 : if(data && (state == RADIOLIB_ERR_NONE)) {
44 0 : for(size_t i = 0; i < len; i++) {
45 0 : data[i] = ((uint32_t)rplBuff[2 + i*sizeof(uint32_t)] << 24) | ((uint32_t)rplBuff[3 + i*sizeof(uint32_t)] << 16) | ((uint32_t)rplBuff[4 + i*sizeof(uint32_t)] << 8) | (uint32_t)rplBuff[5 + i*sizeof(uint32_t)];
46 : }
47 : }
48 :
49 : #if !RADIOLIB_STATIC_ONLY
50 0 : delete[] rplBuff;
51 : #endif
52 :
53 0 : return(state);
54 : }
55 :
56 0 : int16_t LR11x0::writeBuffer8(const uint8_t* data, size_t len) {
57 : // check maximum size
58 0 : if(len > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN) {
59 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
60 : }
61 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WRITE_BUFFER, true, const_cast<uint8_t*>(data), len));
62 : }
63 :
64 0 : int16_t LR11x0::readBuffer8(uint8_t* data, size_t len, size_t offset) {
65 : // check maximum size
66 0 : if(len > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN) {
67 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
68 : }
69 :
70 : // build buffers
71 0 : size_t reqLen = 2*sizeof(uint8_t) + len;
72 : #if RADIOLIB_STATIC_ONLY
73 : uint8_t reqBuff[sizeof(uint32_t) + RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
74 : #else
75 0 : uint8_t* reqBuff = new uint8_t[reqLen];
76 : #endif
77 :
78 : // set the offset and length
79 0 : reqBuff[0] = (uint8_t)offset;
80 0 : reqBuff[1] = (uint8_t)len;
81 :
82 : // send the request
83 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_READ_BUFFER, false, data, len, reqBuff, reqLen);
84 : #if !RADIOLIB_STATIC_ONLY
85 0 : delete[] reqBuff;
86 : #endif
87 0 : return(state);
88 : }
89 :
90 0 : int16_t LR11x0::clearRxBuffer(void) {
91 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CLEAR_RX_BUFFER, true, NULL, 0));
92 : }
93 :
94 0 : int16_t LR11x0::writeRegMemMask32(uint32_t addr, uint32_t mask, uint32_t data) {
95 : uint8_t buff[12] = {
96 0 : (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF),
97 0 : (uint8_t)((mask >> 24) & 0xFF), (uint8_t)((mask >> 16) & 0xFF), (uint8_t)((mask >> 8) & 0xFF), (uint8_t)(mask & 0xFF),
98 0 : (uint8_t)((data >> 24) & 0xFF), (uint8_t)((data >> 16) & 0xFF), (uint8_t)((data >> 8) & 0xFF), (uint8_t)(data & 0xFF),
99 0 : };
100 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WRITE_REG_MEM_MASK, true, buff, sizeof(buff)));
101 : }
102 :
103 0 : int16_t LR11x0::getStatus(uint8_t* stat1, uint8_t* stat2, uint32_t* irq) {
104 0 : uint8_t buff[6] = { 0 };
105 :
106 : // the status check command doesn't return status in the same place as other read commands
107 : // but only as the first byte (as with any other command), hence LR11x0::SPIcommand can't be used
108 : // it also seems to ignore the actual command, and just sending in bunch of NOPs will work
109 0 : int16_t state = this->mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true);
110 :
111 : // pass the replies
112 0 : if(stat1) { *stat1 = buff[0]; }
113 0 : if(stat2) { *stat2 = buff[1]; }
114 0 : if(irq) { *irq = ((uint32_t)(buff[2]) << 24) | ((uint32_t)(buff[3]) << 16) | ((uint32_t)(buff[4]) << 8) | (uint32_t)buff[5]; }
115 :
116 0 : return(state);
117 : }
118 :
119 0 : int16_t LR11x0::getVersion(uint8_t* hw, uint8_t* device, uint8_t* major, uint8_t* minor) {
120 0 : uint8_t buff[4] = { 0 };
121 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_VERSION, false, buff, sizeof(buff));
122 :
123 : // pass the replies
124 0 : if(hw) { *hw = buff[0]; }
125 0 : if(device) { *device = buff[1]; }
126 0 : if(major) { *major = buff[2]; }
127 0 : if(minor) { *minor = buff[3]; }
128 :
129 0 : return(state);
130 : }
131 :
132 0 : int16_t LR11x0::getErrors(uint16_t* err) {
133 0 : uint8_t buff[2] = { 0 };
134 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_ERRORS, false, buff, sizeof(buff));
135 :
136 : // pass the replies
137 0 : if(err) { *err = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1]; }
138 :
139 0 : return(state);
140 : }
141 :
142 0 : int16_t LR11x0::clearErrors(void) {
143 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CLEAR_ERRORS, true, NULL, 0));
144 : }
145 :
146 0 : int16_t LR11x0::calibrate(uint8_t params) {
147 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CALIBRATE, true, ¶ms, 1));
148 : }
149 :
150 0 : int16_t LR11x0::setRegMode(uint8_t mode) {
151 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_REG_MODE, true, &mode, 1));
152 : }
153 :
154 0 : int16_t LR11x0::calibrateImageRejection(float freqMin, float freqMax) {
155 : uint8_t buff[2] = {
156 0 : (uint8_t)floor((freqMin - 1.0f) / 4.0f),
157 0 : (uint8_t)ceil((freqMax + 1.0f) / 4.0f)
158 0 : };
159 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CALIB_IMAGE, true, buff, sizeof(buff)));
160 : }
161 :
162 0 : int16_t LR11x0::setDioAsRfSwitch(uint8_t en, uint8_t stbyCfg, uint8_t rxCfg, uint8_t txCfg, uint8_t txHpCfg, uint8_t txHfCfg, uint8_t gnssCfg, uint8_t wifiCfg) {
163 0 : uint8_t buff[8] = { en, stbyCfg, rxCfg, txCfg, txHpCfg, txHfCfg, gnssCfg, wifiCfg };
164 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_DIO_AS_RF_SWITCH, true, buff, sizeof(buff)));
165 : }
166 :
167 0 : int16_t LR11x0::setDioIrqParams(uint32_t irq1, uint32_t irq2) {
168 : uint8_t buff[8] = {
169 0 : (uint8_t)((irq1 >> 24) & 0xFF), (uint8_t)((irq1 >> 16) & 0xFF), (uint8_t)((irq1 >> 8) & 0xFF), (uint8_t)(irq1 & 0xFF),
170 0 : (uint8_t)((irq2 >> 24) & 0xFF), (uint8_t)((irq2 >> 16) & 0xFF), (uint8_t)((irq2 >> 8) & 0xFF), (uint8_t)(irq2 & 0xFF),
171 0 : };
172 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_DIO_IRQ_PARAMS, true, buff, sizeof(buff)));
173 : }
174 :
175 0 : int16_t LR11x0::setDioIrqParams(uint32_t irq) {
176 0 : return(setDioIrqParams(irq, this->gnss ? 0 : irq));
177 : }
178 :
179 0 : int16_t LR11x0::clearIrqState(uint32_t irq) {
180 : uint8_t buff[4] = {
181 0 : (uint8_t)((irq >> 24) & 0xFF), (uint8_t)((irq >> 16) & 0xFF), (uint8_t)((irq >> 8) & 0xFF), (uint8_t)(irq & 0xFF),
182 0 : };
183 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CLEAR_IRQ, true, buff, sizeof(buff)));
184 : }
185 :
186 0 : int16_t LR11x0::configLfClock(uint8_t setup) {
187 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CONFIG_LF_CLOCK, true, &setup, 1));
188 : }
189 :
190 0 : int16_t LR11x0::setTcxoMode(uint8_t tune, uint32_t delay) {
191 : uint8_t buff[4] = {
192 0 : tune, (uint8_t)((delay >> 16) & 0xFF), (uint8_t)((delay >> 8) & 0xFF), (uint8_t)(delay & 0xFF),
193 0 : };
194 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_TCXO_MODE, true, buff, sizeof(buff)));
195 : }
196 :
197 0 : int16_t LR11x0::reboot(bool stay) {
198 0 : uint8_t buff[1] = { (uint8_t)(stay*3) };
199 0 : return(this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_REBOOT, buff, sizeof(buff), true, false));
200 : }
201 :
202 0 : int16_t LR11x0::getVbat(float* vbat) {
203 0 : uint8_t buff[1] = { 0 };
204 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_VBAT, false, buff, sizeof(buff));
205 :
206 : // pass the replies
207 0 : if(vbat) { *vbat = (((float)buff[0]/51.0f) - 1.0f)*1.35f; }
208 :
209 0 : return(state);
210 : }
211 :
212 0 : int16_t LR11x0::getTemp(float* temp) {
213 0 : uint8_t buff[2] = { 0 };
214 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_TEMP, false, buff, sizeof(buff));
215 :
216 : // pass the replies
217 0 : if(temp) {
218 0 : uint16_t raw = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1];
219 0 : raw = raw & 0x07FF; //According LR1121 datasheet we need [0..10] bits
220 0 : *temp = 25.0f - (1000.0f/1.7f)*(((float)raw/2047.0f)*1.35f - 0.7295f); //According LR1121 datasheet 1.35
221 : }
222 :
223 0 : return(state);
224 : }
225 :
226 0 : int16_t LR11x0::setFs(void) {
227 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_FS, true, NULL, 0));
228 : }
229 :
230 0 : int16_t LR11x0::getRandomNumber(uint32_t* rnd) {
231 0 : uint8_t buff[4] = { 0 };
232 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_RANDOM_NUMBER, false, buff, sizeof(buff));
233 :
234 : // pass the replies
235 0 : if(rnd) { *rnd = ((uint32_t)(buff[0]) << 24) | ((uint32_t)(buff[1]) << 16) | ((uint32_t)(buff[2]) << 8) | (uint32_t)buff[3]; }
236 :
237 0 : return(state);
238 : }
239 :
240 0 : int16_t LR11x0::eraseInfoPage(void) {
241 : // only page 1 can be erased
242 0 : uint8_t buff[1] = { RADIOLIB_LR11X0_INFO_PAGE };
243 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_ERASE_INFO_PAGE, true, buff, sizeof(buff)));
244 : }
245 :
246 0 : int16_t LR11x0::writeInfoPage(uint16_t addr, const uint32_t* data, size_t len) {
247 : // check maximum size
248 0 : if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
249 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
250 : }
251 :
252 : // build buffers - later we need to ensure endians are correct,
253 : // so there is probably no way to do this without copying buffers and iterating
254 0 : size_t buffLen = sizeof(uint8_t) + sizeof(uint16_t) + len*sizeof(uint32_t);
255 : #if RADIOLIB_STATIC_ONLY
256 : uint8_t dataBuff[sizeof(uint8_t) + sizeof(uint16_t) + RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
257 : #else
258 0 : uint8_t* dataBuff = new uint8_t[buffLen];
259 : #endif
260 :
261 : // set the address
262 0 : dataBuff[0] = RADIOLIB_LR11X0_INFO_PAGE;
263 0 : dataBuff[1] = (uint8_t)((addr >> 8) & 0xFF);
264 0 : dataBuff[2] = (uint8_t)(addr & 0xFF);
265 :
266 : // convert endians
267 0 : for(size_t i = 0; i < len; i++) {
268 0 : dataBuff[3 + i] = (uint8_t)((data[i] >> 24) & 0xFF);
269 0 : dataBuff[4 + i] = (uint8_t)((data[i] >> 16) & 0xFF);
270 0 : dataBuff[5 + i] = (uint8_t)((data[i] >> 8) & 0xFF);
271 0 : dataBuff[6 + i] = (uint8_t)(data[i] & 0xFF);
272 : }
273 :
274 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_WRITE_INFO_PAGE, true, dataBuff, buffLen);
275 : #if !RADIOLIB_STATIC_ONLY
276 0 : delete[] dataBuff;
277 : #endif
278 0 : return(state);
279 : }
280 :
281 0 : int16_t LR11x0::readInfoPage(uint16_t addr, uint32_t* data, size_t len) {
282 : // check maximum size
283 0 : if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
284 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
285 : }
286 :
287 : // the request contains the address and length
288 0 : uint8_t reqBuff[4] = {
289 : RADIOLIB_LR11X0_INFO_PAGE,
290 0 : (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF),
291 : (uint8_t)len,
292 0 : };
293 :
294 : // build buffers - later we need to ensure endians are correct,
295 : // so there is probably no way to do this without copying buffers and iterating
296 : #if RADIOLIB_STATIC_ONLY
297 : uint8_t rplBuff[RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
298 : #else
299 0 : uint8_t* rplBuff = new uint8_t[len*sizeof(uint32_t)];
300 : #endif
301 :
302 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_READ_INFO_PAGE, false, rplBuff, len*sizeof(uint32_t), reqBuff, sizeof(reqBuff));
303 :
304 : // convert endians
305 0 : if(data && (state == RADIOLIB_ERR_NONE)) {
306 0 : for(size_t i = 0; i < len; i++) {
307 0 : data[i] = ((uint32_t)rplBuff[2 + i*sizeof(uint32_t)] << 24) | ((uint32_t)rplBuff[3 + i*sizeof(uint32_t)] << 16) | ((uint32_t)rplBuff[4 + i*sizeof(uint32_t)] << 8) | (uint32_t)rplBuff[5 + i*sizeof(uint32_t)];
308 : }
309 : }
310 :
311 : #if !RADIOLIB_STATIC_ONLY
312 0 : delete[] rplBuff;
313 : #endif
314 :
315 0 : return(state);
316 : }
317 :
318 0 : int16_t LR11x0::getChipEui(uint8_t* eui) {
319 0 : RADIOLIB_ASSERT_PTR(eui);
320 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_CHIP_EUI, false, eui, RADIOLIB_LR11X0_EUI_LEN));
321 : }
322 :
323 0 : int16_t LR11x0::getSemtechJoinEui(uint8_t* eui) {
324 0 : RADIOLIB_ASSERT_PTR(eui);
325 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_SEMTECH_JOIN_EUI, false, eui, RADIOLIB_LR11X0_EUI_LEN));
326 : }
327 :
328 0 : int16_t LR11x0::deriveRootKeysAndGetPin(uint8_t* pin) {
329 0 : RADIOLIB_ASSERT_PTR(pin);
330 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_DERIVE_ROOT_KEYS_AND_GET_PIN, false, pin, RADIOLIB_LR11X0_PIN_LEN));
331 : }
332 :
333 0 : int16_t LR11x0::enableSpiCrc(bool en) {
334 : // TODO implement this
335 : (void)en;
336 : // LR11X0 CRC is gen 0xA6 (0x65 but reflected), init 0xFF, input and result reflected
337 : /*RadioLibCRCInstance.size = 8;
338 : RadioLibCRCInstance.poly = 0xA6;
339 : RadioLibCRCInstance.init = 0xFF;
340 : RadioLibCRCInstance.out = 0x00;
341 : RadioLibCRCInstance.refIn = true;
342 : RadioLibCRCInstance.refOut = true;*/
343 0 : return(RADIOLIB_ERR_UNSUPPORTED);
344 : }
345 :
346 0 : int16_t LR11x0::driveDiosInSleepMode(bool en) {
347 0 : uint8_t buff[1] = { (uint8_t)en };
348 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_DRIVE_DIOS_IN_SLEEP_MODE, true, buff, sizeof(buff)));
349 : }
350 :
351 0 : int16_t LR11x0::resetStats(void) {
352 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_RESET_STATS, true, NULL, 0));
353 : }
354 :
355 0 : int16_t LR11x0::getStats(uint16_t* nbPktReceived, uint16_t* nbPktCrcError, uint16_t* data1, uint16_t* data2) {
356 0 : uint8_t buff[8] = { 0 };
357 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_STATS, false, buff, sizeof(buff));
358 :
359 : // pass the replies
360 0 : if(nbPktReceived) { *nbPktReceived = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1]; }
361 0 : if(nbPktCrcError) { *nbPktCrcError = ((uint16_t)(buff[2]) << 8) | (uint16_t)buff[3]; }
362 0 : if(data1) { *data1 = ((uint16_t)(buff[4]) << 8) | (uint16_t)buff[5]; }
363 0 : if(data2) { *data2 = ((uint16_t)(buff[6]) << 8) | (uint16_t)buff[7]; }
364 :
365 0 : return(state);
366 : }
367 :
368 0 : int16_t LR11x0::getPacketType(uint8_t* type) {
369 0 : uint8_t buff[1] = { 0 };
370 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_PACKET_TYPE, false, buff, sizeof(buff));
371 :
372 : // pass the replies
373 0 : if(type) { *type = buff[0]; }
374 :
375 0 : return(state);
376 : }
377 :
378 0 : int16_t LR11x0::getRxBufferStatus(uint8_t* len, uint8_t* startOffset) {
379 0 : uint8_t buff[2] = { 0 };
380 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_RX_BUFFER_STATUS, false, buff, sizeof(buff));
381 :
382 : // pass the replies
383 0 : if(len) { *len = buff[0]; }
384 0 : if(startOffset) { *startOffset = buff[1]; }
385 :
386 0 : return(state);
387 : }
388 :
389 0 : int16_t LR11x0::getPacketStatusLoRa(float* rssiPkt, float* snrPkt, float* signalRssiPkt) {
390 0 : uint8_t buff[3] = { 0 };
391 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_PACKET_STATUS, false, buff, sizeof(buff));
392 :
393 : // pass the replies
394 0 : if(rssiPkt) { *rssiPkt = (float)buff[0] / -2.0f; }
395 0 : if(snrPkt) { *snrPkt = (float)((int8_t)buff[1]) / 4.0f; }
396 0 : if(signalRssiPkt) { *signalRssiPkt = buff[2]; }
397 :
398 0 : return(state);
399 : }
400 :
401 0 : int16_t LR11x0::getPacketStatusGFSK(float* rssiSync, float* rssiAvg, uint8_t* rxLen, uint8_t* stat) {
402 0 : uint8_t buff[4] = { 0 };
403 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_PACKET_STATUS, false, buff, sizeof(buff));
404 :
405 : // pass the replies
406 0 : if(rssiSync) { *rssiSync = (float)buff[0] / -2.0f; }
407 0 : if(rssiAvg) { *rssiAvg = (float)buff[1] / -2.0f; }
408 0 : if(rxLen) { *rxLen = buff[2]; }
409 0 : if(stat) { *stat = buff[3]; }
410 :
411 0 : return(state);
412 : }
413 :
414 0 : int16_t LR11x0::getRssiInst(float* rssi) {
415 0 : uint8_t buff[1] = { 0 };
416 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_RSSI_INST, false, buff, sizeof(buff));
417 :
418 : // pass the replies
419 0 : if(rssi) { *rssi = (float)buff[0] / -2.0f; }
420 :
421 0 : return(state);
422 : }
423 :
424 0 : int16_t LR11x0::setGfskSyncWord(uint8_t* sync) {
425 0 : RADIOLIB_ASSERT_PTR(sync);
426 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_GFSK_SYNC_WORD, true, sync, RADIOLIB_LR11X0_GFSK_SYNC_WORD_LEN));
427 : }
428 :
429 0 : int16_t LR11x0::setLoRaPublicNetwork(bool pub) {
430 0 : uint8_t buff[1] = { (uint8_t)pub };
431 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_LORA_PUBLIC_NETWORK, true, buff, sizeof(buff)));
432 : }
433 :
434 0 : int16_t LR11x0::setRx(uint32_t timeout) {
435 : uint8_t buff[3] = {
436 0 : (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
437 0 : };
438 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RX, true, buff, sizeof(buff)));
439 : }
440 :
441 0 : int16_t LR11x0::setTx(uint32_t timeout) {
442 : uint8_t buff[3] = {
443 0 : (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
444 0 : };
445 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_TX, true, buff, sizeof(buff)));
446 : }
447 :
448 0 : int16_t LR11x0::setRfFrequency(uint32_t rfFreq) {
449 : uint8_t buff[4] = {
450 0 : (uint8_t)((rfFreq >> 24) & 0xFF), (uint8_t)((rfFreq >> 16) & 0xFF),
451 0 : (uint8_t)((rfFreq >> 8) & 0xFF), (uint8_t)(rfFreq & 0xFF),
452 0 : };
453 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RF_FREQUENCY, true, buff, sizeof(buff)));
454 : }
455 :
456 0 : int16_t LR11x0::autoTxRx(uint32_t delay, uint8_t intMode, uint32_t timeout) {
457 : uint8_t buff[7] = {
458 0 : (uint8_t)((delay >> 16) & 0xFF), (uint8_t)((delay >> 8) & 0xFF), (uint8_t)(delay & 0xFF), intMode,
459 0 : (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
460 0 : };
461 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_AUTO_TX_RX, true, buff, sizeof(buff)));
462 : }
463 :
464 0 : int16_t LR11x0::setCadParams(uint8_t symNum, uint8_t detPeak, uint8_t detMin, uint8_t cadExitMode, uint32_t timeout) {
465 : uint8_t buff[7] = {
466 : symNum, detPeak, detMin, cadExitMode,
467 0 : (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
468 0 : };
469 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_CAD_PARAMS, true, buff, sizeof(buff)));
470 : }
471 :
472 0 : int16_t LR11x0::setPacketType(uint8_t type) {
473 0 : uint8_t buff[1] = { type };
474 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_PACKET_TYPE, true, buff, sizeof(buff)));
475 : }
476 :
477 0 : int16_t LR11x0::setModulationParamsLoRa(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro) {
478 : // calculate symbol length and enable low data rate optimization, if auto-configuration is enabled
479 0 : if(this->ldroAuto) {
480 0 : float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float)this->bandwidthKhz;
481 0 : if(symbolLength >= 16.0f) {
482 0 : this->ldrOptimize = RADIOLIB_LR11X0_LORA_LDRO_ENABLED;
483 : } else {
484 0 : this->ldrOptimize = RADIOLIB_LR11X0_LORA_LDRO_DISABLED;
485 : }
486 : } else {
487 0 : this->ldrOptimize = ldro;
488 : }
489 :
490 0 : uint8_t buff[4] = { sf, bw, cr, this->ldrOptimize };
491 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_MODULATION_PARAMS, true, buff, sizeof(buff)));
492 : }
493 :
494 0 : int16_t LR11x0::setModulationParamsGFSK(uint32_t br, uint8_t sh, uint8_t rxBw, uint32_t freqDev) {
495 : uint8_t buff[10] = {
496 0 : (uint8_t)((br >> 24) & 0xFF), (uint8_t)((br >> 16) & 0xFF),
497 0 : (uint8_t)((br >> 8) & 0xFF), (uint8_t)(br & 0xFF), sh, rxBw,
498 0 : (uint8_t)((freqDev >> 24) & 0xFF), (uint8_t)((freqDev >> 16) & 0xFF),
499 0 : (uint8_t)((freqDev >> 8) & 0xFF), (uint8_t)(freqDev & 0xFF)
500 0 : };
501 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_MODULATION_PARAMS, true, buff, sizeof(buff)));
502 : }
503 :
504 0 : int16_t LR11x0::setModulationParamsLrFhss(uint32_t br, uint8_t sh) {
505 : uint8_t buff[5] = {
506 0 : (uint8_t)((br >> 24) & 0xFF), (uint8_t)((br >> 16) & 0xFF),
507 0 : (uint8_t)((br >> 8) & 0xFF), (uint8_t)(br & 0xFF), sh
508 0 : };
509 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_MODULATION_PARAMS, true, buff, sizeof(buff)));
510 : }
511 :
512 0 : int16_t LR11x0::setModulationParamsSigfox(uint32_t br, uint8_t sh) {
513 : // same as for LR-FHSS
514 0 : return(this->setModulationParamsLrFhss(br, sh));
515 : }
516 :
517 0 : int16_t LR11x0::setPacketParamsLoRa(uint16_t preambleLen, uint8_t hdrType, uint8_t payloadLen, uint8_t crcType, uint8_t invertIQ) {
518 : uint8_t buff[6] = {
519 0 : (uint8_t)((preambleLen >> 8) & 0xFF), (uint8_t)(preambleLen & 0xFF),
520 : hdrType, payloadLen, crcType, invertIQ
521 0 : };
522 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_PACKET_PARAMS, true, buff, sizeof(buff)));
523 : }
524 :
525 0 : int16_t LR11x0::setPacketParamsGFSK(uint16_t preambleLen, uint8_t preambleDetectorLen, uint8_t syncWordLen, uint8_t addrCmp, uint8_t packType, uint8_t payloadLen, uint8_t crcType, uint8_t whiten) {
526 : uint8_t buff[9] = {
527 0 : (uint8_t)((preambleLen >> 8) & 0xFF), (uint8_t)(preambleLen & 0xFF),
528 : preambleDetectorLen, syncWordLen, addrCmp, packType, payloadLen, crcType, whiten
529 0 : };
530 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_PACKET_PARAMS, true, buff, sizeof(buff)));
531 : }
532 :
533 0 : int16_t LR11x0::setPacketParamsSigfox(uint8_t payloadLen, uint16_t rampUpDelay, uint16_t rampDownDelay, uint16_t bitNum) {
534 : uint8_t buff[7] = {
535 0 : payloadLen, (uint8_t)((rampUpDelay >> 8) & 0xFF), (uint8_t)(rampUpDelay & 0xFF),
536 0 : (uint8_t)((rampDownDelay >> 8) & 0xFF), (uint8_t)(rampDownDelay & 0xFF),
537 0 : (uint8_t)((bitNum >> 8) & 0xFF), (uint8_t)(bitNum & 0xFF),
538 0 : };
539 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_PACKET_PARAMS, true, buff, sizeof(buff)));
540 : }
541 :
542 0 : int16_t LR11x0::setTxParams(int8_t pwr, uint8_t ramp) {
543 0 : uint8_t buff[2] = { (uint8_t)pwr, ramp };
544 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_TX_PARAMS, true, buff, sizeof(buff)));
545 : }
546 :
547 0 : int16_t LR11x0::setPacketAdrs(uint8_t node, uint8_t broadcast) {
548 0 : uint8_t buff[2] = { node, broadcast };
549 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_PACKET_ADRS, true, buff, sizeof(buff)));
550 : }
551 :
552 0 : int16_t LR11x0::setRxTxFallbackMode(uint8_t mode) {
553 0 : uint8_t buff[1] = { mode };
554 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RX_TX_FALLBACK_MODE, true, buff, sizeof(buff)));
555 : }
556 :
557 0 : int16_t LR11x0::setRxDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, uint8_t mode) {
558 : uint8_t buff[7] = {
559 0 : (uint8_t)((rxPeriod >> 16) & 0xFF), (uint8_t)((rxPeriod >> 8) & 0xFF), (uint8_t)(rxPeriod & 0xFF),
560 0 : (uint8_t)((sleepPeriod >> 16) & 0xFF), (uint8_t)((sleepPeriod >> 8) & 0xFF), (uint8_t)(sleepPeriod & 0xFF),
561 : mode
562 0 : };
563 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RX_DUTY_CYCLE, true, buff, sizeof(buff)));
564 : }
565 :
566 0 : int16_t LR11x0::setPaConfig(uint8_t paSel, uint8_t regPaSupply, uint8_t paDutyCycle, uint8_t paHpSel) {
567 0 : uint8_t buff[4] = { paSel, regPaSupply, paDutyCycle, paHpSel };
568 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_PA_CONFIG, true, buff, sizeof(buff)));
569 : }
570 :
571 0 : int16_t LR11x0::stopTimeoutOnPreamble(bool stop) {
572 0 : uint8_t buff[1] = { (uint8_t)stop };
573 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_STOP_TIMEOUT_ON_PREAMBLE, true, buff, sizeof(buff)));
574 : }
575 :
576 0 : int16_t LR11x0::setCad(void) {
577 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_CAD, true, NULL, 0));
578 : }
579 :
580 0 : int16_t LR11x0::setTxCw(void) {
581 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_TX_CW, true, NULL, 0));
582 : }
583 :
584 0 : int16_t LR11x0::setTxInfinitePreamble(void) {
585 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_TX_INFINITE_PREAMBLE, true, NULL, 0));
586 : }
587 :
588 0 : int16_t LR11x0::setLoRaSynchTimeout(uint8_t symbolNum) {
589 0 : uint8_t buff[1] = { symbolNum };
590 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_LORA_SYNCH_TIMEOUT, true, buff, sizeof(buff)));
591 : }
592 :
593 0 : int16_t LR11x0::setRangingAddr(uint32_t addr, uint8_t checkLen) {
594 : uint8_t buff[5] = {
595 0 : (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF),
596 0 : (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF), checkLen
597 0 : };
598 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RANGING_ADDR, true, buff, sizeof(buff)));
599 : }
600 :
601 0 : int16_t LR11x0::setRangingReqAddr(uint32_t addr) {
602 : uint8_t buff[4] = {
603 0 : (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF),
604 0 : (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF)
605 0 : };
606 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RANGING_REQ_ADDR, true, buff, sizeof(buff)));
607 : }
608 :
609 0 : int16_t LR11x0::getRangingResult(uint8_t type, float* res) {
610 0 : uint8_t reqBuff[1] = { type };
611 0 : uint8_t rplBuff[4] = { 0 };
612 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_RANGING_RESULT, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
613 0 : RADIOLIB_ASSERT(state);
614 :
615 0 : if(res) {
616 0 : if(type == RADIOLIB_LR11X0_RANGING_RESULT_DISTANCE) {
617 0 : uint32_t raw = ((uint32_t)(rplBuff[0]) << 24) | ((uint32_t)(rplBuff[1]) << 16) | ((uint32_t)(rplBuff[2]) << 8) | (uint32_t)rplBuff[3];
618 0 : *res = ((float)(raw*3e8))/((float)(4096*this->bandwidthKhz*1000));
619 : } else {
620 0 : *res = (float)rplBuff[3]/2.0f;
621 : }
622 : }
623 :
624 0 : return(state);
625 : }
626 :
627 0 : int16_t LR11x0::setRangingTxRxDelay(uint32_t delay) {
628 : uint8_t buff[4] = {
629 0 : (uint8_t)((delay >> 24) & 0xFF), (uint8_t)((delay >> 16) & 0xFF),
630 0 : (uint8_t)((delay >> 8) & 0xFF), (uint8_t)(delay & 0xFF)
631 0 : };
632 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RANGING_TX_RX_DELAY, true, buff, sizeof(buff)));
633 : }
634 :
635 0 : int16_t LR11x0::setGfskCrcParams(uint32_t init, uint32_t poly) {
636 : uint8_t buff[8] = {
637 0 : (uint8_t)((init >> 24) & 0xFF), (uint8_t)((init >> 16) & 0xFF),
638 0 : (uint8_t)((init >> 8) & 0xFF), (uint8_t)(init & 0xFF),
639 0 : (uint8_t)((poly >> 24) & 0xFF), (uint8_t)((poly >> 16) & 0xFF),
640 0 : (uint8_t)((poly >> 8) & 0xFF), (uint8_t)(poly & 0xFF)
641 0 : };
642 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_GFSK_CRC_PARAMS, true, buff, sizeof(buff)));
643 :
644 : }
645 :
646 0 : int16_t LR11x0::setGfskWhitParams(uint16_t seed) {
647 : uint8_t buff[2] = {
648 0 : (uint8_t)((seed >> 8) & 0xFF), (uint8_t)(seed & 0xFF)
649 0 : };
650 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_GFSK_WHIT_PARAMS, true, buff, sizeof(buff)));
651 : }
652 :
653 0 : int16_t LR11x0::setRangingParameter(uint8_t symbolNum) {
654 : // the first byte is reserved
655 0 : uint8_t buff[2] = { 0x00, symbolNum };
656 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RANGING_PARAMETER, true, buff, sizeof(buff)));
657 : }
658 :
659 0 : int16_t LR11x0::setRssiCalibration(const int8_t* tune, int16_t gainOffset) {
660 : uint8_t buff[11] = {
661 0 : (uint8_t)((tune[0] & 0x0F) | (uint8_t)(tune[1] & 0x0F) << 4),
662 0 : (uint8_t)((tune[2] & 0x0F) | (uint8_t)(tune[3] & 0x0F) << 4),
663 0 : (uint8_t)((tune[4] & 0x0F) | (uint8_t)(tune[5] & 0x0F) << 4),
664 0 : (uint8_t)((tune[6] & 0x0F) | (uint8_t)(tune[7] & 0x0F) << 4),
665 0 : (uint8_t)((tune[8] & 0x0F) | (uint8_t)(tune[9] & 0x0F) << 4),
666 0 : (uint8_t)((tune[10] & 0x0F) | (uint8_t)(tune[11] & 0x0F) << 4),
667 0 : (uint8_t)((tune[12] & 0x0F) | (uint8_t)(tune[13] & 0x0F) << 4),
668 0 : (uint8_t)((tune[14] & 0x0F) | (uint8_t)(tune[15] & 0x0F) << 4),
669 0 : (uint8_t)((tune[16] & 0x0F) | (uint8_t)(tune[17] & 0x0F) << 4),
670 0 : (uint8_t)(((uint16_t)gainOffset >> 8) & 0xFF), (uint8_t)(gainOffset & 0xFF),
671 0 : };
672 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RSSI_CALIBRATION, true, buff, sizeof(buff)));
673 : }
674 :
675 0 : int16_t LR11x0::setLoRaSyncWord(uint8_t sync) {
676 0 : uint8_t buff[1] = { sync };
677 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_LORA_SYNC_WORD, true, buff, sizeof(buff)));
678 : }
679 :
680 0 : int16_t LR11x0::lrFhssBuildFrame(uint8_t hdrCount, uint8_t cr, uint8_t grid, bool hop, uint8_t bw, uint16_t hopSeq, int8_t devOffset, const uint8_t* payload, size_t len) {
681 : // check maximum size
682 0 : const uint8_t maxLen[4][4] = {
683 : { 189, 178, 167, 155, },
684 : { 151, 142, 133, 123, },
685 : { 112, 105, 99, 92, },
686 : { 74, 69, 65, 60, },
687 : };
688 0 : if((cr > RADIOLIB_LR11X0_LR_FHSS_CR_1_3) || ((hdrCount - 1) > (int)sizeof(maxLen[0])) || (len > maxLen[cr][hdrCount - 1])) {
689 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
690 : }
691 :
692 : // build buffers
693 0 : size_t buffLen = 9 + len;
694 : #if RADIOLIB_STATIC_ONLY
695 : uint8_t dataBuff[9 + 190];
696 : #else
697 0 : uint8_t* dataBuff = new uint8_t[buffLen];
698 : #endif
699 :
700 : // set properties of the packet
701 0 : dataBuff[0] = hdrCount;
702 0 : dataBuff[1] = cr;
703 0 : dataBuff[2] = RADIOLIB_LR11X0_LR_FHSS_MOD_TYPE_GMSK;
704 0 : dataBuff[3] = grid;
705 0 : dataBuff[4] = (uint8_t)hop;
706 0 : dataBuff[5] = bw;
707 0 : dataBuff[6] = (uint8_t)((hopSeq >> 8) & 0x01);
708 0 : dataBuff[7] = (uint8_t)(hopSeq & 0xFF);
709 0 : dataBuff[8] = devOffset;
710 0 : memcpy(&dataBuff[9], payload, len);
711 :
712 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_LR_FHSS_BUILD_FRAME, true, dataBuff, buffLen);
713 : #if !RADIOLIB_STATIC_ONLY
714 0 : delete[] dataBuff;
715 : #endif
716 0 : return(state);
717 : }
718 :
719 0 : int16_t LR11x0::lrFhssSetSyncWord(uint32_t sync) {
720 : uint8_t buff[4] = {
721 0 : (uint8_t)((sync >> 24) & 0xFF), (uint8_t)((sync >> 16) & 0xFF),
722 0 : (uint8_t)((sync >> 8) & 0xFF), (uint8_t)(sync & 0xFF)
723 0 : };
724 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_LR_FHSS_SET_SYNC_WORD, true, buff, sizeof(buff)));
725 : }
726 :
727 0 : int16_t LR11x0::configBleBeacon(uint8_t chan, const uint8_t* payload, size_t len) {
728 0 : return(this->bleBeaconCommon(RADIOLIB_LR11X0_CMD_CONFIG_BLE_BEACON, chan, payload, len));
729 : }
730 :
731 0 : int16_t LR11x0::getLoRaRxHeaderInfo(uint8_t* cr, bool* hasCRC) {
732 : // check if in explicit header mode
733 0 : if(this->headerType == RADIOLIB_LR11X0_LORA_HEADER_IMPLICIT) {
734 0 : return(RADIOLIB_ERR_WRONG_MODEM);
735 : }
736 :
737 0 : uint8_t buff[1] = { 0 };
738 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_LORA_RX_HEADER_INFOS, false, buff, sizeof(buff));
739 :
740 : // pass the replies
741 0 : if(cr) { *cr = (buff[0] & 0x70) >> 4; }
742 0 : if(hasCRC) { *hasCRC = (buff[0] & RADIOLIB_LR11X0_LAST_HEADER_CRC_ENABLED) != 0; }
743 :
744 0 : return(state);
745 : }
746 :
747 0 : int16_t LR11x0::bleBeaconSend(uint8_t chan, const uint8_t* payload, size_t len) {
748 0 : return(this->bleBeaconCommon(RADIOLIB_LR11X0_CMD_BLE_BEACON_SEND, chan, payload, len));
749 : }
750 :
751 0 : int16_t LR11x0::bleBeaconCommon(uint16_t cmd, uint8_t chan, const uint8_t* payload, size_t len) {
752 : // check maximum size
753 : // TODO what is the actual maximum?
754 0 : if(len > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN) {
755 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
756 : }
757 :
758 : // build buffers
759 : #if RADIOLIB_STATIC_ONLY
760 : uint8_t dataBuff[sizeof(uint8_t) + RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
761 : #else
762 0 : uint8_t* dataBuff = new uint8_t[sizeof(uint8_t) + len];
763 : #endif
764 :
765 : // set the channel
766 0 : dataBuff[0] = chan;
767 0 : memcpy(&dataBuff[1], payload, len);
768 :
769 0 : int16_t state = this->SPIcommand(cmd, true, dataBuff, sizeof(uint8_t) + len);
770 : #if !RADIOLIB_STATIC_ONLY
771 0 : delete[] dataBuff;
772 : #endif
773 0 : return(state);
774 : }
775 :
776 0 : int16_t LR11x0::bootEraseFlash(void) {
777 : // erasing flash takes about 2.5 seconds, temporarily tset SPI timeout to 3 seconds
778 0 : RadioLibTime_t timeout = this->mod->spiConfig.timeout;
779 0 : this->mod->spiConfig.timeout = 3000;
780 0 : int16_t state = this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_BOOT_ERASE_FLASH, NULL, 0, false, false);
781 0 : this->mod->spiConfig.timeout = timeout;
782 0 : return(state);
783 : }
784 :
785 0 : int16_t LR11x0::bootWriteFlashEncrypted(uint32_t offset, const uint32_t* data, size_t len, bool nonvolatile) {
786 : // check maximum size
787 0 : if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
788 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
789 : }
790 0 : return(this->writeCommon(RADIOLIB_LR11X0_CMD_BOOT_WRITE_FLASH_ENCRYPTED, offset, data, len, nonvolatile));
791 : }
792 :
793 0 : int16_t LR11x0::bootGetHash(uint8_t hash[RADIOLIB_LR11X0_HASH_LEN]) {
794 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_BOOT_GET_HASH, false, hash, RADIOLIB_LR11X0_HASH_LEN));
795 : }
796 :
797 0 : int16_t LR11x0::bootReboot(bool stay) {
798 0 : uint8_t buff[1] = { (uint8_t)stay };
799 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_BOOT_REBOOT, true, buff, sizeof(buff)));
800 : }
801 :
802 0 : int16_t LR11x0::bootGetPin(uint8_t* pin) {
803 0 : RADIOLIB_ASSERT_PTR(pin);
804 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_BOOT_GET_PIN, false, pin, RADIOLIB_LR11X0_PIN_LEN));
805 : }
806 :
807 0 : int16_t LR11x0::bootGetChipEui(uint8_t* eui) {
808 0 : RADIOLIB_ASSERT_PTR(eui);
809 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_BOOT_GET_CHIP_EUI, false, eui, RADIOLIB_LR11X0_EUI_LEN));
810 : }
811 :
812 0 : int16_t LR11x0::bootGetJoinEui(uint8_t* eui) {
813 0 : RADIOLIB_ASSERT_PTR(eui);
814 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_BOOT_GET_JOIN_EUI, false, eui, RADIOLIB_LR11X0_EUI_LEN));
815 : }
816 :
817 0 : int16_t LR11x0::writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* data, size_t len, bool nonvolatile) {
818 : // build buffers - later we need to ensure endians are correct,
819 : // so there is probably no way to do this without copying buffers and iterating
820 0 : size_t buffLen = sizeof(uint32_t) + len*sizeof(uint32_t);
821 : #if RADIOLIB_STATIC_ONLY
822 : uint8_t dataBuff[sizeof(uint32_t) + RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
823 : #else
824 0 : uint8_t* dataBuff = new uint8_t[buffLen];
825 : #endif
826 :
827 : // set the address or offset
828 0 : dataBuff[0] = (uint8_t)((addrOffset >> 24) & 0xFF);
829 0 : dataBuff[1] = (uint8_t)((addrOffset >> 16) & 0xFF);
830 0 : dataBuff[2] = (uint8_t)((addrOffset >> 8) & 0xFF);
831 0 : dataBuff[3] = (uint8_t)(addrOffset & 0xFF);
832 :
833 : // convert endians
834 0 : for(size_t i = 0; i < len; i++) {
835 0 : uint32_t bin = 0;
836 0 : if(nonvolatile) {
837 0 : uint32_t* ptr = const_cast<uint32_t*>(data) + i;
838 0 : bin = RADIOLIB_NONVOLATILE_READ_DWORD(ptr);
839 : } else {
840 0 : bin = data[i];
841 : }
842 0 : dataBuff[4 + i*sizeof(uint32_t)] = (uint8_t)((bin >> 24) & 0xFF);
843 0 : dataBuff[5 + i*sizeof(uint32_t)] = (uint8_t)((bin >> 16) & 0xFF);
844 0 : dataBuff[6 + i*sizeof(uint32_t)] = (uint8_t)((bin >> 8) & 0xFF);
845 0 : dataBuff[7 + i*sizeof(uint32_t)] = (uint8_t)(bin & 0xFF);
846 : }
847 :
848 0 : int16_t state = this->mod->SPIwriteStream(cmd, dataBuff, buffLen, true, false);
849 : #if !RADIOLIB_STATIC_ONLY
850 0 : delete[] dataBuff;
851 : #endif
852 0 : return(state);
853 : }
854 :
855 : #endif
|