Line data Source code
1 : #include "Module.h"
2 :
3 : // the following is probably only needed on non-Arduino builds
4 : #include <stdio.h>
5 : #include <string.h>
6 :
7 : #if defined(RADIOLIB_BUILD_ARDUINO)
8 : #include "hal/Arduino/ArduinoHal.h"
9 :
10 : Module::Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio) : csPin(cs), irqPin(irq), rstPin(rst), gpioPin(gpio) {
11 : this->hal = new ArduinoHal();
12 : }
13 :
14 : Module::Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio, SPIClass& spi, SPISettings spiSettings) : csPin(cs), irqPin(irq), rstPin(rst), gpioPin(gpio) {
15 : this->hal = new ArduinoHal(spi, spiSettings);
16 : }
17 : #endif
18 :
19 59 : Module::Module(RadioLibHal *hal, uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio) : csPin(cs), irqPin(irq), rstPin(rst), gpioPin(gpio) {
20 59 : this->hal = hal;
21 59 : }
22 :
23 0 : Module::Module(const Module& mod) {
24 0 : *this = mod;
25 0 : }
26 :
27 1 : Module& Module::operator=(const Module& mod) {
28 1 : this->hal = mod.hal;
29 1 : memcpy(&this->spiConfig, reinterpret_cast<void*>(&(const_cast<Module&>(mod)).spiConfig), sizeof(SPIConfig_t));
30 1 : this->csPin = mod.csPin;
31 1 : this->irqPin = mod.irqPin;
32 1 : this->rstPin = mod.rstPin;
33 1 : this->gpioPin = mod.gpioPin;
34 :
35 1 : memcpy(this->rfSwitchPins, mod.rfSwitchPins, Module::RFSWITCH_MAX_PINS*sizeof(this->rfSwitchPins[0]));
36 1 : this->rfSwitchTable = mod.rfSwitchTable;
37 :
38 : #if RADIOLIB_INTERRUPT_TIMING
39 : this->TimerSetupCb = mod.TimerSetupCb;
40 : this->TimerFlag = mod.TimerFlag;
41 : this->prevTimingLen = mod.prevTimingLen;
42 : #endif
43 :
44 1 : return(*this);
45 : }
46 :
47 : static volatile const char rlb_info[] = RADIOLIB_INFO;
48 7 : void Module::init() {
49 7 : this->hal->init();
50 7 : this->hal->pinMode(csPin, this->hal->GpioModeOutput);
51 7 : this->hal->digitalWrite(csPin, this->hal->GpioLevelHigh);
52 : RADIOLIB_DEBUG_BASIC_PRINTLN(RADIOLIB_INFO);
53 7 : RADIOLIB_VALUE_USED(rlb_info);
54 7 : }
55 :
56 7 : void Module::term() {
57 : // stop hardware interfaces (if they were initialized by the library)
58 7 : this->hal->term();
59 7 : }
60 :
61 386 : int16_t Module::SPIgetRegValue(uint32_t reg, uint8_t msb, uint8_t lsb) {
62 386 : if((msb > 7) || (lsb > 7) || (lsb > msb)) {
63 6 : return(RADIOLIB_ERR_INVALID_BIT_RANGE);
64 : }
65 :
66 380 : uint8_t rawValue = SPIreadRegister(reg);
67 380 : uint8_t maskedValue = rawValue & ((0b11111111 << lsb) & (0b11111111 >> (7 - msb)));
68 380 : return(maskedValue);
69 : }
70 :
71 226 : int16_t Module::SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask, bool force) {
72 226 : if((msb > 7) || (lsb > 7) || (lsb > msb)) {
73 6 : return(RADIOLIB_ERR_INVALID_BIT_RANGE);
74 : }
75 :
76 : // read the current value
77 220 : uint8_t currentValue = SPIreadRegister(reg);
78 220 : uint8_t mask = ~((0b11111111 << (msb + 1)) | (0b11111111 >> (8 - lsb)));
79 :
80 : // check if we actually need to update the register
81 220 : if((currentValue & mask) == (value & mask) && !force) {
82 24 : return(RADIOLIB_ERR_NONE);
83 : }
84 :
85 : // update the register
86 196 : uint8_t newValue = (currentValue & ~mask) | (value & mask);
87 196 : SPIwriteRegister(reg, newValue);
88 :
89 : #if RADIOLIB_SPI_PARANOID
90 : // check register value each millisecond until check interval is reached
91 : // some registers need a bit of time to process the change (e.g. SX127X_REG_OP_MODE)
92 196 : RadioLibTime_t start = this->hal->micros();
93 : #if RADIOLIB_DEBUG_SPI
94 : uint8_t readValue = 0x00;
95 : #endif
96 515 : while(this->hal->micros() - start < ((RadioLibTime_t)checkInterval * 1000UL)) {
97 321 : uint8_t val = SPIreadRegister(reg);
98 321 : if((val & checkMask) == (newValue & checkMask)) {
99 : // check passed, we can stop the loop
100 2 : return(RADIOLIB_ERR_NONE);
101 : }
102 : #if RADIOLIB_DEBUG_SPI
103 : readValue = val;
104 : #endif
105 : }
106 :
107 : // check failed, print debug info
108 : RADIOLIB_DEBUG_SPI_PRINTLN();
109 : RADIOLIB_DEBUG_SPI_PRINTLN("address:\t0x%X", reg);
110 : RADIOLIB_DEBUG_SPI_PRINTLN("bits:\t\t%d %d", msb, lsb);
111 : RADIOLIB_DEBUG_SPI_PRINTLN("value:\t\t0x%X", value);
112 : RADIOLIB_DEBUG_SPI_PRINTLN("current:\t0x%X", currentValue);
113 : RADIOLIB_DEBUG_SPI_PRINTLN("mask:\t\t0x%X", mask);
114 : RADIOLIB_DEBUG_SPI_PRINTLN("new:\t\t0x%X", newValue);
115 : RADIOLIB_DEBUG_SPI_PRINTLN("read:\t\t0x%X", readValue);
116 :
117 194 : return(RADIOLIB_ERR_SPI_WRITE_FAILED);
118 : #else
119 : return(RADIOLIB_ERR_NONE);
120 : #endif
121 : }
122 :
123 33 : void Module::SPIreadRegisterBurst(uint32_t reg, size_t numBytes, uint8_t* inBytes) {
124 33 : if(!this->spiConfig.stream) {
125 0 : SPItransfer(this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ], reg, NULL, inBytes, numBytes);
126 : } else {
127 : uint8_t cmd[6];
128 33 : uint8_t* cmdPtr = cmd;
129 99 : for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
130 66 : *(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] >> 8*i) & 0xFF;
131 : }
132 66 : for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
133 33 : *(cmdPtr++) = (reg >> 8*i) & 0xFF;
134 : }
135 33 : SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, false, NULL, inBytes, numBytes, true);
136 : }
137 33 : }
138 :
139 2517 : uint8_t Module::SPIreadRegister(uint32_t reg) {
140 2517 : uint8_t resp = 0;
141 2517 : if(!spiConfig.stream) {
142 106 : SPItransfer(this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ], reg, NULL, &resp, 1);
143 : } else {
144 : uint8_t cmd[6];
145 2411 : uint8_t* cmdPtr = cmd;
146 7190 : for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
147 4779 : *(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] >> 8*i) & 0xFF;
148 : }
149 4865 : for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
150 2454 : *(cmdPtr++) = (reg >> 8*i) & 0xFF;
151 : }
152 2411 : SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, false, NULL, &resp, 1, true);
153 : }
154 2517 : return(resp);
155 : }
156 :
157 6 : void Module::SPIwriteRegisterBurst(uint32_t reg, const uint8_t* data, size_t numBytes) {
158 6 : if(!spiConfig.stream) {
159 0 : SPItransfer(spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE], reg, data, NULL, numBytes);
160 : } else {
161 : uint8_t cmd[6];
162 6 : uint8_t* cmdPtr = cmd;
163 18 : for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
164 12 : *(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] >> 8*i) & 0xFF;
165 : }
166 12 : for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
167 6 : *(cmdPtr++) = (reg >> 8*i) & 0xFF;
168 : }
169 6 : SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, true, data, NULL, numBytes, true);
170 : }
171 6 : }
172 :
173 220 : void Module::SPIwriteRegister(uint32_t reg, uint8_t data) {
174 220 : if(!spiConfig.stream) {
175 5 : SPItransfer(spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE], reg, &data, NULL, 1);
176 : } else {
177 : uint8_t cmd[6];
178 215 : uint8_t* cmdPtr = cmd;
179 640 : for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
180 425 : *(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] >> 8*i) & 0xFF;
181 : }
182 435 : for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
183 220 : *(cmdPtr++) = (reg >> 8*i) & 0xFF;
184 : }
185 215 : SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, true, &data, NULL, 1, true);
186 : }
187 220 : }
188 :
189 111 : void Module::SPItransfer(uint16_t cmd, uint32_t reg, const uint8_t* dataOut, uint8_t* dataIn, size_t numBytes) {
190 : // prepare the buffers
191 111 : size_t buffLen = this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8 + numBytes;
192 : #if RADIOLIB_STATIC_ONLY
193 : uint8_t buffOut[RADIOLIB_STATIC_SPI_ARRAY_SIZE];
194 : uint8_t buffIn[RADIOLIB_STATIC_SPI_ARRAY_SIZE];
195 : #else
196 111 : uint8_t* buffOut = new uint8_t[buffLen];
197 111 : uint8_t* buffIn = new uint8_t[buffLen];
198 : #endif
199 111 : uint8_t* buffOutPtr = buffOut;
200 :
201 : // copy the command
202 : // TODO properly handle variable commands and addresses
203 111 : if(this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] <= 8) {
204 111 : *(buffOutPtr++) = reg | cmd;
205 : } else {
206 0 : *(buffOutPtr++) = (reg >> 8) | cmd;
207 0 : *(buffOutPtr++) = reg & 0xFF;
208 : }
209 :
210 : // copy the data
211 111 : if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE]) {
212 5 : memcpy(buffOutPtr, dataOut, numBytes);
213 : } else {
214 106 : memset(buffOutPtr, this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP], numBytes);
215 : }
216 :
217 : // do the transfer
218 111 : this->hal->spiBeginTransaction();
219 111 : this->hal->digitalWrite(this->csPin, this->hal->GpioLevelLow);
220 111 : this->hal->spiTransfer(buffOut, buffLen, buffIn);
221 111 : this->hal->digitalWrite(this->csPin, this->hal->GpioLevelHigh);
222 111 : this->hal->spiEndTransaction();
223 :
224 : // copy the data
225 111 : if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ]) {
226 106 : memcpy(dataIn, &buffIn[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8], numBytes);
227 : }
228 :
229 : // print debug information
230 : #if RADIOLIB_DEBUG_SPI
231 : const uint8_t* debugBuffPtr = NULL;
232 : if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE]) {
233 : RADIOLIB_DEBUG_SPI_PRINT("W\t%X\t", reg);
234 : debugBuffPtr = &buffOut[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8];
235 : } else if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ]) {
236 : RADIOLIB_DEBUG_SPI_PRINT("R\t%X\t", reg);
237 : debugBuffPtr = &buffIn[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8];
238 : }
239 : for(size_t n = 0; n < numBytes; n++) {
240 : RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", debugBuffPtr[n]);
241 : }
242 : RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG("");
243 : #endif
244 :
245 : #if !RADIOLIB_STATIC_ONLY
246 111 : delete[] buffOut;
247 111 : delete[] buffIn;
248 : #endif
249 111 : }
250 :
251 257 : int16_t Module::SPIreadStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
252 : uint8_t cmdBuf[2];
253 257 : uint8_t* cmdPtr = cmdBuf;
254 569 : for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
255 312 : *(cmdPtr++) = (cmd >> 8*i) & 0xFF;
256 : }
257 514 : return(this->SPIreadStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, data, numBytes, waitForGpio, verify));
258 : }
259 :
260 257 : int16_t Module::SPIreadStream(const uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
261 : // send the command
262 257 : int16_t state = this->SPItransferStream(cmd, cmdLen, false, NULL, data, numBytes, waitForGpio);
263 257 : RADIOLIB_ASSERT(state);
264 :
265 : #if !RADIOLIB_SPI_PARANOID
266 : (void)verify;
267 : return(RADIOLIB_ERR_NONE);
268 : #else
269 :
270 : // check the status
271 0 : if(verify && (this->spiConfig.checkStatusCb != nullptr)) {
272 0 : state = this->spiConfig.checkStatusCb(this);
273 : }
274 :
275 0 : return(state);
276 : #endif
277 : }
278 :
279 327 : int16_t Module::SPIwriteStream(uint16_t cmd, const uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
280 : uint8_t cmdBuf[2];
281 327 : uint8_t* cmdPtr = cmdBuf;
282 981 : for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
283 654 : *(cmdPtr++) = (cmd >> 8*i) & 0xFF;
284 : }
285 654 : return(this->SPIwriteStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, data, numBytes, waitForGpio, verify));
286 : }
287 :
288 327 : int16_t Module::SPIwriteStream(const uint8_t* cmd, uint8_t cmdLen, const uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
289 : // send the command
290 327 : int16_t state = this->SPItransferStream(cmd, cmdLen, true, data, NULL, numBytes, waitForGpio);
291 327 : RADIOLIB_ASSERT(state);
292 :
293 : #if !RADIOLIB_SPI_PARANOID
294 : (void)verify;
295 : return(RADIOLIB_ERR_NONE);
296 : #else
297 :
298 : // check the status
299 185 : if(verify && (this->spiConfig.checkStatusCb != nullptr)) {
300 9 : state = this->spiConfig.checkStatusCb(this);
301 : }
302 :
303 185 : return(state);
304 : #endif
305 : }
306 :
307 30 : int16_t Module::SPIcheckStream() {
308 30 : int16_t state = RADIOLIB_ERR_NONE;
309 :
310 : #if RADIOLIB_SPI_PARANOID
311 : // get the status
312 30 : uint8_t spiStatus = 0;
313 : uint8_t cmdBuf[2];
314 30 : uint8_t* cmdPtr = cmdBuf;
315 90 : for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
316 60 : *(cmdPtr++) = ( this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] >> 8*i) & 0xFF;
317 : }
318 30 : state = this->SPItransferStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, false, NULL, &spiStatus, 1, true);
319 30 : RADIOLIB_ASSERT(state);
320 :
321 : // translate to RadioLib status code
322 0 : if(this->spiConfig.parseStatusCb != nullptr) {
323 0 : this->spiConfig.err = this->spiConfig.parseStatusCb(spiStatus);
324 : }
325 : #endif
326 :
327 0 : return(state);
328 : }
329 :
330 3292 : int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, const uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio) {
331 : // prepare the output buffer
332 3292 : int16_t state = RADIOLIB_ERR_NONE;
333 3292 : size_t buffLen = cmdLen + numBytes;
334 3292 : if(!write) {
335 2744 : buffLen += (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8);
336 : }
337 : #if RADIOLIB_STATIC_ONLY
338 : uint8_t buffOut[RADIOLIB_STATIC_SPI_ARRAY_SIZE];
339 : #else
340 3292 : uint8_t* buffOut = new uint8_t[buffLen];
341 : #endif
342 3292 : uint8_t* buffOutPtr = buffOut;
343 :
344 : // copy the command
345 12313 : for(uint8_t n = 0; n < cmdLen; n++) {
346 9021 : *(buffOutPtr++) = cmd[n];
347 : }
348 :
349 : // copy the data
350 3292 : if(write) {
351 548 : memcpy(buffOutPtr, dataOut, numBytes);
352 : } else {
353 2744 : memset(buffOutPtr, this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP], numBytes + (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8));
354 : }
355 :
356 : // ensure GPIO is low
357 3292 : if(waitForGpio) {
358 3207 : if(this->gpioPin == RADIOLIB_NC) {
359 0 : this->hal->delay(50);
360 : } else {
361 3207 : RadioLibTime_t start = this->hal->millis();
362 3207 : while(this->hal->digitalRead(this->gpioPin)) {
363 0 : this->hal->yield();
364 :
365 : // this timeout check triggers a false positive from cppcheck
366 : // cppcheck-suppress unsignedLessThanZero
367 0 : if(this->hal->millis() - start >= this->spiConfig.timeout) {
368 : RADIOLIB_DEBUG_BASIC_PRINTLN("GPIO pre-transfer timeout, is it connected?");
369 : #if !RADIOLIB_STATIC_ONLY
370 0 : delete[] buffOut;
371 : #endif
372 0 : return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
373 : }
374 :
375 : }
376 : }
377 : }
378 :
379 : // prepare the input buffer
380 : #if RADIOLIB_STATIC_ONLY
381 : uint8_t buffIn[RADIOLIB_STATIC_SPI_ARRAY_SIZE];
382 : #else
383 3292 : uint8_t* buffIn = new uint8_t[buffLen];
384 : #endif
385 :
386 : // do the transfer
387 3292 : this->hal->spiBeginTransaction();
388 3292 : this->hal->digitalWrite(this->csPin, this->hal->GpioLevelLow);
389 3292 : this->hal->spiTransfer(buffOut, buffLen, buffIn);
390 3292 : this->hal->digitalWrite(this->csPin, this->hal->GpioLevelHigh);
391 3292 : this->hal->spiEndTransaction();
392 :
393 : // wait for GPIO to go high and then low
394 3292 : if(waitForGpio) {
395 3207 : if(this->gpioPin == RADIOLIB_NC) {
396 0 : this->hal->delay(1);
397 : } else {
398 3207 : this->hal->delayMicroseconds(1);
399 3207 : RadioLibTime_t start = this->hal->millis();
400 3207 : while(this->hal->digitalRead(this->gpioPin)) {
401 0 : this->hal->yield();
402 :
403 : // this timeout check triggers a false positive from cppcheck
404 : // cppcheck-suppress unsignedLessThanZero
405 0 : if(this->hal->millis() - start >= this->spiConfig.timeout) {
406 : RADIOLIB_DEBUG_BASIC_PRINTLN("GPIO post-transfer timeout, is it connected?");
407 :
408 : // do not return yet to display the debug output
409 0 : state = RADIOLIB_ERR_SPI_CMD_TIMEOUT;
410 0 : break;
411 : }
412 :
413 : }
414 : }
415 : }
416 :
417 : // parse status (only if GPIO did not timeout)
418 3292 : if((state == RADIOLIB_ERR_NONE) && (this->spiConfig.parseStatusCb != nullptr) && (numBytes > 0)) {
419 3059 : state = this->spiConfig.parseStatusCb(buffIn[this->spiConfig.statusPos]);
420 : }
421 :
422 : // copy the data
423 3292 : if(!write) {
424 : // skip the status bytes if present
425 2744 : memcpy(dataIn, &buffIn[cmdLen + (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8)], numBytes);
426 : }
427 :
428 : // print debug information
429 : #if RADIOLIB_DEBUG_SPI
430 : // print command byte(s)
431 : RADIOLIB_DEBUG_SPI_PRINT("CMD");
432 : if(write) {
433 : RADIOLIB_DEBUG_SPI_PRINT_NOTAG("W\t");
434 : } else {
435 : RADIOLIB_DEBUG_SPI_PRINT_NOTAG("R\t");
436 : }
437 : size_t n = 0;
438 : for(; n < cmdLen; n++) {
439 : // tab character intentionally omitted here
440 : // command is a single number so this is easier to parse
441 : RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%02X", cmd[n]);
442 : }
443 : RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG("");
444 :
445 : // print data bytes
446 : RADIOLIB_DEBUG_SPI_PRINT("SI\t");
447 : for(n = 0; n < cmdLen; n++) {
448 : RADIOLIB_DEBUG_SPI_PRINT_NOTAG("\t");
449 : }
450 : // initialization of n to 0 is skipped here, because we want to skip the command bytes
451 : for(; n < buffLen; n++) {
452 : RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%02X\t", buffOut[n]);
453 : }
454 : RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG("");
455 : RADIOLIB_DEBUG_SPI_PRINT("SO\t");
456 : for(n = 0; n < buffLen; n++) {
457 : RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%02X\t", buffIn[n]);
458 : }
459 : RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG("");
460 : #endif
461 :
462 : #if !RADIOLIB_STATIC_ONLY
463 3292 : delete[] buffOut;
464 3292 : delete[] buffIn;
465 : #endif
466 :
467 3292 : return(state);
468 : }
469 :
470 0 : void Module::waitForMicroseconds(RadioLibTime_t start, RadioLibTime_t len) {
471 : #if RADIOLIB_INTERRUPT_TIMING
472 : (void)start;
473 : if((this->TimerSetupCb != nullptr) && (len != this->prevTimingLen)) {
474 : prevTimingLen = len;
475 : this->TimerSetupCb(len);
476 : }
477 : this->TimerFlag = false;
478 : while(!this->TimerFlag) {
479 : this->hal->yield();
480 : }
481 : #else
482 0 : while(this->hal->micros() - start < len) {
483 0 : this->hal->yield();
484 : }
485 : #endif
486 0 : }
487 :
488 : #if RADIOLIB_DEBUG
489 : void Module::regdump(const char* level, uint16_t start, size_t len) {
490 : #if RADIOLIB_STATIC_ONLY
491 : uint8_t buff[RADIOLIB_STATIC_ARRAY_SIZE];
492 : #else
493 : uint8_t* buff = new uint8_t[len];
494 : #endif
495 : SPIreadRegisterBurst(start, len, buff);
496 : rlb_hexdump(level, buff, len, start);
497 : #if !RADIOLIB_STATIC_ONLY
498 : delete[] buff;
499 : #endif
500 : }
501 : #endif
502 :
503 0 : void Module::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
504 : // This can be on the stack, setRfSwitchTable copies the contents
505 0 : const uint32_t pins[] = {
506 : rxEn, txEn, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC,
507 0 : };
508 :
509 : // This must be static, since setRfSwitchTable stores a reference.
510 : static const RfSwitchMode_t table[] = {
511 0 : { MODE_IDLE, {this->hal->GpioLevelLow, this->hal->GpioLevelLow} },
512 0 : { MODE_RX, {this->hal->GpioLevelHigh, this->hal->GpioLevelLow} },
513 0 : { MODE_TX, {this->hal->GpioLevelLow, this->hal->GpioLevelHigh} },
514 : END_OF_MODE_TABLE,
515 0 : };
516 0 : setRfSwitchTable(pins, table);
517 0 : }
518 :
519 0 : void Module::setRfSwitchTable(const uint32_t (&pins)[RFSWITCH_MAX_PINS], const RfSwitchMode_t table[]) {
520 0 : memcpy(this->rfSwitchPins, pins, sizeof(this->rfSwitchPins));
521 0 : this->rfSwitchTable = table;
522 0 : for(size_t i = 0; i < RFSWITCH_MAX_PINS; i++) {
523 0 : this->hal->pinMode(pins[i], this->hal->GpioModeOutput);
524 : }
525 0 : }
526 :
527 154 : const Module::RfSwitchMode_t *Module::findRfSwitchMode(uint8_t mode) const {
528 154 : const RfSwitchMode_t *row = this->rfSwitchTable;
529 154 : while(row && row->mode != MODE_END_OF_TABLE) {
530 0 : if(row->mode == mode) {
531 0 : return row;
532 : }
533 0 : ++row;
534 : }
535 154 : return nullptr;
536 : }
537 :
538 154 : void Module::setRfSwitchState(uint8_t mode) {
539 154 : const RfSwitchMode_t *row = findRfSwitchMode(mode);
540 154 : if(!row) {
541 : // RF switch control is disabled or does not have this mode
542 154 : return;
543 : }
544 :
545 : // set pins
546 0 : const uint32_t *value = &row->values[0];
547 0 : for(size_t i = 0; i < RFSWITCH_MAX_PINS; i++) {
548 0 : uint32_t pin = this->rfSwitchPins[i];
549 0 : if(!(pin & RFSWITCH_PIN_FLAG)) {
550 0 : this->hal->digitalWrite(pin, *value);
551 : }
552 0 : ++value;
553 : }
554 : }
|