diff --git a/src/rcv/novatel.c b/src/rcv/novatel.c index 8dc2027404132c438479e82248687f278d9e38bb..2932a8b1c7d7a9fe6a2f45e9f1a35fe6fa60f368 100644 --- a/src/rcv/novatel.c +++ b/src/rcv/novatel.c @@ -10,6 +10,7 @@ * [3] NovAtel, OM-20000129 Rev2 OEM6 Family Firmware Reference Manual, 2011 * [4] NovAtel, OM-20000127 Rev1 OEMStar Firmware Reference Manual, 2009 * [5] NovAtel, OM-20000129 Rev6 OEM6 Family Firmware Reference Manual, 2014 +* [6] Novatel, OM-20000169 Rev15A OEM7 Commands and Logs Reference Manual, 2020 * * version : $Revision: 1.2 $ $Date: 2008/07/14 00:05:05 $ * history : 2007/10/08 1.0 new @@ -55,37 +56,39 @@ * output L2W instead of L2D for L2Pcodeless * test toc difference to output beidou ephemeris * 2019/05/10 1.17 save galileo E5b data to obs index 2 +* 2020/05/11 1.18 add OEM7 messages *-----------------------------------------------------------------------------*/ #include "rtklib.h" -#define OEM4SYNC1 0xAA /* oem4 message start sync code 1 */ -#define OEM4SYNC2 0x44 /* oem4 message start sync code 2 */ -#define OEM4SYNC3 0x12 /* oem4 message start sync code 3 */ +#define OEM4SYNC1 0xAA /* oem4 message start sync code 1 */ +#define OEM4SYNC2 0x44 /* oem4 message start sync code 2 */ +#define OEM4SYNC3 0x12 /* oem4 message start sync code 3 */ -#define OEM4HLEN 28 /* oem4 message header length (bytes) */ +#define OEM4HLEN 28 /* oem4 message header length (bytes) */ -#define ID_ALMANAC 73 /* message id: oem4 decoded almanac */ -#define ID_GLOALMANAC 718 /* message id: oem4 glonass decoded almanac */ -#define ID_GLOEPHEMERIS 723 /* message id: oem4 glonass ephemeris */ -#define ID_IONUTC 8 /* message id: oem4 iono and utc data */ -#define ID_RANGE 43 /* message id: oem4 range measurement */ -#define ID_RANGECMP 140 /* message id: oem4 range compressed */ -#define ID_RAWALM 74 /* message id: oem4 raw almanac */ -#define ID_RAWEPHEM 41 /* message id: oem4 raw ephemeris */ -#define ID_RAWWAASFRAME 287 /* message id: oem4 raw waas frame */ - -#define ID_QZSSIONUTC 1347 /* message id: oem6 qzss ion/utc parameters */ -#define ID_QZSSRAWEPHEM 1330 /* message id: oem6 qzss raw ephemeris */ -#define ID_QZSSRAWSUBFRAME 1331 /* message id: oem6 qzss raw subframe */ -#define ID_RAWSBASFRAME 973 /* message id: oem6 raw sbas frame */ -#define ID_GALEPHEMERIS 1122 /* message id: oem6 decoded galileo ephemeris */ -#define ID_GALALMANAC 1120 /* message id: oem6 decoded galileo almanac */ -#define ID_GALCLOCK 1121 /* message id: oem6 galileo clockinformation */ -#define ID_GALIONO 1127 /* message id: oem6 decoded galileo iono corrections */ -#define ID_GALFNAVRAWPAGE 1413 /* message id: oem6 raw galileo f/nav paga data */ -#define ID_GALINAVRAWWORD 1414 /* message id: oem6 raw galileo i/nav word data */ -#define ID_RAWCNAVFRAME 1066 /* message id: oem6 raw cnav frame data */ -#define ID_BDSEPHEMERIS 1696 /* message id: oem6 decoded bds ephemeris */ +#define ID_ALMANAC 73 /* message id: oem4 decoded almanac */ +#define ID_GLOALMANAC 718 /* message id: oem4 glonass decoded almanac */ +#define ID_GLOEPHEMERIS 723 /* message id: oem4 glonass ephemeris */ +#define ID_IONUTC 8 /* message id: oem4 iono and utc data */ +#define ID_RANGE 43 /* message id: oem4 range measurement */ +#define ID_RANGECMP 140 /* message id: oem4 range compressed */ +#define ID_RAWALM 74 /* message id: oem4 raw almanac */ +#define ID_RAWEPHEM 41 /* message id: oem4 raw ephemeris */ +#define ID_RAWWAASFRAME 287 /* message id: oem4 raw waas frame */ +#define ID_QZSSIONUTC 1347 /* message id: oem6 qzss ion/utc parameters */ +#define ID_QZSSRAWEPHEM 1330 /* message id: oem6 qzss raw ephemeris */ +#define ID_QZSSRAWSUBFRAME 1331 /* message id: oem6 qzss raw subframe */ +#define ID_RAWSBASFRAME 973 /* message id: oem6 raw sbas frame */ +#define ID_GALEPHEMERIS 1122 /* message id: oem6 decoded galileo ephemeris */ +#define ID_GALINAVEPHEMERIS 1309 /* message id: oem7 decoded galileo inav ephemeris */ +#define ID_GALFNAVEPHEMERIS 1310 /* message id: oem7 decoded galileo fnav ephemeris */ +#define ID_GALALMANAC 1120 /* message id: oem6 decoded galileo almanac */ +#define ID_GALCLOCK 1121 /* message id: oem6 galileo clockinformation */ +#define ID_GALIONO 1127 /* message id: oem6 decoded galileo iono corrections */ +#define ID_GALFNAVRAWPAGE 1413 /* message id: oem6 raw galileo f/nav paga data */ +#define ID_GALINAVRAWWORD 1414 /* message id: oem6 raw galileo i/nav word data */ +#define ID_RAWCNAVFRAME 1066 /* message id: oem6 raw cnav frame data */ +#define ID_BDSEPHEMERIS 1696 /* message id: oem6 decoded bds ephemeris */ #define WL1 0.1902936727984 #define WL2 0.2442102134246 @@ -787,6 +790,168 @@ static int decode_galephemerisb(raw_t *raw) raw->ephsat=eph.sat; return 2; } +/* decode INAV galephemerisb ------------------------------------------------------*/ +static int decode_galinavephemerisb(raw_t *raw) +{ + eph_t eph={0}; + unsigned char *p=raw->buff+OEM4HLEN; + double tow,sqrtA,tt; + char *msg; + int prn,svh_e1b,svh_e5b,dvs_e1b,dvs_e5b; + int toc_inav,week; + + trace(3,"decode_galephemerisb: len=%d\n",raw->len); + + if (raw->len<OEM4HLEN+184) { + trace(2,"oem7 galinavephemrisb length error: len=%d\n",raw->len); + return -1; + } + prn =U4(p); p+=4; + svh_e5b =U1(p)&3; p+=1; + dvs_e5b =U1(p)&1; p+=1+1+1; + svh_e1b =U1(p)&3; p+=1; + dvs_e1b =U1(p)&1; p+=1+1+1; + eph.iode =U2(p); p+=2; /* IODNav */ + eph.sva =U1(p); p+=1; /* SISA index */ + // inav source + p+=1; + // + eph.toes =U4(p); p+=4; + toc_inav =U4(p); p+=4; + eph.M0 =R8(p); p+=8; + eph.deln =R8(p); p+=8; + eph.e =R8(p); p+=8; + sqrtA =R8(p); p+=8; + eph.i0 =R8(p); p+=8; + eph.idot =R8(p); p+=8; + eph.OMG0 =R8(p); p+=8; + eph.omg =R8(p); p+=8; + eph.OMGd =R8(p); p+=8; + eph.cuc =R8(p); p+=8; + eph.cus =R8(p); p+=8; + eph.crc =R8(p); p+=8; + eph.crs =R8(p); p+=8; + eph.cic =R8(p); p+=8; + eph.cis =R8(p); p+=8; + eph.f0 =R8(p); p+=8; + eph.f1 =R8(p); p+=8; + eph.f2 =R8(p); p+=8; + eph.tgd[0]=R8(p); p+=8; /* BGD: E5A-E1 (s) */ + eph.tgd[1]=R8(p); /* BGD: E5B-E1 (s) */ + + eph.iodc =eph.iode; + eph.svh =(svh_e5b<<7)|(dvs_e5b<<6)|(svh_e1b<<1)|dvs_e1b; + eph.A =sqrtA*sqrtA; + + /* set data source defined in rinex 3.03 */ + eph.code=((1<<0)|(1<<9)); + + if (raw->outtype) { + msg=raw->msgtype+strlen(raw->msgtype); + sprintf(msg," prn=%3d iod=%3d toes=%6.0f",prn,eph.iode,eph.toes); + } + if (!(eph.sat=satno(SYS_GAL,prn))) { + trace(2,"oem7 galinavephemeris satellite error: prn=%d\n",prn); + return -1; + } + tow=time2gpst(raw->time,&week); + eph.week=week; /* gps-week = gal-week */ + eph.toe=gpst2time(eph.week,eph.toes); + + /* for week-handover problem */ + tt=timediff(eph.toe,raw->time); + if (tt<-302400.0) eph.week++; + else if (tt> 302400.0) eph.week--; + eph.toe=gpst2time(eph.week,eph.toes); + eph.toc=adjweek(eph.toe,toc_inav); + eph.ttr=adjweek(eph.toe,tow); + + if (!strstr(raw->opt,"-EPHALL")) { + if (raw->nav.eph[eph.sat-1].iode==eph.iode&& + raw->nav.eph[eph.sat-1].code==eph.code) return 0; /* unchanged */ + } + raw->nav.eph[eph.sat-1]=eph; + raw->ephsat=eph.sat; + return 2; +} +/* decode FNAV galephemerisb ------------------------------------------------------*/ +static int decode_galfnavephemerisb(raw_t *raw) +{ + eph_t eph={0}; + unsigned char *p=raw->buff+OEM4HLEN; + double tow,sqrtA,tt; + char *msg; + int prn,svh_e5a,dvs_e5a; + int toc_fnav,week; + + trace(3,"decode_galfnavephemerisb: len=%d\n",raw->len); + + if (raw->len<OEM4HLEN+172) { + trace(2,"oem7 galephemrisb length error: len=%d\n",raw->len); + return -1; + } + prn =U4(p); p+=4; + svh_e5a =U1(p)&3; p+=1; + dvs_e5a =U1(p)&1; p+=1+1+1; + eph.iode =U2(p); p+=2; /* IODNav */ + eph.sva =U1(p); p+=1+1; /* SISA index */ + eph.toes =U4(p); p+=4; + toc_fnav =U4(p); p+=4; + eph.M0 =R8(p); p+=8; + eph.deln =R8(p); p+=8; + eph.e =R8(p); p+=8; + sqrtA =R8(p); p+=8; + eph.i0 =R8(p); p+=8; + eph.idot =R8(p); p+=8; + eph.OMG0 =R8(p); p+=8; + eph.omg =R8(p); p+=8; + eph.OMGd =R8(p); p+=8; + eph.cuc =R8(p); p+=8; + eph.cus =R8(p); p+=8; + eph.crc =R8(p); p+=8; + eph.crs =R8(p); p+=8; + eph.cic =R8(p); p+=8; + eph.cis =R8(p); p+=8; + eph.f0 =R8(p); p+=8; + eph.f1 =R8(p); p+=8; + eph.f2 =R8(p); p+=8; + eph.tgd[0]=R8(p); + + eph.iodc =eph.iode; + eph.svh =(svh_e5a<<4)|(dvs_e5a<<3); + eph.A =sqrtA*sqrtA; + + /* set data source defined in rinex 3.03 */ + eph.code=((1<<1)|(1<<8)); + + if (raw->outtype) { + msg=raw->msgtype+strlen(raw->msgtype); + sprintf(msg," prn=%3d iod=%3d toes=%6.0f",prn,eph.iode,eph.toes); + } + if (!(eph.sat=satno(SYS_GAL,prn))) { + trace(2,"oemv galephemeris satellite error: prn=%d\n",prn); + return -1; + } + tow=time2gpst(raw->time,&week); + eph.week=week; /* gps-week = gal-week */ + eph.toe=gpst2time(eph.week,eph.toes); + + /* for week-handover problem */ + tt=timediff(eph.toe,raw->time); + if (tt<-302400.0) eph.week++; + else if (tt> 302400.0) eph.week--; + eph.toe=gpst2time(eph.week,eph.toes); + eph.toc=adjweek(eph.toe,toc_fnav); + eph.ttr=adjweek(eph.toe,tow); + + if (!strstr(raw->opt,"-EPHALL")) { + if (raw->nav.eph[eph.sat-1].iode==eph.iode&& + raw->nav.eph[eph.sat-1].code==eph.code) return 0; /* unchanged */ + } + raw->nav.eph[eph.sat-1]=eph; + raw->ephsat=eph.sat; + return 2; +} /* decode galalmanacb --------------------------------------------------------*/ static int decode_galalmanacb(raw_t *raw) { @@ -1084,6 +1249,8 @@ static int decode_oem4(raw_t *raw) case ID_QZSSRAWSUBFRAME: return decode_qzssrawsubframeb(raw); case ID_QZSSIONUTC : return decode_qzssionutcb (raw); case ID_GALEPHEMERIS : return decode_galephemerisb (raw); + case ID_GALINAVEPHEMERIS : return decode_galinavephemerisb (raw); + case ID_GALFNAVEPHEMERIS : return decode_galfnavephemerisb (raw); case ID_GALALMANAC : return decode_galalmanacb (raw); case ID_GALCLOCK : return decode_galclockb (raw); case ID_GALIONO : return decode_galionob (raw);