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