LCOV - code coverage report
Current view: top level - src/modules/LR11x0 - LR_common.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 92 257 35.8 %
Date: 2026-02-22 10:42:45 Functions: 10 21 47.6 %

          Line data    Source code
       1             : #include "LR_common.h"
       2             : 
       3             : #include <string.h>
       4             : 
       5          17 : LRxxxx::LRxxxx(Module* mod) : PhysicalLayer() {
       6          17 :   this->mod = mod;
       7          17 :   this->XTAL = false;
       8          17 :   this->mod->spiConfig.stream = true;
       9          17 :   this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_16;
      10          17 :   this->mod->spiConfig.statusPos = 0;
      11          17 :   this->mod->spiConfig.parseStatusCb = SPIparseStatus;
      12          17 :   this->mod->spiConfig.checkStatusCb = SPIcheckStatus;
      13          17 : }
      14             : 
      15           0 : void LRxxxx::setIrqAction(void (*func)(void)) {
      16           0 :   this->mod->hal->attachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()), func, this->mod->hal->GpioInterruptRising);
      17           0 : }
      18             : 
      19           0 : void LRxxxx::clearIrqAction() {
      20           0 :   this->mod->hal->detachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()));
      21           0 : }
      22             : 
      23           0 : void LRxxxx::setPacketReceivedAction(void (*func)(void)) {
      24           0 :   this->setIrqAction(func);
      25           0 : }
      26             : 
      27           0 : void LRxxxx::clearPacketReceivedAction() {
      28           0 :   this->clearIrqAction();
      29           0 : }
      30             : 
      31           0 : void LRxxxx::setPacketSentAction(void (*func)(void)) {
      32           0 :   this->setIrqAction(func);
      33           0 : }
      34             : 
      35           0 : void LRxxxx::clearPacketSentAction() {
      36           0 :   this->clearIrqAction();
      37           0 : }
      38             : 
      39           4 : uint32_t LRxxxx::getIrqStatus() {
      40             :   // there is no dedicated "get IRQ" command, the IRQ bits are sent after the status bytes
      41           4 :   uint8_t buff[6] = { 0 };
      42           4 :   Module::BitWidth_t statusWidth = mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS];
      43           4 :   this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_0;
      44           4 :   mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true);
      45           4 :   this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = statusWidth;
      46           4 :   uint32_t irq = ((uint32_t)(buff[2]) << 24) | ((uint32_t)(buff[3]) << 16) | ((uint32_t)(buff[4]) << 8) | (uint32_t)buff[5];
      47           4 :   return(irq);
      48             : }
      49             : 
      50           3 : RadioLibTime_t LRxxxx::getTimeOnAir(size_t len, ModemType_t modem) {
      51           3 :   DataRate_t dr = {};
      52           3 :   PacketConfig_t pc = {};
      53           3 :   switch(modem) {
      54           0 :     case ModemType_t::RADIOLIB_MODEM_LORA: {
      55           0 :       uint8_t cr = this->codingRate;
      56             :       // We assume same calculation for short and long interleaving, so map CR values 0-4 and 5-7 to the same values
      57           0 :       if (cr < 5) {
      58           0 :         cr = cr + 4;
      59           0 :       } else if (cr == 7) {
      60           0 :         cr = cr + 1;
      61             :       }
      62             : 
      63           0 :       dr.lora.spreadingFactor = this->spreadingFactor;
      64           0 :       dr.lora.bandwidth = this->bandwidthKhz;
      65           0 :       dr.lora.codingRate = cr;
      66             : 
      67           0 :       pc.lora.preambleLength = this->preambleLengthLoRa;
      68           0 :       pc.lora.implicitHeader = (this->headerType == RADIOLIB_LRXXXX_LORA_HEADER_IMPLICIT);
      69           0 :       pc.lora.crcEnabled = (this->crcTypeLoRa == RADIOLIB_LRXXXX_LORA_CRC_ENABLED);
      70           0 :       pc.lora.ldrOptimize = (bool)this->ldrOptimize;
      71           0 :       break;
      72             :     }
      73             : 
      74           0 :     case ModemType_t::RADIOLIB_MODEM_FSK: {
      75           0 :       dr.fsk.bitRate = (float)this->bitRate / 1000.0f;
      76           0 :       dr.fsk.freqDev = (float)this->frequencyDev;
      77           0 :       pc.fsk.preambleLength = this->preambleLengthGFSK;
      78           0 :       pc.fsk.syncWordLength = this->syncWordLength; 
      79           0 :       pc.fsk.crcLength = this->crcLenGFSK;
      80           0 :       break;
      81             :     }
      82             : 
      83           0 :     case ModemType_t::RADIOLIB_MODEM_LRFHSS: {
      84           0 :       dr.lrFhss.bw = this->lrFhssBw;
      85           0 :       dr.lrFhss.cr = this->lrFhssCr;
      86           0 :       dr.lrFhss.narrowGrid = (this->lrFhssGrid == RADIOLIB_LRXXXX_LR_FHSS_GRID_STEP_NON_FCC) ? true : false;
      87             : 
      88           0 :       pc.lrFhss.hdrCount = this->lrFhssHdrCount;
      89           0 :       break;
      90             :     }
      91             : 
      92           3 :     default:
      93           3 :       return(RADIOLIB_ERR_WRONG_MODEM);
      94             :   }
      95             : 
      96           0 :   return(this->calculateTimeOnAir(modem, dr, pc, len));
      97             : }
      98             : 
      99          17 : RadioLibTime_t LRxxxx::calculateTimeOnAir(ModemType_t modem, DataRate_t dr, PacketConfig_t pc, size_t len) {
     100             :   // check active modem
     101          17 :   if (modem == ModemType_t::RADIOLIB_MODEM_LORA) {  
     102           6 :     uint32_t symbolLength_us = ((uint32_t)(1000 * 10) << dr.lora.spreadingFactor) / (dr.lora.bandwidth * 10) ;
     103           6 :     uint8_t sfCoeff1_x4 = 17; // (4.25 * 4)
     104           6 :     uint8_t sfCoeff2 = 8;
     105           6 :     if(dr.lora.spreadingFactor == 5 || dr.lora.spreadingFactor == 6) {
     106           0 :       sfCoeff1_x4 = 25; // 6.25 * 4
     107           0 :       sfCoeff2 = 0;
     108             :     }
     109           6 :     uint8_t sfDivisor = 4*dr.lora.spreadingFactor;
     110           6 :     if(pc.lora.ldrOptimize) {
     111           3 :       sfDivisor = 4*(dr.lora.spreadingFactor - 2);
     112             :     }
     113           6 :     const int8_t bitsPerCrc = 16;
     114           6 :     const int8_t N_symbol_header = pc.lora.implicitHeader ? 0 : 20;
     115             : 
     116             :     // numerator of equation in section 6.1.4 of SX1268 datasheet v1.1 (might not actually be bitcount, but it has len * 8)
     117           6 :     int16_t bitCount = (int16_t) 8 * len + pc.lora.crcEnabled * bitsPerCrc - 4 * dr.lora.spreadingFactor  + sfCoeff2 + N_symbol_header;
     118           6 :     if(bitCount < 0) {
     119           0 :       bitCount = 0;
     120             :     }
     121             :     // add (sfDivisor) - 1 to the numerator to give integer CEIL(...)
     122           6 :     uint16_t nPreCodedSymbols = (bitCount + (sfDivisor - 1)) / (sfDivisor);
     123             : 
     124             :     // preamble can be 65k, therefore nSymbol_x4 needs to be 32 bit
     125           6 :     uint32_t nSymbol_x4 = (pc.lora.preambleLength + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * dr.lora.codingRate * 4;
     126             : 
     127             :     // get time-on-air in us
     128           6 :     return((symbolLength_us * nSymbol_x4) / 4);
     129             : 
     130          11 :   } else if(modem == ModemType_t::RADIOLIB_MODEM_FSK) {
     131           4 :     return((((float)(pc.fsk.crcLength * 8) + pc.fsk.syncWordLength + pc.fsk.preambleLength + (uint32_t)len * 8) / (dr.fsk.bitRate / 1000.0f)));
     132             : 
     133           7 :   } else if(modem == ModemType_t::RADIOLIB_MODEM_LRFHSS) {
     134             :     // calculate the number of bits based on coding rate
     135             :     uint16_t N_bits;
     136           3 :     switch(dr.lrFhss.cr) {
     137           0 :       case RADIOLIB_LRXXXX_LR_FHSS_CR_5_6:
     138           0 :         N_bits = ((len * 6) + 4) / 5; // this is from the official LR11xx driver, but why the extra +4?
     139           0 :         break;
     140           0 :       case RADIOLIB_LRXXXX_LR_FHSS_CR_2_3:
     141           0 :         N_bits = (len * 3) / 2;
     142           0 :         break;
     143           0 :       case RADIOLIB_LRXXXX_LR_FHSS_CR_1_2:
     144           0 :         N_bits = len * 2;
     145           0 :         break;
     146           3 :       case RADIOLIB_LRXXXX_LR_FHSS_CR_1_3:
     147           3 :         N_bits = len * 3;
     148           3 :         break;
     149           0 :       default:
     150           0 :         return(RADIOLIB_ERR_INVALID_CODING_RATE);
     151             :     }
     152             : 
     153             :     // calculate number of bits when accounting for unaligned last block
     154           3 :     uint16_t N_payBits = (N_bits / RADIOLIB_LRXXXX_LR_FHSS_FRAG_BITS) * RADIOLIB_LRXXXX_LR_FHSS_BLOCK_BITS;
     155           3 :     uint16_t N_lastBlockBits = N_bits % RADIOLIB_LRXXXX_LR_FHSS_FRAG_BITS;
     156           3 :     if(N_lastBlockBits) {
     157           3 :       N_payBits += N_lastBlockBits + 2;
     158             :     }
     159             : 
     160             :     // add header bits
     161           3 :     uint16_t N_totalBits = (RADIOLIB_LRXXXX_LR_FHSS_HEADER_BITS * pc.lrFhss.hdrCount) + N_payBits;
     162           3 :     return(((uint32_t)N_totalBits * 8 * 1000000UL) / RADIOLIB_LRXXXX_LR_FHSS_BIT_RATE);
     163             :   
     164             :   } else {
     165           4 :     return(RADIOLIB_ERR_WRONG_MODEM);
     166             :   }
     167             : 
     168             :   return(0);
     169             : }
     170             : 
     171           4 : RadioLibTime_t LRxxxx::calculateRxTimeout(RadioLibTime_t timeoutUs) {
     172             :   // the timeout value is given in units of 30.52 microseconds
     173             :   // the calling function should provide some extra width, as this number of units is truncated to integer
     174           4 :   RadioLibTime_t timeout = timeoutUs / 30.52;
     175           4 :   return(timeout);
     176             : }
     177             : 
     178           0 : int16_t LRxxxx::reset() {
     179             :   // run the reset sequence
     180           0 :   this->mod->hal->pinMode(this->mod->getRst(), this->mod->hal->GpioModeOutput);
     181           0 :   this->mod->hal->digitalWrite(this->mod->getRst(), this->mod->hal->GpioLevelLow);
     182           0 :   this->mod->hal->delay(10);
     183           0 :   this->mod->hal->digitalWrite(this->mod->getRst(), this->mod->hal->GpioLevelHigh);
     184             : 
     185             :   // the typical transition duration should be 273 ms
     186           0 :   this->mod->hal->delay(300);
     187             :   
     188             :   // wait for BUSY to go low
     189           0 :   RadioLibTime_t start = this->mod->hal->millis();
     190           0 :   while(this->mod->hal->digitalRead(this->mod->getGpio())) {
     191           0 :     this->mod->hal->yield();
     192           0 :     if(this->mod->hal->millis() - start >= 3000) {
     193             :       RADIOLIB_DEBUG_BASIC_PRINTLN("BUSY pin timeout after reset!");
     194           0 :       return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
     195             :     }
     196             :   }
     197             : 
     198           0 :   return(RADIOLIB_ERR_NONE);
     199             : }
     200             : 
     201           0 : int16_t LRxxxx::getStatus(uint8_t* stat1, uint8_t* stat2, uint32_t* irq) {
     202           0 :   uint8_t buff[6] = { 0 };
     203             : 
     204             :   // the status check command doesn't return status in the same place as other read commands
     205             :   // but only as the first byte (as with any other command), hence LRxxxx::SPIcommand can't be used
     206             :   // it also seems to ignore the actual command, and just sending in bunch of NOPs will work 
     207           0 :   int16_t state = this->mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true);
     208             : 
     209             :   // pass the replies
     210           0 :   if(stat1) { *stat1 = buff[0]; }
     211           0 :   if(stat2) { *stat2 = buff[1]; }
     212           0 :   if(irq)   { *irq = ((uint32_t)(buff[2]) << 24) | ((uint32_t)(buff[3]) << 16) | ((uint32_t)(buff[4]) << 8) | (uint32_t)buff[5]; }
     213             : 
     214           0 :   return(state);
     215             : }
     216             : 
     217           0 : int16_t LRxxxx::lrFhssBuildFrame(uint16_t cmd, uint8_t hdrCount, uint8_t cr, uint8_t grid, uint8_t hop, uint8_t bw, uint16_t hopSeq, int8_t devOffset, const uint8_t* payload, size_t len) {
     218             :   // check maximum size
     219           0 :   const uint8_t maxLen[4][4] = {
     220             :     { 189, 178, 167, 155, },
     221             :     { 151, 142, 133, 123, },
     222             :     { 112, 105,  99,  92, },
     223             :     {  74,  69,  65,  60, },
     224             :   };
     225           0 :   if((cr > RADIOLIB_LRXXXX_LR_FHSS_CR_1_3) || ((hdrCount - 1) > (int)sizeof(maxLen[0])) || (len > maxLen[cr][hdrCount - 1])) {
     226           0 :     return(RADIOLIB_ERR_SPI_CMD_INVALID);
     227             :   }
     228             : 
     229             :   // build buffers
     230           0 :   size_t buffLen = 9 + len;
     231             :   #if RADIOLIB_STATIC_ONLY
     232             :     uint8_t dataBuff[9 + 190];
     233             :   #else
     234           0 :     uint8_t* dataBuff = new uint8_t[buffLen];
     235             :   #endif
     236             : 
     237             :   // set properties of the packet
     238           0 :   dataBuff[0] = hdrCount;
     239           0 :   dataBuff[1] = cr;
     240           0 :   dataBuff[2] = RADIOLIB_LRXXXX_LR_FHSS_MOD_TYPE_GMSK;
     241           0 :   dataBuff[3] = grid;
     242           0 :   dataBuff[4] = hop;
     243           0 :   dataBuff[5] = bw;
     244           0 :   dataBuff[6] = (uint8_t)((hopSeq >> 8) & 0x01);
     245           0 :   dataBuff[7] = (uint8_t)(hopSeq & 0xFF);
     246           0 :   dataBuff[8] = devOffset;
     247           0 :   memcpy(&dataBuff[9], payload, len);
     248             : 
     249           0 :   int16_t state = this->SPIcommand(cmd, true, dataBuff, buffLen);
     250             :   #if !RADIOLIB_STATIC_ONLY
     251           0 :     delete[] dataBuff;
     252             :   #endif
     253           0 :   return(state);
     254             : }
     255             : 
     256           3 : uint8_t LRxxxx::roundRampTime(uint32_t rampTimeUs) {
     257             :   uint8_t regVal;
     258             : 
     259             :   // Round up the ramp time to nearest discrete register value
     260           3 :   if(rampTimeUs <= 2) {
     261           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_2U;
     262           3 :   } else if(rampTimeUs <= 4) {
     263           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_4U;
     264           3 :   } else if(rampTimeUs <= 8) {
     265           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_8U;
     266           3 :   } else if(rampTimeUs <= 16) {
     267           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_16U;
     268           3 :   } else if(rampTimeUs <= 32) {
     269           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_32U;
     270           3 :   } else if(rampTimeUs <= 48) {
     271           3 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_48U;
     272           0 :   } else if(rampTimeUs <= 64) {
     273           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_64U;
     274           0 :   } else if(rampTimeUs <= 80) {
     275           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_80U;
     276           0 :   } else if(rampTimeUs <= 96) {
     277           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_96U;
     278           0 :   } else if(rampTimeUs <= 112) {
     279           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_112U;
     280           0 :   } else if(rampTimeUs <= 128) {
     281           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_128U;
     282           0 :   } else if(rampTimeUs <= 144) {
     283           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_144U;
     284           0 :   } else if(rampTimeUs <= 160) {
     285           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_160U;
     286           0 :   } else if(rampTimeUs <= 176) {
     287           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_176U;
     288           0 :   } else if(rampTimeUs <= 192) {
     289           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_192U;
     290           0 :   } else if(rampTimeUs <= 208) {
     291           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_208U;
     292           0 :   } else if(rampTimeUs <= 240) {
     293           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_240U;
     294           0 :   } else if(rampTimeUs <= 272) {
     295           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_272U;
     296             :   } else {  // 304
     297           0 :     regVal = RADIOLIB_LRXXXX_PA_RAMP_304U;
     298             :   }
     299             : 
     300           3 :   return regVal;
     301             : }
     302             : 
     303           0 : int16_t LRxxxx::findRxBw(float rxBw, const uint8_t* lut, size_t lutSize, float rxBwMax, uint8_t* val) {
     304             :   // lookup tables to avoid comparing a whole bunch of floats
     305           0 :   const uint16_t rxBwAvg[] = {
     306             :     53, 66, 85, 108, 134, 170, 211, 264,
     307             :     341, 424, 529, 682, 847, 1058, 1364,
     308             :     1695, 2116, 2729, 3390, 4233, 5159,
     309             :     6111, 7179, 9401, 16665, 24440, 28710,
     310             :   };
     311             : 
     312             :   // iterate through the table and find whether the user-provided value
     313             :   // is lower than the pre-computed average of the adjacent bandwidth values
     314             :   // if it is, we consider that to be a match even though the actual value is not precise
     315           0 :   uint16_t rxBwInt = rxBw*10.0f;
     316           0 :   for(size_t i = 0; i < lutSize; i++) {
     317           0 :     if(rxBwInt < rxBwAvg[i]) {
     318           0 :       *val = lut[i];
     319           0 :       return(RADIOLIB_ERR_NONE);
     320             :     }
     321             :   }
     322             : 
     323             :   // if nothing matched up to here, match with the last value
     324           0 :   if(rxBwInt <= rxBwMax*10) {
     325           0 :     *val = lut[lutSize - 1];
     326           0 :     return(RADIOLIB_ERR_NONE);
     327             :   }
     328             : 
     329           0 :   return(RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
     330             : }
     331             : 
     332           8 : int16_t LRxxxx::setU32(uint16_t cmd, uint32_t u32) {
     333             :   uint8_t buff[] = { 
     334           8 :     (uint8_t)((u32 >> 24) & 0xFF), (uint8_t)((u32 >> 16) & 0xFF),
     335           8 :     (uint8_t)((u32 >> 8) & 0xFF), (uint8_t)(u32 & 0xFF),
     336           8 :   };
     337          16 :   return(this->SPIcommand(cmd, true, buff, sizeof(buff)));
     338             : }
     339             : 
     340        3059 : int16_t LRxxxx::SPIparseStatus(uint8_t in) {
     341        3059 :   if((in & 0b00001110) == RADIOLIB_LRXXXX_STAT_1_CMD_PERR) {
     342           0 :     return(RADIOLIB_ERR_SPI_CMD_INVALID);
     343        3059 :   } else if((in & 0b00001110) == RADIOLIB_LRXXXX_STAT_1_CMD_FAIL) {
     344           0 :     return(RADIOLIB_ERR_SPI_CMD_FAILED);
     345        3059 :   } else if((in == 0x00) || (in == 0xFF)) {
     346        3059 :     return(RADIOLIB_ERR_CHIP_NOT_FOUND);
     347             :   }
     348           0 :   return(RADIOLIB_ERR_NONE);
     349             : }
     350             : 
     351           9 : int16_t LRxxxx::SPIcheckStatus(Module* mod) {
     352             :   // the status check command doesn't return status in the same place as other read commands,
     353             :   // but only as the first byte (as with any other command), hence LR11x0::SPIcommand can't be used
     354             :   // it also seems to ignore the actual command, and just sending in bunch of NOPs will work 
     355           9 :   uint8_t buff[6] = { 0 };
     356           9 :   Module::BitWidth_t statusWidth = mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS];
     357           9 :   mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_0;
     358           9 :   int16_t state = mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true);
     359           9 :   mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = statusWidth;
     360           9 :   RADIOLIB_ASSERT(state);
     361           0 :   return(LRxxxx::SPIparseStatus(buff[0]));
     362             : }
     363             : 
     364           0 : int16_t LRxxxx::writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* data, size_t len, bool nonvolatile) {
     365             :   // build buffers - later we need to ensure endians are correct, 
     366             :   // so there is probably no way to do this without copying buffers and iterating
     367           0 :   size_t buffLen = sizeof(uint32_t) + len*sizeof(uint32_t);
     368             :   #if RADIOLIB_STATIC_ONLY
     369             :     uint8_t dataBuff[sizeof(uint32_t) + RADIOLIB_LRXXXX_SPI_MAX_READ_WRITE_LEN];
     370             :   #else
     371           0 :     uint8_t* dataBuff = new uint8_t[buffLen];
     372             :   #endif
     373             : 
     374             :   // set the address or offset
     375           0 :   uint8_t* dataBuffPtr = reinterpret_cast<uint8_t*>(dataBuff);
     376           0 :   if(this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] >= Module::BITS_32) {
     377             :     // LR2021 has 24-bit address, whereas LR11x0 has 32-bit
     378           0 :     *(dataBuffPtr++) = (uint8_t)((addrOffset >> 24) & 0xFF);
     379             :   }
     380             :   
     381           0 :   *(dataBuffPtr++) = (uint8_t)((addrOffset >> 16) & 0xFF);
     382           0 :   *(dataBuffPtr++) = (uint8_t)((addrOffset >> 8) & 0xFF);
     383           0 :   *(dataBuffPtr++) = (uint8_t)(addrOffset & 0xFF);
     384             : 
     385             :   // convert endians
     386           0 :   for(size_t i = 0; i < len; i++) {
     387           0 :     uint32_t bin = 0;
     388           0 :     if(nonvolatile) {
     389           0 :       uint32_t* ptr = const_cast<uint32_t*>(data) + i;
     390           0 :       bin = RADIOLIB_NONVOLATILE_READ_DWORD(ptr);
     391             :     } else {
     392           0 :       bin = data[i];
     393             :     }
     394           0 :     *(dataBuffPtr++) = (uint8_t)((bin >> 24) & 0xFF);
     395           0 :     *(dataBuffPtr++) = (uint8_t)((bin >> 16) & 0xFF);
     396           0 :     *(dataBuffPtr++) = (uint8_t)((bin >> 8) & 0xFF);
     397           0 :     *(dataBuffPtr++) = (uint8_t)(bin & 0xFF);
     398             :   }
     399             : 
     400           0 :   int16_t state = this->mod->SPIwriteStream(cmd, dataBuff, buffLen, true, false);
     401             :   #if !RADIOLIB_STATIC_ONLY
     402           0 :     delete[] dataBuff;
     403             :   #endif
     404           0 :   return(state);
     405             : }
     406             : 
     407         149 : int16_t LRxxxx::SPIcommand(uint16_t cmd, bool write, uint8_t* data, size_t len, const uint8_t* out, size_t outLen) {
     408         149 :   int16_t state = RADIOLIB_ERR_UNKNOWN;
     409         149 :   if(!write) {
     410             :     // the SPI interface of LR11x0 requires two separate transactions for reading
     411             :     // send the 16-bit command
     412         101 :     state = this->mod->SPIwriteStream(cmd, out, outLen, true, false);
     413         101 :     RADIOLIB_ASSERT(state);
     414             : 
     415             :     // read the result without command
     416         101 :     this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_0;
     417         101 :     state = this->mod->SPIreadStream(RADIOLIB_LRXXXX_CMD_NOP, data, len, true, false);
     418         101 :     this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_16;
     419             : 
     420             :   } else {
     421             :     // write is just a single transaction
     422          48 :     state = this->mod->SPIwriteStream(cmd, data, len, true, true);
     423             :   
     424             :   }
     425             :   
     426         149 :   return(state);
     427             : }

Generated by: LCOV version 1.14