diff --git a/app/consapp/convbin/bcc/_convbin.cbproj b/app/consapp/convbin/bcc/_convbin.cbproj
index b6391586d..4103f4ac5 100644
--- a/app/consapp/convbin/bcc/_convbin.cbproj
+++ b/app/consapp/convbin/bcc/_convbin.cbproj
@@ -230,6 +230,9 @@
26
+
+ 28
+
8
13
diff --git a/app/consapp/convbin/convbin.c b/app/consapp/convbin/convbin.c
index 44aa24234..f1c0479bb 100644
--- a/app/consapp/convbin/convbin.c
+++ b/app/consapp/convbin/convbin.c
@@ -86,6 +86,7 @@ static const char *help[]={
" 0x01-01,0x01-02,0x01-03,0x01-04,0x01-06,0x7f-05",
" Trimble : RT17",
" Septentrio : SBF",
+" Advanded Navigation : ANPP",
" RINEX : OBS, NAV, GNAV, HNAV, LNAV, QNAV",
"",
" Options [default]",
@@ -111,6 +112,7 @@ static const char *help[]={
" rt17 = Trimble RT17",
" sbf = Septentrio SBF",
" unicore = Unicore binary data output",
+" anpp = Advanced Navigation Packet Protocol",
" rinex= RINEX",
" -ro opt receiver options",
" -f freq number of frequencies [all]",
@@ -170,6 +172,7 @@ static const char *help[]={
" *.rt17 Trimble RT17",
" *.sbf Septentrio SBF",
" *.unc Unicore binary data output",
+" *.anpp Advanced Navigation Packet Protocol",
" *.obs,*.*o RINEX OBS",
" *.rnx RINEX OBS",
" *.nav,*.*n RINEX NAV",
@@ -403,7 +406,11 @@ static int get_filetime(const char *file, gtime_t *time)
struct stat st;
if (!stat(path, &st)) {
struct tm tm;
+#ifdef _MSC_VER
+ if (gmtime_s(&tm, &st.st_mtime) != 0) {
+#else
if (gmtime_r(&st.st_mtime, &tm)) {
+#endif
double ep[6];
ep[0] = tm.tm_year + 1900;
ep[1] = tm.tm_mon + 1;
@@ -633,6 +640,7 @@ static int cmdopts(int argc, char **argv, rnxopt_t *opt, char **ifile,
#ifdef RTK_DISABLED
else if (!strcmp(fmt,"tersus")) format=STRFMT_TERSUS;
#endif
+ else if (!strcmp(fmt,"anpp" )) format=STRFMT_ANPP;
else if (!strcmp(fmt,"rinex")) format=STRFMT_RINEX;
}
else {
@@ -657,6 +665,7 @@ static int cmdopts(int argc, char **argv, rnxopt_t *opt, char **ifile,
#ifdef RTK_DISABLED
else if (!strcmp(p,".trs" )) format=STRFMT_TERSUS;
#endif
+ else if (!strcmp(p,".anpp" )) format=STRFMT_ANPP;
else if (!strcmp(p,".obs" )) format=STRFMT_RINEX;
else if (!strcmp(p+3,"o" )) format=STRFMT_RINEX;
else if (!strcmp(p+3,"O" )) format=STRFMT_RINEX;
diff --git a/app/consapp/convbin/gcc/makefile b/app/consapp/convbin/gcc/makefile
index b6399ceac..9e0deba38 100644
--- a/app/consapp/convbin/gcc/makefile
+++ b/app/consapp/convbin/gcc/makefile
@@ -17,7 +17,7 @@ all : convbin
convbin : convbin.o rtkcmn.o trace.o rinex.o sbas.o preceph.o rcvraw.o convrnx.o
convbin : rtcm.o rtcm2.o rtcm3.o rtcm3e.o pntpos.o ephemeris.o ionex.o
convbin : novatel.o ublox.o crescent.o skytraq.o javad.o nvs.o
-convbin : binex.o rt17.o septentrio.o swiftnav.o unicore.o
+convbin : binex.o rt17.o septentrio.o swiftnav.o unicore.o adnav.o
convbin : sofa.o
convbin.o : ../convbin.c
@@ -72,6 +72,8 @@ swiftnav.o: $(SRC)/rcv/swiftnav.c
$(CC) -c $(CFLAGS) $(SRC)/rcv/swiftnav.c
unicore.o: $(SRC)/rcv/unicore.c
$(CC) -c $(CFLAGS) $(SRC)/rcv/unicore.c
+adnav.o : $(SRC)/rcv/adnav.c
+ $(CC) -c $(CFLAGS) $(SRC)/rcv/adnav.c
sofa.o : $(SRC)/sofa.c
$(CC) -c $(CFLAGS) $(SRC)/sofa.c
@@ -101,6 +103,7 @@ rt17.o : $(SRC)/rtklib.h
septentrio.o: $(SRC)/rtklib.h
swiftnav.o : $(SRC)/rtklib.h
unciore.o : $(SRC)/rtklib.h
+adnav.o : $(SRC)/rtklib.h
DATDIR = ../../../test/data/rcvraw
diff --git a/app/consapp/convbin/msc/msc.vcxproj b/app/consapp/convbin/msc/msc.vcxproj
index 7186a99e8..ad262aa1e 100644
--- a/app/consapp/convbin/msc/msc.vcxproj
+++ b/app/consapp/convbin/msc/msc.vcxproj
@@ -198,6 +198,7 @@
+
diff --git a/app/consapp/rtkrcv/gcc/makefile b/app/consapp/rtkrcv/gcc/makefile
index fdde9a9c7..5d7e44e0d 100644
--- a/app/consapp/rtkrcv/gcc/makefile
+++ b/app/consapp/rtkrcv/gcc/makefile
@@ -15,7 +15,7 @@ rtkrcv : rtkrcv.o vt.o rtkcmn.o trace.o rtksvr.o rtkpos.o geoid.o solution.o
rtkrcv : sbas.o stream.o rcvraw.o rtcm.o preceph.o options.o pntpos.o ppp.o ppp_ar.o
rtkrcv : novatel.o ublox.o crescent.o skytraq.o javad.o nvs.o binex.o
rtkrcv : rt17.o ephemeris.o rinex.o ionex.o rtcm2.o rtcm3.o rtcm3e.o
-rtkrcv : tides.o septentrio.o swiftnav.o unicore.o
+rtkrcv : tides.o septentrio.o swiftnav.o unicore.o adnav.o
rtkrcv : sofa.o
@@ -91,6 +91,8 @@ septentrio.o: $(SRC)/rcv/septentrio.c
$(CC) -c $(CFLAGS) $(SRC)/rcv/septentrio.c
unicore.o: $(SRC)/rcv/unicore.c
$(CC) -c $(CFLAGS) $(SRC)/rcv/unicore.c
+adnav.o: $(SRC)/rcv/adnav.c
+ $(CC) -c $(CFLAGS) $(SRC)/rcv/adnav.c
sofa.o : $(SRC)/sofa.c
$(CC) -c $(CFLAGS) $(SRC)/sofa.c
@@ -126,6 +128,7 @@ binex.o : $(SRC)/rtklib.h
rt17.o : $(SRC)/rtklib.h
septentrio.o: $(SRC)/rtklib.h
unciore.o : $(SRC)/rtklib.h
+adnav.o : $(SRC)/rtklib.h
ephemeris.o: $(SRC)/rtklib.h
rinex.o : $(SRC)/rtklib.h
ionex.o : $(SRC)/rtklib.h
diff --git a/app/consapp/rtkrcv/rtkrcv.c b/app/consapp/rtkrcv/rtkrcv.c
index f0eba0b1c..5dd5dbbb0 100644
--- a/app/consapp/rtkrcv/rtkrcv.c
+++ b/app/consapp/rtkrcv/rtkrcv.c
@@ -185,7 +185,7 @@ static const char *pathopts[]={ /* path options help */
#define FLGOPT "0:off,1:std+2:age/ratio/ns"
#define ISTOPT "0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripcli,7:ftp,8:http"
#define OSTOPT "0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,5:ntripsvr,9:ntripcas,11:udpcli"
-#define FMTOPT "0:rtcm2,1:rtcm3,2:oem4,4:ubx,5:swift,6:hemis,7:skytraq,8:javad,9:nvs,10:binex,11:rt17,12:sbf,14:unicore,15:rinex,16:sp3,17:clk"
+#define FMTOPT "0:rtcm2,1:rtcm3,2:oem4,4:ubx,5:swift,6:hemis,7:skytraq,8:javad,9:nvs,10:binex,11:rt17,12:sbf,14:unicore,15:anpp,16:rinex,17:sp3,18:clk"
#define NMEOPT "0:off,1:latlon,2:single"
#define SOLOPT "0:llh,1:xyz,2:enu,3:nmea,4:stat"
#define MSGOPT "0:all,1:rover,2:base,3:corr"
@@ -1029,7 +1029,7 @@ static void prstream(vt_t *vt)
"http","ntripcas","udpsvr","udpcli","membuf"
};
const char *fmt[]={"rtcm2","rtcm3","oem4","","ubx","swift","hemis","skytreq",
- "javad","nvs","binex","rt17","sbf","","unicore","sp3",""};
+ "javad","nvs","binex","rt17","sbf","","unicore","anpp","sp3",""};
const char *sol[]={"llh","xyz","enu","nmea","stat","-"};
stream_t stream[9];
int i,format[9]={0};
diff --git a/app/consapp/str2str/gcc/makefile b/app/consapp/str2str/gcc/makefile
index 0c6bd9c24..f0f33018b 100644
--- a/app/consapp/str2str/gcc/makefile
+++ b/app/consapp/str2str/gcc/makefile
@@ -15,7 +15,7 @@ all : str2str
str2str : str2str.o stream.o rtkcmn.o trace.o solution.o sbas.o geoid.o
str2str : rcvraw.o novatel.o ublox.o crescent.o skytraq.o javad.o
str2str : nvs.o binex.o rt17.o rtcm.o rtcm2.o rtcm3.o rtcm3e.o preceph.o streamsvr.o
-str2str : septentrio.o swiftnav.o unicore.o
+str2str : septentrio.o swiftnav.o unicore.o adnav.o
str2str : sofa.o
str2str.o : ../str2str.c
@@ -68,6 +68,8 @@ swiftnav.o: $(SRC)/rcv/swiftnav.c
$(CC) -c $(CFLAGS) $(SRC)/rcv/swiftnav.c
unicore.o: $(SRC)/rcv/unicore.c
$(CC) -c $(CFLAGS) $(SRC)/rcv/unicore.c
+adnav.o: $(SRC)/rcv/adnav.c
+ $(CC) -c $(CFLAGS) $(SRC)/rcv/adnav.c
sofa.o: $(SRC)/sofa.c
$(CC) -c $(CFLAGS) $(SRC)/sofa.c
@@ -96,6 +98,7 @@ preceph.o : $(SRC)/rtklib.h
septentrio.o: $(SRC)/rtklib.h
swiftnav.o : $(SRC)/rtklib.h
unicore.o : $(SRC)/rtklib.h
+adnav.o : $(SRC)/rtklib.h
install:
cp str2str $(BINDIR)
diff --git a/app/consapp/str2str/str2str.c b/app/consapp/str2str/str2str.c
index 7c1708a44..fff2e2b94 100644
--- a/app/consapp/str2str/str2str.c
+++ b/app/consapp/str2str/str2str.c
@@ -91,6 +91,7 @@ static const char *help[]={
" rt17 : Trimble RT17 (only in)",
" sbf : Septentrio SBF (only in)",
" unicore : Unicore (only in)",
+" anpp : Advanced Navigation Packet Protocol (only in)",
"",
" -msg \"type[(tint)][,type[(tint)]...]\"",
" rtcm message types and output intervals (s)",
@@ -168,6 +169,7 @@ static void decodefmt(char *path, int *fmt)
else if (!strcmp(p,"#rt17" )) *fmt=STRFMT_RT17;
else if (!strcmp(p,"#sbf" )) *fmt=STRFMT_SEPT;
else if (!strcmp(p,"#unicore" )) *fmt=STRFMT_UNICORE;
+ else if (!strcmp(p,"#anpp" )) *fmt=STRFMT_ANPP;
else return;
*p='\0';
}
diff --git a/app/qtapp/rtkconv_qt/convmain.cpp b/app/qtapp/rtkconv_qt/convmain.cpp
index 183cc6d93..63415ea82 100644
--- a/app/qtapp/rtkconv_qt/convmain.cpp
+++ b/app/qtapp/rtkconv_qt/convmain.cpp
@@ -449,7 +449,7 @@ void MainWindow::selectInputFile()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Input RTCM, RCV RAW or RINEX File"), ui->cBInputFile->currentText(),
tr("All (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;"
- "Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);;Septentrio (*.sbf)"));
+ "Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);;Septentrio (*.sbf);;ANPP (*.anpp)"));
if (!filename.isEmpty()) {
ui->cBInputFile->setCurrentText(QDir::toNativeSeparators(filename));
@@ -798,6 +798,8 @@ void MainWindow::convertFile()
conversionThread->format = STRFMT_SEPT;
} else if (fi.completeSuffix() == "unc") {
conversionThread->format = STRFMT_UNICORE;
+ } else if (fi.completeSuffix() == "anpp") {
+ conversionThread->format = STRFMT_ANPP;
} else if (fi.completeSuffix().toLower() == "obs") {
conversionThread->format = STRFMT_RINEX;
} else if (fi.completeSuffix().toLower().contains("nav")) {
diff --git a/app/qtapp/rtknavi_qt/navimain.cpp b/app/qtapp/rtknavi_qt/navimain.cpp
index 1f3f4db6b..31a7e7be2 100644
--- a/app/qtapp/rtknavi_qt/navimain.cpp
+++ b/app/qtapp/rtknavi_qt/navimain.cpp
@@ -94,7 +94,7 @@ static int strfmt[] = { /* stream formats */
#define FLGOPT "0:off,1:std+2:age/ratio/ns"
#define ISTOPT "0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripcli,7:ftp,8:http"
#define OSTOPT "0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,5:ntripsvr,9:ntripcas"
-#define FMTOPT "0:rtcm2,1:rtcm3,2:oem4,4:ubx,5:swift,6:hemis,7:skytraq,8:javad,9:nvs,10:binex,11:rt17,12:sbf,14:unicore,15:rinex,16:sp3,17:clk"
+#define FMTOPT "0:rtcm2,1:rtcm3,2:oem4,4:ubx,5:swift,6:hemis,7:skytraq,8:javad,9:nvs,10:binex,11:rt17,12:sbf,14:unicore,15:anpp,16:rinex,17:sp3,18:clk"
#define NMEOPT "0:off,1:latlon,2:single"
#define SOLOPT "0:llh,1:xyz,2:enu,3:nmea,4:stat"
diff --git a/app/winapp/rtkconv/convmain.cpp b/app/winapp/rtkconv/convmain.cpp
index df004f4fa..fcdf4bc70 100644
--- a/app/winapp/rtkconv/convmain.cpp
+++ b/app/winapp/rtkconv/convmain.cpp
@@ -896,6 +896,7 @@ void __fastcall TMainWindow::ConvertFile(void)
else if (!strcmp(p,".trs" )) format=STRFMT_TERSUS;
else if (!strcmp(p,".cnb" )) format=STRFMT_CNAV;
#endif
+ else if (!strcmp(p,".anpp" )) format=STRFMT_ANPP;
else if (!strcmp(p,".obs" )) format=STRFMT_RINEX;
else if (!strcmp(p,".OBS" )) format=STRFMT_RINEX;
else if (!strcmp(p,".nav" )) format=STRFMT_RINEX;
diff --git a/app/winapp/rtkconv/convmain.dfm b/app/winapp/rtkconv/convmain.dfm
index 2fd620a70..a781b0601 100644
--- a/app/winapp/rtkconv/convmain.dfm
+++ b/app/winapp/rtkconv/convmain.dfm
@@ -1151,7 +1151,7 @@ object MainWindow: TMainWindow
'All (*.*)|*.*|RTCM 2 (*.rtcm2)|*.rtcm2|RTCM 3 (*.rtcm3)|*.rtcm3|' +
'NovtAtel (*.gps)|*.gps|ublox (*.ubx)|*.ubx' +
'|Hemisphere (*.bin)|*.bin|Javad (*.jps)|*.jps|' +
- 'Septentrio (*.sbf)|*.sbf|' +
+ 'Septentrio (*.sbf)|*.sbf|ANPP (*.anpp)|*.anpp|' +
'RINEX OBS (*.obs,*.*O)|*.obs;*.*O'
Options = [ofHideReadOnly, ofNoChangeDir, ofEnableSizing]
Left = 260
diff --git a/app/winapp/rtkconv/rtkconv.cbproj b/app/winapp/rtkconv/rtkconv.cbproj
index dfd5d201c..58355a0aa 100644
--- a/app/winapp/rtkconv/rtkconv.cbproj
+++ b/app/winapp/rtkconv/rtkconv.cbproj
@@ -338,6 +338,9 @@
39
+
+ 42
+
31
diff --git a/app/winapp/rtknavi/naviopt.cpp b/app/winapp/rtknavi/naviopt.cpp
index c974459d9..a291b92b4 100644
--- a/app/winapp/rtknavi/naviopt.cpp
+++ b/app/winapp/rtknavi/naviopt.cpp
@@ -47,7 +47,7 @@ static char proxyaddr[MAXSTR]=""; /* proxy address */
#define FLGOPT "0:off,1:std+2:age/ratio/ns"
#define ISTOPT "0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripcli,7:ftp,8:http"
#define OSTOPT "0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,5:ntripsvr,9:ntripcas"
-#define FMTOPT "0:rtcm2,1:rtcm3,2:oem4,4:ubx,5:swift,6:hemis,7:skytraq,8:javad,9:nvs,10:binex,11:rt17,12:sbf,14:unicore,15:rinex,16:sp3,17:clk"
+#define FMTOPT "0:rtcm2,1:rtcm3,2:oem4,4:ubx,5:swift,6:hemis,7:skytraq,8:javad,9:nvs,10:binex,11:rt17,12:sbf,14:unicore,15:anpp,16:rinex,17:sp3,18:clk"
#define NMEOPT "0:off,1:latlon,2:single"
#define SOLOPT "0:llh,1:xyz,2:enu,3:nmea,4:stat"
#define MSGOPT "0:all,1:rover,2:base,3:corr"
diff --git a/app/winapp/rtknavi/rtknavi.cbproj b/app/winapp/rtknavi/rtknavi.cbproj
index 62857f6a5..4095e151c 100644
--- a/app/winapp/rtknavi/rtknavi.cbproj
+++ b/app/winapp/rtknavi/rtknavi.cbproj
@@ -445,6 +445,9 @@
60
+
+ 64
+
47
16
diff --git a/app/winapp/rtkplot/rtkplot.cbproj b/app/winapp/rtkplot/rtkplot.cbproj
index d00b039b8..27d1df2d6 100644
--- a/app/winapp/rtkplot/rtkplot.cbproj
+++ b/app/winapp/rtkplot/rtkplot.cbproj
@@ -457,6 +457,9 @@
60
+
+ 64
+
52
diff --git a/app/winapp/srctblbrows/srctblbrows.cbproj b/app/winapp/srctblbrows/srctblbrows.cbproj
index 9e57cee70..4de264c03 100644
--- a/app/winapp/srctblbrows/srctblbrows.cbproj
+++ b/app/winapp/srctblbrows/srctblbrows.cbproj
@@ -290,6 +290,9 @@
23
+
+ 27
+
23
diff --git a/app/winapp/strsvr/strsvr.cbproj b/app/winapp/strsvr/strsvr.cbproj
index 26f509edc..000fb6747 100644
--- a/app/winapp/strsvr/strsvr.cbproj
+++ b/app/winapp/strsvr/strsvr.cbproj
@@ -365,6 +365,9 @@
41
+
+ 43
+
31
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1801464de..59251ef76 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -25,6 +25,7 @@ endif()
aux_source_directory(. DIR_SRCS_RTKLIB)
set(DIR_SRCS_RTKLIB_RCV
${DIR_SRCS_RTKLIB_RCV}
+ rcv/adnav.c
rcv/binex.c
rcv/crescent.c
rcv/javad.c
diff --git a/src/convrnx.c b/src/convrnx.c
index 696666e69..31f92d58a 100644
--- a/src/convrnx.c
+++ b/src/convrnx.c
@@ -340,15 +340,9 @@ static int open_strfile(strfile_t *str, const char *file)
static void close_strfile(strfile_t *str)
{
trace(3,"close_strfile:\n");
-
- if (str->format==STRFMT_RTCM2||str->format==STRFMT_RTCM3) {
- if (str->fp) fclose(str->fp);
- }
- else if (str->format<=MAXRCVFMT) {
- if (str->fp) fclose(str->fp);
- }
- else if (str->format==STRFMT_RINEX) {
- if (str->fp) fclose(str->fp);
+ if (str->fp) {
+ fclose(str->fp);
+ str->fp = NULL;
}
}
/* set format and files in RINEX options comments ----------------------------*/
diff --git a/src/rcv/adnav.c b/src/rcv/adnav.c
new file mode 100644
index 000000000..9ffca4906
--- /dev/null
+++ b/src/rcv/adnav.c
@@ -0,0 +1,613 @@
+/*------------------------------------------------------------------------------
+ * adnav.c : Advanced Navigation Packet Protocol (ANPP) decoder
+ *
+ * Copyright (C) 2026 by Joseph Fox-Rabinovitz, All rights reserved.
+ *
+ * reference :
+ * [1] Advanced Navigation, Advanced Navigation Packet Protocol Reference,
+ * https://docs.advancednavigation.com/boreas-d/ANPP/Advanced%20Navigation%20Packet.htm
+ *
+ * history : 2026/05/05 1.0 new
+ *-----------------------------------------------------------------------------*/
+#include
+
+#include "rtklib.h"
+
+/* ANPP packet IDs */
+#define ID_SYSTEMSTATE 20 /* system state */
+#define ID_UNIXTIME 21 /* unix time */
+#define ID_RAWSATDATA 60 /* raw satellite data */
+#define ID_RAWSATEPH 61 /* raw satellite ephemeris */
+
+/* ANPP satellite system IDs (packets 60/61 sys field) */
+#define ANPP_SYS_UNK 0 // Unknown
+#define ANPP_SYS_GPS 1 // GPS
+#define ANPP_SYS_GLO 2 // GLONASS
+#define ANPP_SYS_BDS 3 // BeiDou
+#define ANPP_SYS_GAL 4 // Galileo
+#define ANPP_SYS_SBS 5 // SBAS
+#define ANPP_SYS_QZS 6 // QZSS
+// 7 // Reserved
+#define ANPP_SYS_OMN 8 // OmniStar
+// 9 // Reserved
+#define ANPP_SYS_NAV 10 // NavIC
+
+/* header size for all packets */
+#define HDR_LEN 5
+
+/* packet 20 payload length */
+#define SYSSTATE_LEN 100 /* system state */
+
+/* packet 21 payload length */
+#define UNIXTIME_LEN 8 /* unix time */
+
+/* packet 60 sub-record sizes */
+#define OBS_HDR_LEN 16 /* per-epoch header (time + counters) */
+#define SAT_HDR_LEN 6 /* per-satellite header */
+#define FREQ_BLK_LEN 26 /* per-frequency block size */
+
+/* tracking status bits (packet 60, per-frequency block, byte 1) */
+#define TRKS_CARRIER 0x01 /* carrier phase valid */
+#define TRKS_SLIP 0x02 /* cycle slip detected */
+#define TRKS_HALFCYCLE 0x04 /* half-cycle ambiguity unresolved */
+#define TRKS_PSEUDORANGE 0x08 /* pseudorange valid */
+#define TRKS_DOPPLER 0x10 /* Doppler valid */
+#define TRKS_SNR 0x20 /* SNR valid */
+
+/* packet 61 payload lengths */
+#define EPH_LEN_GPS 132 /* GPS ephemeris */
+#define EPH_LEN_GLO 94 /* GLONASS ephemeris */
+
+/* get fields (little-endian) ------------------------------------------------*/
+static uint8_t U1(const raw_t* raw, size_t index) {
+ RTKBOUNDSCHECK(raw->buff, sizeof(raw->buff), index);
+ RTKBOUNDSCHECK(raw->buff, raw->len, index);
+ return raw->buff[index];
+}
+static int8_t I1(const raw_t* raw, size_t index) {
+ RTKBOUNDSCHECK(raw->buff, sizeof(raw->buff), index);
+ RTKBOUNDSCHECK(raw->buff, raw->len, index);
+ return (int8_t)raw->buff[index];
+}
+static uint16_t U2(const raw_t* raw, size_t index) {
+ RTKBOUNDSCHECK(raw->buff, sizeof(raw->buff), index + 1);
+ RTKBOUNDSCHECK(raw->buff, raw->len, index + 1);
+ uint16_t u;
+ memcpy(&u, raw->buff + index, 2);
+ return u;
+}
+static uint32_t U4(const raw_t* raw, size_t index) {
+ RTKBOUNDSCHECK(raw->buff, sizeof(raw->buff), index + 3);
+ RTKBOUNDSCHECK(raw->buff, raw->len, index + 3);
+ uint32_t u;
+ memcpy(&u, raw->buff + index, 4);
+ return u;
+}
+static float R4(const raw_t* raw, size_t index) {
+ RTKBOUNDSCHECK(raw->buff, sizeof(raw->buff), index + 3);
+ RTKBOUNDSCHECK(raw->buff, raw->len, index + 3);
+ float r;
+ memcpy(&r, raw->buff + index, 4);
+ return r;
+}
+static double R8(const raw_t* raw, size_t index) {
+ RTKBOUNDSCHECK(raw->buff, sizeof(raw->buff), index + 7);
+ RTKBOUNDSCHECK(raw->buff, raw->len, index + 7);
+ double r;
+ memcpy(&r, raw->buff + index, 8);
+ return r;
+}
+
+/* receiver state ------------------------------------------------------------*/
+typedef struct {
+ gtime_t time; /* last cached epoch time (UTC) */
+ uint32_t cur_unix_time; /* unix_time of packet-60 epoch being assembled */
+ uint32_t cur_nanoseconds; /* nanoseconds of packet-60 epoch being assembled */
+ int epoch_active; /* 1 if obuf currently holds a partial epoch */
+} anpp_t;
+
+/* init/free -----------------------------------------------------------------*/
+extern int init_anpp(raw_t* raw) {
+ if (raw->format != STRFMT_ANPP) return 0;
+ anpp_t* anpp = calloc(1, sizeof(anpp_t));
+ if (!anpp) {
+ trace(0, "init_anpp: memory allocation error\n");
+ return 0;
+ }
+ raw->rcv_data = (void*)anpp;
+ return 1;
+}
+
+extern void free_anpp(raw_t* raw) {
+ if (raw->format != STRFMT_ANPP) return;
+ if (raw->rcv_data) {
+ free(raw->rcv_data);
+ raw->rcv_data = NULL;
+ }
+}
+
+/* initialize one obs buffer slot --------------------------------------------*/
+static void init_obsd_anpp(gtime_t time, int sat, obsd_t* data) {
+ data->time = time;
+ data->sat = (uint8_t)sat;
+
+ for (int i = 0; i < NFREQ + NEXOBS; i++) {
+ data->L[i] = data->P[i] = 0.0;
+ data->D[i] = data->SNR[i] = 0.0;
+ data->Lstd[i] = data->Pstd[i] = 0.0;
+ data->LLI[i] = 0;
+ data->code[i] = CODE_NONE;
+ }
+}
+
+/* flush observation data buffer ---------------------------------------------*/
+static int flush_obuf_anpp(raw_t* raw) {
+ trace(3, "flush_obuf_anpp: n=%d\n", raw->obuf.n);
+
+ int n = 0;
+ for (int i = 0; i < raw->obuf.n && i < MAXOBS; i++) {
+ if (!satsys(raw->obuf.data[i].sat, NULL)) continue;
+ if (raw->obuf.data[i].time.time == 0) continue;
+ raw->obs.data[n++] = raw->obuf.data[i];
+ }
+ raw->obs.n = n;
+
+ for (int i = 0; i < MAXOBS; i++) {
+ raw->obuf.data[i].time.time = 0;
+ raw->obuf.data[i].time.sec = 0.0;
+ for (int j = 0; j < NFREQ + NEXOBS; j++) {
+ raw->obuf.data[i].L[j] = raw->obuf.data[i].P[j] = 0.0;
+ raw->obuf.data[i].D[j] = raw->obuf.data[i].SNR[j] = 0.0;
+ raw->obuf.data[i].Lstd[j] = raw->obuf.data[i].Pstd[j] = 0.0;
+ raw->obuf.data[i].LLI[j] = 0;
+ raw->obuf.data[i].code[j] = CODE_NONE;
+ }
+ }
+ return n > 0 ? 1 : 0;
+}
+
+/* map ANPP satellite system code to rtklib SYS_* ---------------------------*/
+static int anpp2sys(uint8_t anpp_sys) {
+ switch (anpp_sys) {
+ case ANPP_SYS_UNK:
+ return SYS_NONE;
+ case ANPP_SYS_GPS:
+ return SYS_GPS;
+ case ANPP_SYS_GLO:
+ return SYS_GLO;
+ case ANPP_SYS_BDS:
+ return SYS_CMP;
+ case ANPP_SYS_GAL:
+ return SYS_GAL;
+ case ANPP_SYS_SBS:
+ return SYS_SBS;
+ case ANPP_SYS_QZS:
+ return SYS_QZS;
+ case ANPP_SYS_OMN:
+ return SYS_SBS;
+ case ANPP_SYS_NAV:
+ return SYS_IRN;
+ }
+ return SYS_NONE;
+}
+
+/* map ANPP (sys, freq_code) to rtklib observation code ---------------------*/
+static uint8_t anpp2code(uint8_t anpp_sys, uint8_t freq_code) {
+ switch (anpp_sys) {
+ case ANPP_SYS_GPS:
+ switch (freq_code) {
+ case 1:
+ return CODE_L1C; /* L1 C/A */
+ case 2:
+ return CODE_L1L; /* L1 C */
+ case 3:
+ return CODE_L1P; /* L1 P */
+ case 4:
+ return CODE_L1M; /* L1 M */
+ case 5:
+ return CODE_L2L; /* L2 C */
+ case 6:
+ return CODE_L2P; /* L2 P */
+ case 7:
+ return CODE_L2M; /* L2 M */
+ case 8:
+ return CODE_L5Q; /* L5 */
+ }
+ break;
+ case ANPP_SYS_GLO:
+ switch (freq_code) {
+ case 1:
+ return CODE_L1C; /* G1 C/A */
+ case 3:
+ return CODE_L1P; /* G1 P */
+ case 5:
+ return CODE_L2C; /* G2 C/A */
+ case 6:
+ return CODE_L2P; /* G2 P */
+ case 8:
+ return CODE_L3Q; /* G3 */
+ }
+ break;
+ case ANPP_SYS_GAL:
+ switch (freq_code) {
+ case 1:
+ return CODE_L1C; /* E1 OS */
+ case 2:
+ return CODE_L1A; /* E1 PRS */
+ case 5:
+ return CODE_L6B; /* E6 CS */
+ case 6:
+ return CODE_L6A; /* E6 PRS */
+ case 8:
+ return CODE_L5Q; /* E5 a */
+ case 9:
+ return CODE_L7Q; /* E5 b */
+ case 10:
+ return CODE_L8Q; /* E5 a+b */
+ }
+ break;
+ case ANPP_SYS_BDS:
+ switch (freq_code) {
+ case 1:
+ return CODE_L2Q; /* B1 */
+ case 5:
+ return CODE_L7Q; /* B2 */
+ case 8:
+ return CODE_L6Q; /* B3 */
+ }
+ break;
+ case ANPP_SYS_SBS:
+ switch (freq_code) {
+ case 1:
+ return CODE_L1C; /* L1 C/A */
+ case 8:
+ return CODE_L5Q; /* L5 */
+ }
+ break;
+ case ANPP_SYS_QZS:
+ switch (freq_code) {
+ case 1:
+ return CODE_L1C; /* L1 C/A */
+ case 2:
+ return CODE_L1S; /* L1 C */
+ case 3:
+ return CODE_L1Z; /* L1 SAIF */
+ case 5:
+ return CODE_L2S; /* L2 C */
+ case 6:
+ return CODE_L6X; /* LEX */
+ case 8:
+ return CODE_L5P; /* L5 */
+ }
+ break;
+ case ANPP_SYS_OMN:
+ switch (freq_code) {
+ case 0:
+ return CODE_L1C; /* L1 C/A */
+ }
+ break;
+ case ANPP_SYS_NAV:
+ switch (freq_code) {
+ case 8:
+ return CODE_L5C; /* L5 */
+ }
+ break;
+ }
+ return CODE_NONE;
+}
+
+/* find or allocate-and-init obs buffer slot for satellite -------------------*/
+static int obuf_slot(raw_t* raw, gtime_t time, int sat) {
+ for (int i = 0; i < raw->obuf.n; i++) {
+ if (raw->obuf.data[i].sat == sat) return i;
+ }
+ if (raw->obuf.n >= MAXOBS) {
+ trace(2, "obuf_slot: buffer full sat=%d\n", sat);
+ return -1;
+ }
+
+ int n = raw->obuf.n++;
+ init_obsd_anpp(time, sat, &raw->obuf.data[n]);
+ return n;
+}
+
+/* packet 20/21: cache epoch time --------------------------------------------*/
+static int decode_systemstate(raw_t* raw) {
+ if (raw->len < HDR_LEN + SYSSTATE_LEN) {
+ trace(2, "decode_systemstate: short packet len=%d\n", raw->len);
+ return 0;
+ }
+ anpp_t* anpp = raw->rcv_data;
+ anpp->time.time = (time_t)U4(raw, HDR_LEN + 4);
+ anpp->time.sec = U4(raw, HDR_LEN + 8) * 1e-6;
+ return 0;
+}
+
+static int decode_unixtime(raw_t* raw) {
+ if (raw->len < HDR_LEN + UNIXTIME_LEN) {
+ trace(2, "decode_unixtime: short packet len=%d\n", raw->len);
+ return 0;
+ }
+ anpp_t* anpp = (anpp_t*)raw->rcv_data;
+ anpp->time.time = (time_t)U4(raw, HDR_LEN);
+ anpp->time.sec = U4(raw, HDR_LEN + 4) * 1e-6;
+ return 0;
+}
+
+/* packet 60: raw satellite data (observations) ------------------------------*/
+static int decode_rawsatdata(raw_t* raw) {
+ if (raw->len < HDR_LEN + OBS_HDR_LEN) {
+ trace(2, "decode_rawsatdata: short packet len=%d\n", raw->len);
+ return 0;
+ }
+
+ uint32_t unix_time = U4(raw, HDR_LEN);
+ uint32_t nanoseconds = U4(raw, HDR_LEN + 4);
+ uint8_t receiver_number = U1(raw, HDR_LEN + 12);
+ uint8_t packet_number = U1(raw, HDR_LEN + 13);
+ uint8_t total_packets = U1(raw, HDR_LEN + 14);
+ uint8_t nsats = U1(raw, HDR_LEN + 15);
+
+ /* select which receiver_number to emit: parse -RCVR from raw->opt
+ (default 0) */
+ const char* q;
+ int rcvr_sel = 0;
+ if ((q = strstr(raw->opt, "-RCVR")) != NULL) sscanf(q + 5, "%d", &rcvr_sel);
+
+ /* skip fragments from antennae we are not interested in */
+ if (receiver_number != (uint8_t)rcvr_sel) return 0;
+
+ /* if a new epoch begins before the previous one finished, flush partial */
+ int ret = 0;
+ anpp_t* anpp = (anpp_t*)raw->rcv_data;
+ if (anpp->epoch_active &&
+ (unix_time != anpp->cur_unix_time || nanoseconds != anpp->cur_nanoseconds)) {
+ ret = flush_obuf_anpp(raw);
+ anpp->epoch_active = 0;
+ }
+
+ /* start a fresh epoch if no assembly is in progress */
+ if (!anpp->epoch_active) {
+ gtime_t time;
+ time.time = (time_t)unix_time;
+ time.sec = nanoseconds * 1e-9;
+ raw->time = utc2gpst(time);
+ raw->obuf.n = 0;
+ anpp->cur_unix_time = unix_time;
+ anpp->cur_nanoseconds = nanoseconds;
+ anpp->epoch_active = 1;
+ }
+
+ size_t offset = HDR_LEN + OBS_HDR_LEN;
+
+ for (int i = 0; i < nsats && offset + SAT_HDR_LEN <= (size_t)raw->len; i++) {
+ uint8_t sys_id = U1(raw, offset);
+ int sys = anpp2sys(sys_id);
+ int sat = satno(sys, U1(raw, offset + 1));
+ uint8_t nfreqs = U1(raw, offset + 5);
+ offset += SAT_HDR_LEN;
+
+ if (sat == 0) {
+ offset += nfreqs * FREQ_BLK_LEN;
+ continue;
+ }
+ int n = obuf_slot(raw, raw->time, sat);
+ if (n < 0) {
+ offset += nfreqs * FREQ_BLK_LEN;
+ continue;
+ }
+
+ for (; nfreqs > 0 && offset + FREQ_BLK_LEN <= (size_t)raw->len;
+ nfreqs--, offset += FREQ_BLK_LEN) {
+ uint8_t freq_id = U1(raw, offset);
+ uint8_t trks = U1(raw, offset + 1);
+ uint8_t code = anpp2code(sys_id, freq_id);
+ if (code == CODE_NONE) continue;
+ int idx = code2idx(sys, code);
+ if (idx < 0 || idx >= NFREQ + NEXOBS) continue;
+
+ if (trks & TRKS_CARRIER) {
+ raw->obuf.data[n].L[idx] = R8(raw, offset + 2);
+ raw->obuf.data[n].LLI[idx] = (trks & TRKS_SLIP) ? LLI_SLIP : 0;
+ raw->obuf.data[n].LLI[idx] |= (trks & TRKS_HALFCYCLE) ? LLI_HALFC : 0;
+ }
+ if (trks & TRKS_PSEUDORANGE) raw->obuf.data[n].P[idx] = R8(raw, offset + 10);
+ if (trks & TRKS_DOPPLER) raw->obuf.data[n].D[idx] = R4(raw, offset + 18);
+ if (trks & TRKS_SNR) raw->obuf.data[n].SNR[idx] = R4(raw, offset + 22);
+
+ raw->obuf.data[n].code[idx] = code;
+ }
+ }
+
+ /* flush when the final fragment of this epoch arrives */
+ if (packet_number == total_packets) {
+ ret = flush_obuf_anpp(raw);
+ anpp->epoch_active = 0;
+ }
+ return ret;
+}
+
+/* packet 61: raw satellite ephemeris ----------------------------------------*/
+static int decode_gps_eph(raw_t* raw, int sat, size_t e) {
+ eph_t eph = {0};
+ eph.sat = sat;
+ eph.iodc = (int)U2(raw, e + 4);
+ eph.iode = (int)U2(raw, e + 6);
+ eph.week = (int)U2(raw, e + 116);
+ eph.toes = (double)U4(raw, e + 0);
+ eph.toe = gpst2time(eph.week, eph.toes);
+ eph.toc = eph.toe;
+ eph.ttr = gpst2time(eph.week, (double)U4(raw, e + 118));
+ eph.f0 = (double)R4(raw, e + 8);
+ eph.f1 = (double)R4(raw, e + 12);
+ eph.f2 = (double)R4(raw, e + 16);
+ eph.crs = (double)R4(raw, e + 20);
+ eph.deln = (double)R4(raw, e + 24);
+ eph.M0 = R8(raw, e + 28);
+ eph.cuc = (double)R4(raw, e + 36);
+ eph.e = R8(raw, e + 40);
+ eph.cus = (double)R4(raw, e + 48);
+ double sqrtA = R8(raw, e + 52);
+ eph.A = sqrtA * sqrtA;
+ eph.cic = (double)R4(raw, e + 60);
+ eph.OMG0 = R8(raw, e + 64);
+ eph.cis = (double)R4(raw, e + 72);
+ eph.i0 = R8(raw, e + 76);
+ eph.crc = (double)R4(raw, e + 84);
+ eph.omg = R8(raw, e + 88);
+ eph.OMGd = R8(raw, e + 96);
+ eph.idot = R8(raw, e + 104);
+ eph.tgd[0] = (double)R4(raw, e + 112);
+ eph.sva = 0;
+ eph.svh = 0;
+ eph.code = 0;
+ eph.flag = 0;
+ eph.fit = 4.0;
+
+ if (eph.iode == raw->nav.eph[sat - 1].iode && eph.iodc == raw->nav.eph[sat - 1].iodc &&
+ fabs(timediff(eph.toe, raw->nav.eph[sat - 1].toe)) < 1e-9)
+ return 0;
+
+ raw->nav.eph[sat - 1] = eph;
+ raw->ephsat = sat;
+ raw->ephset = 0;
+ return 2;
+}
+
+static int decode_glo_eph(raw_t* raw, int prn, size_t e) {
+ geph_t geph = {0};
+ geph.sat = satno(SYS_GLO, prn);
+ geph.frq = (int)I1(raw, e + 85);
+ geph.svh = (int)U1(raw, e + 86);
+ geph.age = (int)U1(raw, e + 84);
+ geph.taun = (double)R4(raw, e + 0);
+ geph.gamn = (double)R4(raw, e + 4);
+ geph.pos[0] = R8(raw, e + 8);
+ geph.pos[1] = R8(raw, e + 16);
+ geph.pos[2] = R8(raw, e + 24);
+ geph.vel[0] = R8(raw, e + 32);
+ geph.vel[1] = R8(raw, e + 40);
+ geph.vel[2] = R8(raw, e + 48);
+ geph.acc[0] = R8(raw, e + 56);
+ geph.acc[1] = R8(raw, e + 64);
+ geph.acc[2] = R8(raw, e + 72);
+ gtime_t utc;
+ utc.time = (time_t)U4(raw, e + 80);
+ utc.sec = 0.0;
+ geph.toe = utc2gpst(utc);
+ geph.tof = geph.toe;
+
+ if (geph.svh == raw->nav.geph[prn - 1].svh &&
+ fabs(timediff(geph.toe, raw->nav.geph[prn - 1].toe)) < 1e-9)
+ return 0;
+
+ raw->nav.geph[prn - 1] = geph;
+ raw->ephsat = geph.sat;
+ raw->ephset = 0;
+ return 2;
+}
+
+static int decode_rawsateph(raw_t* raw) {
+ uint8_t sys_id = U1(raw, HDR_LEN + 4);
+ int sys = anpp2sys(sys_id);
+ int prn = (int)U1(raw, HDR_LEN + 5);
+ int sat = satno(sys, prn);
+ if (sat == 0) return 0;
+
+ switch (sys) {
+ case SYS_GPS:
+ if (raw->len < HDR_LEN + EPH_LEN_GPS) {
+ trace(2, "decode_rawsateph GPS: short packet len=%d\n", raw->len);
+ return 0;
+ }
+ return decode_gps_eph(raw, sat, HDR_LEN + 6);
+ case SYS_GLO:
+ if (raw->len < HDR_LEN + EPH_LEN_GLO) {
+ trace(2, "decode_rawsateph GLO: short packet len=%d\n", raw->len);
+ return 0;
+ }
+ return decode_glo_eph(raw, prn, HDR_LEN + 6);
+ default:
+ trace(2, "decode_rawsateph: unsupported sys=%d\n", sys_id);
+ return 0;
+ }
+}
+
+/* sync, dispatch, public API ------------------------------------------------*/
+static uint16_t crc_ccitt(const uint8_t* buff, int len) {
+ uint16_t crc = 0xFFFF;
+ for (int i = 0; i < len; i++) {
+ crc ^= (uint16_t)buff[i] << 8;
+ for (int j = 0; j < 8; j++) {
+ crc = (crc & 0x8000) ? (crc << 1) ^ 0x1021 : crc << 1;
+ }
+ }
+ return crc;
+}
+
+static int valid_hdr(const raw_t* raw) {
+ return ((U1(raw, 0) + U1(raw, 1) + U1(raw, 2) + U1(raw, 3) + U1(raw, 4)) & 0xFF) == 0;
+}
+
+static int decode_anpp(raw_t* raw) {
+ int id = (int)U1(raw, 1);
+
+ trace(4, "decode_anpp: id=%d len=%d\n", id, raw->len);
+
+ switch (id) {
+ case ID_SYSTEMSTATE:
+ return decode_systemstate(raw);
+ case ID_UNIXTIME:
+ return decode_unixtime(raw);
+ case ID_RAWSATDATA:
+ return decode_rawsatdata(raw);
+ case ID_RAWSATEPH:
+ return decode_rawsateph(raw);
+ }
+ return 0;
+}
+
+extern int input_anpp(raw_t* raw, uint8_t data) {
+ RTKBOUNDSCHECK(raw->buff, sizeof(raw->buff), raw->nbyte);
+ raw->buff[raw->nbyte] = data;
+ raw->nbyte++;
+
+ if (raw->nbyte < HDR_LEN) return 0;
+
+ if (raw->nbyte == HDR_LEN) {
+ raw->len = HDR_LEN;
+ if (!valid_hdr(raw)) {
+ memmove(raw->buff, raw->buff + 1, HDR_LEN - 1);
+ raw->nbyte = raw->len = HDR_LEN - 1;
+ return 0;
+ }
+ raw->len = HDR_LEN + (int)U1(raw, 2);
+ if (raw->len > MAXRAWLEN) {
+ trace(2, "adnav length error: len=%d\n", raw->len);
+ raw->nbyte = raw->len = 0;
+ return -1;
+ }
+ }
+
+ if (raw->nbyte < raw->len) return 0;
+ raw->nbyte = 0;
+
+ if (crc_ccitt(raw->buff + HDR_LEN, raw->len - HDR_LEN) != U2(raw, 3)) {
+ trace(2, "input_anpp: CRC error id=%d\n", (int)raw->buff[1]);
+ raw->nbyte = raw->len = 0;
+ return -1;
+ }
+ return decode_anpp(raw);
+}
+
+extern int input_anppf(raw_t* raw, FILE* fp) {
+ trace(4, "input_anppf:\n");
+
+ for (int i = 0; i < 4096; i++) {
+ int data = fgetc(fp);
+ if (data == EOF) return -2;
+ int ret = input_anpp(raw, (uint8_t)data);
+ if (ret != 0) return ret;
+ }
+ return 0;
+}
diff --git a/src/rcvraw.c b/src/rcvraw.c
index 512040e3f..76e54f012 100644
--- a/src/rcvraw.c
+++ b/src/rcvraw.c
@@ -1382,6 +1382,7 @@ extern int init_raw(raw_t *raw, int format)
/* initialize receiver dependent data */
raw->format=format;
switch (format) {
+ case STRFMT_ANPP: ret=init_anpp(raw); break;
case STRFMT_RT17: ret=init_rt17(raw); break;
case STRFMT_SEPT: ret=init_sbf(raw); break;
}
@@ -1409,6 +1410,7 @@ extern void free_raw(raw_t *raw)
/* free receiver dependent data */
switch (raw->format) {
+ case STRFMT_ANPP: free_anpp(raw); break;
case STRFMT_RT17: free_rt17(raw); break;
case STRFMT_SEPT: free_sbf(raw); break;
}
@@ -1441,6 +1443,7 @@ extern int input_raw(raw_t *raw, int format, uint8_t data)
case STRFMT_SEPT : return input_sbf (raw,data);
/*case STRFMT_TERSUS: return input_tersus(raw,data);*/
case STRFMT_UNICORE : return input_unicore (raw,data);
+ case STRFMT_ANPP : return input_anpp (raw,data);
}
return 0;
}
@@ -1467,8 +1470,9 @@ extern int input_rawf(raw_t *raw, int format, FILE *fp)
case STRFMT_BINEX: return input_bnxf (raw,fp);
case STRFMT_RT17 : return input_rt17f (raw,fp);
case STRFMT_SEPT : return input_sbff (raw,fp);
- /*case STRFMT_TERSUS: return input_tersusf(raw,fp); */
+ /*case STRFMT_TERSUS: return input_tersusf (raw,fp); */
case STRFMT_UNICORE : return input_unicoref (raw,fp);
+ case STRFMT_ANPP : return input_anppf (raw,fp);
}
return -2;
}
diff --git a/src/rtkcmn.c b/src/rtkcmn.c
index bb4ac760c..349d722bd 100644
--- a/src/rtkcmn.c
+++ b/src/rtkcmn.c
@@ -247,11 +247,12 @@ const char *formatstrs[32]={ /* stream format strings */
"Septentrio SBF", /* 12 */
"------", /* 13 Tersus currently not supported */
"Unicore", /* 14 */
- "RINEX", /* 15 */
- "SP3", /* 16 */
- "RINEX CLK", /* 17 */
- "SBAS", /* 18 */
- "NMEA 0183", /* 19 */
+ "Adv. Nav. ANPP", /* 15 */
+ "RINEX", /* 16 */
+ "SP3", /* 17 */
+ "RINEX CLK", /* 18 */
+ "SBAS", /* 19 */
+ "NMEA 0183", /* 20 */
NULL
};
@@ -389,6 +390,24 @@ extern void add_fatal(fatalfunc_t *func)
{
fatalfunc=func;
}
+/* check indices within bounds -------------------------------------------------
+* Check that the index is within the buffer, generating a fatal error if not.
+* See the macro RTKBOUNDSCHECK()
+* args : const char *func I name of caller performing check
+* int line I line number
+* const void *buff I buffer to check against
+* size_t size I size of the buffer in bytes
+* size_t index I index to check; when checking against a byte
+* size, this is the index of the last byte to
+* be accessed
+*-----------------------------------------------------------------------------*/
+extern void rtkboundscheck(const char *func, int line, const void *buff, size_t size, size_t index) {
+ if (index >= size) {
+ fatalerr("rtk out of bound in %s line %d for buffer %p of size %zu at index %zu\n",
+ func, line, buff, size, index);
+ }
+}
+
/* satellite system+prn/slot number to satellite number ------------------------
* convert satellite system+prn/slot number to satellite number
* args : int sys I satellite system (SYS_GPS,SYS_GLO,...)
diff --git a/src/rtklib.h b/src/rtklib.h
index 2d3093453..5f941d44d 100644
--- a/src/rtklib.h
+++ b/src/rtklib.h
@@ -328,7 +328,7 @@ extern "C" {
#define CODE_L1B 11 /* obs code: E1B (GAL) */
#define CODE_L1X 12 /* obs code: E1B+C,L1C(D+P),B1D+P (GAL,QZS,BDS) */
#define CODE_L1Z 13 /* obs code: E1A+B+C,L1S (GAL,QZS) */
-#define CODE_L2C 14 /* obs code: L2C/A,G1C/A (GPS,GLO) */
+#define CODE_L2C 14 /* obs code: L2C/A,G2C/A (GPS,GLO) */
#define CODE_L2D 15 /* obs code: L2 L1C/A-(P2-P1) (GPS) */
#define CODE_L2S 16 /* obs code: L2C(M) (GPS,QZS) */
#define CODE_L2L 17 /* obs code: L2C(L) (GPS,QZS) */
@@ -498,13 +498,14 @@ extern "C" {
#define STRFMT_SEPT 12 /* stream format: Septentrio */
/* Tersus currently not supported */
/* #define STRFMT_TERSUS 13 */ /* stream format: TERSUS */
-#define STRFMT_UNICORE 14 /* stream format: UNICORE */
-#define STRFMT_RINEX 15 /* stream format: RINEX */
-#define STRFMT_SP3 16 /* stream format: SP3 */
-#define STRFMT_RNXCLK 17 /* stream format: RINEX CLK */
-#define STRFMT_SBAS 18 /* stream format: SBAS messages */
-#define STRFMT_NMEA 19 /* stream format: NMEA 0183 */
-#define MAXRCVFMT 14 /* max number of receiver format */
+#define STRFMT_UNICORE 14 /* stream format: UNICORE */
+#define STRFMT_ANPP 15 /* stream format: Advanced Navigation ANPP */
+#define STRFMT_RINEX 16 /* stream format: RINEX */
+#define STRFMT_SP3 17 /* stream format: SP3 */
+#define STRFMT_RNXCLK 18 /* stream format: RINEX CLK */
+#define STRFMT_SBAS 19 /* stream format: SBAS messages */
+#define STRFMT_NMEA 20 /* stream format: NMEA 0183 */
+#define MAXRCVFMT STRFMT_ANPP /* number of raw receiver formats */
#define STR_MODE_R 0x1 /* stream mode: read */
#define STR_MODE_W 0x2 /* stream mode: write */
@@ -1564,6 +1565,10 @@ EXPORT void traceb_impl (int level, const uint8_t *p, int n);
#endif /* TRACE */
+/* correctness utility function ----------------------------------------------*/
+#define RTKBOUNDSCHECK(buff, size, index) rtkboundscheck(__func__, __LINE__, buff, size, index);
+EXPORT void rtkboundscheck(const char *func, int line, const void *buff, size_t size, size_t index);
+
/* platform dependent functions ----------------------------------------------*/
EXPORT int execcmd(const char *cmd);
EXPORT int expath (const char *path, char *paths[], int nmax);
@@ -1714,8 +1719,10 @@ EXPORT int input_rawf (raw_t *raw, int format, FILE *fp);
EXPORT int init_rt17 (raw_t *raw);
EXPORT int init_sbf (raw_t *raw);
+EXPORT int init_anpp (raw_t *raw);
EXPORT void free_rt17 (raw_t *raw);
EXPORT void free_sbf (raw_t *raw);
+EXPORT void free_anpp (raw_t *raw);
EXPORT int input_oem4 (raw_t *raw, uint8_t data);
EXPORT int input_cnav (raw_t *raw, uint8_t data);
@@ -1730,6 +1737,7 @@ EXPORT int input_rt17 (raw_t *raw, uint8_t data);
EXPORT int input_sbf (raw_t *raw, uint8_t data);
EXPORT int input_tersus(raw_t *raw, uint8_t data);
EXPORT int input_unicore(raw_t *raw, uint8_t data);
+EXPORT int input_anpp (raw_t *raw, uint8_t data);
EXPORT int input_oem4f (raw_t *raw, FILE *fp);
EXPORT int input_cnavf (raw_t *raw, FILE *fp);
EXPORT int input_ubxf (raw_t *raw, FILE *fp);
@@ -1743,6 +1751,7 @@ EXPORT int input_rt17f (raw_t *raw, FILE *fp);
EXPORT int input_sbff (raw_t *raw, FILE *fp);
EXPORT int input_tersusf(raw_t *raw, FILE *fp);
EXPORT int input_unicoref(raw_t *raw, FILE *fp);
+EXPORT int input_anppf (raw_t *raw, FILE *fp);
EXPORT int gen_ubx (const char *msg, uint8_t *buff);
EXPORT int gen_stq (const char *msg, uint8_t *buff);
diff --git a/src/src.pro b/src/src.pro
index 720560808..f57d7fa3a 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -78,7 +78,8 @@ SOURCES += rtkcmn.c \
rcv/skytraq.c \
rcv/swiftnav.c \
rcv/ublox.c \
- rcv/unicore.c
+ rcv/unicore.c \
+ rcv/adnav.c
HEADERS += rtklib.h