diff --git a/RTKBASE/lib/rtklib/src/convgpx.c b/RTKBASE/lib/rtklib/src/convgpx.c deleted file mode 100644 index 79332af..0000000 --- a/RTKBASE/lib/rtklib/src/convgpx.c +++ /dev/null @@ -1,175 +0,0 @@ -/*------------------------------------------------------------------------------ -* convgpx.c : gpx converter -* -* Copyright (C) 2016 by T.TAKASU, All rights reserved. -* -* references : -* [1] GPX The GPS Exchange Format http://www.topografix.com/gpx.asp -* -* version : $Revision:$ $Date:$ -* history : 2016/06/11 1.0 new -* 2016/09/18 1.1 modify labels according GPX specs -*-----------------------------------------------------------------------------*/ -#include "rtklib.h" - -/* constants -----------------------------------------------------------------*/ - -#define HEADXML "\n" -#define HEADGPX "\n" -#define TAILGPX "" - -static const char *XMLNS="http://www.topografix.com/GPX/1/1"; - -/* output waypoint -----------------------------------------------------------*/ -static void outpoint(FILE *fp, gtime_t time, const double *pos, - const char *label, int stat, int outalt, int outtime) -{ - /* fix, float, sbas and ppp are rtklib extentions to GPX */ - const char *fix_label[]={"fix","float","sbas","dgps","3d","ppp"}; - double ep[6]; - - fprintf(fp,"\n",pos[0]*R2D,pos[1]*R2D); - if (outalt) { - fprintf(fp," %.4f\n",pos[2]-(outalt==2?geoidh(pos):0.0)); - } - if (outtime) { - if (outtime==2) time=gpst2utc(time); - else if (outtime==3) time=timeadd(gpst2utc(time),9*3600.0); - time2epoch(time,ep); - fprintf(fp," \n", - ep[0],ep[1],ep[2],ep[3],ep[4],ep[5]); - } - if (outalt==2) { - fprintf(fp," %.4f\n",geoidh(pos)); - } - if (stat>=1&&stat<=6) { - fprintf(fp," %s\n",fix_label[stat-1]); - } - if (*label) { - fprintf(fp," %s\n",label); - } - fprintf(fp,"\n"); -} -/* output track --------------------------------------------------------------*/ -static void outtrack(FILE *fp, const solbuf_t *solbuf, int outalt, int outtime) -{ - gtime_t time; - double pos[3],ep[6]; - int i; - - fprintf(fp,"\n"); - fprintf(fp," \n"); - for (i=0;in;i++) { - ecef2pos(solbuf->data[i].rr,pos); - fprintf(fp," \n",pos[0]*R2D, - pos[1]*R2D); - if (outalt) { - fprintf(fp," %.4f\n",pos[2]-(outalt==2?geoidh(pos):0.0)); - } - if (outtime) { - time=solbuf->data[i].time; - if (outtime==2) time=gpst2utc(time); - else if (outtime==3) time=timeadd(gpst2utc(time),9*3600.0); - time2epoch(time,ep); - fprintf(fp," \n", - ep[0],ep[1],ep[2],ep[3],ep[4],ep[5]); - } - if (outalt==2) { - fprintf(fp," %.4f\n",geoidh(pos)); - } - fprintf(fp," \n"); - } - fprintf(fp," \n"); - fprintf(fp,"\n"); -} -/* save gpx file -------------------------------------------------------------*/ -static int savegpx(const char *file, const solbuf_t *solbuf, int outtrk, - int outpnt, int outalt, int outtime) -{ - FILE *fp; - double pos[3]; - int i; - - if (!(fp=fopen(file,"w"))) { - fprintf(stderr,"file open error : %s\n",file); - return 0; - } - fprintf(fp,HEADXML); - fprintf(fp,HEADGPX,"RTKLIB " VER_RTKLIB,XMLNS); - - /* output waypoint */ - if (outpnt) { - for (i=0;in;i++) { - ecef2pos(solbuf->data[i].rr,pos); - outpoint(fp,solbuf->data[i].time,pos,"",solbuf->data[i].stat,outalt, - outtime); - } - } - /* output waypoint of ref position */ - if (norm(solbuf->rb,3)>0.0) { - ecef2pos(solbuf->rb,pos); - outpoint(fp,solbuf->data[0].time,pos,"Reference Position",0,outalt,0); - } - /* output track */ - if (outtrk) { - outtrack(fp,solbuf,outalt,outtime); - } - fprintf(fp,"%s\n",TAILGPX); - fclose(fp); - return 1; -} -/* convert to GPX file --------------------------------------------------------- -* convert solutions to GPX file [1] -* args : char *infile I input solutions file -* char *outfile I output google earth kml file ("":.kml) -* gtime_t ts,te I start/end time (gpst) -* int tint I time interval (s) (0.0:all) -* int qflg I quality flag (0:all) -* double *offset I add offset {east,north,up} (m) -* int outtrk I output track (0:off,1:on) -* int outpnt I output waypoint (0:off,1:on) -* int outalt I output altitude (0:off,1:elipsoidal,2:geodetic) -* int outtime I output time (0:off,1:gpst,2:utc,3:jst) -* return : status (0:ok,-1:file read,-2:file format,-3:no data,-4:file write) -*-----------------------------------------------------------------------------*/ -extern int convgpx(const char *infile, const char *outfile, gtime_t ts, - gtime_t te, double tint, int qflg, double *offset, - int outtrk, int outpnt, int outalt, int outtime) -{ - solbuf_t solbuf={0}; - double rr[3]={0},pos[3],dr[3]; - int i,j; - char *p,file[1024]; - - trace(3,"convgpx : infile=%s outfile=%s\n",infile,outfile); - - if (!*outfile) { - if ((p=strrchr(infile,'.'))) { - strncpy(file,infile,p-infile); - strcpy(file+(p-infile),".gpx"); - } - else sprintf(file,"%s.gpx",infile); - } - else strcpy(file,outfile); - - /* read solution file */ - if (!readsolt((char **)&infile,1,ts,te,tint,qflg,&solbuf)) return -1; - - /* mean position */ - for (i=0;i<3;i++) { - for (j=0;j0.0) { - for (i=0;i<3;i++) solbuf.rb[i]+=dr[i]; - } - /* save gpx file */ - return savegpx(file,&solbuf,outtrk,outpnt,outalt,outtime)?0:-4; -} - diff --git a/RTKBASE/lib/rtklib/src/gis.c b/RTKBASE/lib/rtklib/src/gis.c deleted file mode 100644 index f981de5..0000000 --- a/RTKBASE/lib/rtklib/src/gis.c +++ /dev/null @@ -1,383 +0,0 @@ -/*------------------------------------------------------------------------------ -* gis.c: GIS data functions -* -* Copyright (C) 2016 by T.TAKASU, All rights reserved. -* -* references: -* [1] ESRI Shapefile Technical Description, An ESRI White Paper, July, 1998 -* -* version : $Revision:$ $Date:$ -* history : 2016/06/10 1.0 new -* 2016/07/31 1.1 add boundary of polyline and polygon -*-----------------------------------------------------------------------------*/ -#include "rtklib.h" - -static const char rcsid[]="$Id:$"; - -#define SHAPE_CODE 9994 /* shapefile code */ - -/* get integer big-endian ----------------------------------------------------*/ -static int I4_B(unsigned char *buff) -{ - int i,val=0; - unsigned char *p=buff,*q=(unsigned char *)&val+3; - - for (i=0;i<4;i++) { - *q--=*p++; - } - return val; -} -/* get integer little-endian -------------------------------------------------*/ -static int I4_L(unsigned char *buff) -{ - int val; - - memcpy(&val,buff,4); - return val; -} -/* get double little-endian --------------------------------------------------*/ -static double D8_L(unsigned char *buff) -{ - double val; - - memcpy(&val,buff,8); - return val; -} -/* read shapefile header -----------------------------------------------------*/ -static int read_shape_head(FILE *fp) -{ - unsigned char buff[128]; - - if (fread(buff,100,1,fp)!=1) { - return -1; - } - if (I4_B(buff)!=SHAPE_CODE) { - return -1; - } - return I4_L(buff+32); -} -/* initialize boundary -------------------------------------------------------*/ -static void init_bound(double *bound) -{ - bound[0]= PI/2.0; - bound[1]=-PI/2.0; - bound[2]= PI; - bound[3]=-PI; -} -/* update boundary -----------------------------------------------------------*/ -static void update_bound(const double *pos, double *bound) -{ - if (pos[0]bound[1]) bound[1]=pos[0]; - if (pos[1]bound[3]) bound[3]=pos[1]; -} -/* add gis data --------------------------------------------------------------*/ -static int gis_add(gisd_t **p, int type, void *data) -{ - gisd_t *new_data; - - if (!(new_data=(gisd_t *)malloc(sizeof(gisd_t)))) { - return 0; - } - new_data->next=*p; - new_data->type=type; - new_data->data=data; - *p=new_data; - return 1; -} -/* read point data -----------------------------------------------------------*/ -static int read_pnt(FILE *fp, double *bound, gisd_t **p) -{ - gis_pnt_t *pnt; - double pos[3]={0}; - unsigned char buff[16]; - - if (fread(buff,16,1,fp)!=1) { - return 0; - } - if (!(pnt=(gis_pnt_t *)malloc(sizeof(gis_pnt_t)))) { - return 0; - } - pos[0]=D8_L(buff+8)*D2R; - pos[1]=D8_L(buff )*D2R; - update_bound(pos,bound); - pos2ecef(pos,pnt->pos); - - return gis_add(p,1,pnt); -} -/* read multi-point data ------------------------------------------------------*/ -static int read_mpnt(FILE *fp, double *bound, gisd_t **p) -{ - unsigned char buff[36]; - int i,np; - - if (fread(buff,36,1,fp)!=1) { - return 0; - } - np=I4_L(buff+32); - - for (i=0;ipos=(double *)malloc(sizeof(double)*nr*3))) { - free(poly); - free(part); - return 0; - } - init_bound(poly->bound); - - for (j=n=0;jpos); - free(poly); - free(part); - return 0; - } - pos[0]=D8_L(buff+8)*D2R; - pos[1]=D8_L(buff )*D2R; - if (pos[0]<-1E16||pos[1]<-1E16) { - continue; - } - update_bound(pos,poly->bound); - update_bound(pos,bound); - pos2ecef(pos,poly->pos+n*3); - n++; - } - poly->npnt=n; - if (!gis_add(p,2,(void *)poly)) { - free(poly->pos); - free(poly); - free(part); - return 0; - } - } - free(part); - return 1; -} -/* read polygon data ---------------------------------------------------------*/ -static int read_polygon(FILE *fp, double *bound, gisd_t **p) -{ - gis_polygon_t *polygon; - double pos[3]={0}; - unsigned char buff[40]; - int i,j,nt,np,nr,n,*part; - - if (fread(buff,40,1,fp)!=1) { - return 0; - } - nt=I4_L(buff+32); - np=I4_L(buff+36); - - if (!(part=(int *)malloc(sizeof(int)*nt))) { - return 0; - } - for (i=0;ipos=(double *)malloc(sizeof(double)*nr*3))) { - free(polygon); - free(part); - return 0; - } - init_bound(polygon->bound); - - for (j=n=0;jpos); - free(polygon); - free(part); - return 0; - } - pos[0]=D8_L(buff+8)*D2R; - pos[1]=D8_L(buff )*D2R; - if (pos[0]<-1E16||pos[1]<-1E16) { - continue; - } - update_bound(pos,polygon->bound); - update_bound(pos,bound); - pos2ecef(pos,polygon->pos+n*3); - n++; - } - polygon->npnt=n; - if (!gis_add(p,3,(void *)polygon)) { - free(polygon->pos); - free(polygon); - free(part); - return 0; - } - } - free(part); - return 1; -} -/* read shapefile records ----------------------------------------------------*/ -static int gis_read_record(FILE *fp, FILE *fp_idx, int type, double *bound, - gisd_t **data) -{ - gisd_t *p,*next; - unsigned char buff[16]; - int i,off,num,len1,len2,typ2; - - for (i=0;fread(buff,1,8,fp_idx)==8;i++) { - off =I4_B(buff )*2; - len1=I4_B(buff+4)*2; - - if (fseek(fp,(long)off,SEEK_SET)<0||fread(buff,12,1,fp)!=1) { - return 0; - } - num =I4_B(buff ); - len2=I4_B(buff+4)*2; - typ2=I4_L(buff+8); - - if (num!=i+1||len1!=len2||type!=typ2) { - trace(2,"shapefile record error n=%d %d len=%d %d type=%d %d\n", - i+1,num,len1,len2,type,typ2); - continue; - } - if (type==1) { /* point */ - read_pnt(fp,bound,data); - } - else if (type==8) { /* multi-point */ - read_mpnt(fp,bound,data); - } - else if (type==3) { /* polyline */ - read_poly(fp,bound,data); - } - else if (type==5) { /* polygon */ - read_polygon(fp,bound,data); - } - else { /* skip record */ - for (i=0;inext; - p->next=*data; - *data=p; - } - return 1; -} -/* read gis data from shapefile ------------------------------------------------ -* read gis data from shapefile (ref [1]) -* args : char *file I shapefile -* gis_t *gis IO GIS data -* return : status (0:error) -* notes : only support point, multipoint, polyline and polygon. -* only support lat-lon for map projection. -*-----------------------------------------------------------------------------*/ -extern int gis_read(const char *file, gis_t *gis, int layer) -{ - FILE *fp,*fp_idx; - char path[1024],*p,*q; - int type1=0,type2=0; - - trace(3,"gis_read file=%s layer=%d\n",file,layer); - - strcpy(path,file); - - if ((p=strrchr(path,'.'))) { - sprintf(p,".shx"); - } - else { - sprintf(path+strlen(path),".shx"); - } - if (!(fp=fopen(file,"rb"))) { /* shapefile */ - trace(2,"shapefile open error: %s\n",file); - return 0; - } - if (!(fp_idx=fopen(path,"rb"))) { /* index file */ - fclose(fp); - trace(2,"shapefile index open error: %s\n",path); - return 0; - } - /* read header */ - if ((type1=read_shape_head(fp))<0||(type2=read_shape_head(fp_idx))<0|| - type1!=type2) { - trace(2,"shapefile header error: %s type=%d %d\n",file,type1,type2); - fclose(fp); - fclose(fp_idx); - return 0; - } - init_bound(gis->bound); - - /* read records */ - if (!gis_read_record(fp,fp_idx,type1,gis->bound,gis->data+layer)) { - fclose(fp); - fclose(fp_idx); - return 0; - } - fclose(fp); - fclose(fp_idx); - gis->name[layer][0]='\0'; - gis->flag[layer]=1; - return 1; -} -/* free gis-data --------------------------------------------------------------- -* free and initialize gis data -* args : gis_t *gis IO gis data -* return : none -*-----------------------------------------------------------------------------*/ -extern void gis_free(gis_t *gis) -{ - gisd_t *data,*next; - int i; - - for (i=0;idata[i];data;data=next) { - next=data->next; - if (data->type==2) { - free(((gis_poly_t *)data->data)->pos); - } - else if (data->type==3) { - free(((gis_polygon_t *)data->data)->pos); - } - free(data); - } - gis->data[i]=NULL; - gis->name[i][0]='\0'; - gis->flag[i]=0; - } -} diff --git a/RTKBASE/lib/rtklib/src/ppp_corr.c b/RTKBASE/lib/rtklib/src/ppp_corr.c deleted file mode 100644 index f2c975d..0000000 --- a/RTKBASE/lib/rtklib/src/ppp_corr.c +++ /dev/null @@ -1,66 +0,0 @@ -/*------------------------------------------------------------------------------ -* ppp_corr.c : ppp corrections functions -* -* Copyright (C) 2015 by T.TAKASU, All rights reserved. -* -* version : $Revision:$ $Date:$ -* history : 2015/05/20 1.0 new -* 2016/05/10 1.1 delete codes -*-----------------------------------------------------------------------------*/ -#include "rtklib.h" - -static const char rcsid[]="$Id:$"; - -/* read ppp corrections -------------------------------------------------------- -* read ppp correction data from external file -* args : pppcorr_t *corr IO ppp correction data -* char *file I file -* return : status (1:ok,0:error) -* notes : file types are recognized by file extenstions as follows. -* .stat,.STAT : solution status file by rtklib -* .stec,.STEC : stec parameters file by mgest -* others : sinex troposphere file -* read data are added to ppp correction data. -* To clear data, call pppcorr_free() -*-----------------------------------------------------------------------------*/ -extern int pppcorr_read(pppcorr_t *corr, const char *file) -{ - return 0; -} -/* free ppp corrections -------------------------------------------------------- -* free and clear ppp correction data -* args : pppcorr_t *corr IO ppp correction data -* return : none -*-----------------------------------------------------------------------------*/ -extern void pppcorr_free(pppcorr_t *corr) -{ -} -/* get tropospheric correction ------------------------------------------------- -* get tropospheric correction from ppp correcion data -* args : pppcorr_t *corr I ppp correction data -* gtime_t time I time (GPST) -* double *pos I receiver position {lat,lon,heght} (rad,m) -* double *trp O tropos parameters {ztd,grade,gradn} (m) -* double *std O standard deviation (m) -* return : status (1:ok,0:error) -*-----------------------------------------------------------------------------*/ -extern int pppcorr_trop(const pppcorr_t *corr, gtime_t time, const double *pos, - double *trp, double *std) -{ - return 0; -} -/* get ionospherec correction -------------------------------------------------- -* get ionospheric correction from ppp correction data -* args : pppcorr_t *corr I ppp correction data -* gtime_t time I time (GPST) -* double *pos I receiver ecef position {x,y,z} (m) -* double *ion O L1 slant ionos delay for each sat (MAXSAT x 1) -* (ion[i]==0: no correction data) -* double *std O standard deviation (m) -* return : status (1:ok,0:error) -*-----------------------------------------------------------------------------*/ -extern int pppcorr_stec(const pppcorr_t *corr, gtime_t time, const double *pos, - double *ion, double *std) -{ - return 0; -} diff --git a/RTKBASE/lib/rtklib/src/rcv/cmr.c b/RTKBASE/lib/rtklib/src/rcv/cmr.c deleted file mode 100644 index e71b6ec..0000000 --- a/RTKBASE/lib/rtklib/src/rcv/cmr.c +++ /dev/null @@ -1,2781 +0,0 @@ -/*------------------------------------------------------------------------------ -* cmr.c : CMR dependent functions -* -* Copyright (C) 2016 Daniel A. Cook, All rights reserved. -* -* references: -* [1] https://github.com/astrodanco/RTKLIB/tree/cmr/src/cmr.c -* -* version : $Revision:$ $Date:$ -* history : 2016/07/15 1.0 imported from GitHub (ref [1]) -* 2016/07/16 1.3 modified by T.T -* raw->strfmt -> raw->format -* int free_cmr() -> void free_cmr() -* 2016/07/29 1.4 fix typo -* suppress warning -*-----------------------------------------------------------------------------*/ - -/* -| CMR protocol stream and file handler functions. -| -| Written in June 2016 by Daniel A. Cook, for inclusion into the RTKLIB library. -| Copyright (C) 2016 by Daniel A. Cook. All Rights Reserved. -| -| The Compact Measurement Record Format (CMR) is a de facto industry standard -| reference station data transmission protocol for RTK positioning. Despite -| the availability of practical alternatives such RTCM v3.1, CMR and CMR+ -| still remain de facto industry standards, especially in the US market. -| -| Here we implement five public functions, one for reading CMR format streams -| and another for reading CMR format files, a third to supply rover observations -| to the CMR base observations referencing engine and a fourth to initialize -| CMR related memory storage and a fifth to free up CMR related memory storage. -| -| Although a Trimble proprietary protocol, CMR was documented in reference #1 -| and CMR+ was documented in reference #2. These were then adopted by many -| other manufacurers in addition to Trimble. Leica extended the protocol to -| handle GLONASS observations and other manufacturers adopted Leica's extention, -| but there was apparently a disconnect with Trimble on how Trimble implemented -| the same extension making GLONASS compatibility between Trimble and non- -| Trimble receivers problematic whenever the CMR protocol is used. Note that -| so far as the author knows, Trimble never documented their own GLONASS -| extension to the protocol. It is not implemented here. -| -| RTCM3 should always be used whenever possible in lieu of CMR. Use CMR only -| when there is no other option. -| -| Receiver dependent options: -| -| -STA=nn - Set the base station ID to receive (0-31 for CMR). -| -| Notes: -| -| CMR message types 0, 1 and 2 are implemented as described by reference #1. -| -| CMR message type 3 (GLONASS) is implemented as described by reference #3, -| but I don't have suitable receivers with which to test and debug it. This -| message is the Leica (or rather non-Trimble since other manufacturers also -| output it) implementation of GLONASS base observations for CMR. -| -| CMR message type 4 is high speed CMR (5, 10, or 20 Hz). Support for this -| message is limited to utilizing the GPS L1 carrier phase observables -| contained therein. -| -| CMR+ message types 1, 2 and 3 are implemented. I have not yet been able -| to obtain reference #2 which presumably describes CMR+ in detail. -| -| Ag scrambled CMR+ (sCMR+) is not implemented. -| -| CMRW (message number 0x098) aka CMR-W is not implemented. -| -| CMRx (Compressed Measurement Record Extended) and sCMRx (scrambled CMRx) -| are patented (see the patents) therefore are absolutely positively not -| implemented! -| -| If you have a copy of reference #2, please be kind and send the author -| a copy. In fact if you have any technical information concerning any of -| the CMR family protocols the author would appreciate if you would share -| it with him. -| -| Both stream and file input of raw binary CMR base data are supported. -| -| Design notes: -| -| CMR messages increment ????[] -| CMR+ messages increment ????[] -| -| Note that because the L1 pseudorange is transmitted modulo one light -| millisecond, the base to rover distance must be less than 300 KM. -| CMR will not work at all beyond that distance. -| -| Note that CMR observables are not standalone. Before being utilized as -| base observations they must first be "referenced" to closely matching -| (in time) rover L1 pseudorange observables. Thus they are of little to -| no practical use in the absence of matching rover observations. -| -| CMR does not stream any almanac or ephemeris data. Only observations -| and reference station parameters. Ephemeris data must be obtained from -| the rover or from other sources. -| -| The time in the CMR header is relative rather than absolute. It is also -| ambiguous. It is GPS time in milliseconds modulo four minutes (240,000 -| milliseconds or 240 seconds). In a rover receiver this would be aligned -| based upon the rover's current GPS time. We do the same here. Absolute -| time comes from the rover observations. Note that with CMR message type -| 4 (high speed observations) the time is modulo four seconds (4000 milli- -| seconds). Also note that according to reference #3 the time in CMR type -| 3 messages is UTC time, not GPS or GLONASS time. We convert it to GPS time. -| -| This code was tested using CMR/CMR+ data output by the following receivers: -| -| 1. Trimble 4000SSI, firmware version 7.32 -| 2. Trimble 5700, firmware version 2.32 -| 3. Spectra Precision Epoch 25 Base, firmware version 2.32 -| -| For testing purposes one would normally use the Trimble GPS Configurator utility -| to configure the test receiver, but that utility does not understand all receiver -| features such as CMR 5Hz and 10Hz output. The Trimble WINPAN utility was used -| to configure CMR 5Hz and 10Hz output. -| -| For the purposes of this explaination the following terms mean the following things: -| -| C 299,792,458 One light second in meters. -| CMS C / 1000 One light millisecond in meters. -| L1F 1,574,420,000 L1 frequency in cycles per second. -| L2F 1,227,600,000 L2 frequency in cycles per second. -| L1W C / L1F L1 wavelength in meters. -| L2W C / L2F L2 wavelength in meters. -| -| L1P L1 pseudorange. -| L2P L2 pseudorange. -| L1L L1 carrier phase. -| L2L L2 carrier phase. -| -| BT Base time in millseconds. -| BTS Base time in seconds. -| BP1 Base L1 pseudorange in meters. -| BL1 Base L1 carrier phase in L1 cycles per second. -| BP2 Base L2 pseudorange in meters. -| BL2 Base L2 carrier phase in L2 cycles per second. -| -| CBS Base time in milliseconds modulo 240,000. -| CP1 Base L1 pseudorange modulo CMS in 1/8 L1 cycles. -| CL1 Base L1 carrier phase delta in 1/256 L1 cycles. -| CP2 Base L2 pseudorange delta in centimeters. -| CL2 Base L2 carrier phase delta in 1/256 L2 cycles. -| -| RTS Rover time in seconds. -| RP1 Rover L1 pseudorange in meters. -| -| UBS Base time in seconds modulo 240. -| UP1 Base L1 pseudorange in meters modulo CMS. -| UL1 Base L1 carrier phase delta in L1 cycles. -| UP2 Base L2 pseudorange delta in meters. -| UL2 Base L2 carrier phase delta in L2 cycles. -| -| CMR type 0 messaages contain the following GPS observables for each satellite: -| -| 1. CBS (actually just once in the message header) -| 2. CP1 8 * ((BP1 modulo CMS) / L1W) -| 3. CL1 256 * (BL1 - (BP1 / L1W)) -| 4. CP2 100 * (BP2 - BP1) -| 5. CL2 256 * (BL2 - (BP1 / L2W)) -| -| We temporarilly store them internally as "unreferenced" observables as follows: -| -| 1. UBS CBS * 0.001 Milliseconds to seconds. -| 2. UP1 CP1 / 8 * L1W 1/8 L1 cycles to meters. -| 3. UL1 CL1 / 256 1/256 L1 cycles to cycles. -| 4. UP2 CP2 / 100 Centimeters to meters. -| 5. UL2 CL2 / 256 1/256 L2 cycles to cycles. -| -| These above "unreferenced" observables are output by RTKCONV and CONVBIN -| because they have no rover data to reference. -| -| Before use as base observables the above unreferenced observables must be -| referenced to closely corresponding (in time) rover observables as follows: -| -| 1. BTS UBT + (RTS modulo 240) -| 2. BP1 UP1 + (RP1 - (RP1 modulo CMS)) -| 3. BL1 UL1 + (BP1 / L1W) -| 4. BP2 UP2 + BP1 -| 5. BL2 UL2 + (BP1 / L2W) -| -| Time in CMR type 0 messages is GPS time. -| -| CMR type 3 messages contain all the same information as CMR type 0 messages -| except that the carrier phase frequencies and wavelengths are those as for -| GLONASS. For GLONASS those things need to be looked up for every satellite -| and every signal. -| -| According to reference #3 the time in CMR type 3 messages is UTC time, not -| GPS time and not GLONASS time. We convert it to GPS time. -| -| CMR type 4 messages contain the following GPS observables for each satellite: -| -| 1. CBT (Actually just once in the messsage header and it's modulo 4000 instead of 240000.) -| 2. CL1 (But it's a delta against the prior CMR type 3 BL1 for this satellte.) -| -| CMR type 4 messages are only received with time represending the intervals -| between the seconds and never on an exact second. -| -| By convention functions within this source file appear in alphabetical order. -| Public functions appear as a set first (there are only three of them), followed -| by private functions as a set. Because of this, forward definitions are required -| for the private functions. Please keep that in mind when making changes to this -| source file. -| -| References: -| -| 1. Talbot, N.C., (1996), Compact Data Transmission Standard for -| High-Precision GPS, in: Proc. of the 9th International Technical -| Meeting of the Satellite Division of The Institute of Navigation, -| Kansas City, Missouri, USA, September, pp. 861-871. -| -| 2. Talbot, N.C., (1997), Improvements in the Compact Measurement -| Record Format, Trimble User?s Conference, San Jose, California, -| pp. 322-337 -| -| 3. A GLONASS Observation Message Compatible With The Compact -| Measurement Record Format, Leica Geosystems AG, -| -| -| 4. Trimble Serial Reference Specification, Version 4.82, Revision A, -| December 2013. Though not being in any way specific to the BD9xx -| family of receivers, a handy downloadable copy of this document -| is contained in the "Trimble OEM BD9xx GNSS Receiver Family ICD" -| document located at -| -| 5. RTKLIB Version 2.4.2 Manual, April 29 2013 -| -| -| 6. RTKLIB source code located at -*/ - -/* Included files: */ -#include "rtklib.h" - -#ifndef FALSE -#define FALSE (0) -#endif -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -/* General purpose flag bits masks: */ -#define M_BIT0 (1 << 0) -#define M_BIT1 (1 << 1) -#define M_BIT2 (1 << 2) -#define M_BIT3 (1 << 3) -#define M_BIT4 (1 << 4) -#define M_BIT5 (1 << 5) -#define M_BIT6 (1 << 6) -#define M_BIT7 (1 << 7) -#define M_BIT8 (1 << 8) -#define M_BIT9 (1 << 9) -#define M_BIT10 (1 << 10) -#define M_BIT11 (1 << 11) -#define M_BIT12 (1 << 12) -#define M_BIT13 (1 << 13) -#define M_BIT14 (1 << 14) -#define M_BIT15 (1 << 15) - -/* Misc. constant definitions: */ -#define CMR 0x93 /* Trimble CMR message number */ -#define CMRPLUS 0x94 /* Trimble CMR+ message number */ -#define STX 0x02 /* Start of message character */ -#define ETX 0x03 /* End of message character */ -#define BUFFER_LENGTH 512 /* CMR+ message buffer size */ -#define MESSAGEBUFFER_LENGTH 2048 /* Message buffer size */ - -/* CMR message types: */ -#define CMR_TYPE_0 0 /* GPS Observables */ -#define CMR_TYPE_1 1 /* ECEF Reference Station Coordinates */ -#define CMR_TYPE_2 2 /* Reference Station Description */ -#define CMR_TYPE_3 3 /* GLONASS Observables */ -#define CMR_TYPE_4 4 /* High Speed Observables */ - -/* CMR+ message types: */ -#define CMRPLUS_TYPE_1 1 /* Reference Station Information */ -#define CMRPLUS_TYPE_2 2 /* ECEF Reference Station Coordinates */ -#define CMRPLUS_TYPE_3 3 /* Reference Station Description */ - -/* Clock state constants: */ -#define CLOCK_OFFSET_INVALID 0 -#define CLOCK_OFFSET_VALID 3 - -/* Receiver status byte bit masks: */ -#define M_STATUS_LOW_MEMORY M_BIT0 /* 0 = Memory OK, 1 = Memory low */ -#define M_STATUS_LOW_BATTERY M_BIT1 /* 0 = Battery OK, 1 = Battery low */ -#define M_STATUS_RETURNTOPOINT M_BIT2 -#define M_STATUS_ROVING M_BIT3 /* 0 = Static base, 1 = Moving base */ -#define M_STATUS_CONTKIN M_BIT4 -#define M_STATUS_NEWBASE M_BIT5 -#define M_STATUS_SYNCED M_BIT6 -#define M_STATUS_RTKINITED M_BIT7 - -/* CMR type 1 and 2 flag bit masks: */ -#define M_CFLAG_RESERVED_01 M_BIT0 -#define M_CFLAG_L2ENABLE M_BIT1 /* L2 reception is enabled on the base */ -#define M_CFLAG_RESERVED_04 M_BIT2 -#define M_CFLAG_LOW_MEMORY M_BIT3 /* 0 = Memory OK, 1 = Memory low */ -#define M_CFLAG_LOW_BATTERY M_BIT4 /* 0 = Battery OK, 1 = Battery low */ - -/* CMR+ type 1 (Station Information) flag word bit masks: */ -#define M_PFLAG_UNKNOWN_0001 M_BIT0 -#define M_PFLAG_UNKNOWN_0002 M_BIT1 -#define M_PFLAG_UNKNOWN_0004 M_BIT2 -#define M_PFLAG_UNKNOWN_0008 M_BIT3 -#define M_PFLAG_BASE_MOTION (M_BIT4|M_BIT5) -#define BASE_MOTION_STATIC 1 -#define BASE_MOTION_KINEMATIC 2 -#define M_PFLAG_UNKNOWN_0040 M_BIT6 -#define M_PFLAG_UNKNOWN_0080 M_BIT7 -#define M_PFLAG_UNKNOWN_0100 M_BIT8 -#define M_PFLAG_L2ENABLE M_BIT9 /* L2 reception is enabled on the base */ -#define M_PFLAG_MAXWELL M_BIT10 /* Receiver uses a MAXWELL chipset */ -#define M_PFLAG_LOW_MEMORY M_BIT11 /* 0 = Memory OK, 1 = Memory low */ -#define M_PFLAG_LOW_BATTERY M_BIT12 /* 0 = Battery OK, 1 = Battery low */ -#define M_PFLAG_UNKNOWN_2000 M_BIT13 -#define M_PFLAG_UNKNOWN_4000 M_BIT14 -#define M_PFLAG_UNKNOWN_8000 M_BIT15 - -/* L1 observables flag bit masks: */ -#define M_L1_L2_FOLLOWS M_BIT0 /* L2 1 = L2 FOLLOWS, 0 = NO L2 */ -#define M_L1_PHASE_VALID M_BIT1 /* Ph 1 = VALID, 0 = INVALID */ -#define M_L1_PCODE M_BIT2 /* P/C 1 = L1P, 0 = L1C */ - -/* L2 observables flag bit masks: */ -#define M_L2_PHASE_FULL M_BIT0 /* (E) */ -#define M_L2_PHASE_VALID M_BIT1 /* (D) */ -#define M_L2_CODE_VALID M_BIT2 /* (C) */ -#define M_L2_WCODE M_BIT3 /* (B) GPS 0 = L2P, 1 = L2W */ -#define M_L2_PCODE M_BIT3 /* (B) GLONASS 0 = L2P, 1 = L2C */ -#define M_L2_CODE_AVAILABLE M_BIT4 /* (A) */ - -/* Special message flags bits: */ -#define M_MFLAG_LOWBATMSG1 M_BIT0 -#define M_MFLAG_LOWBATMSG2 M_BIT1 -#define M_MFLAG_LOWBATMSG3 M_BIT2 -#define M_MFLAG_LOWMEMMSG1 M_BIT3 -#define M_MFLAG_LOWMEMMSG2 M_BIT4 -#define M_MFLAG_LOWMEMMSG3 M_BIT5 -#define M_MFLAG_NOL2MSG1 M_BIT6 -#define M_MFLAG_NOL2MSG2 M_BIT7 - -/* Conversion factors: */ -#define L1_WAVELENGTH (CLIGHT/FREQ1) /* GPS L1 wavelength (meters) */ -#define L2_WAVELENGTH (CLIGHT/FREQ2) /* GPS L2 wavelength (meters) */ -#define RANGE_MS (CLIGHT*0.001) /* Meters per millisecond at light speed */ - -/* -| MAXTIMEDIFF is the maximum tolerable difference in seconds between the base -| and rover observation times. It must be set low enough so that the change in -| satellite range in meters over the time period in question can never exceed -| RANGE_MS. A quick rough back of the envelope calculation says anything over -| about 73 seconds for GPS or 75 seconds for GLONASS is too long. Incomming -| CMR base observables older than this are dropped. -*/ -#define MAXTIMEDIFF 60.0 /* Maximum tolerable time difference in seconds */ - -/* Utility macros: */ -#define SNRATIO(snr) (unsigned char)((snr<=0.0)||(snr>=255.5))?(0.0):((snr*4.0)+0.5) - -/* -| Typedefs: -*/ - -typedef struct { /* Antenna number to name table record */ - unsigned short Number; /* Antenna number */ - char *Name; /* Antenna name */ -} ant_t; - -typedef struct { /* Receiver number to name table record */ - unsigned short Number; /* Receiver number */ - char *Name; /* Receiver name */ -} rcv_t; - -typedef struct { /* Rover observations cache data record */ - gtime_t Time; /* Rover observation time */ - double P; /* Rover L1 pseudorange (meters) */ - unsigned char Valid; /* TRUE = Valid, FALSE = Invalid */ -} obsr_t; - -typedef struct { /* Base observables data record */ - double P[2]; /* L1/L2 pseudoranges (meters) */ - double L[2]; /* L1/L2 carrier-phases (cycles) */ - unsigned int Slot; /* Slot number */ - unsigned char Sat; /* Satellite number */ - unsigned char Code[2]; /* L1/L2 code indicators (CODE_???) */ - unsigned char SNR[2]; /* L1/L2 signal strengths */ - unsigned char Slip[2]; /* L1/L2 slip counts */ - unsigned char LLI[2]; /* L1/L2 loss of lock indicators */ -} obsbd_t; - -typedef struct { /* Base observables header record */ - gtime_t Time; /* Base observables time */ - int n; /* Number of observables */ - unsigned char Type; /* Observables type (0, 3, 4) */ - obsbd_t Data[MAXOBS]; /* Base observables data records */ -} obsb_t; - -typedef struct { /* CMR information struct type */ - unsigned char *Buffer; /* Buffer for building full CMR+ message from little parts */ - unsigned char *MessageBuffer; /* Message buffer */ - obsr_t *RoverObservables;/* Rover observables table */ - rtksvr_t *Svr; /* Pointer to RTK server structure (when running in that environment otherwise NULL) */ - obsbd_t *T4Data; /* Type 3 reference data for type 4 observables */ - unsigned int Flags; /* Miscellaneous internal flag bits */ - unsigned int CurrentMessages; /* Current base messages active */ - unsigned int PreviousMessages; /* Previous base messages active */ - unsigned int BufferBytes; /* Number of bytes of data in CMR+ message buffer */ - unsigned int MessageBytes; /* Number of bytes in message buffer */ - unsigned int MessageLength; /* Message Length */ - int Page; /* Previous page number added to CMR+ message mini-buffer */ - unsigned int StationID; /* Station ID */ - unsigned char SlipC[MAXSAT][2]; /* Slip counts */ - unsigned char SlipV[MAXSAT][2]; /* Slip counts valid indicator */ -} cmr_t; - -/* Static global literals: */ -static const char rcsid[]="$Id:$"; - -/* CMR 0x93 message types: */ -static const char *CMRTable[] = { - /* 0 */ "GPS Observables", - /* 1 */ "ECEF Reference Station Coordinates", - /* 2 */ "Reference Station Description", - /* 3 */ "GLONASS Observables", - /* 4 */ "High Speed GPS Observables" -}; - -/* CMR+ 0x94 message types: */ -static const char *CMRplusTable[] = { - /* 0 */ NULL, - /* 1 */ "Reference Station Information", - /* 2 */ "ECEF Reference Station Coordinates", - /* 3 */ "Reference Station Description" -}; - -/* -| CMR+ protocol defined antenna number to name lookup table. -| -| Note that this is not a table like the ones in igs08.atx or ngs_abs.pcv and -| cannot be replaced with nor derrived from the content of those files. -| -| Adapted from "c:\program files (x86)\common files\trimble\config\antenna.ini" -| after installing the latest Trimble Office Configuration File Update Utility -| found at -| For each antenna definition block in antenna.ini the "Type" keyword provides -| the number and the "IGSAntenna" keyword provides the antenna name. If no -| "IGSAntenna" keyword is present then the "Name" keyword provides the name. -| The comment is taken from the "Manufacturer" keyword followed by the "Name" -| keyword unless the name already contains the manufacturer name in which case -| the manufacturer name is not repeated. -| -| ### CMR+ MESSAGE TYPE 1 HAS ONLY A BYTE FOR THE ANTENNA NUMBER SO HOW CAN ### -| ### THEY POSSIBLY EXCEED 255? THERE MUST EITHER BE A NEW MESSAGE TYPE WE ### -| ### DON'T KNOW ABOUT OR A FLAG BIT THAT WE DON'T KNOW ABOUT, ETC. THAT ### -| ### EXTENDS THIS OTHERWISE SOMEONE DROPPED THE BALL... ### -*/ -static const ant_t AntennasTable[] = { -{ 0,"UNKNOWN_EXT NONE"}, /* Unknown External */ -{ 1,"TRM4000ST_INT NONE"}, /* Trimble 4000ST Internal */ -{ 2,"TRM14156.00-GP NONE"}, /* Trimble 4000ST Kinematic Ext. */ -{ 3,"TRM16741.00 NONE"}, /* Trimble Compact Dome */ -{ 4,"TRM14177.00 NONE"}, /* Trimble 4000ST L1 Geodetic */ -{ 5,"TRM14532.00 NONE"}, /* Trimble 4000SST/SSE L1/L2 Geodetic */ -{ 6,"TRM12562.00+SGP NONE"}, /* Trimble 4000SLD L1/L2 Square */ -{ 7,"TRM10877.10_H NONE"}, /* Trimble 4000SX Helical */ -{ 8,"TRM11877.10+SGP NONE"}, /* Trimble 4000SX Micro Square */ -{ 9,"TRM12333.00+RGP NONE"}, /* Trimble 4000SL Micro Round */ -{ 10,"TRM17200.00 NONE"}, /* Trimble 4000SE Attachable */ -{ 11,"TRM14532.10 NONE"}, /* Trimble 4000SSE Kin L1/L2 */ -{ 12,"TRM22020.00+GP NONE"}, /* Trimble Compact L1/L2 w/Ground Plane */ -{ 13,"TRM22020.00-GP NONE"}, /* Trimble Compact L1/L2 */ -{ 14,"TRM16741.00_RTK NONE"}, /* Trimble Compact Dome w/Init */ -{ 15,"TRM14532.10_RTK NONE"}, /* Trimble L1/L2 Kinematic w/Init */ -{ 16,"TRM22020.00_RTK NONE"}, /* Trimble Compact L1/L2 w/Init */ -{ 17,"TRM23965.00_RTK NONE"}, /* Trimble Compact L1 w/Init */ -{ 18,"TRM23965.00 NONE"}, /* Trimble Compact L1 w/Ground Plane */ -{ 19,"TRM23965.00-GP NONE"}, /* Trimble Compact L1 */ -{ 20,"TRM23903.00 NONE"}, /* Trimble Permanent L1/L2 */ -{ 21,"TRM4600LS NONE"}, /* Trimble 4600LS Internal */ -{ 22,"TRM12562.10+RGP NONE"}, /* Trimble 4000SLD L1/L2 Round */ -{ 23,"AOAD/M_T NONE"}, /* Dorne Margolin Model T */ -{ 24,"ASH700228A NONE"}, /* Ashtech L1/L2 (A-B) */ -{ 25,"ASH700936A_M NONE"}, /* Ashtech 700936A_M */ -{ 26,"LEISRX99+GP NONE"}, /* Leica SR299/SR399 External w/Ground Plane */ -{ 27,"TRM29659.00 NONE"}, /* Trimble Choke Ring */ -{ 28,"JPLD/M_R NONE"}, /* Dorne Margolin Model R */ -{ 29,"ASH700829.2 SNOW"}, /* Ashtech Geodetic III USCG w/Radome */ -{ 30,"TRM29653.00 NONE"}, /* Trimble Integrated GPS/Beacon */ -{ 31,"Mobile GPS Antenna"}, /* Trimble Mobile GPS Antenna */ -{ 32,"GeoExplorer Internal"}, /* Trimble GeoExplorer Internal */ -{ 33,"TOP72110 NONE"}, /* Topcon Turbo-SII */ -{ 34,"TRM22020.00+GP TCWD"}, /* Trimble Compact L1/L2 w/Ground Plane+Radome */ -{ 35,"TRM23903.00 TCWD"}, /* Trimble Permanent L1/L2 w/Radome */ -{ 36,"LEISRX99-GP NONE"}, /* Leica SR299/SR399 External */ -{ 37,"AOAD/M_B NONE"}, /* Dorne Margolin Model B */ -{ 38,"TRM4800 NONE"}, /* Trimble 4800 Internal */ -{ 39,"TRM33429.00-GP NONE"}, /* Trimble Micro-centered L1/L2 */ -{ 40,"TRM33429.00+GP NONE"}, /* Trimble Micro-centered L1/L2 w/Ground Plane */ -{ 41,"TRM33580.50 NONE"}, /* Trimble Integrated GPS/Beacon/Sat DGPS */ -{ 42,"TRM35143.00 NONE"}, /* Trimble AeroAntenna */ -{ 43,"TOP700779A NONE"}, /* Topcon Geodetic 3 Rev.D */ -{ 44,"ASH700718A NONE"}, /* Ashtech Geodetic III L1/L2 */ -{ 45,"ASH700936A_M SNOW"}, /* Ashtech Choke w/Radome */ -{ 46,"TOP700337 NONE"}, /* Topcon Geodetic 1 Rev.B */ -{ 47,"TRM36569.00+GP NONE"}, /* Trimble Rugged Micro-centered w/13Inch GP */ -{ 48,"GeoExplorer 3"}, /* Trimble GeoExplorer 3 */ -{ 49,"TRM33429.20+GP NONE"}, /* Trimble Micro-centered L1/L2 Permanent */ -{ 50,"TRM33429.20+GP TCWD"}, /* Trimble Micro-centered L1/L2 Permanent w/Radome */ -{ 51,"TRM27947.00-GP NONE"}, /* Trimble Rugged L1/L2 */ -{ 52,"TRM27947.00+GP NONE"}, /* Trimble Rugged L1/L2 w/Ground Plane */ -{ 53,"ASH701008.01B NONE"}, /* Ashtech Geodetic IIIA */ -{ 54,"ASH700228C NONE"}, /* Ashtech L1/L2, no Level (C) */ -{ 55,"ASH700228E NONE"}, /* Ashtech L1/L2, Rev. B (D-E) */ -{ 56,"ASH700700.A NONE"}, /* Ashtech Marine L1/L2 (A) */ -{ 57,"ASH700700.B NONE"}, /* Ashtech Marine L1/L2 (B) */ -{ 58,"JPSLEGANT_E NONE"}, /* Javad Positioning Systems JPS Legant w/Flat Groundplane */ -{ 59,"JPSREGANT_SD_E NONE"}, /* Javad Positioning Systems JPS Regant w/Single Depth Choke, Ext */ -{ 60,"JPSREGANT_DD_E NONE"}, /* Javad Positioning Systems JPS Regant w/Dual Depth Choke, Ext */ -{ 61,"LEIAT202-GP NONE"}, /* Leica AT202 */ -{ 62,"LEIAT302-GP NONE"}, /* Leica AT302 */ -{ 63,"LEIAT303 LEIC"}, /* Leica AT303 w/Choke Ring+Radome */ -{ 64,"LEIAT303 NONE"}, /* Leica AT303 w/Choke Ring */ -{ 65,"LEIAT502 NONE"}, /* Leica AT502 */ -{ 66,"LEIAT504 NONE"}, /* Leica AT504 w/Choke Ring */ -{ 67,"MAC4647942 MMAC"}, /* Macrometer Crossed Dipoles */ -{ 68,"NOV501 NONE"}, /* NovAtel GPS-501 L1 */ -{ 69,"NOV501+CR NONE"}, /* NovAtel GPS-501 L1 w/Choke */ -{ 70,"NOV502 NONE"}, /* NovAtel GPS-502 L1/L2 */ -{ 71,"NOV502+CR NONE"}, /* NovAtel GPS-502 L1/L2 w/Choke */ -{ 72,"NOV531 NONE"}, /* NovAtel GPS-531 L1 */ -{ 73,"NOV531+CR NONE"}, /* NovAtel GPS-531 L1 w/Choke */ -{ 74,"SEN67157514 NONE"}, /* Sensor Systems L1/L2, Passive */ -{ 75,"SEN67157514+CR NONE"}, /* Sensor Systems L1/L2 w/Choke, Passive */ -{ 76,"SEN67157549 NONE"}, /* Sensor Systems L1 */ -{ 77,"SEN67157549+CR NONE"}, /* Sensor Systems L1 w/Choke Ring */ -{ 78,"SEN67157596 NONE"}, /* Sensor Systems L1/L2, Active */ -{ 79,"SEN67157596+CR NONE"}, /* Sensor Systems L1/L2 w/Choke, Active */ -{ 80,"NGSD/M+GP60 NONE"}, /* NGS D/M+gp60 */ -{ 81,"ASH701945.02B NONE"}, /* Ashtech D/M Choke, Rev B */ -{ 82,"ASH701946.2 NONE"}, /* Ashtech D/M Choke, Rev B, GPS-Glonass */ -{ 83,"SPP571908273 NONE"}, /* Spectra Precision Choke */ -{ 84,"SPP571908273 SPKE"}, /* Spectra Precision Choke w/Radome */ -{ 85,"TRM39105.00 NONE"}, /* Trimble Zephyr */ -{ 86,"TRM41249.00 NONE"}, /* Trimble Zephyr Geodetic */ -{ 87,"PF Power Internal"}, /* Trimble PF Power Internal */ -{ 88,"SPP571212430 NONE"}, /* Spectra Precision Compact L2 */ -{ 89,"SPP571212238+GP NONE"}, /* Spectra Precision Geod. w/GP L2 */ -{ 90,"SPP571908941 NONE"}, /* Spectra Precision Mini-Geodetic L1/L2 */ -{ 91,"SPPGEOTRACER2000NONE"}, /* Spectra Precision SPP Geotracer 2000/2100 L1 Internal */ -{ 92,"SPP571212240 NONE"}, /* Spectra Precision Compact L1 */ -{ 93,"SPP571212236 NONE"}, /* Spectra Precision Geod. w/GP L1 */ -{ 94,"SPP571212774 NONE"}, /* Spectra Precision Mini-Geodetic L1 */ -{ 95,"SPP571212790 NONE"}, /* Spectra Precision GG/GPS Pro L1 */ -{ 96,"ZEIMINI_GEOD NONE"}, /* Zeiss Mini-Geodetic L1/L2 */ -{ 97,"TRM5800 NONE"}, /* Trimble R8/5800/SPS78x Internal */ -{ 98,"NOV503+CR NONE"}, /* NovAtel GPS-503 L1/L2 w/Choke */ -{ 99,"NOV503+CR SPKE"}, /* NovAtel GPS-503 L1/L2 w/Choke+Radome */ -{100,"ASH103661 NONE"}, /* Ashtech Marine IV L1 */ -{101,"ASH104847 NONE"}, /* Ashtech Marine IV GG L1 */ -{102,"ASH700489 NONE"}, /* Ashtech Dimension L1 */ -{103,"ASH700699A NONE"}, /* Ashtech Marine III A L1 */ -{104,"ASH700699B NONE"}, /* Ashtech Marine III B L1 */ -{105,"DSNP DGU001 NONE"}, /* DSNP DGU001 */ -{106,"DSNP DGU002 NONE"}, /* DSNP DGU002 */ -{107,"DSNP NAP001 NONE"}, /* DSNP NAP001 */ -{108,"DSNP NAP002 NONE"}, /* DSNP NAP002 */ -{109,"TRM53406.00 NONE"}, /* Trimble A3 */ -{110,"ASH701933C_M NONE"}, /* Ashtech 701933 */ -{111,"ASH701933C_M SNOW"}, /* Ashtech 701933 w/Radome */ -{112,"ASH701941.1 NONE"}, /* Ashtech 701941.021 */ -{113,"ASH701975.01A NONE"}, /* Ashtech Geodetic IV */ -{114,"ASH701975.01AGP NONE"}, /* Ashtech Geodetic IV w/Ground Plane */ -{115,"NOV600 NONE"}, /* NovAtel GPS-600 */ -{116,"SOKA110 NONE"}, /* Sokkia A110 */ -{117,"SOKA120 NONE"}, /* Sokkia A120 */ -{118,"LEISR299_INT NONE"}, /* Leica SR299/SR399A Internal */ -{119,"TRM26738.00 NONE"}, /* Trimble Permanent L1 */ -{120,"GeoXT Internal"}, /* Trimble GeoXT Internal */ -{121,"TRM47950.00 NONE"}, /* Trimble MS980 Internal */ -{122,"GeoXM Internal"}, /* Trimble GeoXM Internal */ -{123,"TRM41249.00 TZGD"}, /* Trimble Zephyr Geodetic w/Radome */ -{124,"External Mini"}, /* Trimble External Mini */ -{125,"Hurricane"}, /* Trimble Hurricane */ -{126,"LEISR399_INT NONE"}, /* Leica SR399 Internal */ -{127,"AERAT2775_42 NONE"}, /* AeroAntenna AT2775-42 */ -{128,"AERAT2775_43 NONE"}, /* AeroAntenna AT2775-43 */ -{129,"AERAT2775_43 SPKE"}, /* AeroAntenna AT2775-43+rd */ -{130,"AERAT2775_62 NONE"}, /* AeroAntenna AT2775-62 */ -{131,"AERAT2775_160 NONE"}, /* AeroAntenna AT2775-160 */ -{132,"ASH110454 NONE"}, /* Ashtech ProAntenna L1 */ -{133,"JNSMARANT_GGD NONE"}, /* Javad Positioning Systems Marant GGD */ -{134,"MPL1230 NONE"}, /* Micro Pulse MPL1230 */ -{135,"MPL1370W NONE"}, /* Micro Pulse MPL1370W */ -{136,"MPL_WAAS_2224NW NONE"}, /* Micro Pulse MPLWAAS */ -{137,"SOK502 NONE"}, /* Sokkia 502 */ -{138,"SOK600 NONE"}, /* Sokkia 600 */ -{139,"SOK_RADIAN_IS NONE"}, /* Sokkia Radian IS */ -{140,"TPSCR3_GGD NONE"}, /* Topcon CR3 GGD */ -{141,"TPSCR3_GGD CONE"}, /* Topcon CR3 GGD w/Radome */ -{142,"TPSHIPER_GD NONE"}, /* Topcon HiPer GD */ -{143,"TPSLEGANT_G NONE"}, /* Topcon Legant G */ -{144,"TPSLEGANT3_UHF NONE"}, /* Topcon Legant 3 UHF */ -{145,"TRM29659.00 UNAV"}, /* Trimble Choke Ring w/Dome */ -{146,"TRMR10 NONE"}, /* Trimble R10 Internal */ -{147,"TRMSPS985 NONE"}, /* Trimble SPS985 Internal */ -{148,"TRM59900.00 NONE"}, /* Trimble GNSS-Ti Choke Ring */ -{149,"NOV_WAAS_600 NONE"}, /* NovAtel WAAS-600 */ -{150,"Ag252 Internal Phat"}, /* Trimble Ag252 Internal Phat */ -{151,"TPSLEGANT2 NONE"}, /* Topcon Legant 2 */ -{152,"TPSCR4 NONE"}, /* Topcon CR4 */ -{153,"TPSCR4 CONE"}, /* Topcon CR4 w/Radome */ -{154,"TPSODYSSEY_I NONE"}, /* Topcon Odyssey */ -{155,"TPSPG_A1 NONE"}, /* Topcon PG-A1 */ -{156,"TPSHIPER_LITE NONE"}, /* Topcon HiPer Lite */ -{157,"TPSHIPER_PLUS NONE"}, /* Topcon HiPer Plus */ -{158,"TRM33429.20+GP UNAV"}, /* Trimble Micro-centered L1/L2 Perm. w/UNAV Dome */ -{159,"ASH701945.02B SNOW"}, /* Ashtech 701945 D/M Choke w/Snow Dome */ -{160,"ASH701945.02B SCIS"}, /* Ashtech 701945 D/M Choke w/SCIS Dome */ -{161,"ASH701945.02B SCIT"}, /* Ashtech 701945 D/M Choke w/SCIT Dome */ -{162,"ASH700936D_M SCIS"}, /* Ashtech 700936 D/M Choke w/SCIS Dome */ -{163,"LEIAT504 LEIS"}, /* Leica AT504 w/LEIS Dome */ -{164,"AERAT2775_41 NONE"}, /* AeroAntenna AT2775-41 */ -{165,"NOV702 NONE"}, /* NovAtel 702 Rev 2.02 */ -{166,"SOKSTRATUS NONE"}, /* Sokkia Stratus L1 */ -{167,"AOARASCAL NONE"}, /* Alan Osborne Associates Rascal */ -{168,"NAVAN2004T NONE"}, /* NavCom AN2004T */ -{169,"NAVAN2008T NONE"}, /* NavCom AN2008T */ -{170,"NAVSF2040G NONE"}, /* NavCom SF2040G */ -{171,"NAVRT3010S NONE"}, /* NavCom RT3010S */ -{172,"LEIAX1202 NONE"}, /* Leica AX1202 */ -{173,"THAZMAX NONE"}, /* Thales ZMax */ -{174,"GeoXH Internal"}, /* Trimble GeoXH Internal */ -{175,"Pathfinder XB Internal"}, /* Trimble Pathfinder XB Internal */ -{176,"ProXT Internal"}, /* Trimble ProXT Internal */ -{177,"ProXH Internal"}, /* Trimble ProXH Internal */ -{178,"NOV702_3.00 NONE"}, /* NovAtel 702 Rev 3.00 */ -{179,"SOK702_3.00 NONE"}, /* Sokkia 702 Rev 3.00 */ -{180,"TPSPG_A1+GP NONE"}, /* Topcon PG-A1 w/GP */ -{181,"TPSPG_A5 NONE"}, /* Topcon PG-A5 */ -{182,"TRM59900.00 SCIS"}, /* Trimble GNSS-Ti Choke w/SCIS Dome */ -{183,"Recon GPS CF Card Internal"}, /* Trimble Recon GPS CF Card Internal */ -{184,"TRM55970.00 NONE"}, /* Trimble Zephyr - Model 2 */ -{185,"TRM55971.00 NONE"}, /* Trimble Zephyr Geodetic 2 */ -{186,"TRMR8_GNSS NONE"}, /* Trimble R8 GNSS/SPS88x Internal */ -{187,"TRM67770.00 NONE"}, /* Trimble MS99x Internal */ -{188,"LEIAT503 LEIC"}, /* Leica AT503 w/Choke Ring+Radome */ -{189,"LEIAT503 NONE"}, /* Leica AT503 w/Choke Ring */ -{190,"SPP53406.90 NONE"}, /* Spectra Precision EPOCH L1 */ -{191,"TRM55971.00 TZGD"}, /* Trimble Zephyr Geodetic 2 w/Dome */ -{192,"SPP39105.90 NONE"}, /* Spectra Precision EPOCH L1/L2 */ -{193,"TRM57200.00 NONE"}, /* Trimble Z Plus */ -{194,"TRM55550.00 NONE"}, /* Trimble GA510 */ -{195,"TRM29659.00 SCIS"}, /* Trimble Choke Ring w/SCIS Dome */ -{196,"TRM29659.00 SCIT"}, /* Trimble Choke Ring w/SCIT Dome */ -{197,"TRM59800.00 SCIT"}, /* Trimble GNSS Choke w/SCIT Dome */ -{198,"TRMR4-2 NONE"}, /* Trimble R4-2 Internal */ -{199,"TRMR6 NONE"}, /* Trimble R6 Internal */ -{200,"Pathfinder XC Internal"}, /* Trimble Pathfinder XC Internal */ -{201,"AOAD/M_T AUST"}, /* Dorne Margolin D/M Model T w/AUST Dome */ -{202,"AOAD/M_T JPLA"}, /* Dorne Margolin D/M Model T w/JPLA Dome */ -{203,"TRM55971.00 SCIT"}, /* Trimble Zephyr Geodetic 2 w/SCIT */ -{204,"Juno Internal"}, /* Trimble Juno Internal */ -{205,"MPL_WAAS_2225NW NONE"}, /* Micro Pulse MPLWAAS+L5 */ -{206,"TRM41249.00 SCIT"}, /* Trimble Zephyr Geodetic w/SCIT Dome */ -{207,"TRM41249USCG SCIT"}, /* Trimble Zephyr Geodetic w/USCG SCIT Dome */ -{208,"LEIAX1202A NONE"}, /* Leica AX1202A */ -{209,"TRM59800.00 NONE"}, /* Trimble GNSS Choke */ -{210,"TRM59800.00 SCIS"}, /* Trimble GNSS Choke w/SCIS Dome */ -{211,"LEIAX1202GG NONE"}, /* Leica AX1202GG */ -{212,"TPSCR.G3 NONE"}, /* Topcon TPS CR.G3 */ -{213,"TPSCR.G3 TPSH"}, /* Topcon TPS CR.G3 w/TPSH */ -{214,"TPSG3_A1 NONE"}, /* Topcon TPS G3_A1 */ -{215,"TPSG3_A1 TPSD"}, /* Topcon TPS G3_A1 w/TPSD */ -{216,"TPSGR3 NONE"}, /* Topcon TPS GR3 */ -{217,"TPSMAPANT_B NONE"}, /* Topcon TPSMAPANT_B */ -{218,"TPSMG_A2 NONE"}, /* Topcon TPSMG_A2 */ -{219,"TPSPG_A1 TPSD"}, /* Topcon TPSPG_A1 w/GP+TPSD */ -{220,"TPSPG_A2 NONE"}, /* Topcon TPS PG_A2 */ -{221,"TPS_CR.3 SCIS"}, /* Topcon TPSCR.3 w/SCIS */ -{222,"TPS_CR4 SCIS"}, /* Topcon TPS CR4 w/SCIS */ -{223,"TPS_MC.A5 NONE"}, /* Topcon TPS MC.A5 */ -{224,"LEIAT504GG NONE"}, /* Leica LEI AT504GG */ -{225,"LEIAT504GG LEIS"}, /* Leica LEI AT504GG w/LEIS */ -{226,"LEIAT504GG SCIS"}, /* Leica LEI AT504GG w/SCIS */ -{227,"LEIAT504GG SCIT"}, /* Leica LEI AT504GG w/SCIT */ -{228,"LEIATX1230 NONE"}, /* Leica LEI ATX1230 */ -{229,"LEIATX1230GG NONE"}, /* Leica LEI ATX1230GG */ -{230,"THA800961+REC NONE"}, /* Thales THA 800961+REC */ -{231,"THA800961+RTK NONE"}, /* Thales THA 800961+RTK */ -{232,"THA800961RECUHF NONE"}, /* Thales THA 800961RECUHF */ -{233,"THA800961RTKUHF NONE"}, /* Thales THA 800961RTKUHF */ -{234,"THANAP002 NONE"}, /* Thales THA NAP002 */ -{235,"NOV533 RADM"}, /* NovAtel NOV 533 w/RADM */ -{236,"NOV702L_1.01 NONE"}, /* NovAtel NOV 702L_1.01 */ -{237,"SOK702 NONE"}, /* Sokkia SOK 702 */ -{238,"SOK_GSR2700IS NONE"}, /* Sokkia SOK GSR2700IS */ -{239,"ASH701975.01BGP NONE"}, /* Ashtech ASH 701975.01BGP */ -{240,"AERAT2775_42+CR NONE"}, /* AeroAntenna AER AT2775-42 w/Chokering */ -{241,"AERAT2775_150 NONE"}, /* AeroAntenna AER AT2775-150 */ -{242,"AERAT2775_159 NONE"}, /* AeroAntenna AER AT2775-159 */ -{243,"AERAT2775_159 SPKE"}, /* AeroAntenna AER AT2775-159 w/SPKE */ -{244,"AERAT2775_270 NONE"}, /* AeroAntenna AER AT2775-270 */ -{245,"Nomad Internal"}, /* Trimble Nomad Internal */ -{246,"GeoXH 2008 Internal"}, /* Trimble GeoXH 2008 Internal */ -{247,"ASH701933C_M SCIS"}, /* Ashtech 701933 w/SCIS Dome */ -{248,"ASH701933C_M SCIT"}, /* Ashtech 701933 w/SCIT Dome */ -{249,"TRM65212.00 NONE"}, /* Trimble Zephyr - Model 2 Rugged */ -{250,"TRM44530.00 NONE"}, /* Trimble GA530 */ -{251,"SPP77410.00 NONE"}, /* Spectra Precision EPOCH 35 Internal */ -{252,"TRMR4 NONE"}, /* Trimble R4 Internal */ -{253,"TRMR6-2 NONE"}, /* Trimble R6-2 Internal */ -{254,"RELNULLANTENNA NONE"}, /* Relative Null Antenna */ -{255,"GPPNULLANTENNA NONE"}, /* AdV Null Antenna */ -{256,"TRM29659.00 TCWD"}, /* Trimble Choke Ring w/TCWD Dome */ -{257,"LEIAT302+GP NONE"}, /* Leica AT302 w/Ground Plane */ -{258,"JNSCR_C146-22-1 NONE"}, /* Javad Navigation Systems JNSCR_C146-22-1 */ -{259,"LEIAR25 NONE"}, /* Leica AR25 */ -{260,"LEIAR25 LEIT"}, /* Leica AR25 w/LEIT Dome */ -{261,"NOV702GG NONE"}, /* NovAtel 702GG */ -{262,"3S-02-TSADM NONE"}, /* 3S Navigation 3S-02-TSADM */ -{263,"LEIAT504 OLGA"}, /* Leica AT504 w/OLGA Dome */ -{264,"Yuma Internal"}, /* Trimble Yuma Internal */ -{265,"TRM57971.00 NONE"}, /* Trimble Zephyr Geodetic 2 RoHS */ -{266,"TRMAG25 NONE"}, /* Trimble AG25 GNSS */ -{267,"TRM57972.00 NONE"}, /* Trimble Tornado */ -{268,"TRM59800.80 NONE"}, /* Trimble TRM59800-80 */ -{269,"TRM59800.80 SCIS"}, /* Trimble TRM59800-80 w/SCIS Dome */ -{270,"MAG990596 NONE"}, /* Magellan ProMark 500 */ -{271,"LEIAX1203+GNSS NONE"}, /* Leica AX1203+GNSS */ -{272,"TRMR8-4 NONE"}, /* Trimble R8-4 Internal */ -{273,"TRM60600.02 NONE"}, /* Trimble AG15 */ -{274,"Tempest"}, /* Trimble Tempest */ -{275,"TRM59800.80 SCIT"}, /* Trimble TRM59800-80 w/SCIT Dome */ -{276,"TRM57971.00 SCIT"}, /* Trimble Zephyr Geodetic 2 RoHS w/SCIT Dome */ -{277,"TRM57971.00 TZGD"}, /* Trimble Zephyr Geodetic 2 RoHS w/TZGD Dome */ -{278,"ASH701945B_M NONE"}, /* Ashtech 701945B_M */ -{279,"ASH701945C_M NONE"}, /* Ashtech 701945C_M */ -{280,"ASH701945D_M NONE"}, /* Ashtech 701945D_M */ -{281,"ASH701945E_M NONE"}, /* Ashtech 701945E_M */ -{282,"ASH701945G_M NONE"}, /* Ashtech 701945G_M */ -{283,"ASH701945B_M SCIS"}, /* Ashtech 701945B_M w/SCIS Dome */ -{284,"ASH701945C_M SCIS"}, /* Ashtech 701945C_M w/SCIS Dome */ -{285,"ASH701945D_M SCIS"}, /* Ashtech 701945D_M w/SCIS Dome */ -{286,"ASH701945E_M SCIS"}, /* Ashtech 701945E_M w/SCIS Dome */ -{287,"ASH701945G_M SCIS"}, /* Ashtech 701945G_M w/SCIS Dome */ -{288,"ASH701945B_M SCIT"}, /* Ashtech 701945B_M w/SCIT Dome */ -{289,"ASH701945C_M SCIT"}, /* Ashtech 701945C_M w/SCIT Dome */ -{290,"ASH701945D_M SCIT"}, /* Ashtech 701945D_M w/SCIT Dome */ -{291,"ASH701945E_M SCIT"}, /* Ashtech 701945E_M w/SCIT Dome */ -{292,"ASH701945G_M SCIT"}, /* Ashtech 701945G_M w/SCIT Dome */ -{293,"ASH701945B_M SNOW"}, /* Ashtech 701945B_M w/Snow Dome */ -{294,"ASH701945C_M SNOW"}, /* Ashtech 701945C_M w/Snow Dome */ -{295,"ASH701945D_M SNOW"}, /* Ashtech 701945D_M w/Snow Dome */ -{296,"ASH701945E_M SNOW"}, /* Ashtech 701945E_M w/Snow Dome */ -{297,"ASH701945G_M SNOW"}, /* Ashtech 701945G_M w/Snow Dome */ -{298,"ASH701945.02B UNAV"}, /* Ashtech 701945.02B w/UNAV Dome */ -{299,"ASH701945C_M UNAV"}, /* Ashtech 701945C_M w/UNAV Dome */ -{300,"ASH701945D_M UNAV"}, /* Ashtech 701945D_M w/UNAV Dome */ -{301,"ASH701945E_M UNAV"}, /* Ashtech 701945E_M w/UNAV Dome */ -{302,"ASH701933B_M SCIT"}, /* Ashtech 701933B_M w/SCIT Dome */ -{303,"ASH700936D_M SCIT"}, /* Ashtech 700936D_M w/SCIT Dome */ -{304,"ASH700936D_M CAFG"}, /* Ashtech 700936D_M w/CAFG Dome */ -{305,"ASH700936E_C NONE"}, /* Ashtech 700936E_C */ -{306,"ASH700936E_C SCIT"}, /* Ashtech 700936E_C w/SCIT Dome */ -{307,"ASH700936B_M SNOW"}, /* Ashtech 700936B_M w/SNOW Dome */ -{308,"ASH700936B_M SCIT"}, /* Ashtech 700936B_M w/SCIT Dome */ -{309,"TRMAV59 NONE"}, /* Trimble AV59 */ -{310,"AERAT1675_182 NONE"}, /* AeroAntenna AT1675-182 */ -{311,"ASH700936B_M NONE"}, /* Ashtech 700936B_M */ -{312,"ASH700936C_M NONE"}, /* Ashtech 700936C_M */ -{313,"ASH700936D_M NONE"}, /* Ashtech 700936D_M */ -{314,"ASH700936E NONE"}, /* Ashtech 700936E */ -{315,"ASH701073.1 NONE"}, /* Ashtech 701073.1 */ -{316,"ASH701073.3 NONE"}, /* Ashtech 701073.3 */ -{317,"TRM99810.00 NONE"}, /* Trimble GA810 */ -{318,"GeoXT 6000 Internal"}, /* Trimble GeoXT 6000 Internal */ -{319,"GeoXH 6000 Internal"}, /* Trimble GeoXH 6000 Internal */ -{320,"SOK_GSR2700ISX NONE"}, /* Sokkia SOK GSR2700ISX */ -{321,"JAV_TRIUMPH-1 NONE"}, /* Javad GNSS JAV TRIUMPH-1 */ -{322,"TPSCR3_GGD OLGA"}, /* Topcon CR3 GGD w/OLGA */ -{323,"LEIAR25.R3 NONE"}, /* Leica AR25.R3 */ -{324,"LEIAR25.R3 LEIT"}, /* Leica AR25.R3 w/LEIT Dome */ -{325,"AERAT1675_20W SPKE"}, /* AeroAntenna AT1675-20W w/SPKE Dome */ -{326,"NAV_ANT3001BR SPKE"}, /* NavCom ANT3001BR w/SPKE Dome */ -{327,"LEIAR10 NONE"}, /* Leica AR10 */ -{328,"LEIAS10 NONE"}, /* Leica AS10 */ -{329,"SPP68410_10 NONE"}, /* Spectra Precision Epoch 50 Internal */ -{330,"LEIGS15 NONE"}, /* Leica GS15 */ -{331,"LEIAR25.R4 NONE"}, /* Leica AR25.R4 */ -{332,"LEIAR25.R4 LEIT"}, /* Leica AR25.R4 w/LEIT Dome */ -{333,"LEIAR25.R4 SCIT"}, /* Leica AR25.R4 w/SCIT Dome */ -{334,"NOV750.R4 NONE"}, /* NovAtel 750.R4 */ -{335,"NOV750.R4 NOVS"}, /* NovAtel 750.R4 w/NOVS Dome */ -{336,"JAV_GRANT-G3T NONE"}, /* Javad GNSS JAV GRANT-G3T */ -{337,"JAV_RINGANT_G3T NONE"}, /* Javad GNSS JAV RINGANT-G3T */ -{338,"JAVRINGANT_DM NONE"}, /* Javad GNSS JAV RINGANT-DM */ -{339,"JAV_RINGANT_G3T JAVC"}, /* Javad GNSS JAV RINGANT-G3T w/JAVC */ -{340,"JAVRINGANT_DM JVDM"}, /* Javad GNSS JAV RINGANT-DM w/JVDM */ -{341,"JAVRINGANT_DM SCIS"}, /* Javad GNSS JAV RINGANT-DM w/SCIS */ -{342,"JAVRINGANT_DM SCIT"}, /* Javad GNSS JAV RINGANT-DM w/SCIT */ -{343,"LEIMNA950GG NONE"}, /* Leica MNA950GG */ -{344,"TPSCR.G3 SCIS"}, /* Topcon TPS CR.G3 w/SCIS */ -{345,"ASH701945C_M PFAN"}, /* Ashtech 701945C_M w/PFAN */ -{346,"LEIATX1230+GNSS NONE"}, /* Leica ATX1230+GNSS */ -{347,"TRM_MS972 NONE"}, /* Trimble MS972 */ -{348,"MAG111406 NONE"}, /* Magellan ProFLEX 500 Survey Antenna */ -{349,"TRM_AV33 NONE"}, /* Trimble AV33 */ -{350,"AOAD/M_B OSOD"}, /* Allen Osborne Associates AOAD Model B w/OSOD Dome */ -{351,"AOAD/M_T OSOD"}, /* Allen Osborne Associates AOAD Model T w/OSOD Dome */ -{352,"ASH700936A_M OSOD"}, /* Ashtech 700936A_M w/OSOD Dome */ -{353,"ASH700936D_M OSOD"}, /* Ashtech 700936D_M w/OSOD Dome */ -{354,"ASH700936E OSOD"}, /* Ashtech 700936E w/OSOD Dome */ -{355,"ASH700936F_C OSOD"}, /* Ashtech 700936F_C w/OSOD Dome */ -{356,"701073.1 OSOD"}, /* Ashtech 701073.1 w/OSOD Dome */ -{357,"ASH701941.B OSOD"}, /* Ashtech 701941.B w/OSOD Dome */ -{358,"701945B_M OSOD"}, /* Ashtech 701945B_M w/OSOD Dome */ -{359,"701945C_M OSOD"}, /* Ashtech 701945C_M w/OSOD Dome */ -{360,"701945E_M OSOD"}, /* Ashtech 701945E_M w/OSOD Dome */ -{361,"701946.3 OSOD"}, /* Ashtech 701946.3 w/OSOD Dome */ -{362,"JAVRINGANT_DM OSOD"}, /* Javad GNSS RINGANT-DM w/OSOD Dome */ -{363,"JNSCR_C146-22-1 OSOD"}, /* Javad Navigation Systems JNSCR_C146-22-1 w/OSOD DOme */ -{364,"ASH700936F_C NONE"}, /* Ashtech 700936F_C */ -{365,"ASH700936E SNOW"}, /* Ashtech 700936E w/SNOW Dome */ -{366,"ASH701941.B NONE"}, /* Ashtech 701941.B */ -{367,"ASH701946.3 NONE"}, /* Ashtech 701946.3 */ -{368,"ASH700936C_M SNOW"}, /* Ashtech 700936C_M w/SNOW Dome */ -{369,"ASH700936D_M SNOW"}, /* Ashtech 700936D_M w/SNOW Dome */ -{370,"ASH700936E_C SNOW"}, /* Ashtech 700936E_C w/SNOW Dome */ -{371,"Controller Internal"}, /* Trimble Controller Internal */ -{372,"GeoXR 6000 Internal"}, /* Trimble GeoXR 6000 Internal */ -{373,"ASH700936B_M OSOD"}, /* Ashtech 700936B_M w/OSOD Dome */ -{374,"ASH701933B_M NONE"}, /* Ashtech 701933B_M */ -{375,"ASH701933B_M SNOW"}, /* Ashtech 701933B_M w/SNOW Dome */ -{376,"ASH701933B_M OSOD"}, /* Ashtech 701933B_M w/OSOD Dome */ -{377,"JNSCHOKERING_DM NONE"}, /* Javad Navigation Systems JNSCHOKERING_DM */ -{378,"JNSCHOKERING_DM OSOD"}, /* Javad Navigation Systems JNSCHOKERING_DM w/OSOD DOme */ -{379,"TRMSPS585 NONE"}, /* Trimble SPS585 Internal */ -{380,"TRM44530R.00 NONE"}, /* Trimble Rugged GA530 */ -{381,"TRMR6-3 NONE"}, /* Trimble R6-3 Internal */ -{382,"RNG80971.00 NONE"}, /* Rusnavgeoset RNG80971.00 */ -{383,"RNG80971.00 SCIT"}, /* Rusnavgeoset RNG80971.00 w/SCIT Dome */ -{384,"RNG80971.00 TZGD"}, /* Rusnavgeoset RNG80971.00 w/TZGD Dome */ -{385,"TPSCR.G3 SCIT"}, /* Topcon TPS CR.G3 w/SCIT */ -{386,"ASH111660 NONE"}, /* Ashtech 111660 */ -{387,"ASH111661 NONE"}, /* Ashtech 111661 */ -{388,"ASH802129 NONE"}, /* Ashtech ProMark 500 Galileo */ -{389,"LEIAR25.R3 SCIS"}, /* Leica AR25.R3 w/SCIS Dome */ -{390,"LEIAR25.R3 SCIT"}, /* Leica AR25.R3 w/SCIT Dome */ -{391,"ASH802147_A NONE"}, /* Spectra Precision ProMark 800 */ -{392,"APSAPS-3 NONE"}, /* Altus APS-3 */ -{393,"TPSHIPER_II NONE"}, /* Topcon HiPer II */ -{394,"Tempest Rev. B"}, /* Trimble Tempest Rev. B */ -{395,"Pro 6H Internal"}, /* Trimble Pro 6H Internal */ -{396,"Pro 6T Internal"}, /* Trimble Pro 6T Internal */ -{397,"ASH701941.B SCIS"}, /* Ashtech 701941.B w/SCIS Dome */ -{398,"TPSCR.G5 NONE"}, /* Topcon CR.G5 */ -{399,"TPSCR.G5 SCIS"}, /* Topcon CR.G5 w/SCIS Dome */ -{400,"TPSCR.G5 SCIT"}, /* Topcon CR.G5 w/SCIT Dome */ -{401,"TPSCR.G5 TPSH"}, /* Topcon CR.G5 w/TPSH Dome */ -{402,"STXS9SA7224V3.0 NONE"}, /* STONEX S9II GNSS Internal */ -{403,"TRM_AV34 NONE"}, /* Trimble AV34 */ -{404,"TRMAV37 NONE"}, /* Trimble AV37 */ -{405,"AERAT1675_80 NONE"}, /* AeroAntenna AT1675-80 */ -{406,"TRMLV59 NONE"}, /* Trimble LV59 */ -{407,"AERAT1675_382 NONE"}, /* AeroAntenna AT1675-382 */ -{408,"ASH802111 NONE"}, /* Ashtech MobileMapper 100 Internal */ -{409,"TRMGEO5T NONE"}, /* Trimble Geo 5T Internal */ -{410,"TRM57970.00 NONE"}, /* Trimble Zephyr - Model 2 RoHS */ -{411,"TPSGR5 NONE"}, /* Topcon GR5 */ -{412,"TRMAG_342 NONE"}, /* Trimble AG-342 Internal */ -{413,"HEMS320 NONE"}, /* Hemisphere S320 */ -{414,"ACC123CGNSSA_XN NONE"}, /* Antcom 123CGNSSA-XN */ -{415,"ACC2G1215A_XT_1 NONE"}, /* Antcom 2G1215A-XT-1 */ -{416,"ACC3G1215A_XT_1 NONE"}, /* Antcom 3G1215A-XT-1 */ -{417,"ACC42G1215A_XT1 NONE"}, /* Antcom 42G1215A-XT1 */ -{418,"ACC4G1215A_XT_1 NONE"}, /* Antcom 4G1215A-XT-1 */ -{419,"ACC53G1215A_XT1 NONE"}, /* Antcom 53G1215A-XT1 */ -{420,"ACC53GO1215AXT1 NONE"}, /* Antcom 53GO1215AXT1 */ -{421,"ACC72CGNSSA NONE"}, /* Antcom 72CGNSSA */ -{422,"ACC72GNSSA_XT_1 NONE"}, /* Antcom 72GNSSA-XT-1 */ -{423,"ACCG3ANT_3AT1 NONE"}, /* Antcom G3ANT-3AT1 */ -{424,"ACCG3ANT_42AT NONE"}, /* Antcom G3ANT-42AT1 */ -{425,"ACCG3ANT_52AT NONE"}, /* Antcom G3ANT-52AT1 */ -{426,"ACCG5ANT_123CAN NONE"}, /* Antcom G5ANT_123CAN */ -{427,"ACCG5ANT_2AT1 NONE"}, /* Antcom G5ANT_2AT1 */ -{428,"ACCG5ANT_3AT1 NONE"}, /* Antcom G5ANT_3AT1 */ -{429,"ACCG5ANT_42AT1 NONE"}, /* Antcom G5ANT_42AT1 */ -{430,"ACCG5ANT_52AT1 NONE"}, /* Antcom G5ANT_52AT1 */ -{431,"ACCG5ANT_72AT1 NONE"}, /* Antcom G5ANT_72AT1 */ -{432,"MAG105645 NONE"}, /* Magellan L1/L2 GPS Antenna */ -{433,"CHCA300GNSS NONE"}, /* CHC A300GNSS */ -{434,"CHCX900B NONE"}, /* CHC X900B */ -{435,"CHCX900R NONE"}, /* CHC X900R */ -{436,"CHCX91B NONE"}, /* CHC X91B */ -{437,"CHCX91R NONE"}, /* CHC X91R */ -{438,"TRMR6-4 NONE"}, /* Trimble R6-4 Internal */ -{439,"TRMR4-3 NONE"}, /* Trimble R4-3 Internal */ -{440,"SPP89823_10 NONE"}, /* Spectra Precision ProMark 700 */ -{441,"NOV750.R4 SCIT"}, /* NovAtel 750.R4 w/SCIT Dome */ -{442,"NOV750.R4 SCIS"}, /* NovAtel 750.R4 w/SCIS Dome */ -{443,"NOV702L_1.03 NONE"}, /* NovAtel 702L 1.03 */ -{444,"NOV702GGL_1.01 NONE"}, /* NovAtel 702-GGL 1.01 */ -{445,"NOV702GG_1.02 NONE"}, /* NovAtel 702-GG 1.02 */ -{446,"NOV702GG_1.03 NONE"}, /* NovAtel 702-GG 1.03 */ -{447,"NOV701GGL NONE"}, /* NovAtel 701-GGL */ -{448,"NOV701GG_1.03 NONE"}, /* NovAtel 701-GG 1.03 */ -{449,"SOKGRX1 NONE"}, /* Sokkia GRX1 */ -{450,"SOKGRX1+10 NONE"}, /* Sokkia GRX1 + 10cm Standoff */ -{451,"SOKGRX2 NONE"}, /* Sokkia GRX2 */ -{452,"SOKGRX2+10 NONE"}, /* Sokkia GRX2 + 10cm Standoff */ -{453,"SOKLOCUS NONE"}, /* Sokkia Locus */ -{454,"HITV30 NONE"}, /* Hi-Target V30 GNSS */ -{455,"MAGNAP100 NONE"}, /* Magellan NAP100 */ -{456,"AERAT1675_29 NONE"}, /* AeroAntenna AT1675-29 */ -{457,"JAV_TRIUMPH-1R NONE"}, /* Javad GNSS TRIUMPH-1R */ -{458,"SEPCHOKE_MC NONE"}, /* Septentrio Choke MC */ -{459,"SEPCHOKE_MC SPKE"}, /* Septentrio Choke MC w/SPKE Dome */ -{460,"TRM77970.00 NONE"}, /* Trimble Zephyr - Model 2 US/CAN */ -{461,"TRM77971.00 NONE"}, /* Trimble Zephyr Geodetic 2 US/CAN */ -{462,"LEIGS08 NONE"}, /* Leica GS08 */ -{463,"LEIGS08PLUS NONE"}, /* Leica GS08plus */ -{464,"LEIGS09 NONE"}, /* Leica GS09 */ -{465,"LEIGS12 NONE"}, /* Leica GS12 */ -{466,"LEIGS14 NONE"}, /* Leica GS14 */ -{467,"Geo 7X Internal"}, /* Trimble Geo 7X Internal */ -{468,"SPP91564_1 NONE"}, /* Spectra Precision SP80 */ -{469,"SPP91564_2 NONE"}, /* Spectra Precision SP80 UHF */ -{470,"TRM44830.00 NONE"}, /* Trimble GA830 */ -{473,"TPSHIPER_SR NONE"}, /* Topcon HiPer SR */ -{474,"JAVTRIUMPH-VS NONE"}, /* Javad GNSS Triumph-VS */ -{477,"AERAT1675_180 NONE"}, /* AeroAntenna AT1675-180 */ -{478,"TRMAV39 NONE"}, /* Trimble AV39 */ -{479,"LEIAR20 NONE"}, /* Leica AR20 */ -{480,"LEIAR20 LEIM"}, /* Leica AR20 w/LEIM Dome */ -{481,"TPSHIPER_V NONE"}, /* Topcon HiPer V */ -{482,"AERAT1675_120 NONE"}, /* AeroAntenna AT1675-120 */ -{483,"AERAT1675_120 SPKE"}, /* AeroAntenna AT1675-120 w/SPKE Dome */ -{484,"R1/PG200 Internal"}, /* Trimble R1/PG200 Internal */ -{485,"ITT3750323 NONE"}, /* ITT 3750323 */ -{486,"ITT3750323 SCIS"}, /* ITT 3750323 w/SCIS Dome */ -{487,"TPSPG_A1_6 NONE"}, /* Topcon PG-A1-6 */ -{488,"TPSPG_A1_6+GP NONE"}, /* Topcon PG-A1-6 w/GP */ -{489,"TPSPG_F1 NONE"}, /* Topcon PG-F1 */ -{490,"TPSPG_F1+GP NONE"}, /* Topcon PG-F1 w/GP */ -{491,"TPSPG_S1 NONE"}, /* Topcon PG-S1 */ -{492,"TPSPG_S1+GP NONE"}, /* Topcon PG-S1 w/GP */ -{493,"TPSPN.A5 NONE"}, /* Topcon PN-A5 */ -{494,"TPSPN.A5 SCIS"}, /* Topcon PN-A5 w/SCIS */ -{495,"TPSPN.A5 SCIT"}, /* Topcon PN-A5 w/SCIT */ -{496,"TPSPN.A5 TPSH"}, /* Topcon PN-A5 w/TPSH */ -{497,"TPSHIPER_XT NONE"}, /* Topcon HiPer XT */ -{498,"TPSHIPER_II+10 NONE"}, /* Topcon HiPer II + 10cm Standoff */ -{499,"TPSHIPER_SR+10 NONE"}, /* Topcon HiPer SR + 10cm Standoff */ -{500,"TPSHIPER_V+10 NONE"}, /* Topcon HiPer V + 10cm Standoff */ -{501,"TPSCR3_GGD PFAN"}, /* Topcon CR3 GGD w/PFAN */ -{507,"HXCGG486A NONE"}, /* Harxon HX-GG486A */ -{508,"HXCGG486A HXCS"}, /* Harxon HX-GG486A w/HXCS */ -{509,"HXCGS488A NONE"}, /* Harxon HX-GS488A */ -{510,"SPP98147_10 NONE"}, /* Spectra Precision MobileMapper 300 */ -{511,"AERAT1675_219 NONE"}, /* AeroAntenna AT1675-219 */ -{514,"STXS9PX001A NONE"}, /* STONEX S9III+ GNSS Internal */ -{515,"STXG5ANT_72AT1 NONE"}, /* STONEX G5Ant_72AT1 */ -{516,"TRMR2 NONE"}, /* Trimble R2 Internal */ -{517,"SEPPOLANT_X_MF NONE"}, /* Septentrio PolaNt-x MF */ -{518,"SEPPOLANT_X_SF NONE"}, /* Septentrio PolaNt-x SF */ -{519,"SEP_POLANT+ NONE"}, /* Septentrio PolaNt* */ -{520,"SEP_POLANT+_GG NONE"}, /* Septentrio PolaNt* GG */ -{521,"TRMAT1675_540TS NONE"}, /* Trimble AT1675-540TS */ -{523,"UX5_HP NONE"}, /* Trimble UX5 HP Internal GNSS */ -{524,"TRM77971.00 SCIT"}, /* Trimble Zephyr Geodetic 2 US/CAN w/SCIT */ -{525,"TPSLEGANT NONE"}, /* Topcon Legant */ -{526,"TPSHIPER_GGD NONE"}, /* Topcon HiPer GGD */ -{527,"TRMR8S NONE"}, /* Trimble R8s Internal */ -{528,"STH82VHX-BS601A NONE"}, /* SOUTH S82V2 GNSS */ -{529,"STHS82HX-BS601A NONE"}, /* SOUTH S82-2013 GNSS */ -{530,"STHS82_7224V3.0 NONE"}, /* SOUTH S82T/S82V GNSS */ -{531,"STHS86HX-BS611A NONE"}, /* SOUTH S86-2013 GNSS */ -{532,"STHS86_7224V3.1 NONE"}, /* SOUTH S86 GNSS */ -{533,"TRMAG_372 NONE"}, /* Trimble AG-372 Internal */ -{534,"HXCCG7601A NONE"}, /* Harxon HX-CG7601A */ -{535,"HXCCG7601A HXCG"}, /* Harxon HX-CG7601A w/HXCG */ -{536,"HXCCGX601A NONE"}, /* Harxon HX-CGX601A */ -{537,"HXCCGX601A HXCS"}, /* Harxon HX-CGX601A w/HXCS */ -{538,"HXCCSX601A NONE"}, /* Harxon HX-CSX601A */ -{539,"HXCCA7607A NONE"}, /* Harxon HX-CA7607A */ -{540,"HXCCG7602A NONE"}, /* Harxon HX-CG7602A */ -{541,"HXCCG7602A HXCG"}, /* Harxon HX-CG7602A w/HXCG */ -{542,"LEIICG60 NONE"}, /* Leica ICG60 */ -{543,"CHCA220GR NONE"}, /* CHC A220GR */ -{544,"CHCC220GR NONE"}, /* CHC C220GR */ -{545,"CHCC220GR CHCD"}, /* C220GR w/CHCD */ -{546,"CHCX90D-OPUS NONE"}, /* CHC X90D-OPUS */ -{547,"CHCX91+S NONE"}, /* CHC X91+S */ -{550,"JAVTRIUMPH_2A NONE"}, /* Javad GNSS TRIUMPH-2 */ -{551,"JAVTRIUMPH_LS NONE"}, /* Javad GNSS TRIUMPH-LS */ -{552,"ACCG8ANT-CHOKES NONE"}, /* Antcom G8ANT-CHOKES */ -{553,"ACCG8ANT_3A4TB1 NONE"}, /* Antcom G8ANT_3A4TB1 */ -{554,"ACCG8ANT_3A4_M1 NONE"}, /* Antcom G8ANT_3A4_M1 */ -{555,"ACCG8ANT_52A4T1 NONE"}, /* Antcom G8ANT_52A4T1 */ -{556,"ACCG8ANT_52A4TC NONE"}, /* Antcom G8ANT_52A4TC */ -{557,"SPP101861 NONE"}, /* Spectra Precision SP60 */ -{559,"GMXZENITH20 NONE"}, /* GeoMax ZENITH 20 */ -{560,"NAX3G+C NONE"}, /* NavXperience 3G+C */ -{561,"CHANV3 NONE"}, /* Champion Instruments NV3 */ -{562,"CHATKO NONE"}, /* Champion Instruments TKO GNSS */ -{563,"TRMBEACONIM3_NF NONE"}, /* Trimble Beacon IM3-NF */ -{564,"RAVMBA2_NF NONE"}, /* Raven MBA-2 NF */ -{565,"RAVMBA2_FF NONE"}, /* Raven MBA-2 FF */ -{568,"SLGSL600_V1 NONE"}, /* Satlab SL600 V1 */ -{571,"STXS10SX017A NONE"}, /* STONEX S10 Internal */ -{572,"TWI3870+GP NONE"}, /* Tallysman 33-3870 GNSS */ -{573,"TWIVP6000 NONE"}, /* Tallysman VP6000 */ -{575,"TRMAV14 NONE"}, /* Trimble AV14 */ -{576,"HXCGX606A NONE"}, /* Harxon HX-CGX606A */ -{577,"HXCGX606A HXCS"}, /* Harxon HX-CGX606A w/HXCS */ -{578,"NAVANT3001A NONE"}, /* NavCom ANT30001A */ -{579,"NAVANT3001B NONE"}, /* NavCom ANT30001B */ -{580,"NAV_ANT3001R NONE"}, /* NavCom ANT30001R */ -{581,"NAVSF3040 NONE"} /* NavCom SF3040 */ -}; - -/* -| CMR+ protocol defined receiver number to name lookup table. -| -| Adapted from "c:\program files (x86)\common files\trimble\config\receiver.ini" -| after installing the latest Trimble Office Configuration File Update Utility -| found at -| For each receiver definition block in receiver.ini the "RxId" keyword provides -| the receiver number and the "IGSReceiver" keyword provides the receiver name. -| A handful of receivers also have an "OldRxId" entry which provides an additional -| number with the same name. -| -| ### CMR+ MESSAGE TYPE 1 HAS ONLY A BYTE FOR THE RECEIVER NUMBER SO HOW CAN ### -| ### THEY POSSIBLY EXCEED 255? THERE MUST EITHER BE A NEW MESSAGE TYPE WE ### -| ### DON'T KNOW ABOUT OR A FLAG BIT THAT WE DON'T KNOW ABOUT, ETC. THAT ### -| ### EXTENDS THIS OTHERWISE SOMEONE DROPPED THE BALL... ### -*/ -static const rcv_t ReceiversTable[] = { -{1,"TRIMBLE 4000A"}, -{2,"TRIMBLE 4000ST"}, -{3,"TRIMBLE 4000SE"}, -{4,"TRIMBLE 4000SE"}, -{5,"TRIMBLE 4000SI"}, -{6,"TRIMBLE 4400"}, -{7,"TRIMBLE 4600"}, -{8,"TRIMBLE MSGR"}, -{9,"TRIMBLE 4800"}, -{10,"TRIMBLE 4000A"}, -{11,"TRIMBLE 4000SX"}, -{12,"TRIMBLE 4000SLD"}, -{13,"TRIMBLE 4000ST"}, -{14,"TRIMBLE 4000SST"}, -{15,"TRIMBLE 4000SE"}, -{16,"TRIMBLE 4000SE"}, -{17,"TRIMBLE 4000SSE"}, -{18,"TRIMBLE 4000SI"}, -{19,"TRIMBLE 4000SSI"}, -{20,"TRIMBLE 4400"}, -{21,"TRIMBLE 4600"}, -{22,"TRIMBLE MSGR"}, -{23,"TRIMBLE 4800"}, -{24,"TRIMBLE 4700"}, -{25,"TRIMBLE MS750"}, -{26,"TRIMBLE 5700"}, -{27,"TRIMBLE 5800"}, -{28,"TRIMBLE MS980"}, -{29,"TRIMBLE NETRS"}, -{30,"TRIMBLE BD950"}, -{31,"TRIMBLE R7"}, -{32,"TRIMBLE R8"}, -{33,"TRIMBLE R3"}, -{34,"TRIMBLE SPS750"}, -{35,"TRIMBLE NETR9 GEO"}, -{36,"TRIMBLE SPS780"}, -{37,"TRIMBLE SPS770"}, -{38,"TRIMBLE SPS850"}, -{39,"TRIMBLE SPS880"}, -{40,"TRIMBLE EPOCH10"}, -{41,"TRIMBLE SPS651"}, -{42,"TRIMBLE SPS550"}, -{43,"TRIMBLE MS990"}, -{44,"TRIMBLE R8 GNSS"}, -{45,"TRIMBLE NETR5"}, -{46,"TRIMBLE SPS550H"}, -{47,"TRIMBLE EPOCH25"}, -{48,"TRIMBLE R4-2"}, -{49,"TRIMBLE AGRTKBASE"}, -{50,"TRIMBLE R7 GNSS"}, -{51,"TRIMBLE R6"}, -{52,"TRIMBLE R8-4"}, -{53,"TRIMBLE R6-2"}, -{54,"TRIMBLE SPS781"}, -{55,"TRIMBLE SPS881"}, -{56,"TRIMBLE SPS551"}, -{57,"TRIMBLE SPS551H"}, -{58,"TRIMBLE SPS751"}, -{59,"TRIMBLE SPS851"}, -{60,"TRIMBLE AGGPS432"}, -{61,"TRIMBLE AGGPS442"}, -{62,"TRIMBLE BD960"}, -{63,"TRIMBLE NETR8"}, -{64,"TRIMBLE 5800II"}, -{65,"TRIMBLE SPS351"}, -{66,"TRIMBLE SPS361"}, -{67,"TRIMBLE PROXRT"}, -{68,"TRIMBLE NETR3"}, -{69,"TRIMBLE 5700II"}, -{70,"TRIMBLE SPS461"}, -{71,"TRIMBLE R8 GNSS3"}, -{72,"TRIMBLE SPS882"}, -{73,"TRIMBLE 9200-G2"}, -{74,"TRIMBLE MS992"}, -{75,"TRIMBLE BD970"}, -{76,"TRIMBLE NETR9"}, -{77,"TRIMBLE BD982"}, -{78,"TRIMBLE 9205 GNSS"}, -{79,"TRIMBLE GEOXR 6000"}, -{80,"TRIMBLE R6-3"}, -{81,"TRIMBLE GEOXH2008"}, -{82,"TRIMBLE JUNOST"}, -{83,"TRIMBLE PFXC"}, -{84,"TRIMBLE RECONGPSCF"}, -{85,"TRIMBLE PROXH"}, -{86,"TRIMBLE PROXT"}, -{87,"TRIMBLE PFXB"}, -{88,"TRIMBLE GEOXH"}, -{89,"TRIMBLE GEOXM"}, -{90,"TRIMBLE GEOXT"}, -{91,"TRIMBLE PROXRT-3"}, -{92,"TRIMBLE PFPOWER"}, -{93,"TRIMBLE AGL2"}, -{94,"TRIMBLE GEOEXPLORER3"}, -{95,"TRIMBLE PROXRS"}, -{96,"TRIMBLE PROXR"}, -{97,"TRIMBLE PROXL"}, -{98,"TRIMBLE GEOEXPLORER"}, -{99,"TRIMBLE PFBASIC"}, -{100,"TRIMBLE R10"}, -{101,"TRIMBLE SPS985"}, -{102,"TRIMBLE MS952"}, -{103,"RNG FASA+"}, -{105,"TRIMBLE SPS552H"}, -{106,"TRIMBLE MS972"}, -{107,"TRIMBLE SPS852"}, -{108,"TRIMBLE PROXRT-2"}, -{109,"TRIMBLE BD910"}, -{110,"TRIMBLE BD920"}, -{111,"TRIMBLE BD930"}, -{112,"TRIMBLE AGGPS542"}, -{113,"TRIMBLE EPOCH35GNSS"}, -{114,"TRIMBLE R4"}, -{115,"TRIMBLE R5"}, -{116,"TRIMBLE EPOCH50"}, -{117,"TRIMBLE MS352"}, -{118,"TRIMBLE SPS855"}, -{119,"TRIMBLE SPS555H"}, -{120,"LEICA L1"}, -{121,"LEICA L2"}, -{122,"WILD WM101"}, -{123,"WILD WM102"}, -{124,"LEICA SR261"}, -{125,"LEICA SR299"}, -{126,"LEICA SR399"}, -{127,"LEICA SR9400"}, -{128,"LEICA SR9500"}, -{129,"LEICA CRS1000"}, -{130,"LEICA SR510"}, -{131,"LEICA SR520"}, -{132,"LEICA SR530"}, -{133,"LEICA MC500"}, -{134,"LEICA GPS1200"}, -{135,"LEICA RS500"}, -{136,"TRIMBLE R8S"}, -{137,"TRIMBLE AG-342"}, -{138,"TRIMBLE SPS356"}, -{139,"TRIMBLE DELTA7"}, -{140,"ASHTECH L1"}, -{141,"ASHTECH L2"}, -{142,"ASHTECH DIMENSION"}, -{143,"ASHTECH L-XII"}, -{144,"ASHTECH M-XII"}, -{145,"ASHTECH P-XII3"}, -{146,"ASHTECH Z-XII3"}, -{147,"ASHTECH GG24C"}, -{148,"ASHTECH UZ-12"}, -{149,"ASHTECH ICGRS"}, -{150,"TRIMBLE GEO 5T"}, -{151,"TRIMBLE R6-4"}, -{152,"TRIMBLE R4-3"}, -{153,"SPP PROMARK700"}, -{154,"TRIMBLE NETR9 TI-M"}, -{155,"TRIMBLE M7-PPS"}, -{156,"TRIMBLE APX-15"}, -{159,"TRIMBLE MX100"}, -{160,"TOPCON GP-R1"}, -{161,"TOPCON GP-R1D"}, -{166,"TRIMBLE APX-15V2"}, -{168,"TRIMBLE R9S"}, -{170,"DELNORTE 3009"}, -{171,"SOK RADIAN"}, -{172,"SOK GSR2600"}, -{180,"GEOD GEOTRACER2000"}, -{181,"SPP GPSMODULEL1"}, -{182,"SPP GEOTRACERL1L2"}, -{185,"NOV MILLEN-STD"}, -{186,"NIKON LOGPAK"}, -{187,"NIKON LOGPAKII"}, -{195,"ZEISS EXPERIENCE"}, -{196,"LEICA GRX1200GGPRO"}, -{197,"TPS NETG3"}, -{198,"LEICA GRX1200+GNSS"}, -{199,"TPS NET-G3A"}, -{200,"LITTON MINIMAC"}, -{220,"TOPCON GP-SX1"}, -{221,"TOPCON GP-DX1"}, -{222,"NGS NETSURV1000"}, -{223,"NGS NETSURV1000L"}, -{224,"NGS NETSURV2000"}, -{230,"JPS LEGACY"}, -{231,"JPS REGENCY"}, -{232,"JPS ODYSSEY"}, -{233,"TPS HIPER_GD"}, -{234,"JPS PREGO"}, -{235,"JPS E_GGD"}, -{236,"JAVAD TRE_G3TH DELTA"}, -{239,"SPP MOBILEMAPPER300"}, -{240,"TRIMBLE BD935"}, -{242,"TRIMBLE SPS985L"}, -{243,"TRIMBLE CPS205"}, -{244,"TRIMBLE M7-SPS"}, -{250,"TRIMBLE SPS585"}, -{251,"TRIMBLE BRAVO7"}, -{252,"TRIMBLE GEOXT6000"}, -{253,"TRIMBLE GEOXH6000"}, -{254,"VRS"}, -{255,"UNKNOWN"}, -{257,"LEICA 10"}, -{258,"TPS GB-1000"}, -{259,"TRIMBLE YUMA"}, -{260,"TRIMBLE TSC3"}, -{261,"ASHTECH PROMARK120"}, -{262,"ASHTECH PROMARK220"}, -{263,"ASHTECH PROMARK500"}, -{264,"ASHTECH PF500"}, -{265,"SPP PROMARK800"}, -{266,"ASHTECH PF800"}, -{267,"SOK GSR2700 RS"}, -{268,"SOK GSR2700 RSX"}, -{269,"SOK RADIAN_IS"}, -{270,"TRIMBLE PRO_6H"}, -{271,"TRIMBLE PRO_6T"}, -{272,"STONEX S9II GNSS"}, -{273,"ASHTECH MM100"}, -{274,"TPS GR5"}, -{275,"HEM S320"}, -{276,"TRIMBLE JUNO5"}, -{277,"SOK_GSR2700IS"}, -{278,"SOK_GSR2700ISX"}, -{279,"SOK_GRX1"}, -{280,"SOK_GRX2"}, -{281,"SOK_LOCUS"}, -{282,"TRIMBLE GEOXH6000_CM"}, -{283,"TRIMBLE GEO7T"}, -{284,"TRIMBLE GEO7H"}, -{285,"TRIMBLE GEO7HCM"}, -{286,"HITARGET V30"}, -{287,"TRIMBLE GEO7X"}, -{288,"LEICA GS08"}, -{289,"LEICA GS08PLUS"}, -{290,"LEICA GS09"}, -{291,"LEICA GS10"}, -{292,"LEICA GS12"}, -{293,"LEICA GS14"}, -{294,"LEICA GS15"}, -{295,"LEICA GS25"}, -{296,"JPS EGGDT"}, -{297,"BKG EGGDT"}, -{298,"LEICA GR25"}, -{299,"JAVAD TRE_G3TH SIGMA"}, -{300,"SPECTRA SP80"}, -{301,"TPSHIPER_SR"}, -{302,"JAVAD TR_VS"}, -{303,"TPSHIPER_V"}, -{304,"JAVAD TRE_G3T SIGMA"}, -{305,"TRIMBLE R1/PG200"}, -{306,"TRIMBLE SG160_0X"}, -{307,"TRIMBLE BD930_SG"}, -{308,"TRIMBLE BD982_SG"}, -{309,"STONEX S9III+ GNSS"}, -{310,"TRIMBLE R2"}, -{1022,"ASHTECH MB-ONE"}, -{1024,"NVS NV08C-CSM V4.0"}, -{1025,"UBLOX NEO-6P"}, -{1026,"QUALCOMM GOBI"}, -{1027,"TRIMBLE SOFTGNSS"}, -{1029,"TRIMBLE FMX"}, -{1030,"TRIMBLE FMX_III"}, -{1031,"TRIMBLE CFX"}, -{1032,"TRIMBLE TM_200"}, -{1034,"SOUTH S82T GNSS"}, -{1035,"SOUTH S82V GNSS"}, -{1036,"TRIMBLE AG_372"}, -{1037,"LEICA ICG60"}, -{1038,"SEPT POLARX4"}, -{1039,"JAVAD TRIUMPH2"}, -{1040,"JAVAD TRIUMPH_LS"}, -{1041,"SPECTRA SP60"}, -{1042,"GEOMAX ZENITH20"}, -{1043,"SATLAB SL600_V1"}, -{1044,"TPS NET-G5"}, -{1045,"STONEX S10"}, -{1046,"ASHTECH MB-TWO"}, -{1047,"SOK STRATUS L1"}, -{1048,"CHC X900B"}, -{1049,"CHC X900R"}, -{1050,"CHC X91B"}, -{1051,"CHC X91R"}, -{1052,"CHC X90D-OPUS"}, -{1053,"CHC X91+S"} -}; - -/* -| Signal to noise ratio conversion for CMR type 3 (GLONASS) observables. -| See reference #3. -*/ -static const unsigned char SnrTable[][2] = - {{0,0}, {30,4}, {32,8}, {34,12}, - {36,16}, {38,20}, {40,24}, {42,28}, - {44,32}, {46,36}, {48,40}, {50,44}, - {52,48}, {54,52}, {56,56}, {58,60} -}; - -/* -| Internal private function forward declarations (in alphabetical order): -*/ -static const char *AntennaNumberToName(unsigned short Number); -static void CheckCmrFlags(cmr_t *Cmr, unsigned char *p); -static int CheckMessageChecksum(unsigned char *MessageBuffer); -static int CheckMessageFlags(raw_t *Raw); -static int CheckStation(raw_t *Raw, unsigned int StationID); -static gtime_t CmrTimeToGtime(unsigned int CmrTime); -static gtime_t DoubleToGtime(double Time); -static int DecodeCmr(raw_t *Raw); -static int DecodeCmrPlus(raw_t *Raw); -static int DecodeBuffer(raw_t *Raw); -static int DecodeCmrType0(raw_t *Raw); -static int DecodeCmrType1(raw_t *Raw); -static int DecodeCmrType2(raw_t *Raw); -static int DecodeCmrType3(raw_t *Raw); -static int DecodeCmrType4(raw_t *Raw); -static double GtimeToDouble(gtime_t Time); -static int OutputCmrObs(raw_t *Raw, obsb_t *Obs); -static const char *ReceiverNumberToName(unsigned short Number); -static int ReferenceCmrObs(raw_t *Raw, gtime_t Time, unsigned char Type, double P0, obsbd_t *Obs); -static gtime_t ReferenceCmrTime(gtime_t CmrTime, gtime_t RoverTime, double WindowSize); -static int sbitn(const unsigned char *Address, int BitPosition, int BitLength); -static void SetStationCoordinates(raw_t *Raw, unsigned char *p); -static void SetStationDescription(raw_t *Raw, unsigned char *p, size_t Length); -static void SetStationInfo(raw_t *Raw, unsigned char *p); -static void StatusReport(raw_t *Raw); -static int SyncMessage(cmr_t *Cmr, unsigned char Data); -static size_t TrimCopy(char *Destination, size_t DestinationLength, char *Source, size_t SourceLength); -static unsigned int ubitn(const unsigned char *Address, int BitPosition, int BitLength); - -/* -| Public functions (in alphabetical order): -*/ - -/* free_cmr - Free up CMR dependent private storage */ -EXPORT void free_cmr(raw_t *Raw) -{ - cmr_t *Cmr = NULL; - - if (Raw->format != STRFMT_CMR) - return; - - if ((Cmr = (cmr_t*) Raw->rcv_data)) - { - if (Cmr->Buffer) - { - free(Cmr->Buffer); - Cmr->Buffer = NULL; - } - - if (Cmr->MessageBuffer) - { - free(Cmr->MessageBuffer); - Cmr->MessageBuffer = NULL; - } - - if (Cmr->RoverObservables) - { - free(Cmr->RoverObservables); - Cmr->RoverObservables = NULL; - } - - if (Cmr->T4Data) - { - free(Cmr->T4Data); - Cmr->T4Data = NULL; - } - - free(Cmr); - Raw->rcv_data = NULL; - } -} - -/* init_cmr = Initialize CMR dependent private storage */ -EXPORT int init_cmr(raw_t *Raw) -{ - cmr_t *Cmr = NULL; - obsr_t *RoverObservables = NULL; - obsbd_t *T4Data = NULL; - unsigned char *MessageBuffer = NULL, *Buffer = NULL; - - if (Raw->format != STRFMT_CMR) - return 0; - - if (!(Cmr = (cmr_t*) calloc(1, sizeof(cmr_t)))) - { - tracet(0, "CMR: init_cmr(); unable to allocate CMR dependent private data structure.\n"); - return 0; - } - Raw->rcv_data = (void*) Cmr; - - if (!(Buffer = (unsigned char*) calloc(BUFFER_LENGTH, sizeof(unsigned char)))) - { - tracet(0, "CMR: init_cmr(); unable to allocate CMR+ message buffer.\n"); - free_cmr(Raw); - return 0; - } - Cmr->Buffer = Buffer; - - if (!(MessageBuffer = (unsigned char*) calloc(MESSAGEBUFFER_LENGTH, sizeof(unsigned char)))) - { - tracet(0, "CMR: init_cmr(); unable to allocate CMR message buffer.\n"); - free_cmr(Raw); - return 0; - } - Cmr->MessageBuffer = MessageBuffer; - - if (!(RoverObservables = (obsr_t*) calloc(MAXSAT, sizeof(obsr_t)))) - { - tracet(0, "CMR: init_cmr(); unable to allocate rover observables table.\n"); - free_cmr(Raw); - return 0; - } - Cmr->RoverObservables = RoverObservables; - - if (!(T4Data = (obsbd_t*) calloc(MAXOBS, sizeof(obsbd_t)))) - { - tracet(0, "CMR: init_cmr(); unable to allocate high speed GPS observations reference table.\n"); - free_cmr(Raw); - return 0; - } - Cmr->T4Data = T4Data; - - return 1; -} - -/* -| input_cmr - Read a CMR data stream -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 1: input observation data -| 5: input station pos/ant parameters -| -| Supported CMR messages: 0, 1, 2, 3, 4; CMR+ messages 1, 2, 3. -*/ -EXPORT int input_cmr(raw_t *Raw, unsigned char Data) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - unsigned char *MessageBuffer = Cmr->MessageBuffer; - int Ret; - - /* If no current message */ - if (!Cmr->MessageBytes) - { - /* Find something that looks like a message */ - if (SyncMessage(Cmr, Data)) - { - /* Found one */ - Cmr->MessageLength = 4 + (unsigned char) MessageBuffer[3] + 2; /* 4 (header) + length + 2 (trailer) */ - Cmr->MessageBytes = 4; /* We now have four bytes in the stream buffer */ - } - - /* Continue reading the rest of the message from the stream */ - return CheckMessageFlags(Raw); - } - - /* Store the next byte of the message */ - MessageBuffer[Cmr->MessageBytes++] = Data; - - /* - | Keep storing bytes into the current message - | until we have what we think are all of them. - */ - if (Cmr->MessageBytes < Cmr->MessageLength) - return CheckMessageFlags(Raw); - - /* - | At this point we think have an entire message. - | The prospective message must end with an ETX. - */ - if (MessageBuffer[Cmr->MessageLength-1] != ETX) - { - tracet(2, "CMR: Message did not end with an ETX character. Some data lost.\n"); - Cmr->MessageBytes = 0; - return CheckMessageFlags(Raw); - } - - /* - | We do indeed have an entire message. - | Check the message checksum. - */ - if (!CheckMessageChecksum(MessageBuffer)) - { - tracet(2, "CMR: Message checksum failure. Message discarded.\n"); - Cmr->MessageBytes = 0; - return CheckMessageFlags(Raw); - } - - /* For the RTK monitor */ - if (Raw->outtype) - sprintf(Raw->msgtype, "CMR: 0x%02X (%4d)", MessageBuffer[2], Cmr->MessageLength); - - StatusReport(Raw); - - /* If this is a CMR message, then decode it */ - if (MessageBuffer[2] == CMR) - { - Ret = DecodeCmr(Raw); - Cmr->MessageBytes = 0; - return Ret; - } - - /* If this is a CMR+ message, then decode it */ - if (MessageBuffer[2] == CMRPLUS) - { - Ret = DecodeCmrPlus(Raw); - Cmr->MessageBytes = 0; - return Ret; - } - - /* - | If we fall through to here, then the message is not one that we support - | (and hence we can't really even get here). Dump the message on the floor - | and continue reading from the stream. - */ - tracet(2, "CMR: Message is not CMR or CMR+. Message discarded.\n"); - Cmr->MessageBytes = 0; - - return CheckMessageFlags(Raw); -} - -/* -| input_cmrf - Read a CMR mesasge from a file -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 1: input observation data -| 5: input station pos/ant parameters -| -| Supported CMR messages: 0, 1, 2, 3, 4; CMR+ messages 1, 2, 3. -*/ -extern int input_cmrf(raw_t *Raw, FILE *fp) -{ - int i, Data, Ret; - - for (i = 0; i < 4096; i++) - { - if ((Data = fgetc(fp)) == EOF) return -2; - if ((Ret = input_cmr(Raw, (unsigned char) Data))) return Ret; - } - - return 0; /* return at every 4k bytes */ -} - -/* -| update_cmr - Update the CMR rover observations table -| -| Returns: -| -| -1: error -| 0: no error -| -| Call this function in the RTK SERVER immediately -| after any rover observations have been received. -*/ -extern int update_cmr(raw_t *Raw, rtksvr_t *Svr, obs_t *obs) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - obsr_t *RoverObsTable = (obsr_t*) Cmr->RoverObservables; - obsd_t *r; int n; unsigned char Sat; - - Cmr->Svr = Svr; - - for (n = 0; (n < obs->n) && (n < MAXOBS); n++) - { - r = &obs->data[n]; - Sat = r->sat; - - if ((Sat < MAXSAT) && (r->rcv != 2) && (timediff(r->time, RoverObsTable[Sat].Time) > 0)) - { - RoverObsTable[Sat].Time = r->time; - RoverObsTable[Sat].P = r->P[0]; - RoverObsTable[Sat].Valid = TRUE; - } - } - - return 0; -} - -/* -| Private functions (in alphabetical order): -*/ - -/* AntennaNumberToName - Lookup antenna name by antenna number */ -static const char *AntennaNumberToName(unsigned short Number) -{ - int i, j, k, n; - - /* Binary search */ - for (i = 0, j = (sizeof(AntennasTable) / sizeof(ant_t)) - 1; i < j;) - { - k = (i + j) / 2; - n = AntennasTable[k].Number; - if (n == Number) - return AntennasTable[k].Name; - else if (n < Number) - i = k + 1; - else - j = k; - } - - return "UNKNOWN EXT NONE"; -} - -/* CheckCmrFlags - Check the CMR type 1 and 2 flags */ -static void CheckCmrFlags(cmr_t *Cmr, unsigned char *p) -{ - unsigned int Flags = ubitn(p+1,0,5); - - if (Flags & M_CFLAG_LOW_BATTERY) - Cmr->CurrentMessages |= M_MFLAG_LOWBATMSG1; - else - Cmr->CurrentMessages &= ~M_MFLAG_LOWBATMSG1; - - if (Flags & M_CFLAG_LOW_MEMORY) - Cmr->CurrentMessages |= M_MFLAG_LOWMEMMSG1; - else - Cmr->CurrentMessages &= ~M_MFLAG_LOWMEMMSG1; - - if (!(Flags & M_CFLAG_L2ENABLE)) - Cmr->CurrentMessages |= M_MFLAG_NOL2MSG1; - else - Cmr->CurrentMessages &= ~M_MFLAG_NOL2MSG1; -} - -/* -| CheckMessageChecksum - Check the message checksum -| -| The checksum is computed as the modulo 256 (unsigned 8-bit byte integer) -| sum of the message contents starting with the status byte, including the -| message type byte, length byte, data bytes and ending with the last byte -| of the data bytes. It does not include the STX leader, the ETX trailer -| nor the checksum byte. -*/ -static int CheckMessageChecksum(unsigned char *MessageBuffer) -{ - unsigned char Checksum = 0; - unsigned char *p = &MessageBuffer[1]; /* Starting with status */ - unsigned int Length = MessageBuffer[3] + 3;/* status, type, length, data */ - - /* Compute the message checksum */ - while (Length > 0) - { - Checksum += *p++; - Length--; - } - - /* - | Make sure our computed checksum matches the one at the end of the - | message. (Note that the above loop by design very conveniently left - | *p pointing to the checksum byte at the end of the message.) - */ - return (Checksum == *p); -} - -/* CheckMessageFlags - Check for a message */ -static int CheckMessageFlags(raw_t *Raw) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - char msg[128] = {0}; - - if (Cmr->CurrentMessages != Cmr->PreviousMessages) - { - if (Cmr->CurrentMessages & (M_MFLAG_LOWBATMSG1|M_MFLAG_LOWBATMSG2|M_MFLAG_LOWBATMSG3)) - strcat(msg, "Low battery at the base"); - - if (Cmr->CurrentMessages & (M_MFLAG_LOWMEMMSG1|M_MFLAG_LOWMEMMSG2|M_MFLAG_LOWMEMMSG3)) - { - if (strlen(msg)) strcat(msg,", "); - strcat(msg, "Low memory at the base"); - } - - if (Cmr->CurrentMessages & (M_MFLAG_NOL2MSG1|M_MFLAG_NOL2MSG2)) - { - if (strlen(msg)) strcat(msg, ", "); - strcat(msg, "L2 disabled at the base"); - } - - if (strlen(msg)) strcat(msg, "."); - - Cmr->PreviousMessages = Cmr->CurrentMessages; - - /* ### WHERE TO PLACE THE BASE STATUS MESSAGE? ### */ -#if 0 - strncpy(rtcm->msg, msg, sizeof(rtcm->msg) - 1); - tracet(2, "CMR: %s\n", msg); -#endif - } - - return 0; -} - -/* CheckStation - Check the Station ID number */ -static int CheckStation(raw_t *Raw, unsigned int StationID) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - unsigned int ID; - char *p; - - /* If an explicit Station ID has been specified, then enforce it */ - if ((p = strstr(Raw->opt, "-STA=")) && sscanf(p, "-STA=%u", &ID) == 1) - { - if (StationID != ID) - { - tracet(2, "CMR: Message with wrong Base Station ID (%d) ignored.\n", StationID); - return 0; - } - } - - /* - | We're accepting any Station ID. - | Let them know what it is and if it changes on them. - */ - if (!Cmr->StationID) - tracet(2, "CMR: Base Station ID set to %d.\n", StationID); - else if (Cmr->StationID != StationID) - tracet(2, "CMR: Base Station ID changed from %d to %d.\n", Cmr->StationID, StationID); - - Cmr->StationID = StationID; - - return 1; -} - -/* Convert CMR time in milliseconds to a gtime_t time */ -static gtime_t CmrTimeToGtime(unsigned int CmrTime) -{ - return DoubleToGtime(CmrTime*0.001); -} - - -/* -| DecodeCmr - Decode a CMR message -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 1: input observation data -| 5: input station pos/ant parameters -| -| The CMR record format is divided into header portions and a data portions. -| See reference #1 and reference #3 for more information. -| -| Supported CMR message types: 0, 1, 2, 3, 4 -| -| 0. GPS Observables -| -| This message contains a GPS observables header followed by multiple -| GPS observables blocks containing L1 observables. Each L1 observables -| block can optionally be followed by an L2 observable block. Documented -| in reference #1. -| -| 1. ECEF Reference Station Coordinates -| -| This message contains a reference Station Coordinates header followed -| by an Earth-Centred, Earth-Fixed Coordinates Data Block. Documented in -| reference #1. -| -| 2. Reference Station Description -| -| This message contains a Reference Station Description Header followed -| by a Station Description Data Block. Documented in reference #1. -| -| 3. GLONASS Observables (NOT YET TESTED WITH A REAL RECEIVER) -| -| This message contains a GLONASS observables header followed by multiple -| GLONASS observable blocks containing L1 observables. Each L1 observables -| block can optionally be followed by an L2 observables block. Documented -| in reference #3. -| -| 4. High Speed Observables -| -| This message contains a high speed observables header followed by -| multiple high speed observable blocks containing 24 bits of L1 carrier -| phase observables and 16 bits of IONO? something or other corresponding -| to each PRN that was transmitted in the immediately prior CMR type 0 -| message. The transmitted carrier phase values are deltas based on those -| contained in prior CMR type 0 message. -*/ -static int DecodeCmr(raw_t *Raw) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - int Ret = 0; - char *Type_s = NULL; - unsigned char *p = (unsigned char*) &Cmr->MessageBuffer[4]; - unsigned int Type = ubitn(p+1,5,3), Version = ubitn(p,5,3); - - if (GtimeToDouble(Raw->time) == 0.0) - Raw->time = utc2gpst(timeget()); - - if (Type < (sizeof(CMRTable) / sizeof(char*))) - Type_s = (char*) CMRTable[Type]; - - if (!Type_s) - Type_s = "Unknown"; - - tracet(3, "CMR: Trimble Packet Type=0x93 (CMR), CMR Type=%u (%s), CMR Version=%u, Length=%d.\n", Type, Type_s, Version, Cmr->MessageLength); - - /* - | We support version 3 and below for all messages except message type 4 - | for which we support version 4 only. - */ - if ((Version > 3) && !((Version == 4) && (Type == 4))) - { - tracet(2, "CMR: Unsupported CMR type %u message version: %u\n", Type, Version); - return -1; - } - - /* Decode (or possibly ignore) the message */ - switch (Type) - { - case CMR_TYPE_0: - Ret = DecodeCmrType0(Raw); - break; - case CMR_TYPE_1: - Ret = DecodeCmrType1(Raw); - break; - case CMR_TYPE_2: - Ret = DecodeCmrType2(Raw); - break; - case CMR_TYPE_3: - Ret = DecodeCmrType3(Raw); - break; - case CMR_TYPE_4: - Ret = DecodeCmrType4(Raw); - break; - default: - tracet(2, "CMR: Unsupported CMR message type %u ignored.\n", Type); - } - - /* ### WHERE TO PLACE THE VARIOUS BASE MESSAGE TYPE COUNTS? ### */ -#if 0 - rtcm->nmsg2[Type]++; -#endif - - return Ret; -} - -/* -| DecodeCmrPlus - Decode a CMR+ message -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 1: input observation data -| 5: input station pos/ant parameters -| -| CMR+ is also known as CMR type 5 which is funny because it comes in -| from the base as a separate message 0x94 instead of 0x93 and contains -| no classic CMR header with version and type fields as described for -| CMR in reference #1. -| -| CMR+ messages can be (and are) interleaved with CMR messages. When -| CMR+ messages are being sent CMR message types 1 and 2, containing -| basically the same information, are normally supressed (otherewise -| there would be no point to CMR+). -| -| We can't process CMR+ messages immediately as they are received -| because they are incomplete. They are each just a small incomplete -| portion of an original whole message that has been broken down on -| arbitrary boundaries and tricked out over time. We must buffer all -| the little pieces, wait for them all to come in, assemble the whole -| original message from the little parts, then process it. It takes -| 15 seconds for a full CMR+ message to be received and assembled. -| -| Each small incomplete portion has a header consisting of a station -| number byte, a page number byte, a total number of pages byte, then -| some payload data bytes. We strip off the station number, page number -| and total pages bytes, then concatenate the payload data from each -| page together in page order into a single monolithic message. This -| larger message as assembled then consists of a header containing a -| type byte and a length byte followed by message data, then another -| header consisting of a type byte and a length byte followed by -| message data, etcetera, etcetera until the message ends. The length -| bytes within this message are all high by two because they count the -| header in the length. -*/ -static int DecodeCmrPlus(raw_t *Raw) -{ - int Page, Pages, Ret = 0; - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - unsigned char *Buffer = (unsigned char*) Cmr->Buffer; - unsigned int StationID, Length = Cmr->MessageBuffer[3] - 3; - unsigned char *p = (unsigned char*) &Cmr->MessageBuffer[4]; - - if (GtimeToDouble(Raw->time) == 0.0) - Raw->time = utc2gpst(timeget()); - - StationID = *p++; - Page = *p++; - Pages = *p++; - - tracet(3, "CMR: Trimble Packet Type=0x94 (CMR+), Base Station=%u, Page=%d of %d.\n", StationID, Page, Pages); - - if (!CheckStation(Raw, StationID)) - return 0; - - if (((Page == Pages) && Cmr->BufferBytes) || ((Page == 0) && (Pages == 0))) - { - /* - | It's the last page or the only page. Either way process it. - | But first check for buffer overflow. - */ - if ((Page != 0) && ((Cmr->BufferBytes + Length) > BUFFER_LENGTH)) - { - tracet(2, "CMR: Buffer would overflow. %d CMR+ messages discarded.\n", Pages+1); - memset(Buffer, 0, BUFFER_LENGTH); - Cmr->BufferBytes = 0; - Cmr->Page = 0; - return 0; - } - - memcpy(Buffer + Cmr->BufferBytes, p, Length); - Cmr->BufferBytes += Length; - Cmr->Page = 0; - - Ret = DecodeBuffer(Raw); - } - else if (Page == 0) - { - /* - | Cool it's page zero. Clear the buffer and add it to the buffer. - | But first check for buffer overflow. - */ - memset(Buffer, 0, BUFFER_LENGTH); - if (Length > BUFFER_LENGTH) - { - tracet(2, "CMR: Buffer would overflow. %d CMR+ messages discarded.\n", Pages+1); - Cmr->BufferBytes = 0; - Cmr->Page = 0; - return 0; - } - - memcpy(Buffer, p, Length); - Cmr->BufferBytes = Length; - Cmr->Page = 0; - } - else if (Cmr->BufferBytes) - { - /* - | It's not page zero, not the last page, but we have accumulated - | some prior pages. We must be in the middle of accumulating a set - | of pages starting from page zero and working our way up to the - | last page. Make sure this page is the one we're expecting. If it - | is, then concatenate it to the buffer. If it isn't the one we're - | expecting, then it's an out of order page so dump the buffer and - | start over. - */ - if (Page == (Cmr->Page + 1)) - { - /* But first check for buffer overflow */ - if ((Cmr->BufferBytes + Length) > BUFFER_LENGTH) - { - tracet(2, "CMR: Buffer would overflow. %d CMR+ messages discarded.\n", Pages+1); - memset(Buffer, 0, BUFFER_LENGTH); - Cmr->BufferBytes = 0; - Cmr->Page = 0; - return 0; - } - - memcpy(Buffer + Cmr->BufferBytes, p, Length); - Cmr->BufferBytes += Length; - Cmr->Page = Page; - } - else - { - memset(Buffer, 0, BUFFER_LENGTH); - Cmr->BufferBytes = 0; - Cmr->Page = 0; - } - } - else - { - /* - | It's not page zero, not the last page and we haven't already - | accumulated anything into our page buffer. We must have started - | receiving the stream already in progress in the middle somewhere. - | Ignore all further pages until next page zero comes along. - */ - Cmr->Page = 0; - } - - return Ret; -} - -/* -| DecodeBuffer - Decode a set of buffered CMR+ messages -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 1: input observation data -| 5: input station pos/ant parameters -| -| Supported CMR+ message types: 1, 2, 3 -| -| 1. Reference Station Information -| -| After the type and length byte this message contains 16 bits worth of -| flag bits, a receiver number byte and an antenna number byte. This is -| new with CMR+ and has no equivilent in CMR. -| -| 2. ECEF Reference Station Coordinates -| -| After the type and length byte this message contains the Earth-Centred, -| Earth-Fixed Coordinates Data Block in the same format as in CMR. -| -| 3. Reference Station Description -| -| After the type and length byte this message contains the Station -| Description Data Block in the same format as in CMR. -| -| Fortunately these all require the same function return value of 5. -| That makes them nicely compatible with the RTKLIB architecture. -*/ -static int DecodeBuffer(raw_t *Raw) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - unsigned char *Buffer = (unsigned char*) Cmr->Buffer; - char *Type_s = NULL; - int BufferBytes = Cmr->BufferBytes; - unsigned int Type; - size_t Length; - - while (BufferBytes > 0) - { - Type = Buffer[0]; - Length = Buffer[1]; - - if (Type < (sizeof(CMRplusTable) / sizeof(char*))) - Type_s = (char*) CMRplusTable[Type]; - - if (!Type_s) - Type_s = "Unknown"; - - tracet(3, "CMR: CMR+ Message type=%u (%s), Length=%u.\n", Type, Type_s, Length); - - switch (Type) - { - case CMRPLUS_TYPE_1: - SetStationInfo(Raw, &Buffer[2]); - break; - case CMRPLUS_TYPE_2: - SetStationCoordinates(Raw, &Buffer[2]); - break; - case CMRPLUS_TYPE_3: - SetStationDescription(Raw, &Buffer[2], Length-2); - break; - default: - tracet(2, "CMR: Unsupported CMR+ message type %u ignored.\n", Type); - } - - /* ### WHERE TO PLACE THE VARIOUS BASE MESSAGE TYPE COUNTS? ### */ -#if 0 - rtcm->nmsg3[Type]++; -#endif - - Buffer += Length; - BufferBytes -= Length; - } - - return 5; -} - -/* -| DecodeCmrType0 - Decode CMR GPS Observables -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 1: input observation data -*/ -static int DecodeCmrType0(raw_t *Raw) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - unsigned char *p = (unsigned char*) &Cmr->MessageBuffer[4]; - unsigned int L1Flags, L2Flags, nsat = ubitn(p+1,0,5), Slot, StationID = ubitn(p,0,5); - gtime_t CmrTime = CmrTimeToGtime(ubitn(p+4,6,18)); - obsb_t Obs; obsbd_t *b; - int Prn, Sat; - - if (!CheckStation(Raw, StationID)) - return 0; - - memset(&Obs, 0, sizeof(Obs)); - Obs.Time = CmrTime; - Obs.Type = CMR_TYPE_0; - - /* Position past the header */ - p += 6; - - for (Slot = 0; (Slot < nsat) && (Slot < MAXOBS); Slot++) - { - b = &Obs.Data[Obs.n]; - b->Slot = Slot; - - if (!(Prn = ubitn(p,3,5))) Prn = 32; - L1Flags = ubitn(p,0,3); - b->P[0] = (ubitn(p+3,0,24) / 8.0) * L1_WAVELENGTH; - if (L1Flags & M_L1_PHASE_VALID) - b->L[0] = sbitn(p+6,4,20) / 256.0; - b->Code[0] = (L1Flags & M_L1_PCODE) ? CODE_L1P : CODE_L1C; - b->SNR[0] = 28+(ubitn(p+6,0,4)*2); - b->Slip[0] = ubitn(p+7,0,8); - - /* Position past the L1 observables block */ - p += 8; - - if (L1Flags & M_L1_L2_FOLLOWS) - { - L2Flags = ubitn(p,3,5); - - if ((L2Flags & M_L2_CODE_AVAILABLE) && (L2Flags & M_L2_CODE_VALID)) - { - b->P[1] = sbitn(p+2,0,16) / 100.0; - b->Code[1] = (L2Flags & M_L2_WCODE) ? CODE_L2W : CODE_L2P; - if (L2Flags & M_L2_WCODE) - b->LLI[1] |= 4; /* Tracking encrypted code */ - } - - if ((L2Flags & M_L2_PHASE_VALID) && (L2Flags & M_L2_PHASE_FULL)) - b->L[1] = sbitn(p+5,4,20) / 256.0; - - b->SNR[1] = 28+(ubitn(p+5,0,4)*2); - b->Slip[1] = ubitn(p+6,0,8); - - /* Position past the L2 observables block */ - p += 7; - } - - if (!(b->Sat = satno(SYS_GPS, Prn))) - { - tracet(1, "CMR: GPS satellite number error, PRN=%d.\n", Prn); - continue; - } - - Sat = b->Sat - 1; - if (Cmr->SlipV[Sat][0] && Cmr->SlipC[Sat][0] != b->Slip[0]) b->LLI[0] |= 1; - if (Cmr->SlipV[Sat][1] && Cmr->SlipC[Sat][1] != b->Slip[1]) b->LLI[1] |= 1; - Cmr->SlipC[Sat][0] = b->Slip[0]; - Cmr->SlipC[Sat][1] = b->Slip[1]; - Cmr->SlipV[Sat][0] = TRUE; - Cmr->SlipV[Sat][1] = TRUE; - - Obs.n++; - } - - return (Obs.n > 0) ? OutputCmrObs(Raw, &Obs) : 0; -} - -/* -| DecodeCmrType1 - Decode CMR ECEF Reference Station Coordinates -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 5: input station pos/ant parameters -*/ -static int DecodeCmrType1(raw_t *Raw) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - unsigned char *p = (unsigned char*) &Cmr->MessageBuffer[4]; - unsigned int StationID = ubitn(p, 0, 5); - - if (!CheckStation(Raw, StationID)) - return 0; - - CheckCmrFlags(Cmr, p); - - /* Position past the header */ - p += 6; - - SetStationCoordinates(Raw, p); - return 5; -} - -/* -| DecodeCmrType2 - Decode CMR Reference Station Description -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 5: input station pos/ant parameters -*/ -static int DecodeCmrType2(raw_t *Raw) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - unsigned char *p = (unsigned char*) &Cmr->MessageBuffer[4]; - unsigned int Length, StationID = ubitn(p, 0, 5); - - if (!CheckStation(Raw, StationID)) - return 0; - - CheckCmrFlags(Cmr, p); - - /* - | Position past the header. - | Fetch the length. - | Position past the length. - */ - p += 6; - Length = *p; - p++; - - SetStationDescription(Raw, p, Length); - - return 5; -} - -/* -| DecodeCmrType3 - Decode CMR GLONASS Observables -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 1: input observation data -| -| According to reference #3 the epoch time in the CMR type 3 observables -| header is similar to the CMR type 1 header except that it is UTC time -| instead of GLONASS or GPS time. We convert it to GPS time. -*/ -static int DecodeCmrType3(raw_t *Raw) -{ - double L1WaveLength; - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - rtksvr_t *Svr = Cmr->Svr; - nav_t *Nav = (Svr) ? &Svr->nav : &Raw->nav; - unsigned char *p = (unsigned char*) &Cmr->MessageBuffer[4]; - gtime_t CmrTime = utc2gpst(CmrTimeToGtime(ubitn(p+4,6,18))); - unsigned int L1Flags, L2Flags, nsat = ubitn(p+1,0,5), Slot, StationID = ubitn(p,0,5); - obsb_t Obs; obsbd_t *b; - int Prn, Sat; - - /* ### NEEDS ALPHA TESTING BY SOMEONE WITH APPROPRIATE RECEIVERS ### */ - tracet(2, "CMR: WARNING: CMR type 3 (GLONASS) support is untested.\n"); - - if (!CheckStation(Raw, StationID)) - return 0; - - memset(&Obs, 0, sizeof(Obs)); - Obs.Time = CmrTime; - Obs.Type = CMR_TYPE_3; - - /* Position past the header */ - p += 6; - - for (Slot = 0; (Slot < nsat) && (Slot < MAXOBS); Slot++) - { - b = &Obs.Data[Obs.n]; - memset(b, 0, sizeof(obsd_t)); - b->Slot = Slot; - - if (!(Prn = ubitn(p,3,5))) Prn = 32; - L1Flags = ubitn(p,0,3); - b->P[0] = ubitn(p+3,0,24) / 8.0; - if (L1Flags & M_L1_PHASE_VALID) - b->L[0] = sbitn(p+6,4,20) / 256.0; - b->Code[0] = (L1Flags & M_L1_PCODE) ? CODE_L1P : CODE_L1C; - b->SNR[0] = SnrTable[ubitn(p+6,0,4)][0]; - b->Slip[0] = ubitn(p+7,0,8); - - /* Position past the L1 observables block */ - p += 8; - - if (L1Flags & M_L1_L2_FOLLOWS) - { - L2Flags = ubitn(p,3,5); - - if ((L2Flags & M_L2_CODE_AVAILABLE) && (L2Flags & M_L2_CODE_VALID)) - { - b->P[1] = sbitn(p+2,0,16) / 100.0; - b->Code[1] = (L2Flags & M_L2_PCODE) ? CODE_L2C : CODE_L2P; - } - - if ((L2Flags & M_L2_PHASE_VALID) && (L2Flags & M_L2_PHASE_FULL)) - b->L[1] = sbitn(p+5,4,20) / 256.0; - - b->SNR[1] = SnrTable[ubitn(p+5,0,4)][1]; - b->Slip[1] = ubitn(p+6,0,8); - - /* Position past the L2 observables block */ - p += 7; - } - - if (!(b->Sat = satno(SYS_GLO, Prn))) - { - tracet(1, "CMR: GLONASS satellite number error, PRN=%d.\n", Prn); - continue; - } - - if ((L1WaveLength = satwavelen(b->Sat, 0, Nav)) == 0.0) - { - tracet(0, "CMR: internal error; satwavelen() failure.\n"); - continue; - } - b->P[0] *= L1WaveLength; - - Sat = b->Sat - 1; - if (Cmr->SlipV[Sat][0] && Cmr->SlipC[Sat][0] != b->Slip[0]) b->LLI[0] |= 1; - if (Cmr->SlipV[Sat][1] && Cmr->SlipC[Sat][1] != b->Slip[1]) b->LLI[1] |= 1; - Cmr->SlipC[Sat][0] = b->Slip[0]; - Cmr->SlipC[Sat][1] = b->Slip[1]; - Cmr->SlipV[Sat][0] = TRUE; - Cmr->SlipV[Sat][1] = TRUE; - - Obs.n++; - } - - return (Obs.n > 0) ? OutputCmrObs(Raw, &Obs) : 0; -} - -/* -| DecodeCmrType4 - Decode CMR High Speed Observables -| -| Returns: -| -| -1: error message -| 0: no message (tells caller to please read more data from the stream) -| 1: input observation data -| -| The CMR type 4 message is for high speed observables (5, 10, or 20 Hz). -| Support for this message is limited to utilizing the GPS L1 carrier phase -| observables contained therein. This message also contains other data, but -| I'm not certain exactly what that data is nor how RTKLIB might utilize it. -| The GPS L1 carrier phase observables are 24 bit twos complement signed -| deltas from those which where transmitted at the last CMR type 0 message. -| The PRN numbers are not re-transmitted and are assumed to be the same -| ones in the same order transmitted in the last CMR type 0 message. -| -| So far as I know this is a GPS only message and it has not been extended -| to GLONASS. I therefore make the assumption herein that CMR type 3 messages -| are transparent to CMR type 4 messages. But I could be wrong about that. -| I don't have suitable receivers with which to test that assumption. If -| this assumption is incorrect it is trivially easy so correct it - so long -| as one also knows how to tell a GLONASS type 4 message from a GPS type -| 4 message. Presumably there would be something either in the header or -| somewhere else to indicate that. -| -| I suppose the fastest these could possibly be sent would be every four -| milliseconds or 250Hz because the time in the message header is in units -| of four milliseconds. -*/ -static int DecodeCmrType4(raw_t *Raw) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - obsbd_t *t4 = (obsbd_t*) Cmr->T4Data; - unsigned char *p = (unsigned char*) &Cmr->MessageBuffer[4]; - gtime_t CmrTime = CmrTimeToGtime(ubitn(p+4,6,10)<<2); - unsigned int nsat = ubitn(p+1,0,5), Slot, StationID = ubitn(p,0,5); - obsb_t Obs; obsbd_t *b; - - if (!CheckStation(Raw, StationID)) - return 0; - - memset(&Obs, 0, sizeof(Obs)); - Obs.Time = CmrTime; - Obs.Type = CMR_TYPE_4; - - /* Position past the header */ - p += 6; - - for (Slot = 0; (Slot < nsat) && (Slot < MAXOBS); Slot++) - { - b = &Obs.Data[Obs.n]; - memset(b, 0, sizeof(obsd_t)); - b->Slot = Slot; - b->Sat = t4[b->Slot].Sat; - - b->L[0] = sbitn(p+2,0,24); - b->L[0] = (b->L[0] == 8388608.0) ? 0.0 : b->L[0] / 256.0; - - /* - | Position past the L1 observables block. 24 bits for an L1 carrier - | phase delta plus another 16 bits for something called "IONO". - */ - p += 5; - - if (!b->Sat || (b->L[0] == 0.0)) - continue; - - Obs.n++; - } - - return (Obs.n > 0) ? OutputCmrObs(Raw, &Obs) : 0; -} - -/* Convert a double to a gtime_t time */ -static gtime_t DoubleToGtime(double Double) -{ - gtime_t Gtime; - Gtime.time = floor(Double); - Gtime.sec = Double - Gtime.time; - return Gtime; -} - -/* Convert a gtime_t time to a double */ -static double GtimeToDouble(gtime_t Gtime) -{ - return Gtime.sec + Gtime.time; -} - -/* Output a set of CMR base observations */ -static int OutputCmrObs(raw_t *Raw, obsb_t *Obs) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - rtksvr_t *Svr = Cmr->Svr; - obsr_t *r, *RoverObsTable = (obsr_t*) Cmr->RoverObservables; - obsbd_t *b; int n, Ret = 0; unsigned char Sat; - double WindowSize = (Obs->Type == CMR_TYPE_4) ? 4.0 : 240.0; - gtime_t ObsTime; - - Raw->obs.n = 0; - - if (Svr && RoverObsTable) - { - for (n = 0; !(Ret < 0) && (n < Obs->n) && (Raw->obs.n < MAXOBS); n++) - { - b = &Obs->Data[n]; - Sat = b->Sat; - r = &RoverObsTable[Sat]; - - if (r->Valid) - { - ObsTime = ReferenceCmrTime(Obs->Time, r->Time, WindowSize); - if (fabs(timediff(r->Time, ObsTime)) < MAXTIMEDIFF) - Ret = ReferenceCmrObs(Raw, ObsTime, Obs->Type, r->P, b); - } - } - } - else - { - /* Throw RTKCONV and CONVBIN a bone */ - for (n = 0; !(Ret < 0) && (n < Obs->n); n++) - Ret = ReferenceCmrObs(Raw, Obs->Time, Obs->Type, 0.0, &Obs->Data[n]); - } - - if (Raw->obs.n > 0) - { - tracet(2, "CMR: Base observations referenced and output:\n"); - traceobs(2, Raw->obs.data, Raw->obs.n); - } - - return (Ret < 0) ? Ret : (Raw->obs.n > 0); -} - -/* Reference and output a single CMR base observation */ -static int ReferenceCmrObs(raw_t *Raw, gtime_t Time, unsigned char Type, double P0, obsbd_t *b) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - obsbd_t *t4 = (obsbd_t*) Cmr->T4Data; - rtksvr_t *Svr = Cmr->Svr; - nav_t *Nav = (Svr) ? &Svr->nav : &Raw->nav; - obsd_t *obs = &Raw->obs.data[Raw->obs.n]; - double L0, L1WaveLength = L1_WAVELENGTH, L2WaveLength = L2_WAVELENGTH; - - if (Type == CMR_TYPE_0) - { - L1WaveLength = L1_WAVELENGTH; - L2WaveLength = L2_WAVELENGTH; - } - else if (Type == CMR_TYPE_3) - { - if ((L1WaveLength = satwavelen(b->Sat, 0, Nav) == 0.0) || - (L2WaveLength = satwavelen(b->Sat, 1, Nav) == 0.0)) - { - tracet(0, "CMR: internal error; satwavelen() failure.\n"); - return -1; - } - } - - /* Reference the CMR base observables */ - if ((Type != CMR_TYPE_4) && (P0 != 0.0)) - { - b->P[0] += P0 - fmod(P0, RANGE_MS); - if (b->L[0] != 0.0) - b->L[0] += b->P[0] / L1WaveLength; - if (b->P[1] != 0.0) - b->P[1] += b->P[0]; - if (b->L[1] != 0.0) - b->L[1] += b->P[0] / L2WaveLength; - } - - if (Type == CMR_TYPE_0) - memcpy(&t4[b->Slot], b, sizeof(obsbd_t)); - - if (Type == CMR_TYPE_4) - { - L0 = (Svr) ? b->L[0] + t4[b->Slot].L[0] : b->L[0]; - memcpy(b, &t4[b->Slot], sizeof(obsbd_t)); - b->L[0] = L0; -#if 0 - b->Code[0] = CODE_L1L; - b->Code[1] = CODE_NONE; -#endif - } - - memset(obs, 0, sizeof(obsd_t)); - - obs->rcv = 2; /* And we don't accept rcv=2 in update_cmr() as a rover */ - obs->time = Time; - obs->P[0] = b->P[0]; - obs->P[1] = b->P[1]; - obs->L[0] = b->L[0]; - obs->L[1] = b->L[1]; - obs->sat = b->Sat; - obs->code[0] = b->Code[0]; - obs->code[1] = b->Code[1]; - obs->SNR[0] = SNRATIO(b->SNR[0]); - obs->SNR[1] = SNRATIO(b->SNR[1]); - obs->LLI[0] = b->LLI[0]; - obs->LLI[1] = b->LLI[1]; - - Raw->time = Time; - Raw->obs.n++; - - return 1; -} - -/* ReceiverNumberToName - Lookup receiver name by receiver number */ -static const char *ReceiverNumberToName(unsigned short Number) -{ - int i, j, k, n; - - /* Binary search */ - for (i = 0, j = (sizeof(ReceiversTable) / sizeof(rcv_t)) - 1; i < j;) - { - k = (i + j) / 2; - n = ReceiversTable[k].Number; - if (n == Number) - return ReceiversTable[k].Name; - else if (n < Number) - i = k + 1; - else - j = k; - } - - return ""; -} - -/* ReferenceCmrTime- Reference the CMR base time to the rover time */ -static gtime_t ReferenceCmrTime(gtime_t CmrTime, gtime_t RoverTime, double WindowSize) -{ - double modtime = GtimeToDouble(RoverTime); - return DoubleToGtime((modtime - fmod(modtime, WindowSize)) + CmrTime.time + CmrTime.sec); -} - -/* -| sbitn - Fetch a bit aligned signed integer value -| -| Returns: Signed integer value -| -| Bits are numbered from least significant to most significant with bit -| zero in a byte being the least significant bit and bit 7 in a byte being -| the most significant bit. -| -| For the purposes of this function the input data is always considered to -| be big-endian. Bits beyond 7 are taken from bytes at increasingly lower -| addresses, not higher addresses. Works the same on big-endian or little -| endian machines. -| -| The minimum bit position is 0, the maximum bit position is 31, -| the minimum length is 1 and the maximum length is 32. Other values -| for position and length cause a zero value to be returned. -| -| Adapted from similar code written for RTKLIB by T.TAKASU. -*/ -static int sbitn(const unsigned char *Address, int BitPosition, int BitLength) -{ - unsigned int Number = ubitn(Address, BitPosition, BitLength); - if ((BitLength == 0) || (32 <= BitLength) || !(Number & (1 << (BitLength - 1)))) - return (int) Number; - Number |= (~0UL << BitLength); /* extend sign */ - return (int) Number; -} - -/* SetStationCoordinates - Set the station coordinates*/ -static void SetStationCoordinates(raw_t *Raw, unsigned char *p) -{ - sta_t *sta = &Raw->sta; - sta->pos[0] = ((sbitn(p+3, 0,32)*4.0)+ubitn(p+4, 6,2))*0.001; - sta->pos[1] = ((sbitn(p+9, 0,32)*4.0)+ubitn(p+10,6,2))*0.001; - sta->pos[2] = ((sbitn(p+15,0,32)*4.0)+ubitn(p+16,6,2))*0.001; - sta->del[0] = sbitn(p+11,0,14)*0.001; - sta->del[1] = sbitn(p+17,0,14)*0.001; - sta->del[2] = 0.0; - sta->hgt = sbitn(p+5, 0,14)*0.001; - sta->deltype = 0; /* e/n/u */ - - tracet(3, "CMR: Reference station coordinates received. X=%f, Y=%f, Z=%f, East offset=%f, North offset=%f, Up offset=0.0, Height=%f\n", - sta->pos[0], sta->pos[1], sta->pos[2], sta->del[0], sta->del[1], sta->hgt); -} - -/* SetStationDescription - Set the station description */ -static void SetStationDescription(raw_t *Raw, unsigned char *p, size_t Length) -{ - /* Set the station name with any leading or trailing nulls & white space trimmed off */ - sta_t *sta = &Raw->sta; - if (Length > 8) Length = 8; - memset(sta->name, 0, sizeof(sta->name)); - TrimCopy(sta->name, sizeof(sta->name) - 1, (char*) p, Length); - - tracet(3, "CMR: Reference station decription received. STATION=\"%s\"\n", sta->name); -} - -/* SetStationInfo - Set miscellaneous base station information */ -static void SetStationInfo(raw_t *Raw, unsigned char *p) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - sta_t *sta = &Raw->sta; - unsigned int Flags = ubitn(p+1,0,16); - - memset(sta->rectype, 0, sizeof(sta->rectype)); - strncpy(sta->rectype, ReceiverNumberToName(p[2]), sizeof(sta->rectype)-1); - memset(sta->antdes, 0, sizeof(sta->antdes)); - strncpy(sta->antdes, AntennaNumberToName(p[3]), sizeof(sta->antdes)-1); - - tracet(3, "CMR: Reference station information received. RECEIVER=\"%s\", ANTENNA=\"%s\"\n", sta->rectype, sta->antdes); - - if (Flags & M_PFLAG_LOW_BATTERY) - Cmr->CurrentMessages |= M_MFLAG_LOWBATMSG2; - else - Cmr->CurrentMessages &= ~M_MFLAG_LOWBATMSG2; - - if (Flags & M_PFLAG_LOW_MEMORY) - Cmr->CurrentMessages |= M_MFLAG_LOWMEMMSG2; - else - Cmr->CurrentMessages &= ~M_MFLAG_LOWMEMMSG2; - - if (!(Flags & M_PFLAG_L2ENABLE)) - Cmr->CurrentMessages |= M_MFLAG_NOL2MSG2; - else - Cmr->CurrentMessages &= ~M_MFLAG_NOL2MSG2; -} - -/* StatusReport - Output once a minute base status */ -static void StatusReport(raw_t *Raw) -{ - cmr_t *Cmr = (cmr_t*) Raw->rcv_data; - unsigned char Status = (unsigned char) Cmr->MessageBuffer[1]; - - if (Status & M_STATUS_LOW_BATTERY) - Cmr->CurrentMessages |= M_MFLAG_LOWBATMSG3; - else - Cmr->CurrentMessages &= ~M_MFLAG_LOWBATMSG3; - - if (Status & M_STATUS_LOW_MEMORY) - Cmr->CurrentMessages |= M_MFLAG_LOWMEMMSG3; - else - Cmr->CurrentMessages &= ~M_MFLAG_LOWMEMMSG3; -} - -/* SyncMessage - Synchronize the CMR data stream to the start of a series of CMR messages */ -static int SyncMessage(cmr_t *Cmr, unsigned char Data) -{ - unsigned char Type, *MessageBuffer = Cmr->MessageBuffer; - - MessageBuffer[0] = MessageBuffer[1]; - MessageBuffer[1] = MessageBuffer[2]; - MessageBuffer[2] = MessageBuffer[3]; - MessageBuffer[3] = Data; - - Type = MessageBuffer[2]; - - /* - | Byte 0 must be an STX character. - | Byte 1 = status byte which we always ignore (for now). - | Byte 2 = message type which must be CMR (93h) or CMR+ (94h). - | Byte 3 = data length which must be non-zero for any message we're interested in. - */ - return ((MessageBuffer[0] == STX) && (Data != 0) && ((Type == CMR) || (Type == CMRPLUS))); -} - -/* TrimCopy - Copy source to destination with trim */ -static size_t TrimCopy(char *Destination, size_t DestinationLength, char *Source, size_t SourceLength) -{ - char *e; - - /* - | Trim sequences leading and training spaces & nulls off the source. - | (Adjusts the starting address and the source length.) - */ - for (; (SourceLength > 0) && ((*Source == 0) || isspace(*Source)); Source++, SourceLength--); - for (e = Source + SourceLength - 1; (SourceLength > 0) && ((*e == 0) || isspace(*e)); e--, SourceLength--); - - /* Only copy as many characters as we actually have */ - if (DestinationLength > SourceLength) - DestinationLength = SourceLength; - - memcpy(Destination, Source, DestinationLength); - return DestinationLength; -} - -/* -| ubitn - Fetch a bit aligned unsigned integer value -| -| Returns: Unsigned integer value. -| -| Bits are numbered from least significant to most significant with bit -| zero in a byte being the least significant bit and bit 7 in a byte being -| the most significant bit. -| -| WARNING: For the purposes of this function The input data is always -| considered to be in network byte order (AKA BIG-ENDIAN or Motorola format). -| Bits beyond 7 are taken from bytes at increasingly lower addresses, not -| higher addresses. -| -| For the purposes of this function our machine endianess is irrelevant. -| -| The minimum bit position is 0, the maximum bit position is 31, -| the minimum length is 1 and the maximum length is 32. Other values -| for position and length cause a zero value to be returned. -| -| Adapted from similar code written for RTKLIB by T.TAKASU. -*/ -static unsigned int ubitn(const unsigned char *Address, int BitPosition, int BitLength) -{ - int i; - unsigned int n; - - if ((BitPosition < 0) || (BitPosition > 31) || (BitLength <= 0) || (BitLength > 32)) - { - tracet(0, "CMR: internal error; ubitn() bit position:length violation %u:%u.\n", BitPosition, BitLength); - return 0; - } - - for (n=0, i= BitPosition + BitLength - 1; i >= BitPosition; i--) - n = (n << 1) | ((*(Address - (i/8)) >> (i%8)) & 1UL); - - return n; -} diff --git a/RTKBASE/lib/rtklib/src/rcv/tersus.c b/RTKBASE/lib/rtklib/src/rcv/tersus.c deleted file mode 100644 index 98028c7..0000000 --- a/RTKBASE/lib/rtklib/src/rcv/tersus.c +++ /dev/null @@ -1,704 +0,0 @@ -/*------------------------------------------------------------------------------ -* tersus.c : Tersus Precis receiver functions -* -* Copyright (C) 2017 by T.TAKASU, All rights reserved. -* -* reference : -* [1] Tersus GNSS Inc., Command & Log Reference For Precis-BX306 & BX316 -* GNSS RTK Board, Version V1.0-20170421 -* -* version : $Revision:$ $Date:$ -* history : 2017/05/26 1.0 new -*-----------------------------------------------------------------------------*/ -#include "rtklib.h" - -static const char rcsid[]="$Id:$"; - -#define TERSUSSYNC1 0xAA /* tersus message start sync code 1 */ -#define TERSUSSYNC2 0x44 /* tersus message start sync code 2 */ -#define TERSUSSYNC3 0x12 /* tersus message start sync code 3 */ - -#define TERSUSHLEN 28 /* tersus message header length (bytes) */ - -#define ID_RANGE 43 /* message id: tersus range measurement */ -#define ID_RANGECMP 140 /* message id: tersus range compressed */ -#define ID_IONUTC 8 /* message id: tersus iono and utc data */ -#define ID_GPSEPHEM 7 /* message id: tersus gps ephemeris */ -#define ID_GLOEPHEMERIS 723 /* message id: tersus glonass ephemeris */ -#define ID_BDSEPHEMERIS 1696 /* message id: tersus beidou ephemeris */ - -#define MAXVAL 8388608.0 - -#define OFF_FRQNO -7 /* offset of glonass freq number */ - -/* get fields (little-endian) ------------------------------------------------*/ -#define U1(p) (*((unsigned char *)(p))) -static unsigned short U2(unsigned char *p) {unsigned short u; memcpy(&u,p,2); return u;} -static unsigned int U4(unsigned char *p) {unsigned int u; memcpy(&u,p,4); return u;} -static int I4(unsigned char *p) {int i; memcpy(&i,p,4); return i;} -static float R4(unsigned char *p) {float r; memcpy(&r,p,4); return r;} -static double R8(unsigned char *p) {double r; memcpy(&r,p,8); return r;} - -/* extend sign ---------------------------------------------------------------*/ -static int exsign(unsigned int v, int bits) -{ - return (int)(v&(1<<(bits-1))?v|(~0u<tow_p+302400.0) tow-=604800.0; - return gpst2time(week,tow); -} -/* get observation data index ------------------------------------------------*/ -static int obsindex(obs_t *obs, gtime_t time, int sat) -{ - int i,j; - - if (obs->n>=MAXOBS) return -1; - for (i=0;in;i++) { - if (obs->data[i].sat==sat) return i; - } - obs->data[i].time=time; - obs->data[i].sat=sat; - for (j=0;jdata[i].L[j]=obs->data[i].P[j]=0.0; - obs->data[i].D[j]=0.0; - obs->data[i].SNR[j]=obs->data[i].LLI[j]=0; - obs->data[i].code[j]=CODE_NONE; - } - obs->n++; - return i; -} -/* ura value (m) to ura index ------------------------------------------------*/ -static int uraindex(double value) -{ - static const double ura_eph[]={ - 2.4,3.4,4.85,6.85,9.65,13.65,24.0,48.0,96.0,192.0,384.0,768.0,1536.0, - 3072.0,6144.0,0.0 - }; - int i; - for (i=0;i<15;i++) if (ura_eph[i]>=value) break; - return i; -} -/* decode tersus tracking status ----------------------------------------------- -* deocode tersus tracking status -* args : unsigned int stat I tracking status field -* int *sys O system (SYS_???) -* int *code O signal code (CODE_L??) -* int *track O tracking state -* 0=idle 7=freq-lock loop -* 2=wide freq band pull-in 9=channel alignment -* 3=narrow freq band pull-in 10=code search -* 4=phase lock loop 11=aided phase lock loop -* int *plock O phase-lock flag (0=not locked, 1=locked) -* int *clock O code-lock flag (0=not locked, 1=locked) -* int *parity O parity known flag (0=not known, 1=known) -* int *halfc O phase measurement (0=half-cycle not added, -* 1=added) -* return : signal frequency (0:L1,1:L2,2:L5,3:L6,4:L7,5:L8,-1:error) -*-----------------------------------------------------------------------------*/ -static int decode_trackstat(unsigned int stat, int *sys, int *code, int *track, - int *plock, int *clock, int *parity, int *halfc) -{ - int satsys,sigtype,freq=0; - - *track =stat&0x1F; - *plock =(stat>>10)&1; - *parity=(stat>>11)&1; - *clock =(stat>>12)&1; - satsys =(stat>>16)&7; - *halfc =(stat>>28)&1; - sigtype=(stat>>21)&0x1F; - - switch (satsys) { - case 0: *sys=SYS_GPS; break; - case 1: *sys=SYS_GLO; break; - case 2: *sys=SYS_SBS; break; - case 3: *sys=SYS_GAL; break; - case 4: *sys=SYS_CMP; break; - case 5: *sys=SYS_QZS; break; - default: - trace(2,"tersus unknown system: sys=%d\n",satsys); - return -1; - } - if (*sys==SYS_GPS||*sys==SYS_QZS) { - switch (sigtype) { - case 0: freq=0; *code=CODE_L1C; break; /* L1C/A */ - case 5: freq=0; *code=CODE_L1P; break; /* L1P */ - case 9: freq=1; *code=CODE_L2D; break; /* L2Pcodeless */ - case 14: freq=2; *code=CODE_L5Q; break; /* L5Q */ - case 17: freq=1; *code=CODE_L2X; break; /* L2C(M+L) */ - default: freq=-1; break; - } - } - else if (*sys==SYS_GLO) { - switch (sigtype) { - case 0: freq=0; *code=CODE_L1C; break; /* L1C/A */ - case 1: freq=1; *code=CODE_L2C; break; /* L2C/A (OEM6) */ - case 5: freq=1; *code=CODE_L2P; break; /* L2P */ - default: freq=-1; break; - } - } - else if (*sys==SYS_GAL) { - switch (sigtype) { - case 1: freq=0; *code=CODE_L1B; break; /* E1B */ - case 2: freq=0; *code=CODE_L1C; break; /* E1C */ - case 12: freq=2; *code=CODE_L5Q; break; /* E5aQ */ - case 17: freq=4; *code=CODE_L7Q; break; /* E5bQ */ - case 20: freq=5; *code=CODE_L8Q; break; /* AltBOCQ */ - default: freq=-1; break; - } - } - else if (*sys==SYS_CMP) { - switch (sigtype) { - case 0: freq=0; *code=CODE_L1I; break; /* B1 with D1 */ - case 1: freq=1; *code=CODE_L7I; break; /* B2 with D1 */ - case 4: freq=0; *code=CODE_L1I; break; /* B1 with D2 */ - case 5: freq=1; *code=CODE_L7I; break; /* B2 with D2 */ - default: freq=-1; break; - } - } - else if (*sys==SYS_SBS) { - switch (sigtype) { - case 0: freq=0; *code=CODE_L1C; break; /* L1C/A */ - case 6: freq=2; *code=CODE_L5I; break; /* L5I */ - default: freq=-1; break; - } - } - if (freq<0) { - trace(2,"tersus signal type error: sys=%d sigtype=%d\n",*sys,sigtype); - return -1; - } - return freq; -} -/* check code priority and return obs position -------------------------------*/ -static int checkpri(const char *opt, int sys, int code, int freq) -{ - int nex=NEXOBS; /* number of extended obs data */ - - if (sys==SYS_GPS) { - if (strstr(opt,"-GL1P")&&freq==0) return code==CODE_L1P?0:-1; - if (strstr(opt,"-GL2X")&&freq==1) return code==CODE_L2X?1:-1; - if (code==CODE_L1P) return nex<1?-1:NFREQ; - if (code==CODE_L2X) return nex<2?-1:NFREQ+1; - } - else if (sys==SYS_GLO) { - if (strstr(opt,"-RL2C")&&freq==1) return code==CODE_L2C?1:-1; - if (code==CODE_L2C) return nex<1?-1:NFREQ; - } - else if (sys==SYS_GAL) { - if (strstr(opt,"-EL1B")&&freq==0) return code==CODE_L1B?0:-1; - if (code==CODE_L1B) return nex<1?-1:NFREQ; - if (code==CODE_L7Q) return nex<2?-1:NFREQ+1; - if (code==CODE_L8Q) return nex<3?-1:NFREQ+2; - } - return freqbuff+TERSUSHLEN; - - trace(3,"decode_rangeb: len=%d\n",raw->len); - - nobs=U4(p); - - if (raw->outtype) { - msg=raw->msgtype+strlen(raw->msgtype); - sprintf(msg," nobs=%2d",nobs); - } - if (raw->lenlen,nobs); - return -1; - } - for (i=0,p+=4;iopt,sys,code,freq))<0) continue; - - prn=U2(p); - if (sys==SYS_GLO) prn-=37; - else if (sys==SYS_CMP) prn-=160; - - if (!(sat=satno(sys,prn))) { - trace(3,"tersus rangeb satellite number error: sys=%d,prn=%d\n",sys,prn); - continue; - } - if (sys==SYS_GLO&&!parity) continue; /* invalid if GLO parity unknown */ - - gfrq =U2(p+ 2); - psr =R8(p+ 4); - adr =R8(p+16); - dop =R4(p+28); - snr =R4(p+32); - lockt=R4(p+36); - - /* set glonass frequency channel number */ - if (sys==SYS_GLO&&raw->nav.geph[prn-1].sat!=sat) { - raw->nav.geph[prn-1].frq=gfrq-7; - } - tt=timediff(raw->time,raw->tobs); - if (raw->tobs.time!=0) { - lli=lockt-raw->lockt[sat-1][pos]+0.05<=tt|| - halfc!=raw->halfc[sat-1][pos]; - } - else { - lli=0; - } - if (!parity) lli|=2; - raw->lockt[sat-1][pos]=lockt; - raw->halfc[sat-1][pos]=halfc; - if (!clock) psr=0.0; /* code unlock */ - if (!plock) adr=dop=0.0; /* phase unlock */ - - if (fabs(timediff(raw->obs.data[0].time,raw->time))>1E-9) { - raw->obs.n=0; - } - if ((index=obsindex(&raw->obs,raw->time,sat))>=0) { - raw->obs.data[index].L [pos]=-adr; - raw->obs.data[index].P [pos]=psr; - raw->obs.data[index].D [pos]=(float)dop; - raw->obs.data[index].SNR[pos]= - 0.0<=snr&&snr<255.0?(unsigned char)(snr*4.0+0.5):0; - raw->obs.data[index].LLI[pos]=(unsigned char)lli; - raw->obs.data[index].code[pos]=code; - } - } - raw->tobs=raw->time; - return 1; -} -/* decode rangecmpb ----------------------------------------------------------*/ -static int decode_rangecmpb(raw_t *raw) -{ - double psr,adr,adr_rolls,lockt,tt,dop,snr,wavelen; - int i,index,nobs,prn,sat,sys,code,freq,pos; - int track,plock,clock,parity,halfc,lli; - char *msg; - unsigned char *p=raw->buff+TERSUSHLEN; - - trace(3,"decode_rangecmpb: len=%d\n",raw->len); - - nobs=U4(p); - - if (raw->outtype) { - msg=raw->msgtype+strlen(raw->msgtype); - sprintf(msg," nobs=%2d",nobs); - } - if (raw->lenlen,nobs); - return -1; - } - for (i=0,p+=4;iopt,sys,code,freq))<0) continue; - - prn=U1(p+17); - if (sys==SYS_GLO) prn-=37; - else if (sys==SYS_CMP) prn-=160; - - if (!(sat=satno(sys,prn))) { - trace(3,"tersus rangecmpb satellite number error: sys=%d,prn=%d\n",sys,prn); - continue; - } - if (sys==SYS_GLO&&!parity) continue; /* invalid if GLO parity unknown */ - - dop=exsign(U4(p+4)&0xFFFFFFF,28)/256.0; - psr=(U4(p+7)>>4)/128.0+U1(p+11)*2097152.0; - - if ((wavelen=satwavelen(sat,freq,&raw->nav))<=0.0) { - if (sys==SYS_GLO) wavelen=CLIGHT/(freq==0?FREQ1_GLO:FREQ2_GLO); - else wavelen=lam_carr[freq]; - } - adr=I4(p+12)/256.0; - adr_rolls=(psr/wavelen+adr)/MAXVAL; - adr=-adr+MAXVAL*floor(adr_rolls+(adr_rolls<=0?-0.5:0.5)); - - lockt=(U4(p+18)&0x1FFFFF)/32.0; /* lock time */ - - tt=timediff(raw->time,raw->tobs); - if (raw->tobs.time!=0) { - lli=(lockt<65535.968&&lockt-raw->lockt[sat-1][pos]+0.05<=tt)|| - halfc!=raw->halfc[sat-1][pos]; - } - else { - lli=0; - } - if (!parity) lli|=2; - raw->lockt[sat-1][pos]=lockt; - raw->halfc[sat-1][pos]=halfc; - - snr=((U2(p+20)&0x3FF)>>5)+20.0; - if (!clock) psr=0.0; /* code unlock */ - if (!plock) adr=dop=0.0; /* phase unlock */ - - if (fabs(timediff(raw->obs.data[0].time,raw->time))>1E-9) { - raw->obs.n=0; - } - if ((index=obsindex(&raw->obs,raw->time,sat))>=0) { - raw->obs.data[index].L [pos]=adr; - raw->obs.data[index].P [pos]=psr; - raw->obs.data[index].D [pos]=(float)dop; - raw->obs.data[index].SNR[pos]= - 0.0<=snr&&snr<255.0?(unsigned char)(snr*4.0+0.5):0; - raw->obs.data[index].LLI[pos]=(unsigned char)lli; - raw->obs.data[index].code[pos]=code; - } - } - raw->tobs=raw->time; - return 1; -} -/* decode gpsphemb -----------------------------------------------------------*/ -static int decode_gpsephemb(raw_t *raw) -{ - unsigned char *p=raw->buff+TERSUSHLEN; - eph_t eph={0}; - char *msg; - double tow,toc,n,ura,tt; - int prn,week,zweek,iode2,as; - - trace(3,"decode_gpsephemb: len=%d\n",raw->len); - - if (raw->lenlen); - return -1; - } - prn =U2(p); p+=4; - - if (raw->outtype) { - msg=raw->msgtype+strlen(raw->msgtype); - sprintf(msg," prn=%3d",prn); - } - if (!(eph.sat=satno(SYS_GPS,prn))) { - trace(2,"tersus gpsephemb prn error: prn=%d\n",prn); - return -1; - } - tow =R8(p); p+=8; - eph.svh =(int)U4(p); p+=4; - eph.iode =(int)U4(p); p+=4; - iode2 =(int)U4(p); p+=4; - week =(int)U4(p); p+=4; - zweek =U4(p); p+=4; - eph.toes =R8(p); p+=8; - eph.A =R8(p); p+=8; - eph.deln =R8(p); p+=8; - eph.M0 =R8(p); p+=8; - eph.e =R8(p); p+=8; - eph.omg =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.i0 =R8(p); p+=8; - eph.idot =R8(p); p+=8; - eph.OMG0 =R8(p); p+=8; - eph.OMGd =R8(p); p+=8; - eph.iodc =(int)U4(p); p+=4; - toc =R8(p); p+=8; - eph.tgd[0] =R8(p); p+=8; - eph.f0 =R8(p); p+=8; - eph.f1 =R8(p); p+=8; - eph.f2 =R8(p); p+=8; - as =(int)U4(p); p+=4; /* AS-ON */ - n =R8(p); p+=8; - ura =R8(p); p+=8; - - if (eph.iode!=iode2) { - trace(2,"tersus gpsephemb iode error: iode=%d %d\n",eph.iode,iode2); - return -1; - } - eph.week=adjgpsweek(week); - eph.toe=gpst2time(eph.week,eph.toes); - 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=gpst2time(eph.week,toc); - eph.ttr=adjweek(eph.toe,tow); - eph.sva=uraindex(ura); - - if (!strstr(raw->opt,"-EPHALL")) { - if (timediff(raw->nav.eph[eph.sat-1].toe,eph.toe)==0.0&& - raw->nav.eph[eph.sat-1].iode==eph.iode&& - raw->nav.eph[eph.sat-1].iodc==eph.iodc) return 0; /* unchanged */ - } - raw->nav.eph[eph.sat-1]=eph; - raw->ephsat=eph.sat; - return 2; -} -/* decode gloephemerisb ------------------------------------------------------*/ -static int decode_gloephemerisb(raw_t *raw) -{ - unsigned char *p=raw->buff+TERSUSHLEN; - geph_t geph={0}; - char *msg; - double tow,tof,toff; - int prn,sat,week; - - trace(3,"decode_gloephemerisb: len=%d\n",raw->len); - - if (raw->lenlen); - return -1; - } - prn =U2(p)-37; - - if (raw->outtype) { - msg=raw->msgtype+strlen(raw->msgtype); - sprintf(msg," prn=%3d",prn); - } - if (!(sat=satno(SYS_GLO,prn))) { - trace(2,"tersus gloephemerisb prn error: prn=%d\n",prn); - return -1; - } - geph.frq =U2(p+ 2)+OFF_FRQNO; - week =U2(p+ 6); - tow =floor(U4(p+8)/1000.0+0.5); /* rounded to integer sec */ - toff =U4(p+ 12); - geph.iode =U4(p+ 20)&0x7F; - geph.svh =U4(p+ 24); - geph.pos[0]=R8(p+ 28); - geph.pos[1]=R8(p+ 36); - geph.pos[2]=R8(p+ 44); - geph.vel[0]=R8(p+ 52); - geph.vel[1]=R8(p+ 60); - geph.vel[2]=R8(p+ 68); - geph.acc[0]=R8(p+ 76); - geph.acc[1]=R8(p+ 84); - geph.acc[2]=R8(p+ 92); - geph.taun =R8(p+100); - geph.gamn =R8(p+116); - tof =U4(p+124)-toff; /* glonasst->gpst */ - geph.age =U4(p+136); - geph.toe=gpst2time(week,tow); - tof+=floor(tow/86400.0)*86400; - if (toftow+43200.0) tof-=86400.0; - geph.tof=gpst2time(week,tof); - - if (!strstr(raw->opt,"-EPHALL")) { - if (fabs(timediff(geph.toe,raw->nav.geph[prn-1].toe))<1.0&& - geph.svh==raw->nav.geph[prn-1].svh) return 0; /* unchanged */ - } - geph.sat=sat; - raw->nav.geph[prn-1]=geph; - raw->ephsat=sat; - return 2; -} -/* decode bdsephemeris -------------------------------------------------------*/ -static int decode_bdsephemerisb(raw_t *raw) -{ - eph_t eph={0}; - unsigned char *p=raw->buff+TERSUSHLEN; - double ura,sqrtA; - char *msg; - int prn,toc; - - trace(3,"decode_bdsephemerisb: len=%d\n",raw->len); - - if (raw->lenlen); - return -1; - } - prn =U4(p)-160; p+=4; - eph.week =U4(p); p+=4; - ura =R8(p); p+=8; - eph.svh =U4(p)&1; p+=4; - eph.tgd[0]=R8(p); p+=8; /* TGD1 for B1 (s) */ - eph.tgd[1]=R8(p); p+=8; /* TGD2 for B2 (s) */ - eph.iodc =U4(p); p+=4; /* AODC */ - toc =U4(p); p+=4; - eph.f0 =R8(p); p+=8; - eph.f1 =R8(p); p+=8; - eph.f2 =R8(p); p+=8; - eph.iode =U4(p); p+=4; /* AODE */ - eph.toes =U4(p); p+=4; - sqrtA =R8(p); p+=8; - eph.e =R8(p); p+=8; - eph.omg =R8(p); p+=8; - eph.deln =R8(p); p+=8; - eph.M0 =R8(p); p+=8; - eph.OMG0 =R8(p); p+=8; - eph.OMGd =R8(p); p+=8; - eph.i0 =R8(p); p+=8; - eph.idot =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); - eph.A =sqrtA*sqrtA; - eph.sva =uraindex(ura); - - 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_CMP,prn))) { - trace(2,"tersus bdsephemeris satellite error: prn=%d\n",prn); - return -1; - } - eph.toe=bdt2gpst(bdt2time(eph.week,eph.toes)); /* bdt -> gpst */ - eph.toc=bdt2gpst(bdt2time(eph.week,toc)); /* bdt -> gpst */ - eph.ttr=raw->time; - - if (!strstr(raw->opt,"-EPHALL")) { - if (timediff(raw->nav.eph[eph.sat-1].toe,eph.toe)==0.0&& - raw->nav.eph[eph.sat-1].iode==eph.iode&& - raw->nav.eph[eph.sat-1].iodc==eph.iodc) return 0; /* unchanged */ - } - raw->nav.eph[eph.sat-1]=eph; - raw->ephsat=eph.sat; - return 2; -} -/* decode ionutcb ------------------------------------------------------------*/ -static int decode_ionutcb(raw_t *raw) -{ - unsigned char *p=raw->buff+TERSUSHLEN; - int i; - - trace(3,"decode_ionutcb: len=%d\n",raw->len); - - if (raw->lenlen); - return -1; - } - for (i=0;i<8;i++) raw->nav.ion_gps[i]=R8(p+i*8); - raw->nav.utc_gps[0]=R8(p+72); - raw->nav.utc_gps[1]=R8(p+80); - raw->nav.utc_gps[2]=U4(p+68); - raw->nav.utc_gps[3]=U4(p+64); - raw->nav.leaps =I4(p+96); - return 9; -} -/* decode tersus message -----------------------------------------------------*/ -static int decode_tersus(raw_t *raw) -{ - double tow; - int msg,week,type=U2(raw->buff+4); - - trace(3,"decode_tersus: type=%3d len=%d\n",type,raw->len); - - /* check crc32 */ - if (rtk_crc32(raw->buff,raw->len)!=U4(raw->buff+raw->len)) { - trace(2,"tersus crc error: type=%3d len=%d\n",type,raw->len); - return -1; - } - msg =(U1(raw->buff+6)>>4)&0x3; - if (!(week=U2(raw->buff+14))) { - return -1; - } - week=adjgpsweek(week); - tow =U4(raw->buff+16)*0.001; - raw->time=gpst2time(week,tow); - - if (raw->outtype) { - sprintf(raw->msgtype,"TERSUS%4d (%4d): msg=%d %s",type,raw->len,msg, - time_str(gpst2time(week,tow),2)); - } - switch (type) { - case ID_RANGE : return decode_rangeb (raw); - case ID_RANGECMP : return decode_rangecmpb (raw); - case ID_IONUTC : return decode_ionutcb (raw); - case ID_GPSEPHEM : return decode_gpsephemb (raw); - case ID_GLOEPHEMERIS : return decode_gloephemerisb(raw); - case ID_BDSEPHEMERIS : return decode_bdsephemerisb(raw); - } - return 0; -} -/* sync header ---------------------------------------------------------------*/ -static int sync_tersus(unsigned char *buff, unsigned char data) -{ - buff[0]=buff[1]; buff[1]=buff[2]; buff[2]=data; - return buff[0]==TERSUSSYNC1&&buff[1]==TERSUSSYNC2&&buff[2]==TERSUSSYNC3; -} -/* input tersus raw data from stream ------------------------------------------- -* fetch next tersus raw data and input a mesasge from stream -* args : raw_t *raw IO receiver raw data control struct -* unsigned char data I stream data (1 byte) -* return : status (-1: error message, 0: no message, 1: input observation data, -* 2: input ephemeris, 3: input sbas message, -* 9: input ion/utc parameter) -* -* notes : to specify input options for tersus, set raw->opt to the following -* option strings separated by spaces. -* -* -EPHALL : input all ephemerides -*-----------------------------------------------------------------------------*/ -extern int input_tersus(raw_t *raw, unsigned char data) -{ - trace(5,"input_tersus: data=%02x\n",data); - - /* synchronize frame */ - if (raw->nbyte==0) { - if (sync_tersus(raw->buff,data)) raw->nbyte=3; - return 0; - } - raw->buff[raw->nbyte++]=data; - - if (raw->nbyte==10&&(raw->len=U2(raw->buff+8)+TERSUSHLEN)>MAXRAWLEN-4) { - trace(2,"tersus length error: len=%d\n",raw->len); - raw->nbyte=0; - return -1; - } - if (raw->nbyte<10||raw->nbytelen+4) return 0; - raw->nbyte=0; - - /* decode tersus message */ - return decode_tersus(raw); -} -/* input tersus raw data from file --------------------------------------------- -* fetch next tersus raw data and input a message from file -* args : raw_t *raw IO receiver raw data control struct -* int format I receiver raw data format (STRFMT_???) -* FILE *fp I file pointer -* return : status(-2: end of file, -1...9: same as above) -*-----------------------------------------------------------------------------*/ -extern int input_tersusf(raw_t *raw, FILE *fp) -{ - int i,data; - - trace(4,"input_tersusf:\n"); - - /* synchronize frame */ - if (raw->nbyte==0) { - for (i=0;;i++) { - if ((data=fgetc(fp))==EOF) return -2; - if (sync_tersus(raw->buff,(unsigned char)data)) break; - if (i>=4096) return 0; - } - } - if (fread(raw->buff+3,7,1,fp)<1) return -2; - raw->nbyte=10; - - if ((raw->len=U2(raw->buff+8)+TERSUSHLEN)>MAXRAWLEN-4) { - trace(2,"tersus length error: len=%d\n",raw->len); - raw->nbyte=0; - return -1; - } - if (fread(raw->buff+10,raw->len-6,1,fp)<1) return -2; - raw->nbyte=0; - - /* decode tersus message */ - return decode_tersus(raw); -} diff --git a/RTKBASE/lib/rtklib/src/src.pro b/RTKBASE/lib/rtklib/src/src.pro deleted file mode 100644 index c64d2b5..0000000 --- a/RTKBASE/lib/rtklib/src/src.pro +++ /dev/null @@ -1,70 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-02-09T08:58:44 -# -#------------------------------------------------- - -QT -= core gui - -TARGET = RTKLib -TEMPLATE = lib -CONFIG += staticlib - -include(../RTKLib.pri) - -QMAKE_CFLAGS += -Wall -ansi -pedantic -Wno-unused-but-set-variable -DTRACE -g -DEFINES -= UNICODE - -SOURCES += rtkcmn.c \ - convkml.c \ - convrnx.c \ - convgpx.c \ - datum.c \ - download.c \ - ephemeris.c \ - geoid.c \ - gis.c \ - ionex.c \ - lambda.c \ - options.c \ - pntpos.c \ - postpos.c \ - ppp.c \ - ppp_ar.c \ - ppp_corr.c \ - preceph.c \ - qzslex.c \ - rcvraw.c \ - rinex.c \ - rtcm.c \ - rtcm2.c \ - rtcm3.c \ - rtcm3e.c \ - rtkpos.c \ - rtksvr.c \ - sbas.c \ - solution.c \ - stream.c \ - streamsvr.c \ - tides.c \ - tle.c \ - rcv/binex.c \ - rcv/crescent.c \ - rcv/gw10.c \ - rcv/javad.c \ - rcv/novatel.c \ - rcv/nvs.c \ - rcv/rcvlex.c \ - rcv/rt17.c \ - rcv/septentrio.c \ - rcv/skytraq.c \ - rcv/ss2.c \ - rcv/ublox.c \ - rcv/cmr.c - -HEADERS += rtklib.h - -unix { - target.path = /usr/lib - INSTALLS += target -} diff --git a/RTKBASE/lib/rtklib/src/tides.c b/RTKBASE/lib/rtklib/src/tides.c deleted file mode 100644 index 1208394..0000000 --- a/RTKBASE/lib/rtklib/src/tides.c +++ /dev/null @@ -1,290 +0,0 @@ -/*------------------------------------------------------------------------------ -* tides.c : tidal displacement corrections -* -* Copyright (C) 2015-2017 by T.TAKASU, All rights reserved. -* -* options : -DIERS_MODEL use IERS tide model -* -* references : -* [1] D.D.McCarthy, IERS Technical Note 21, IERS Conventions 1996, July 1996 -* [2] D.D.McCarthy and G.Petit, IERS Technical Note 32, IERS Conventions -* 2003, November 2003 -* [3] D.A.Vallado, Fundamentals of Astrodynamics and Applications 2nd ed, -* Space Technology Library, 2004 -* [4] J.Kouba, A Guide to using International GNSS Service (IGS) products, -* May 2009 -* [5] G.Petit and B.Luzum (eds), IERS Technical Note No. 36, IERS -* Conventions (2010), 2010 -* -* version : $Revision:$ $Date:$ -* history : 2015/05/10 1.0 separated from ppp.c -* 2015/06/11 1.1 fix bug on computing days in tide_oload() (#128) -* 2017/04/11 1.2 fix bug on calling geterp() in timdedisp() -*-----------------------------------------------------------------------------*/ -#include "rtklib.h" - -static const char rcsid[]="$Id:$"; - -#define SQR(x) ((x)*(x)) - -#define AS2R (D2R/3600.0) /* arc sec to radian */ -#define GME 3.986004415E+14 /* earth gravitational constant */ -#define GMS 1.327124E+20 /* sun gravitational constant */ -#define GMM 4.902801E+12 /* moon gravitational constant */ - -/* function prototypes -------------------------------------------------------*/ -#ifdef IERS_MODEL -extern int dehanttideinel_(double *xsta, int *year, int *mon, int *day, - double *fhr, double *xsun, double *xmon, - double *dxtide); -#endif - -/* solar/lunar tides (ref [2] 7) ---------------------------------------------*/ -#ifndef IERS_MODEL -static void tide_pl(const double *eu, const double *rp, double GMp, - const double *pos, double *dr) -{ - const double H3=0.292,L3=0.015; - double r,ep[3],latp,lonp,p,K2,K3,a,H2,L2,dp,du,cosp,sinl,cosl; - int i; - - trace(4,"tide_pl : pos=%.3f %.3f\n",pos[0]*R2D,pos[1]*R2D); - - if ((r=norm(rp,3))<=0.0) return; - - for (i=0;i<3;i++) ep[i]=rp[i]/r; - - K2=GMp/GME*SQR(RE_WGS84)*SQR(RE_WGS84)/(r*r*r); - K3=K2*RE_WGS84/r; - latp=asin(ep[2]); lonp=atan2(ep[1],ep[0]); - cosp=cos(latp); sinl=sin(pos[0]); cosl=cos(pos[0]); - - /* step1 in phase (degree 2) */ - p=(3.0*sinl*sinl-1.0)/2.0; - H2=0.6078-0.0006*p; - L2=0.0847+0.0002*p; - a=dot(ep,eu,3); - dp=K2*3.0*L2*a; - du=K2*(H2*(1.5*a*a-0.5)-3.0*L2*a*a); - - /* step1 in phase (degree 3) */ - dp+=K3*L3*(7.5*a*a-1.5); - du+=K3*(H3*(2.5*a*a*a-1.5*a)-L3*(7.5*a*a-1.5)*a); - - /* step1 out-of-phase (only radial) */ - du+=3.0/4.0*0.0025*K2*sin(2.0*latp)*sin(2.0*pos[0])*sin(pos[1]-lonp); - du+=3.0/4.0*0.0022*K2*cosp*cosp*cosl*cosl*sin(2.0*(pos[1]-lonp)); - - dr[0]=dp*ep[0]+du*eu[0]; - dr[1]=dp*ep[1]+du*eu[1]; - dr[2]=dp*ep[2]+du*eu[2]; - - trace(5,"tide_pl : dr=%.3f %.3f %.3f\n",dr[0],dr[1],dr[2]); -} -/* displacement by solid earth tide (ref [2] 7) ------------------------------*/ -static void tide_solid(const double *rsun, const double *rmoon, - const double *pos, const double *E, double gmst, int opt, - double *dr) -{ - double dr1[3],dr2[3],eu[3],du,dn,sinl,sin2l; - - trace(3,"tide_solid: pos=%.3f %.3f opt=%d\n",pos[0]*R2D,pos[1]*R2D,opt); - - /* step1: time domain */ - eu[0]=E[2]; eu[1]=E[5]; eu[2]=E[8]; - tide_pl(eu,rsun, GMS,pos,dr1); - tide_pl(eu,rmoon,GMM,pos,dr2); - - /* step2: frequency domain, only K1 radial */ - sin2l=sin(2.0*pos[0]); - du=-0.012*sin2l*sin(gmst+pos[1]); - - dr[0]=dr1[0]+dr2[0]+du*E[2]; - dr[1]=dr1[1]+dr2[1]+du*E[5]; - dr[2]=dr1[2]+dr2[2]+du*E[8]; - - /* eliminate permanent deformation */ - if (opt&8) { - sinl=sin(pos[0]); - du=0.1196*(1.5*sinl*sinl-0.5); - dn=0.0247*sin2l; - dr[0]+=du*E[2]+dn*E[1]; - dr[1]+=du*E[5]+dn*E[4]; - dr[2]+=du*E[8]+dn*E[7]; - } - trace(5,"tide_solid: dr=%.3f %.3f %.3f\n",dr[0],dr[1],dr[2]); -} -#endif /* !IERS_MODEL */ - -/* displacement by ocean tide loading (ref [2] 7) ----------------------------*/ -static void tide_oload(gtime_t tut, const double *odisp, double *denu) -{ - const double args[][5]={ - {1.40519E-4, 2.0,-2.0, 0.0, 0.00}, /* M2 */ - {1.45444E-4, 0.0, 0.0, 0.0, 0.00}, /* S2 */ - {1.37880E-4, 2.0,-3.0, 1.0, 0.00}, /* N2 */ - {1.45842E-4, 2.0, 0.0, 0.0, 0.00}, /* K2 */ - {0.72921E-4, 1.0, 0.0, 0.0, 0.25}, /* K1 */ - {0.67598E-4, 1.0,-2.0, 0.0,-0.25}, /* O1 */ - {0.72523E-4,-1.0, 0.0, 0.0,-0.25}, /* P1 */ - {0.64959E-4, 1.0,-3.0, 1.0,-0.25}, /* Q1 */ - {0.53234E-5, 0.0, 2.0, 0.0, 0.00}, /* Mf */ - {0.26392E-5, 0.0, 1.0,-1.0, 0.00}, /* Mm */ - {0.03982E-5, 2.0, 0.0, 0.0, 0.00} /* Ssa */ - }; - const double ep1975[]={1975,1,1,0,0,0}; - double ep[6],fday,days,t,t2,t3,a[5],ang,dp[3]={0}; - int i,j; - - trace(3,"tide_oload:\n"); - - /* angular argument: see subroutine arg.f for reference [1] */ - time2epoch(tut,ep); - fday=ep[3]*3600.0+ep[4]*60.0+ep[5]; - ep[3]=ep[4]=ep[5]=0.0; - days=timediff(epoch2time(ep),epoch2time(ep1975))/86400.0+1.0; - t=(27392.500528+1.000000035*days)/36525.0; - t2=t*t; t3=t2*t; - - a[0]=fday; - a[1]=(279.69668+36000.768930485*t+3.03E-4*t2)*D2R; /* H0 */ - a[2]=(270.434358+481267.88314137*t-0.001133*t2+1.9E-6*t3)*D2R; /* S0 */ - a[3]=(334.329653+4069.0340329577*t-0.010325*t2-1.2E-5*t3)*D2R; /* P0 */ - a[4]=2.0*PI; - - /* displacements by 11 constituents */ - for (i=0;i<11;i++) { - ang=0.0; - for (j=0;j<5;j++) ang+=a[j]*args[i][j]; - for (j=0;j<3;j++) dp[j]+=odisp[j+i*6]*cos(ang-odisp[j+3+i*6]*D2R); - } - denu[0]=-dp[1]; - denu[1]=-dp[2]; - denu[2]= dp[0]; - - trace(5,"tide_oload: denu=%.3f %.3f %.3f\n",denu[0],denu[1],denu[2]); -} -/* iers mean pole (ref [7] eq.7.25) ------------------------------------------*/ -static void iers_mean_pole(gtime_t tut, double *xp_bar, double *yp_bar) -{ - const double ep2000[]={2000,1,1,0,0,0}; - double y,y2,y3; - - y=timediff(tut,epoch2time(ep2000))/86400.0/365.25; - - if (y<3653.0/365.25) { /* until 2010.0 */ - y2=y*y; y3=y2*y; - *xp_bar= 55.974+1.8243*y+0.18413*y2+0.007024*y3; /* (mas) */ - *yp_bar=346.346+1.7896*y-0.10729*y2-0.000908*y3; - } - else { /* after 2010.0 */ - *xp_bar= 23.513+7.6141*y; /* (mas) */ - *yp_bar=358.891-0.6287*y; - } -} -/* displacement by pole tide (ref [7] eq.7.26) --------------------------------*/ -static void tide_pole(gtime_t tut, const double *pos, const double *erpv, - double *denu) -{ - double xp_bar,yp_bar,m1,m2,cosl,sinl; - - trace(3,"tide_pole: pos=%.3f %.3f\n",pos[0]*R2D,pos[1]*R2D); - - /* iers mean pole (mas) */ - iers_mean_pole(tut,&xp_bar,&yp_bar); - - /* ref [7] eq.7.24 */ - m1= erpv[0]/AS2R-xp_bar*1E-3; /* (as) */ - m2=-erpv[1]/AS2R+yp_bar*1E-3; - - /* sin(2*theta) = sin(2*phi), cos(2*theta)=-cos(2*phi) */ - cosl=cos(pos[1]); - sinl=sin(pos[1]); - denu[0]= 9E-3*sin(pos[0]) *(m1*sinl-m2*cosl); /* de= Slambda (m) */ - denu[1]= -9E-3*cos(2.0*pos[0])*(m1*cosl+m2*sinl); /* dn=-Stheta (m) */ - denu[2]=-33E-3*sin(2.0*pos[0])*(m1*cosl+m2*sinl); /* du= Sr (m) */ - - trace(5,"tide_pole : denu=%.3f %.3f %.3f\n",denu[0],denu[1],denu[2]); -} -/* tidal displacement ---------------------------------------------------------- -* displacements by earth tides -* args : gtime_t tutc I time in utc -* double *rr I site position (ecef) (m) -* int opt I options (or of the followings) -* 1: solid earth tide -* 2: ocean tide loading -* 4: pole tide -* 8: elimate permanent deformation -* double *erp I earth rotation parameters (NULL: not used) -* double *odisp I ocean loading parameters (NULL: not used) -* odisp[0+i*6]: consituent i amplitude radial(m) -* odisp[1+i*6]: consituent i amplitude west (m) -* odisp[2+i*6]: consituent i amplitude south (m) -* odisp[3+i*6]: consituent i phase radial (deg) -* odisp[4+i*6]: consituent i phase west (deg) -* odisp[5+i*6]: consituent i phase south (deg) -* (i=0:M2,1:S2,2:N2,3:K2,4:K1,5:O1,6:P1,7:Q1, -* 8:Mf,9:Mm,10:Ssa) -* double *dr O displacement by earth tides (ecef) (m) -* return : none -* notes : see ref [1], [2] chap 7 -* see ref [4] 5.2.1, 5.2.2, 5.2.3 -* ver.2.4.0 does not use ocean loading and pole tide corrections -*-----------------------------------------------------------------------------*/ -extern void tidedisp(gtime_t tutc, const double *rr, int opt, const erp_t *erp, - const double *odisp, double *dr) -{ - gtime_t tut; - double pos[2],E[9],drt[3],denu[3],rs[3],rm[3],gmst,erpv[5]={0}; - int i; -#ifdef IERS_MODEL - double ep[6],fhr; - int year,mon,day; -#endif - - trace(3,"tidedisp: tutc=%s\n",time_str(tutc,0)); - - if (erp) { - geterp(erp,utc2gpst(tutc),erpv); - } - tut=timeadd(tutc,erpv[2]); - - dr[0]=dr[1]=dr[2]=0.0; - - if (norm(rr,3)<=0.0) return; - - pos[0]=asin(rr[2]/norm(rr,3)); - pos[1]=atan2(rr[1],rr[0]); - xyz2enu(pos,E); - - if (opt&1) { /* solid earth tides */ - - /* sun and moon position in ecef */ - sunmoonpos(tutc,erpv,rs,rm,&gmst); - -#ifdef IERS_MODEL - time2epoch(tutc,ep); - year=(int)ep[0]; - mon =(int)ep[1]; - day =(int)ep[2]; - fhr =ep[3]+ep[4]/60.0+ep[5]/3600.0; - - /* call DEHANTTIDEINEL */ - dehanttideinel_((double *)rr,&year,&mon,&day,&fhr,rs,rm,drt); -#else - tide_solid(rs,rm,pos,E,gmst,opt,drt); -#endif - for (i=0;i<3;i++) dr[i]+=drt[i]; - } - if ((opt&2)&&odisp) { /* ocean tide loading */ - tide_oload(tut,odisp,denu); - matmul("TN",3,1,3,1.0,E,denu,0.0,drt); - for (i=0;i<3;i++) dr[i]+=drt[i]; - } - if ((opt&4)&&erp) { /* pole tide */ - tide_pole(tut,pos,erpv,denu); - matmul("TN",3,1,3,1.0,E,denu,0.0,drt); - for (i=0;i<3;i++) dr[i]+=drt[i]; - } - trace(5,"tidedisp: dr=%.3f %.3f %.3f\n",dr[0],dr[1],dr[2]); -}