From 15b8489f1dd148aec6342692b706ed3f8e71efde Mon Sep 17 00:00:00 2001
From: jgromes <jan.gromes@gmail.com>
Date: Thu, 18 Jul 2024 17:16:53 +0200
Subject: [PATCH] [LR11x0] Cleanup, mark GNSS methods as work-in-progress

---
 src/modules/LR11x0/LR11x0.cpp | 162 ++++++++++++++++++++++++++++++----
 src/modules/LR11x0/LR11x0.h   |  57 ++++++++++--
 2 files changed, 194 insertions(+), 25 deletions(-)

diff --git a/src/modules/LR11x0/LR11x0.cpp b/src/modules/LR11x0/LR11x0.cpp
index 3a1ffa39..a20d04b9 100644
--- a/src/modules/LR11x0/LR11x0.cpp
+++ b/src/modules/LR11x0/LR11x0.cpp
@@ -1660,13 +1660,42 @@ int16_t LR11x0::isGnssScanCapable() {
 
   // check the device firmware version is sufficient
   uint16_t versionFull = ((uint16_t)version.fwMajor << 8) | (uint16_t)version.fwMinor;
+  state = RADIOLIB_ERR_UNSUPPORTED;
   if((version.device == RADIOLIB_LR11X0_DEVICE_LR1110) && (versionFull >= 0x0401)) {
-    return(RADIOLIB_ERR_NONE);
+    state = RADIOLIB_ERR_NONE;
   } else if((version.device == RADIOLIB_LR11X0_DEVICE_LR1120) && (versionFull >= 0x0201)) {
-    return(RADIOLIB_ERR_NONE);
+    state = RADIOLIB_ERR_NONE;
+  }
+  RADIOLIB_ASSERT(state);
+
+  // in debug mode, dump the almanac
+  #if RADIOLIB_DEBUG_BASIC
+  uint32_t addr = 0;
+  uint16_t sz = 0;
+  state = this->gnssAlmanacReadAddrSize(&addr, &sz);
+  RADIOLIB_ASSERT(state);
+  RADIOLIB_DEBUG_BASIC_PRINTLN("Almanac@%08x, %d bytes", addr, sz);
+  uint32_t buff[32] = { 0 };
+  while(sz > 0) {
+    size_t len = sz > 32 ? 32 : sz/sizeof(uint32_t);
+    state = this->readRegMem32(addr, buff, len);
+    RADIOLIB_ASSERT(state);
+    Module::hexdump(NULL, (uint8_t*)buff, len*sizeof(uint32_t), addr);
+    addr += len*sizeof(uint32_t);
+    sz -= len*sizeof(uint32_t);
   }
 
-  return(RADIOLIB_ERR_UNSUPPORTED);
+  uint8_t almanac[22] = { 0 };
+  for(uint8_t i = 0; i < 128; i++) {
+    RADIOLIB_DEBUG_BASIC_PRINTLN("Almanac[%d]:", i);
+    state = this->gnssAlmanacReadSV(i, almanac);
+    RADIOLIB_ASSERT(state);
+    Module::hexdump(NULL, almanac, 22);
+  }
+
+  #endif
+
+  return(state);
 }
 
 int16_t LR11x0::gnssScan(uint16_t* resSize) {
@@ -1681,7 +1710,7 @@ int16_t LR11x0::gnssScan(uint16_t* resSize) {
   state = this->gnssSetConstellationToUse(0x03);
   RADIOLIB_ASSERT(state);
 
-  // set scan mode
+  // set scan mode (single vs multiple)
   state = this->gnssSetMode(0x03);
   RADIOLIB_ASSERT(state);
 
@@ -1732,12 +1761,43 @@ int16_t LR11x0::gnssScan(uint16_t* resSize) {
 }
 
 int16_t LR11x0::getGnssScanResult(uint16_t size) {
+  uint32_t timing[31] = { 0 };
+  uint8_t constDemod = 0;
+  int16_t state = this->gnssReadCumulTiming(timing, &constDemod);
+  RADIOLIB_ASSERT(state);
+  RADIOLIB_DEBUG_BASIC_PRINTLN("Timing:");
+  for(size_t i = 0; i < 31; i++) {
+    uint32_t t = (timing[i] * 1000UL) / 32768UL;
+    RADIOLIB_DEBUG_BASIC_PRINTLN("  %d: %lu ms", i*4, t);
+  }
+  RADIOLIB_DEBUG_BASIC_PRINTLN("constDemod: %d", constDemod);
+
+  uint8_t nbSv = 0;
+  state = this->gnssGetNbSvDetected(&nbSv);
+  RADIOLIB_ASSERT(state);
+  RADIOLIB_DEBUG_BASIC_PRINTLN("Detected %d SVs:", nbSv);
+
+  uint8_t svId[32] = { 0 };
+  uint8_t snr[32] = { 0 };
+  int16_t doppler[32] = { 0 };
+  state = this->gnssGetSvDetected(svId, snr, doppler, nbSv);
+  RADIOLIB_ASSERT(state);
+  for(size_t i = 0; i < nbSv; i++) {
+    RADIOLIB_DEBUG_BASIC_PRINTLN("  SV %d: C/N0 %i dB, Doppler %i Hz", i, snr[i] + 31, doppler[i]);
+  }
+
+  float lat = 0;
+  float lon = 0;
+  state = this->gnssReadAssistancePosition(&lat, &lon);
+  RADIOLIB_ASSERT(state);
+  RADIOLIB_DEBUG_BASIC_PRINTLN("lat = %.5f, lon = %.5f", lat, lon);
+
   // read the result
   uint8_t res[256] = { 0 };
-  int16_t state = this->gnssReadResults(res, size);
+  state = this->gnssReadResults(res, size);
   RADIOLIB_ASSERT(state);
   RADIOLIB_DEBUG_BASIC_PRINTLN("Result type: %02x", (int)res[0]);
-  //Module::hexdump(NULL, res, size);
+  Module::hexdump(NULL, res, size);
 
   return(state);
 }
@@ -2836,6 +2896,15 @@ int16_t LR11x0::wifiReadVersion(uint8_t* major, uint8_t* minor) {
   return(state);
 }
 
+int16_t LR11x0::gnssReadRssi(int8_t* rssi) {
+  uint8_t reqBuff[1] = { 0x09 };  // some undocumented magic byte, from the official driver
+  uint8_t rplBuff[2] = { 0 };
+  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_RSSI, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
+  RADIOLIB_ASSERT(state);
+  if(rssi) { *rssi = rplBuff[1]; }
+  return(state);
+}
+
 int16_t LR11x0::gnssSetConstellationToUse(uint8_t mask) {
   uint8_t buff[1] = { mask };
   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_CONSTELLATION_TO_USE, true, buff, sizeof(buff)));
@@ -2866,6 +2935,18 @@ int16_t LR11x0::gnssReadAlmanacUpdate(uint8_t* mask) {
   return(state);
 }
 
+int16_t LR11x0::gnssSetFreqSearchSpace(uint8_t freq) {
+  uint8_t buff[1] = { freq };
+  return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_FREQ_SEARCH_SPACE, true, buff, sizeof(buff)));
+}
+
+int16_t LR11x0::gnssReadFreqSearchSpace(uint8_t* freq) {
+  uint8_t buff[1] = { 0 };
+  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_FREQ_SEARCH_SPACE, false, buff, sizeof(buff));
+  if(freq) { *freq = buff[0]; }
+  return(state);
+}
+
 int16_t LR11x0::gnssReadVersion(uint8_t* fw, uint8_t* almanac) {
   uint8_t buff[2] = { 0 };
   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_VERSION, false, buff, sizeof(buff));
