LCOV - code coverage report
Current view: top level - src/modules/LR11x0 - LR11x0_gnss.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 423 0.0 %
Date: 2025-10-24 15:14:50 Functions: 0 58 0.0 %

          Line data    Source code
       1             : #include "LR11x0.h"
       2             : 
       3             : #include <string.h>
       4             : 
       5             : #if !RADIOLIB_EXCLUDE_LR11X0
       6             : 
       7           0 : int16_t LR11x0::isGnssScanCapable() {
       8             :   // get the version
       9             :   LR11x0VersionInfo_t version;
      10           0 :   int16_t state = this->getVersionInfo(&version);
      11           0 :   RADIOLIB_ASSERT(state);
      12             : 
      13             :   // check the device firmware version is sufficient
      14           0 :   uint16_t versionFull = ((uint16_t)version.fwMajor << 8) | (uint16_t)version.fwMinor;
      15           0 :   state = RADIOLIB_ERR_UNSUPPORTED;
      16           0 :   if((version.device == RADIOLIB_LR11X0_DEVICE_LR1110) && (versionFull >= 0x0401)) {
      17           0 :     state = RADIOLIB_ERR_NONE;
      18           0 :   } else if((version.device == RADIOLIB_LR11X0_DEVICE_LR1120) && (versionFull >= 0x0201)) {
      19           0 :     state = RADIOLIB_ERR_NONE;
      20             :   }
      21           0 :   RADIOLIB_ASSERT(state);
      22             : 
      23             :   // in debug mode, dump the almanac
      24             :   #if RADIOLIB_DEBUG_PROTOCOL
      25             :   uint32_t addr = 0;
      26             :   uint16_t sz = 0;
      27             :   state = this->gnssAlmanacReadAddrSize(&addr, &sz);
      28             :   RADIOLIB_ASSERT(state);
      29             :   RADIOLIB_DEBUG_BASIC_PRINTLN("Almanac@%08x, %d bytes", addr, sz);
      30             :   uint32_t buff[32] = { 0 };
      31             :   while(sz > 0) {
      32             :     size_t len = sz > 32 ? 32 : sz/sizeof(uint32_t);
      33             :     state = this->readRegMem32(addr, buff, len);
      34             :     RADIOLIB_ASSERT(state);
      35             :     RADIOLIB_DEBUG_HEXDUMP(NULL, reinterpret_cast<uint8_t*>(buff), len*sizeof(uint32_t), addr);
      36             :     addr += len*sizeof(uint32_t);
      37             :     sz -= len*sizeof(uint32_t);
      38             :   }
      39             : 
      40             :   uint8_t almanac[22] = { 0 };
      41             :   for(uint8_t i = 0; i < 128; i++) {
      42             :     RADIOLIB_DEBUG_BASIC_PRINTLN("Almanac[%d]:", i);
      43             :     state = this->gnssAlmanacReadSV(i, almanac);
      44             :     RADIOLIB_ASSERT(state);
      45             :     RADIOLIB_DEBUG_HEXDUMP(NULL, almanac, 22);
      46             :   }
      47             : 
      48             :   #endif
      49             : 
      50           0 :   return(state);
      51             : }
      52             : 
      53           0 : int16_t LR11x0::gnssScan(LR11x0GnssResult_t* res) {
      54           0 :   RADIOLIB_ASSERT_PTR(res);
      55             : 
      56             :   // go to standby
      57           0 :   int16_t state = standby();
      58           0 :   RADIOLIB_ASSERT(state);
      59             : 
      60             :   // set DIO mapping
      61           0 :   state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_GNSS_DONE | RADIOLIB_LR11X0_IRQ_GNSS_ABORT);
      62           0 :   RADIOLIB_ASSERT(state);
      63             : 
      64             :   // set scan mode (single vs multiple)
      65           0 :   state = this->gnssSetMode(0x03);
      66           0 :   RADIOLIB_ASSERT(state);
      67             :   
      68             :   // set RF switch
      69           0 :   this->mod->setRfSwitchState(LR11x0::MODE_GNSS);
      70             : 
      71             :   // start scan with high effort
      72             :   RADIOLIB_DEBUG_BASIC_PRINTLN("GNSS scan start");
      73           0 :   state = this->gnssPerformScan(RADIOLIB_LR11X0_GNSS_EFFORT_MID, 0x3C, 16);
      74           0 :   RADIOLIB_ASSERT(state);
      75             : 
      76             :   // wait for scan finished or timeout
      77             :   // this can take very long if both GPS and BeiDou are enabled
      78           0 :   RadioLibTime_t softTimeout = 300UL * 1000UL;
      79           0 :   RadioLibTime_t start = this->mod->hal->millis();
      80           0 :   while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
      81           0 :     this->mod->hal->yield();
      82           0 :     if(this->mod->hal->millis() - start > softTimeout) {
      83           0 :       this->gnssAbort();
      84             :       RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout waiting for IRQ");
      85             :     }
      86             :   }
      87             : 
      88             :   // restore the switch
      89           0 :   this->mod->setRfSwitchState(Module::MODE_IDLE);
      90             :   RADIOLIB_DEBUG_BASIC_PRINTLN("GNSS scan done in %lu ms", (long unsigned int)(this->mod->hal->millis() - start));
      91             : 
      92             :   // distinguish between GNSS-done and GNSS-abort outcomes and clear the flags
      93           0 :   uint32_t irq = this->getIrqStatus();
      94           0 :   this->clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
      95           0 :   if(irq & RADIOLIB_LR11X0_IRQ_GNSS_ABORT) {
      96           0 :     return(RADIOLIB_ERR_RX_TIMEOUT);
      97             :   }
      98             : 
      99             :   // retrieve the demodulator status
     100           0 :   uint8_t info = 0;
     101           0 :   state = this->gnssReadDemodStatus(&res->demodStat, &info);
     102           0 :   RADIOLIB_ASSERT(state);
     103             :   RADIOLIB_DEBUG_BASIC_PRINTLN("Demod status %d, info %02x", (int)res->demodStat, (unsigned int)info);
     104             : 
     105             :   // retrieve the number of detected satellites
     106           0 :   state = this->gnssGetNbSvDetected(&res->numSatsDet);
     107           0 :   RADIOLIB_ASSERT(state);
     108             : 
     109             :   // retrieve the result size
     110           0 :   state = this->gnssGetResultSize(&res->resSize);
     111           0 :   RADIOLIB_ASSERT(state);
     112             : 
     113             :   // check and return demodulator status
     114           0 :   if(res->demodStat < RADIOLIB_LR11X0_GNSS_DEMOD_STATUS_TOW_FOUND) {
     115           0 :     return(RADIOLIB_ERR_GNSS_DEMOD(res->demodStat));
     116             :   }
     117             :   
     118           0 :   return(state);
     119             : }
     120             : 
     121           0 : int16_t LR11x0::getGnssAlmanacStatus(LR11x0GnssAlmanacStatus_t *stat) {
     122           0 :   RADIOLIB_ASSERT_PTR(stat);
     123             : 
     124             :   // save the time the time until subframe is relative to
     125           0 :   stat->start = this->mod->hal->millis();
     126             : 
     127             :   // get the raw data
     128           0 :   uint8_t raw[53] = { 0 };
     129           0 :   int16_t state = this->gnssReadAlmanacStatus(raw);
     130           0 :   RADIOLIB_ASSERT(state);
     131             : 
     132             :   // parse the reply
     133           0 :   stat->gps.status = (int8_t)raw[0];
     134           0 :   stat->gps.timeUntilSubframe = ((uint32_t)(raw[1]) << 24) | ((uint32_t)(raw[2]) << 16) | ((uint32_t)(raw[3]) << 8) | (uint32_t)raw[4];
     135           0 :   stat->gps.numSubframes = raw[5];
     136           0 :   stat->gps.nextSubframe4SvId = raw[6];
     137           0 :   stat->gps.nextSubframe5SvId = raw[7];
     138           0 :   stat->gps.nextSubframeStart = raw[8];
     139           0 :   stat->gps.numUpdateNeeded = raw[9];
     140           0 :   stat->gps.flagsUpdateNeeded[0] = ((uint32_t)(raw[10]) << 24) | ((uint32_t)(raw[11]) << 16) | ((uint32_t)(raw[12]) << 8) | (uint32_t)raw[13];
     141           0 :   stat->gps.flagsActive[0] = ((uint32_t)(raw[14]) << 24) | ((uint32_t)(raw[15]) << 16) | ((uint32_t)(raw[16]) << 8) | (uint32_t)raw[17];
     142           0 :   stat->beidou.status = (int8_t)raw[18];
     143           0 :   stat->beidou.timeUntilSubframe = ((uint32_t)(raw[19]) << 24) | ((uint32_t)(raw[20]) << 16) | ((uint32_t)(raw[21]) << 8) | (uint32_t)raw[22];
     144           0 :   stat->beidou.numSubframes = raw[23];
     145           0 :   stat->beidou.nextSubframe4SvId = raw[24];
     146           0 :   stat->beidou.nextSubframe5SvId = raw[25];
     147           0 :   stat->beidou.nextSubframeStart = raw[26];
     148           0 :   stat->beidou.numUpdateNeeded = raw[27];
     149           0 :   stat->beidou.flagsUpdateNeeded[0] = ((uint32_t)(raw[28]) << 24) | ((uint32_t)(raw[29]) << 16) | ((uint32_t)(raw[30]) << 8) | (uint32_t)raw[31];
     150           0 :   stat->beidou.flagsUpdateNeeded[1] = ((uint32_t)(raw[32]) << 24) | ((uint32_t)(raw[33]) << 16) | ((uint32_t)(raw[34]) << 8) | (uint32_t)raw[35];
     151           0 :   stat->beidou.flagsActive[0] = ((uint32_t)(raw[36]) << 24) | ((uint32_t)(raw[37]) << 16) | ((uint32_t)(raw[38]) << 8) | (uint32_t)raw[39];
     152           0 :   stat->beidou.flagsActive[1] = ((uint32_t)(raw[40]) << 24) | ((uint32_t)(raw[41]) << 16) | ((uint32_t)(raw[42]) << 8) | (uint32_t)raw[43];
     153           0 :   stat->beidouSvNoAlmanacFlags[0] = ((uint32_t)(raw[44]) << 24) | ((uint32_t)(raw[45]) << 16) | ((uint32_t)(raw[46]) << 8) | (uint32_t)raw[47];
     154           0 :   stat->beidouSvNoAlmanacFlags[1] = ((uint32_t)(raw[18]) << 24) | ((uint32_t)(raw[49]) << 16) | ((uint32_t)(raw[50]) << 8) | (uint32_t)raw[51];
     155           0 :   stat->nextAlmanacId = raw[52];
     156             : 
     157           0 :   return(state);
     158             : }
     159             : 
     160           0 : int16_t LR11x0::gnssDelayUntilSubframe(LR11x0GnssAlmanacStatus_t *stat, uint8_t constellation) {
     161           0 :   RADIOLIB_ASSERT_PTR(stat);
     162             : 
     163             :   // almanac update has to be called at least 1.3 seconds before the subframe
     164             :   // we use 2.3 seconds to be on the safe side
     165             : 
     166             :   // calculate absolute times
     167           0 :   RadioLibTime_t window = stat->start + stat->gps.timeUntilSubframe - 2300;
     168           0 :   if(constellation == RADIOLIB_LR11X0_GNSS_CONSTELLATION_BEIDOU) {
     169           0 :     window = stat->start + stat->beidou.timeUntilSubframe - 2300;
     170             :   }
     171           0 :   RadioLibTime_t now = this->mod->hal->millis();
     172           0 :   if(now > window) {
     173             :     // we missed the window
     174           0 :     return(RADIOLIB_ERR_GNSS_SUBFRAME_NOT_AVAILABLE);
     175             :   }
     176             : 
     177           0 :   RadioLibTime_t delay = window - now;
     178             :   RADIOLIB_DEBUG_BASIC_PRINTLN("Time until subframe %lu ms", delay);
     179           0 :   this->mod->hal->delay(delay); 
     180           0 :   return(RADIOLIB_ERR_NONE);
     181             : }
     182             : 
     183             : // TODO fix last satellite always out of date
     184           0 : int16_t LR11x0::updateGnssAlmanac(uint8_t constellation) {
     185           0 :   int16_t state = this->setDioIrqParams(RADIOLIB_LR11X0_IRQ_GNSS_DONE | RADIOLIB_LR11X0_IRQ_GNSS_ABORT);
     186           0 :   RADIOLIB_ASSERT(state);
     187             : 
     188           0 :   state = this->gnssAlmanacUpdateFromSat(RADIOLIB_LR11X0_GNSS_EFFORT_MID, constellation);
     189           0 :   RADIOLIB_ASSERT(state);
     190             : 
     191             :   // wait for scan finished or timeout, assumes 2 subframes and up to 2.3s pre-roll
     192           0 :   uint32_t softTimeout = 16UL * 1000UL;
     193           0 :   uint32_t start = this->mod->hal->millis();
     194           0 :   while (!this->mod->hal->digitalRead(this->mod->getIrq())) {
     195           0 :     this->mod->hal->yield();
     196           0 :     if(this->mod->hal->millis() - start > softTimeout) {
     197           0 :       this->gnssAbort();
     198             :       RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout waiting for almanac update");
     199             :     }
     200             :   }
     201             : 
     202             :   RADIOLIB_DEBUG_BASIC_PRINTLN("GPS almanac update done in %lu ms", (long unsigned int)(this->mod->hal->millis() - start));
     203             : 
     204             :   // distinguish between GNSS-done and GNSS-abort outcomes and clear the flags
     205           0 :   uint32_t irq = this->getIrqStatus();
     206           0 :   this->clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
     207           0 :   if(irq & RADIOLIB_LR11X0_IRQ_GNSS_ABORT) {
     208           0 :     state = RADIOLIB_ERR_RX_TIMEOUT;
     209             :   }
     210             :   
     211           0 :   return(state);
     212             : }
     213             : 
     214           0 : int16_t LR11x0::getGnssPosition(LR11x0GnssPosition_t* pos, bool filtered) {
     215           0 :   RADIOLIB_ASSERT_PTR(pos);
     216             : 
     217           0 :   uint8_t error = 0;
     218             :   int16_t state;
     219           0 :   if(filtered) {
     220           0 :     state = this->gnssReadDopplerSolverRes(&error, &pos->numSatsUsed, NULL, NULL, NULL, NULL, &pos->latitude, &pos->longitude, &pos->accuracy, NULL);
     221             :   } else {
     222           0 :     state = this->gnssReadDopplerSolverRes(&error, &pos->numSatsUsed, &pos->latitude, &pos->longitude, &pos->accuracy, NULL, NULL, NULL, NULL, NULL);
     223             :   }
     224           0 :   RADIOLIB_ASSERT(state);
     225             : 
     226             :   // check the solver error
     227           0 :   if(error != 0) {
     228           0 :     return(RADIOLIB_ERR_GNSS_SOLVER(error));
     229             :   }
     230             : 
     231           0 :   return(state);
     232             : }
     233             : 
     234           0 : int16_t LR11x0::getGnssSatellites(LR11x0GnssSatellite_t* sats, uint8_t numSats) {
     235           0 :   RADIOLIB_ASSERT_PTR(sats);
     236           0 :   if(numSats >= 32) {
     237           0 :     return(RADIOLIB_ERR_MEMORY_ALLOCATION_FAILED);
     238             :   }
     239             : 
     240           0 :   uint8_t svId[32] = { 0 };
     241           0 :   uint8_t snr[32] = { 0 };
     242           0 :   int16_t doppler[32] = { 0 };
     243           0 :   int16_t state = this->gnssGetSvDetected(svId, snr, doppler, numSats);
     244           0 :   RADIOLIB_ASSERT(state);
     245           0 :   for(size_t i = 0; i < numSats; i++) {
     246           0 :     sats[i].svId = svId[i];
     247           0 :     sats[i].c_n0 = snr[i] + 31;
     248           0 :     sats[i].doppler = doppler[i];
     249             :   }
     250             : 
     251           0 :   return(state);
     252             : }
     253             : 
     254           0 : int16_t LR11x0::gnssReadRssi(int8_t* rssi) {
     255           0 :   uint8_t reqBuff[1] = { 0x09 };  // some undocumented magic byte, from the official driver
     256           0 :   uint8_t rplBuff[2] = { 0 };
     257           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_RSSI, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
     258           0 :   RADIOLIB_ASSERT(state);
     259           0 :   if(rssi) { *rssi = rplBuff[1]; }
     260           0 :   return(state);
     261             : }
     262             : 
     263           0 : int16_t LR11x0::gnssSetConstellationToUse(uint8_t mask) {
     264           0 :   uint8_t buff[1] = { mask };
     265           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_CONSTELLATION_TO_USE, true, buff, sizeof(buff)));
     266             : }
     267             : 
     268           0 : int16_t LR11x0::gnssReadConstellationToUse(uint8_t* mask) {
     269           0 :   uint8_t buff[1] = { 0 };
     270           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_CONSTELLATION_TO_USE, false, buff, sizeof(buff));
     271             : 
     272             :   // pass the replies
     273           0 :   if(mask) { *mask = buff[0]; }
     274             : 
     275           0 :   return(state);
     276             : }
     277             : 
     278           0 : int16_t LR11x0::gnssSetAlmanacUpdate(uint8_t mask) {
     279           0 :   uint8_t buff[1] = { mask };
     280           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_ALMANAC_UPDATE, true, buff, sizeof(buff)));
     281             : }
     282             : 
     283           0 : int16_t LR11x0::gnssReadAlmanacUpdate(uint8_t* mask) {
     284           0 :   uint8_t buff[1] = { 0 };
     285           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_UPDATE, false, buff, sizeof(buff));
     286             : 
     287             :   // pass the replies
     288           0 :   if(mask) { *mask = buff[0]; }
     289             : 
     290           0 :   return(state);
     291             : }
     292             : 
     293           0 : int16_t LR11x0::gnssSetFreqSearchSpace(uint8_t freq) {
     294           0 :   uint8_t buff[1] = { freq };
     295           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_FREQ_SEARCH_SPACE, true, buff, sizeof(buff)));
     296             : }
     297             : 
     298           0 : int16_t LR11x0::gnssReadFreqSearchSpace(uint8_t* freq) {
     299           0 :   uint8_t buff[1] = { 0 };
     300           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_FREQ_SEARCH_SPACE, false, buff, sizeof(buff));
     301           0 :   if(freq) { *freq = buff[0]; }
     302           0 :   return(state);
     303             : }
     304             : 
     305           0 : int16_t LR11x0::gnssReadVersion(uint8_t* fw, uint8_t* almanac) {
     306           0 :   uint8_t buff[2] = { 0 };
     307           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_VERSION, false, buff, sizeof(buff));
     308             : 
     309             :   // pass the replies
     310           0 :   if(fw) { *fw = buff[0]; }
     311           0 :   if(almanac) { *almanac = buff[1]; }
     312             : 
     313           0 :   return(state);
     314             : }
     315             : 
     316           0 : int16_t LR11x0::gnssReadSupportedConstellations(uint8_t* mask) {
     317           0 :   uint8_t buff[1] = { 0 };
     318           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_SUPPORTED_CONSTELLATIONS, false, buff, sizeof(buff));
     319             : 
     320             :   // pass the replies
     321           0 :   if(mask) { *mask = buff[0]; }
     322             : 
     323           0 :   return(state);
     324             : }
     325             : 
     326           0 : int16_t LR11x0::gnssSetMode(uint8_t mode) {
     327           0 :   uint8_t buff[1] = { mode };
     328           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_MODE, true, buff, sizeof(buff)));
     329             : }
     330             : 
     331           0 : int16_t LR11x0::gnssAutonomous(uint32_t gpsTime, uint8_t resMask, uint8_t nbSvMask) {
     332           0 :   uint8_t buff[7] = {
     333           0 :     (uint8_t)((gpsTime >> 24) & 0xFF), (uint8_t)((gpsTime >> 16) & 0xFF),
     334           0 :     (uint8_t)((gpsTime >> 8) & 0xFF), (uint8_t)(gpsTime & 0xFF),
     335             :     RADIOLIB_LR11X0_GNSS_AUTO_EFFORT_MODE, resMask, nbSvMask
     336           0 :   };
     337           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_AUTONOMOUS, true, buff, sizeof(buff)));
     338             : }
     339             : 
     340           0 : int16_t LR11x0::gnssAssisted(uint32_t gpsTime, uint8_t effort, uint8_t resMask, uint8_t nbSvMask) {
     341             :   uint8_t buff[7] = {
     342           0 :     (uint8_t)((gpsTime >> 24) & 0xFF), (uint8_t)((gpsTime >> 16) & 0xFF),
     343           0 :     (uint8_t)((gpsTime >> 8) & 0xFF), (uint8_t)(gpsTime & 0xFF),
     344             :     effort, resMask, nbSvMask
     345           0 :   };
     346           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ASSISTED, true, buff, sizeof(buff)));
     347             : }
     348             : 
     349           0 : int16_t LR11x0::gnssSetAssistancePosition(float lat, float lon) {
     350           0 :   int16_t latRaw = (lat*2048.0f)/90.0f + 0.5f;
     351           0 :   int16_t lonRaw = (lon*2048.0f)/180.0f + 0.5f;
     352             :   uint8_t buff[4] = {
     353           0 :     (uint8_t)((latRaw >> 8) & 0xFF), (uint8_t)(latRaw & 0xFF),
     354           0 :     (uint8_t)((lonRaw >> 8) & 0xFF), (uint8_t)(lonRaw & 0xFF),
     355           0 :   };
     356           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_ASSISTANCE_POSITION, true, buff, sizeof(buff)));
     357             : }
     358             : 
     359           0 : int16_t LR11x0::gnssReadAssistancePosition(float* lat, float* lon) {
     360           0 :   uint8_t buff[4] = { 0 };
     361           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ASSISTANCE_POSITION, false, buff, sizeof(buff));
     362             : 
     363             :   // pass the replies
     364           0 :   if(lat) {
     365           0 :     int16_t latRaw = ((int16_t)(buff[0]) << 8) | (int16_t)(buff[1]);
     366           0 :     *lat = ((float)latRaw*90.0f)/2048.0f;
     367             :   }
     368           0 :   if(lon) {
     369           0 :     int16_t lonRaw = ((int16_t)(buff[2]) << 8) | (int16_t)(buff[3]);
     370           0 :     *lon = ((float)lonRaw*180.0f)/2048.0f;
     371             :   }
     372             : 
     373           0 :   return(state);
     374             : }
     375             : 
     376           0 : int16_t LR11x0::gnssPushSolverMsg(uint8_t* payload, size_t len) {
     377           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_PUSH_SOLVER_MSG, true, payload, len));
     378             : }
     379             : 
     380           0 : int16_t LR11x0::gnssPushDmMsg(uint8_t* payload, size_t len) {
     381           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_PUSH_DM_MSG, true, payload, len));
     382             : }
     383             : 
     384           0 : int16_t LR11x0::gnssGetContextStatus(uint8_t* fwVersion, uint32_t* almanacCrc, uint8_t* errCode, uint8_t* almUpdMask, uint8_t* freqSpace) {
     385             :   // send the command - datasheet here shows extra bytes being sent in the request
     386             :   // but doing that fails so treat it like any other read command
     387           0 :   uint8_t buff[9] = { 0 };
     388           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_CONTEXT_STATUS, false, buff, sizeof(buff));
     389             : 
     390             :   // pass the replies
     391           0 :   if(fwVersion) { *fwVersion = buff[2]; }
     392           0 :   if(almanacCrc) { *almanacCrc = ((uint32_t)(buff[3]) << 24) | ((uint32_t)(buff[4]) << 16) | ((uint32_t)(buff[5]) << 8) | (uint32_t)buff[6]; }
     393           0 :   if(errCode) { *errCode = (buff[7] & 0xF0) >> 4; }
     394           0 :   if(almUpdMask) { *almUpdMask = (buff[7] & 0x0E) >> 1; }
     395           0 :   if(freqSpace) { *freqSpace = ((buff[7] & 0x01) << 1) | ((buff[8] & 0x80) >> 7); }
     396             : 
     397           0 :   return(state);
     398             : }
     399             : 
     400           0 : int16_t LR11x0::gnssGetNbSvDetected(uint8_t* nbSv) {
     401           0 :   uint8_t buff[1] = { 0 };
     402           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_NB_SV_DETECTED, false, buff, sizeof(buff));
     403             : 
     404             :   // pass the replies
     405           0 :   if(nbSv) { *nbSv = buff[0]; }
     406             : 
     407           0 :   return(state);
     408             : }
     409             : 
     410           0 : int16_t LR11x0::gnssGetSvDetected(uint8_t* svId, uint8_t* snr, int16_t* doppler, size_t nbSv) {
     411             :   // TODO this is arbitrary - is there an actual maximum?
     412           0 :   if(nbSv > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t)) {
     413           0 :     return(RADIOLIB_ERR_SPI_CMD_INVALID);
     414             :   }
     415             : 
     416             :   // build buffers
     417           0 :   size_t buffLen = nbSv*sizeof(uint32_t);
     418             :   #if RADIOLIB_STATIC_ONLY
     419             :     uint8_t dataBuff[RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
     420             :   #else
     421           0 :     uint8_t* dataBuff = new uint8_t[buffLen];
     422             :   #endif
     423             : 
     424           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_DETECTED, false, dataBuff, buffLen);
     425           0 :   if(state == RADIOLIB_ERR_NONE) {
     426           0 :     for(size_t i = 0; i < nbSv; i++) {
     427           0 :       if(svId) { svId[i] = dataBuff[4*i]; }
     428           0 :       if(snr) { snr[i] = dataBuff[4*i + 1]; }
     429           0 :       if(doppler) { doppler[i] = ((uint16_t)(dataBuff[4*i + 2]) << 8) | (uint16_t)dataBuff[4*i + 3]; }
     430             :     }
     431             :   }
     432             : 
     433             :   #if !RADIOLIB_STATIC_ONLY
     434           0 :     delete[] dataBuff;
     435             :   #endif
     436           0 :   return(state);
     437             : }
     438             : 
     439           0 : int16_t LR11x0::gnssGetConsumption(uint32_t* cpu, uint32_t* radio) {
     440           0 :   uint8_t buff[8] = { 0 };
     441           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_CONSUMPTION, false, buff, sizeof(buff));
     442             : 
     443             :   // pass the replies
     444           0 :   if(cpu) { *cpu = ((uint32_t)(buff[0]) << 24) | ((uint32_t)(buff[1]) << 16) | ((uint32_t)(buff[2]) << 8) | (uint32_t)buff[3]; }
     445           0 :   if(radio) { *radio = ((uint32_t)(buff[4]) << 24) | ((uint32_t)(buff[5]) << 16) | ((uint32_t)(buff[6]) << 8) | (uint32_t)buff[7]; }
     446             : 
     447           0 :   return(state);
     448             : }
     449             : 
     450           0 : int16_t LR11x0::gnssGetResultSize(uint16_t* size) {
     451           0 :   uint8_t buff[2] = { 0 };
     452           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_RESULT_SIZE, false, buff, sizeof(buff));
     453             : 
     454             :   // pass the replies
     455           0 :   if(size) { *size = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1]; }
     456             :   
     457           0 :   return(state);
     458             : }
     459             : 
     460           0 : int16_t LR11x0::gnssReadResults(uint8_t* result, uint16_t size) {
     461           0 :   RADIOLIB_ASSERT_PTR(result);
     462           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_RESULTS, false, result, size));
     463             : }
     464             : 
     465           0 : int16_t LR11x0::gnssAlmanacFullUpdateHeader(uint16_t date, uint32_t globalCrc) {
     466           0 :   uint8_t buff[RADIOLIB_LR11X0_GNSS_ALMANAC_BLOCK_SIZE] = {
     467             :     RADIOLIB_LR11X0_GNSS_ALMANAC_HEADER_ID,
     468           0 :     (uint8_t)((date >> 8) & 0xFF), (uint8_t)(date & 0xFF),
     469           0 :     (uint8_t)((globalCrc >> 24) & 0xFF), (uint8_t)((globalCrc >> 16) & 0xFF), 
     470           0 :     (uint8_t)((globalCrc >> 8) & 0xFF), (uint8_t)(globalCrc & 0xFF),
     471           0 :   };
     472           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_FULL_UPDATE, true, buff, sizeof(buff)));
     473             : }
     474             : 
     475           0 : int16_t LR11x0::gnssAlmanacFullUpdateSV(uint8_t svn, const uint8_t* svnAlmanac) {
     476           0 :   uint8_t buff[RADIOLIB_LR11X0_GNSS_ALMANAC_BLOCK_SIZE] = { svn };
     477           0 :   memcpy(&buff[1], svnAlmanac, RADIOLIB_LR11X0_GNSS_ALMANAC_BLOCK_SIZE - 1);
     478           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_FULL_UPDATE, true, buff, sizeof(buff)));
     479             : }
     480             : 
     481           0 : int16_t LR11x0::gnssAlmanacReadAddrSize(uint32_t* addr, uint16_t* size) {
     482           0 :   uint8_t buff[6] = { 0 };
     483           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_READ_ADDR_SIZE, false, buff, sizeof(buff));
     484             : 
     485           0 :   if(addr) { *addr = ((uint32_t)(buff[0]) << 24) | ((uint32_t)(buff[1]) << 16) | ((uint32_t)(buff[2]) << 8) | (uint32_t)buff[3]; }
     486           0 :   if(size) { *size = ((uint16_t)(buff[4]) << 8) | (uint16_t)buff[5]; }
     487             :   
     488           0 :   return(state);
     489             : }
     490             : 
     491           0 : int16_t LR11x0::gnssAlmanacReadSV(uint8_t svId, uint8_t* almanac) {
     492           0 :   uint8_t reqBuff[2] = { svId, 0x01 }; // in theory multiple SV entries can be read at the same time, but we don't need that
     493           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_PER_SATELLITE, false, almanac, 22, reqBuff, sizeof(reqBuff));
     494           0 :   RADIOLIB_ASSERT(state);
     495           0 :   return(state);
     496             : }
     497             : 
     498           0 : int16_t LR11x0::gnssGetNbSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv) {
     499           0 :   int16_t latRaw = (lat*2048.0f)/90.0f + 0.5f;
     500           0 :   int16_t lonRaw = (lon*2048.0f)/180.0f + 0.5f;
     501             :   uint8_t reqBuff[9] = { 
     502           0 :     (uint8_t)((time >> 24) & 0xFF), (uint8_t)((time >> 16) & 0xFF),
     503           0 :     (uint8_t)((time >> 8) & 0xFF), (uint8_t)(time & 0xFF),
     504           0 :     (uint8_t)((latRaw >> 8) & 0xFF), (uint8_t)(latRaw & 0xFF),
     505           0 :     (uint8_t)((lonRaw >> 8) & 0xFF), (uint8_t)(lonRaw & 0xFF),
     506             :     constellation,
     507           0 :   };
     508           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE, false, nbSv, 1, reqBuff, sizeof(reqBuff)));
     509             : }
     510             : 
     511           0 : int16_t LR11x0::gnssGetSvVisible(uint8_t nbSv, uint8_t** svId, int16_t** doppler, int16_t** dopplerErr) {
     512             :   // enforce a maximum of 12 SVs
     513           0 :   if(nbSv > 12) {
     514           0 :     return(RADIOLIB_ERR_SPI_CMD_INVALID);
     515             :   }
     516             : 
     517           0 :   uint8_t buff[60] = { 0 };
     518           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE_DOPPLER, false, buff, sizeof(buff));
     519           0 :   for(uint8_t i = 0; i < nbSv; i++) {
     520           0 :     if(svId && svId[i]) { *svId[i] = buff[i*12]; }
     521           0 :     if(doppler && doppler[i]) { *doppler[i] = ((uint16_t)(buff[i*12 + 1]) << 8) | (uint16_t)buff[i*12 + 2]; }
     522           0 :     if(dopplerErr && dopplerErr[i]) { *dopplerErr[i] = ((uint16_t)(buff[i*12 + 3]) << 8) | (uint16_t)buff[i*12 + 4]; }
     523             :   }
     524             :   
     525           0 :   return(state);
     526             : }
     527             : 
     528           0 : int16_t LR11x0::gnssPerformScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax) {
     529           0 :   uint8_t buff[3] = { effort, resMask, nbSvMax };
     530             :   // call the SPI write stream directly to skip waiting for BUSY - it will be set to high once the scan starts
     531           0 :   return(this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_GNSS_SCAN, buff, sizeof(buff), false, false));
     532             : }
     533             : 
     534           0 : int16_t LR11x0::gnssReadLastScanModeLaunched(uint8_t* lastScanMode) {
     535           0 :   uint8_t buff[1] = { 0 };
     536           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_LAST_SCAN_MODE_LAUNCHED, false, buff, sizeof(buff));
     537             : 
     538             :   // pass the replies
     539           0 :   if(lastScanMode) { *lastScanMode = buff[0]; }
     540             :   
     541           0 :   return(state);
     542             : }
     543             : 
     544           0 : int16_t LR11x0::gnssFetchTime(uint8_t effort, uint8_t opt) {
     545           0 :   uint8_t buff[2] = { effort, opt };
     546             :   // call the SPI write stream directly to skip waiting for BUSY - it will be set to high once the scan starts
     547           0 :   return(this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_GNSS_FETCH_TIME, buff, sizeof(buff), false, false));
     548             : }
     549             : 
     550           0 : int16_t LR11x0::gnssReadTime(uint8_t* err, uint32_t* time, uint32_t* nbUs, uint32_t* timeAccuracy) {
     551           0 :   uint8_t buff[12] = { 0 };
     552           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_TIME, false, buff, sizeof(buff));
     553             : 
     554             :   // pass the replies
     555           0 :   if(err) { *err = buff[0]; }
     556             :   
     557           0 :   if(time) {
     558           0 :     *time = ((uint32_t)(buff[1]) << 24) | ((uint32_t)(buff[2]) << 16) | ((uint32_t)(buff[3]) << 8) | (uint32_t)buff[4];
     559           0 :     *time += 2UL*1024UL*7UL*24UL*3600UL; // assume WN rollover is at 2, this will fail sometime in 2038
     560           0 :     *time += 315964800UL; // convert to UTC
     561             :   }
     562             : 
     563           0 :   if(nbUs) {
     564           0 :     *nbUs = ((uint32_t)(buff[5]) << 16) | ((uint32_t)(buff[6]) << 8) | (uint32_t)buff[7];
     565           0 :     *nbUs /= 16;
     566             :   }
     567             : 
     568           0 :   if(timeAccuracy) {
     569           0 :     *timeAccuracy = ((uint32_t)(buff[8]) << 24) | ((uint32_t)(buff[9]) << 16) | ((uint32_t)(buff[10]) << 8) | (uint32_t)buff[11];
     570           0 :     *timeAccuracy /= 16;
     571             :   }
     572             :   
     573           0 :   return(state);
     574             : }
     575             : 
     576           0 : int16_t LR11x0::gnssResetTime(void) {
     577           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_RESET_TIME, true, NULL, 0));
     578             : }
     579             : 
     580           0 : int16_t LR11x0::gnssResetPosition(void) {
     581           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_RESET_POSITION, true, NULL, 0));
     582             : }
     583             : 
     584           0 : int16_t LR11x0::gnssReadWeekNumberRollover(uint8_t* status, uint8_t* rollover) {
     585           0 :   uint8_t buff[2] = { 0 };
     586           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_WEEK_NUMBER_ROLLOWER, false, buff, sizeof(buff));
     587           0 :   if(status) { *status = buff[0]; }
     588           0 :   if(rollover) { *rollover = buff[1]; }
     589           0 :   return(state);
     590             : }
     591             : 
     592           0 : int16_t LR11x0::gnssReadDemodStatus(int8_t* status, uint8_t* info) {
     593           0 :   uint8_t buff[2] = { 0 };
     594           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_DEMOD_STATUS, false, buff, sizeof(buff));
     595             : 
     596             :   // pass the replies
     597           0 :   if(status) { *status = (int8_t)buff[0]; }
     598           0 :   if(info) { *info = buff[1]; }
     599             :   
     600           0 :   return(state);
     601             : }
     602             : 
     603           0 : int16_t LR11x0::gnssReadCumulTiming(uint32_t* timing, uint8_t* constDemod) {
     604           0 :   uint8_t rplBuff[125] = { 0 };
     605           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_CUMUL_TIMING, false, rplBuff, 125);
     606           0 :   RADIOLIB_ASSERT(state);
     607             : 
     608             :   // convert endians
     609           0 :   if(timing) {
     610           0 :     for(size_t i = 0; i < 31; i++) {
     611           0 :       timing[i] = ((uint32_t)rplBuff[i*sizeof(uint32_t)] << 24) | ((uint32_t)rplBuff[1 + i*sizeof(uint32_t)] << 16) | ((uint32_t)rplBuff[2 + i*sizeof(uint32_t)] << 8) | (uint32_t)rplBuff[3 + i*sizeof(uint32_t)];
     612             :     }
     613             :   }
     614             : 
     615           0 :   if(constDemod) { *constDemod = rplBuff[124]; }
     616             :   
     617           0 :   return(state);
     618             : }
     619             : 
     620           0 : int16_t LR11x0::gnssSetTime(uint32_t time, uint16_t accuracy) {
     621             :   uint8_t buff[6] = {
     622           0 :     (uint8_t)((time >> 24) & 0xFF), (uint8_t)((time >> 16) & 0xFF),
     623           0 :     (uint8_t)((time >> 8) & 0xFF), (uint8_t)(time & 0xFF),
     624           0 :     (uint8_t)((accuracy >> 8) & 0xFF), (uint8_t)(accuracy & 0xFF),
     625           0 :   };
     626           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_TIME, true, buff, sizeof(buff)));
     627             : }
     628             : 
     629           0 : int16_t LR11x0::gnssReadDopplerSolverRes(uint8_t* error, uint8_t* nbSvUsed, float* lat, float* lon, uint16_t* accuracy, uint16_t* xtal, float* latFilt, float* lonFilt, uint16_t* accuracyFilt, uint16_t* xtalFilt) {
     630           0 :   uint8_t buff[18] = { 0 };
     631           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_DOPPLER_SOLVER_RES, false, buff, sizeof(buff));
     632             : 
     633             :   // pass the replies
     634           0 :   if(error) { *error = buff[0]; }
     635           0 :   if(nbSvUsed) { *nbSvUsed = buff[1]; }
     636           0 :   if(lat) {
     637           0 :     int16_t latRaw = ((int16_t)(buff[2]) << 8) | (int16_t)buff[3];
     638           0 :     *lat = ((float)latRaw * 90.0f)/2048.0f;
     639             :   }
     640           0 :   if(lon) {
     641           0 :     int16_t lonRaw = ((int16_t)(buff[4]) << 8) | (int16_t)buff[5];
     642           0 :     *lon = ((float)lonRaw * 180.0f)/2048.0f;
     643             :   }
     644           0 :   if(accuracy) { *accuracy = ((uint16_t)(buff[6]) << 8) | (uint16_t)buff[7]; }
     645           0 :   if(xtal) { *xtal = ((uint16_t)(buff[8]) << 8) | (uint16_t)buff[9]; }
     646           0 :   if(latFilt) {
     647           0 :     int16_t latRaw = ((int16_t)(buff[10]) << 8) | (int16_t)buff[11];
     648           0 :     *latFilt = ((float)latRaw * 90.0f)/2048.0f;
     649             :   }
     650           0 :   if(lonFilt) {
     651           0 :     int16_t lonRaw = ((int16_t)(buff[12]) << 8) | (int16_t)buff[13];
     652           0 :     *lonFilt = ((float)lonRaw * 180.0f)/2048.0f;
     653             :   }
     654           0 :   if(accuracyFilt) { *accuracyFilt = ((uint16_t)(buff[14]) << 8) | (uint16_t)buff[15]; }
     655           0 :   if(xtalFilt) { *xtalFilt = ((uint16_t)(buff[16]) << 8) | (uint16_t)buff[17]; }
     656             :   
     657           0 :   return(state);
     658             : }
     659             : 
     660           0 : int16_t LR11x0::gnssReadDelayResetAP(uint32_t* delay) {
     661           0 :   uint8_t buff[3] = { 0 };
     662           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_DELAY_RESET_AP, false, buff, sizeof(buff));
     663             : 
     664           0 :   if(delay) { *delay = ((uint32_t)(buff[0]) << 16) | ((uint32_t)(buff[1]) << 8) | (uint32_t)buff[2]; }
     665             :   
     666           0 :   return(state);
     667             : }
     668             : 
     669           0 : int16_t LR11x0::gnssAlmanacUpdateFromSat(uint8_t effort, uint8_t bitMask) {
     670           0 :   uint8_t buff[2] = { effort, bitMask };
     671             :   // call the SPI write stream directly to skip waiting for BUSY - it will be set to high once the scan starts
     672           0 :   return(this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_UPDATE_FROM_SAT, buff, sizeof(buff), false, false));
     673             : }
     674             : 
     675           0 : int16_t LR11x0::gnssReadKeepSyncStatus(uint8_t mask, uint8_t* nbSvVisible, uint32_t* elapsed) {
     676           0 :   uint8_t reqBuff[1] = { mask };
     677           0 :   uint8_t rplBuff[5] = { 0 };
     678           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_KEEP_SYNC_STATUS, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
     679           0 :   RADIOLIB_ASSERT(state);
     680           0 :   if(nbSvVisible) { *nbSvVisible = rplBuff[0]; }
     681           0 :   if(elapsed) { *elapsed = ((uint32_t)(rplBuff[1]) << 24) | ((uint32_t)(rplBuff[2]) << 16) | ((uint32_t)(rplBuff[3]) << 8) | (uint32_t)rplBuff[4]; }
     682           0 :   return(state);
     683             : }
     684             : 
     685           0 : int16_t LR11x0::gnssReadAlmanacStatus(uint8_t* status) {
     686           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_STATUS, false, status, 53));
     687             : }
     688             : 
     689           0 : int16_t LR11x0::gnssConfigAlmanacUpdatePeriod(uint8_t bitMask, uint8_t svType, uint16_t period) {
     690           0 :   uint8_t buff[4] = { bitMask, svType, (uint8_t)((period >> 8) & 0xFF), (uint8_t)(period & 0xFF) };
     691           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_CONFIG_ALMANAC_UPDATE_PERIOD, true, buff, sizeof(buff)));
     692             : }
     693             : 
     694           0 : int16_t LR11x0::gnssReadAlmanacUpdatePeriod(uint8_t bitMask, uint8_t svType, uint16_t* period) {
     695           0 :   uint8_t reqBuff[2] = { bitMask, svType };
     696           0 :   uint8_t rplBuff[2] = { 0 };
     697           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_UPDATE_PERIOD, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
     698           0 :   RADIOLIB_ASSERT(state);
     699             : 
     700           0 :   if(period) { *period = ((uint16_t)(rplBuff[0]) << 8) | (uint16_t)rplBuff[1]; }
     701             : 
     702           0 :   return(state);
     703             : }
     704             : 
     705           0 : int16_t LR11x0::gnssConfigDelayResetAP(uint32_t delay) {
     706           0 :   uint8_t buff[3] = { (uint8_t)((delay >> 16) & 0xFF), (uint8_t)((delay >> 8) & 0xFF), (uint8_t)(delay & 0xFF) };
     707           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_CONFIG_DELAY_RESET_AP, true, buff, sizeof(buff)));
     708             : }
     709             : 
     710           0 : int16_t LR11x0::gnssGetSvWarmStart(uint8_t bitMask, uint8_t* sv, uint8_t nbVisSat) {
     711           0 :   uint8_t reqBuff[1] = { bitMask };
     712           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_WARM_START, false, sv, nbVisSat, reqBuff, sizeof(reqBuff)));
     713             : }
     714             : 
     715           0 : int16_t LR11x0::gnssGetSvSync(uint8_t mask, uint8_t nbSv, uint8_t* syncList) {
     716           0 :   uint8_t reqBuff[2] = { mask, nbSv };
     717           0 :   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_SYNC, false, syncList, nbSv, reqBuff, sizeof(reqBuff)));
     718             : }
     719             : 
     720           0 : int16_t LR11x0::gnssReadWarmStartStatus(uint8_t bitMask, uint8_t* nbVisSat, uint32_t* timeElapsed) {
     721           0 :   uint8_t reqBuff[1] = { bitMask };
     722           0 :   uint8_t rplBuff[5] = { 0 };
     723           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_WARM_START_STATUS, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
     724           0 :   RADIOLIB_ASSERT(state);
     725             : 
     726           0 :   if(nbVisSat) { *nbVisSat = rplBuff[0]; }
     727           0 :   if(timeElapsed) { *timeElapsed = ((uint32_t)(rplBuff[1]) << 24) | ((uint32_t)(rplBuff[2]) << 16) | ((uint32_t)(rplBuff[3]) << 8) | (uint32_t)rplBuff[4]; }
     728             : 
     729           0 :   return(state);
     730             : }
     731             : 
     732           0 : int16_t LR11x0::gnssWriteBitMaskSatActivated(uint8_t bitMask, uint32_t* bitMaskActivated0, uint32_t* bitMaskActivated1) {
     733           0 :   uint8_t reqBuff[1] = { bitMask };
     734           0 :   uint8_t rplBuff[8] = { 0 };
     735           0 :   size_t rplLen = (bitMask & 0x01) ? 8 : 4; // GPS only has the first bit mask
     736           0 :   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_WRITE_BIT_MASK_SAT_ACTIVATED, false, rplBuff, rplLen, reqBuff, sizeof(reqBuff));
     737           0 :   RADIOLIB_ASSERT(state);
     738             : 
     739           0 :   if(bitMaskActivated0) { *bitMaskActivated0 = ((uint32_t)(rplBuff[0]) << 24) | ((uint32_t)(rplBuff[1]) << 16) | ((uint32_t)(rplBuff[2]) << 8) | (uint32_t)rplBuff[3]; }
     740           0 :   if(bitMaskActivated1) { *bitMaskActivated1 = ((uint32_t)(rplBuff[4]) << 24) | ((uint32_t)(rplBuff[5]) << 16) | ((uint32_t)(rplBuff[6]) << 8) | (uint32_t)rplBuff[7]; }
     741             : 
     742           0 :   return(state);
     743             : }
     744             : 
     745           0 : void LR11x0::gnssAbort() {
     746             :   // send the abort signal (single NOP)
     747           0 :   this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
     748             :   // we need to call the most basic overload of the SPI write method otherwise the call will be ambiguous
     749           0 :   const uint8_t cmd[2] = { 0, 0 };
     750           0 :   this->mod->SPIwriteStream(cmd, 2, NULL, 0, false, false);
     751           0 :   this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_16;
     752             : 
     753             :   // wait for at least 2.9 seconds as specified by the user manual
     754           0 :   this->mod->hal->delay(3000);
     755           0 : }
     756             : 
     757             : #endif

Generated by: LCOV version 1.14