@@ -2971,7 +3052,7 @@ int16_t LR11x0::gnssGetNbSvDetected(uint8_t* nbSv) {
   return(state);
 }
 
-int16_t LR11x0::gnssGetSvDetected(uint8_t* svId, uint8_t* snr, uint16_t* doppler, size_t nbSv) {
+int16_t LR11x0::gnssGetSvDetected(uint8_t* svId, uint8_t* snr, int16_t* doppler, size_t nbSv) {
   // TODO this is arbitrary - is there an actual maximum?
   if(nbSv > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t)) {
     return(RADIOLIB_ERR_SPI_CMD_INVALID);
@@ -3044,7 +3125,24 @@ int16_t LR11x0::gnssAlmanacFullUpdateSV(uint8_t svn, uint8_t* svnAlmanac) {
   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_FULL_UPDATE, true, buff, sizeof(buff)));
 }
 
-int16_t LR11x0::gnssGetSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv) {
+int16_t LR11x0::gnssAlmanacReadAddrSize(uint32_t* addr, uint16_t* size) {
+  uint8_t buff[6] = { 0 };
+  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_READ_ADDR_SIZE, false, buff, sizeof(buff));
+
+  if(addr) { *addr = ((uint32_t)(buff[0]) << 24) | ((uint32_t)(buff[1]) << 16) | ((uint32_t)(buff[2]) << 8) | (uint32_t)buff[3]; }
+  if(size) { *size = ((uint16_t)(buff[4]) << 8) | (uint16_t)buff[5]; }
+  
+  return(state);
+}
+
+int16_t LR11x0::gnssAlmanacReadSV(uint8_t svId, uint8_t* almanac) {
+  uint8_t reqBuff[2] = { svId, 0x01 }; // in theory multiple SV entries can be read at the same time, but we don't need that
+  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_PER_SATELLITE, false, almanac, 22, reqBuff, sizeof(reqBuff));
+  RADIOLIB_ASSERT(state);
+  return(state);
+}
+
+int16_t LR11x0::gnssGetNbSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv) {
   uint16_t latRaw = (lat*2048.0f)/90.0f + 0.5f;
   uint16_t lonRaw = (lon*2048.0f)/180.0f + 0.5f;
   uint8_t reqBuff[9] = { 
@@ -3057,6 +3155,23 @@ int16_t LR11x0::gnssGetSvVisible(uint32_t time, float lat, float lon, uint8_t co
   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE, false, nbSv, 1, reqBuff, sizeof(reqBuff)));
 }
 
+int16_t LR11x0::gnssGetSvVisible(uint8_t nbSv, uint8_t** svId, int16_t** doppler, int16_t** dopplerErr) {
+  // enforce a maximum of 12 SVs
+  if(nbSv > 12) {
+    return(RADIOLIB_ERR_SPI_CMD_INVALID);
+  }
+
+  uint8_t buff[60] = { 0 };
+  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE_DOPPLER, false, buff, sizeof(buff));
+  for(uint8_t i = 0; i < nbSv; i++) {
+    if(svId && svId[i]) { *svId[i] = buff[i*12]; }
+    if(doppler && doppler[i]) { *doppler[i] = ((uint16_t)(buff[i*12 + 1]) << 8) | (uint16_t)buff[i*12 + 2]; }
+    if(dopplerErr && dopplerErr[i]) { *dopplerErr[i] = ((uint16_t)(buff[i*12 + 3]) << 8) | (uint16_t)buff[i*12 + 4]; }
+  }
+  
+  return(state);
+}
+
 int16_t LR11x0::gnssPerformScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax) {
   uint8_t buff[3] = { effort, resMask, nbSvMax };
   // call the SPI write stream directly to skip waiting for BUSY - it will be set to high once the scan starts
@@ -3099,6 +3214,14 @@ int16_t LR11x0::gnssResetPosition(void) {
   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_RESET_POSITION, true, NULL, 0));
 }
 
+int16_t LR11x0::gnssReadWeekNumberRollover(uint8_t* status, uint8_t* rollover) {
+  uint8_t buff[2] = { 0 };
+  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_WEEK_NUMBER_ROLLOWER, false, buff, sizeof(buff));
+  if(status) { *status = buff[0]; }
+  if(rollover) { *rollover = buff[1]; }
+  return(state);
+}
+
 int16_t LR11x0::gnssReadDemodStatus(int8_t* status, uint8_t* info) {
   uint8_t buff[2] = { 0 };
   int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_DEMOD_STATUS, false, buff, sizeof(buff));
@@ -3112,7 +3235,7 @@ int16_t LR11x0::gnssReadDemodStatus(int8_t* status, uint8_t* info) {
 
 int16_t LR11x0::gnssReadCumulTiming(uint32_t* timing, uint8_t* constDemod) {
   uint8_t rplBuff[125] = { 0 };
-  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_READ_REG_MEM, false, rplBuff, 125);
+  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_CUMUL_TIMING, false, rplBuff, 125);
   RADIOLIB_ASSERT(state);
 
   // convert endians
@@ -3181,6 +3304,16 @@ int16_t LR11x0::gnssAlmanacUpdateFromSat(uint8_t effort, uint8_t bitMask) {
   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_UPDATE_FROM_SAT, true, buff, sizeof(buff)));
 }
 
+int16_t LR11x0::gnssReadKeepSyncStatus(uint8_t mask, uint8_t* nbSvVisible, uint32_t* elapsed) {
+  uint8_t reqBuff[1] = { mask };
+  uint8_t rplBuff[5] = { 0 };
+  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_KEEP_SYNC_STATUS, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
+  RADIOLIB_ASSERT(state);
+  if(nbSvVisible) { *nbSvVisible = rplBuff[0]; }
+  if(elapsed) { *elapsed = ((uint32_t)(rplBuff[1]) << 24) | ((uint32_t)(rplBuff[2]) << 16) | ((uint32_t)(rplBuff[3]) << 8) | (uint32_t)rplBuff[4]; }
+  return(state);
+}
+
 int16_t LR11x0::gnssReadAlmanacStatus(uint8_t* status) {
   // TODO parse the reply into some structure
   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_STATUS, false, status, 53));
@@ -3212,14 +3345,9 @@ int16_t LR11x0::gnssGetSvWarmStart(uint8_t bitMask, uint8_t* sv, uint8_t nbVisSa
   return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_WARM_START, false, sv, nbVisSat, reqBuff, sizeof(reqBuff)));
 }
 
-int16_t LR11x0::gnssReadWNRollover(uint8_t* status, uint8_t* rollover) {
-  uint8_t buff[2] = { 0 };
-  int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_WN_ROLLOVER, false, buff, sizeof(buff));
-
-  if(status) { *status = buff[0]; }
-  if(rollover) { *rollover = buff[1]; }
-  
-  return(state);
+int16_t LR11x0::gnssGetSvSync(uint8_t mask, uint8_t nbSv, uint8_t* syncList) {
+  uint8_t reqBuff[2] = { mask, nbSv };
+  return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_SYNC, false, syncList, nbSv, reqBuff, sizeof(reqBuff)));
 }
 
 int16_t LR11x0::gnssReadWarmStartStatus(uint8_t bitMask, uint8_t* nbVisSat, uint32_t* timeElapsed) {
diff --git a/src/modules/LR11x0/LR11x0.h b/src/modules/LR11x0/LR11x0.h
index 9177569c..5b16a7c0 100644
--- a/src/modules/LR11x0/LR11x0.h
+++ b/src/modules/LR11x0/LR11x0.h
@@ -103,10 +103,13 @@
 #define RADIOLIB_LR11X0_CMD_WIFI_READ_COUNTRY_CODE_RESULTS      (0x030A)
 #define RADIOLIB_LR11X0_CMD_WIFI_CFG_TIMESTAMP_AP_PHONE         (0x030B)
 #define RADIOLIB_LR11X0_CMD_WIFI_READ_VERSION                   (0x0320)
+#define RADIOLIB_LR11X0_CMD_GNSS_READ_RSSI                      (0x0222)
 #define RADIOLIB_LR11X0_CMD_GNSS_SET_CONSTELLATION_TO_USE       (0x0400)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_CONSTELLATION_TO_USE      (0x0401)
 #define RADIOLIB_LR11X0_CMD_GNSS_SET_ALMANAC_UPDATE             (0x0402)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_UPDATE            (0x0403)
+#define RADIOLIB_LR11X0_CMD_GNSS_SET_FREQ_SEARCH_SPACE          (0x0404)
+#define RADIOLIB_LR11X0_CMD_GNSS_READ_FREQ_SEARCH_SPACE         (0x0405)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_VERSION                   (0x0406)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_SUPPORTED_CONSTELLATIONS  (0x0407)
 #define RADIOLIB_LR11X0_CMD_GNSS_SET_MODE                       (0x0408)
@@ -116,6 +119,7 @@
 #define RADIOLIB_LR11X0_CMD_GNSS_GET_RESULT_SIZE                (0x040C)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_RESULTS                   (0x040D)
 #define RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_FULL_UPDATE            (0x040E)
+#define RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_READ_ADDR_SIZE         (0x040F)
 #define RADIOLIB_LR11X0_CMD_GNSS_SET_ASSISTANCE_POSITION        (0x0410)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_ASSISTANCE_POSITION       (0x0411)
 #define RADIOLIB_LR11X0_CMD_GNSS_PUSH_SOLVER_MSG                (0x0414)
@@ -124,24 +128,28 @@
 #define RADIOLIB_LR11X0_CMD_GNSS_GET_NB_SV_DETECTED             (0x0417)
 #define RADIOLIB_LR11X0_CMD_GNSS_GET_SV_DETECTED                (0x0418)
 #define RADIOLIB_LR11X0_CMD_GNSS_GET_CONSUMPTION                (0x0419)
+#define RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_PER_SATELLITE     (0x041A)
 #define RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE                 (0x041F)
+#define RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE_DOPPLER         (0x0420)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_LAST_SCAN_MODE_LAUNCHED   (0x0426)
 #define RADIOLIB_LR11X0_CMD_GNSS_FETCH_TIME                     (0x0432)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_TIME                      (0x0434)
 #define RADIOLIB_LR11X0_CMD_GNSS_RESET_TIME                     (0x0435)
 #define RADIOLIB_LR11X0_CMD_GNSS_RESET_POSITION                 (0x0437)
+#define RADIOLIB_LR11X0_CMD_GNSS_READ_WEEK_NUMBER_ROLLOWER      (0x0438)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_DEMOD_STATUS              (0x0439)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_CUMUL_TIMING              (0x044A)
 #define RADIOLIB_LR11X0_CMD_GNSS_SET_TIME                       (0x044B)
+#define RADIOLIB_LR11X0_CMD_GNSS_CONFIG_DELAY_RESET_AP          (0x044D)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_DOPPLER_SOLVER_RES        (0x044F)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_DELAY_RESET_AP            (0x0453)
-#define RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_UPDATE_FROM_SAT        (0x0455)
+#define RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_UPDATE_FROM_SAT        (0x0454)
+#define RADIOLIB_LR11X0_CMD_GNSS_READ_KEEP_SYNC_STATUS          (0x0456)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_STATUS            (0x0457)
 #define RADIOLIB_LR11X0_CMD_GNSS_CONFIG_ALMANAC_UPDATE_PERIOD   (0x0463)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_UPDATE_PERIOD     (0x0464)
-#define RADIOLIB_LR11X0_CMD_GNSS_CONFIG_DELAY_RESET_AP          (0x0465)
 #define RADIOLIB_LR11X0_CMD_GNSS_GET_SV_WARM_START              (0x0466)
-#define RADIOLIB_LR11X0_CMD_GNSS_READ_WN_ROLLOVER               (0x0467)
+#define RADIOLIB_LR11X0_CMD_GNSS_GET_SV_SYNC                    (0x0466)
 #define RADIOLIB_LR11X0_CMD_GNSS_READ_WARM_START_STATUS         (0x0469)
 #define RADIOLIB_LR11X0_CMD_GNSS_WRITE_BIT_MASK_SAT_ACTIVATED   (0x0472)
 #define RADIOLIB_LR11X0_CMD_CRYPTO_SET_KEY                      (0x0502)
@@ -1358,14 +1366,39 @@ class LR11x0: public PhysicalLayer {
       \returns \ref status_codes
     */
     int16_t updateFirmware(const uint32_t* image, size_t size, bool nonvolatile = true);
-
+    
+    /*!
+      \brief Method to check whether the device is capable of performing a GNSS scan.
+      CAUTION: Work in progress! Most data is returned via debug prints.
+      \returns \ref status_codes
+    */
     int16_t isGnssScanCapable();
 
+    /*!
+      \brief Performs GNSS scan.
+      CAUTION: Work in progress! Most data is returned via debug prints.
+      \param resSize Pointer to a variable in which the result size will be saved.
+      \returns \ref status_codes
+    */
     int16_t gnssScan(uint16_t* resSize);
 
+    /*!
+      \brief Get GNSS scan result.
+      CAUTION: Work in progress! Most data is returned via debug prints.
+      \param size Result size to read.
+      \returns \ref status_codes
+    */
     int16_t getGnssScanResult(uint16_t size);
     
-    int16_t getGnssPosition(float* lat, float* lon, bool filtered);
+    /*!
+      \brief Get GNSS position.
+      CAUTION: Work in progress! Most data is returned via debug prints.
+      \param lat Pointer to a variable where latitude in degrees will be saved.
+      \param lon Pointer to a variable where longitude in degrees will be saved.
+      \param filtered Whether to save the filtered, or unfiltered value. Defaults to true (filtered).
+      \returns \ref status_codes
+    */
+    int16_t getGnssPosition(float* lat, float* lon, bool filtered = true);
     
 #if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
   protected:
@@ -1467,10 +1500,13 @@ class LR11x0: public PhysicalLayer {
     int16_t wifiCfgTimestampAPphone(uint32_t timestamp);
     int16_t wifiReadVersion(uint8_t* major, uint8_t* minor);
 
+    int16_t gnssReadRssi(int8_t* rssi);
     int16_t gnssSetConstellationToUse(uint8_t mask);
     int16_t gnssReadConstellationToUse(uint8_t* mask);
     int16_t gnssSetAlmanacUpdate(uint8_t mask);
     int16_t gnssReadAlmanacUpdate(uint8_t* mask);
+    int16_t gnssSetFreqSearchSpace(uint8_t freq);
+    int16_t gnssReadFreqSearchSpace(uint8_t* freq);
     int16_t gnssReadVersion(uint8_t* fw, uint8_t* almanac);
     int16_t gnssReadSupportedConstellations(uint8_t* mask);
     int16_t gnssSetMode(uint8_t mode);
@@ -1482,19 +1518,23 @@ class LR11x0: public PhysicalLayer {
     int16_t gnssPushDmMsg(uint8_t* payload, size_t len);
     int16_t gnssGetContextStatus(uint8_t* fwVersion, uint32_t* almanacCrc, uint8_t* errCode, uint8_t* almUpdMask, uint8_t* freqSpace);
     int16_t gnssGetNbSvDetected(uint8_t* nbSv);
-    int16_t gnssGetSvDetected(uint8_t* svId, uint8_t* snr, uint16_t* doppler, size_t nbSv);
+    int16_t gnssGetSvDetected(uint8_t* svId, uint8_t* snr, int16_t* doppler, size_t nbSv);
     int16_t gnssGetConsumption(uint32_t* cpu, uint32_t* radio);
     int16_t gnssGetResultSize(uint16_t* size);
     int16_t gnssReadResults(uint8_t* result, uint16_t size);
     int16_t gnssAlmanacFullUpdateHeader(uint16_t date, uint32_t globalCrc);
     int16_t gnssAlmanacFullUpdateSV(uint8_t svn, uint8_t* svnAlmanac);
-    int16_t gnssGetSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv);
+    int16_t gnssAlmanacReadAddrSize(uint32_t* addr, uint16_t* size);
+    int16_t gnssAlmanacReadSV(uint8_t svId, uint8_t* almanac);
+    int16_t gnssGetNbSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv);
+    int16_t gnssGetSvVisible(uint8_t nbSv, uint8_t** svId, int16_t** doppler, int16_t** dopplerErr);
     int16_t gnssPerformScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax);
     int16_t gnssReadLastScanModeLaunched(uint8_t* lastScanMode);
     int16_t gnssFetchTime(uint8_t effort, uint8_t opt);
     int16_t gnssReadTime(uint8_t* err, uint32_t* time, uint32_t* nbUs, uint32_t* timeAccuracy);
     int16_t gnssResetTime(void);
     int16_t gnssResetPosition(void);
+    int16_t gnssReadWeekNumberRollover(uint8_t* status, uint8_t* rollover);
     int16_t gnssReadDemodStatus(int8_t* status, uint8_t* info);
     int16_t gnssReadCumulTiming(uint32_t* timing, uint8_t* constDemod);
     int16_t gnssSetTime(uint32_t time, uint16_t accuracy);
@@ -1502,12 +1542,13 @@ class LR11x0: public PhysicalLayer {
     int16_t gnssReadDelayResetAP(uint32_t* delay);
     int16_t gnssAlmanacUpdateFromSat(uint8_t effort, uint8_t bitMask);
     int16_t gnssReadAlmanacStatus(uint8_t* status);
+    int16_t gnssReadKeepSyncStatus(uint8_t mask, uint8_t* nbSvVisible, uint32_t* elapsed);
     int16_t gnssConfigAlmanacUpdatePeriod(uint8_t bitMask, uint8_t svType, uint16_t period);
     int16_t gnssReadAlmanacUpdatePeriod(uint8_t bitMask, uint8_t svType, uint16_t* period);
     int16_t gnssConfigDelayResetAP(uint32_t delay);
     int16_t gnssGetSvWarmStart(uint8_t bitMask, uint8_t* sv, uint8_t nbVisSat);
-    int16_t gnssReadWNRollover(uint8_t* status, uint8_t* rollover);
     int16_t gnssReadWarmStartStatus(uint8_t bitMask, uint8_t* nbVisSat, uint32_t* timeElapsed);
+    int16_t gnssGetSvSync(uint8_t mask, uint8_t nbSv, uint8_t* syncList);
     int16_t gnssWriteBitMaskSatActivated(uint8_t bitMask, uint32_t* bitMaskActivated0, uint32_t* bitMaskActivated1);
 
     int16_t cryptoSetKey(uint8_t keyId, uint8_t* key);