//gps support for COM devices
#include {time.htm}
#include {conio.htm}
#include {string.htm}
#include {pci.htm}
#include {dev.htm}
#include {com.htm}
#include {stdlib.htm}
#include {gl.htm}
#include {msg.htm}
#include {accdis.htm}
//#include {svga.htm}
//#include {vesa.htm}
//#include {vga.htm}
#include {gps1.htm}
UL hexchar(UL c)
{
if(c>=0x41){return c-0x41+10;}
else {return c-0x30;}
}
UL hexdigit(UL val);
DB NMEAreal(CH** eptr)
{
CH* ptr=*eptr;
if(!ptr){return 0;}
if(*ptr==','){ptr++;}
DB d=strtod(ptr,&ptr);
*eptr=ptr;
return d;
}
SL NMEAint(CH** eptr)
{
CH* ptr=*eptr;
if(!ptr){return 0;}
if(*ptr==','){ptr++;}
SL d=strtol(ptr,&ptr,10);
*eptr=ptr;
return d;
}
CH NMEAchar(CH** eptr)
{
CH* ptr=*eptr;
if(!ptr){return 0;}
CH c=0;
if(*ptr==','){ptr++;c=*ptr;}
ptr=strchr(ptr,',');
*eptr=ptr;
return c;
}
// GPSNAP g;
// GPSNAP gps[GPBUFSIZE];
// GPSNAP* gp=gps;
// UL gpidx;
// UL gpdisp;
// UL msgtime;
//
// UL etrex;
// UL sigctr;
//
// GPSINFO gpsinfo;
// UL sats[12];
// UL sigctr;
//
//GPSNAP* prev(GPSNAP* g)
//{
// if(g>gps){return g-1;}
// return gps+GPBUFSIZE-1;
//}
//functions to decode NMEA strings into usable data
UL indecodeGPGGA;
SL decodeGPGGA(GPS* g,CH* str)
{
if(indecodeGPGGA){return 1;}
indecodeGPGGA=1;
GPSNAP* gp=&g->gp;
//brk
gp->time=NMEAreal(&str); //gp->utc filled by GPGGA
gp->lat= NMEAreal(&str);
gp->NS= NMEAchar(&str);
gp->lng= NMEAreal(&str);
gp->EW= NMEAchar(&str);
gp->fix= NMEAint (&str);
gp->sats=NMEAint (&str);
gp->hdp =NMEAreal(&str);
gp->amsl=NMEAreal(&str);
indecodeGPGGA=0;
return 0;
}
UL indecodeGPGSA;
SL decodeGPGSA(GPS* g,CH* str)
{
if(indecodeGPGSA){return 1;}
indecodeGPGSA=1;
//brk
GPSNAP* gp=&g->gp;
GPSINFO* gi=&g->gi;
gp->mode=NMEAchar(&str);
gp->fixt=NMEAint (&str);
UL n,satno;
for(n=0;n<12;n++)
{
g->sats[n]=satno=NMEAint (&str);
if(satno)
{
gi->sat[satno].active=1;
}
else
{
gi->sat[satno].active=0;
}
}
gi->pDOP=NMEAreal(&str);
gi->hDOP=NMEAreal(&str);
gi->vDOP=NMEAreal(&str);
indecodeGPGSA=0;
return 0;
}
VD gpspost(GPS* g)
{
qmsg(mtGPS,0,0,0,0,(UL)g,0,0);
}
UL indecodeGPRMC;
SL decodeGPRMC(GPS* g,CH* str)
{
if(indecodeGPRMC){return 1;}
indecodeGPRMC=1;
GPSNAP* gp=&g->gp;
//brk
gp->utc= NMEAreal(&str); //gp->time filled by GPGGA
gp->stat=NMEAchar(&str);
gp->lat= NMEAreal(&str);
gp->NS= NMEAchar(&str);
gp->lng= NMEAreal(&str);
gp->EW= NMEAchar(&str);
gp->gspd=NMEAreal(&str);
gp->trk =NMEAreal(&str);
gp->date=NMEAint(&str);
if(gp->utc==gp->time)
{//gmsg is copy of live info for message
//(gp continues to be updated during interrupt handler)
g->gmsg=g->gp;
gpspost(g);
}
indecodeGPRMC=0;
return 0;
}
UL indecodeGPGSV;
SL decodeGPGSV(GPS* g,CH* str)
{
if(indecodeGPGSV){return 1;}
indecodeGPGSV=1;
//brk
GPSNAP* gp=&g->gp;
GPSINFO* gi=&g->gi;
UL total=NMEAint (&str); //total of GSV sentences
UL cur=NMEAint (&str); //number of this sentence
if(cur==1){g->sigs=g->sigctr;g->sigctr=0;}
gi->siv=NMEAint (&str);
UL n,satno;
for(n=0;n<4;n++)
{
if(*str!='*')
{
satno=NMEAint (&str);
if(satno<33)
{
gi->sat[satno].elevation=NMEAint (&str);
gi->sat[satno].azimuth =NMEAint (&str);
gi->sat[satno].snratio =NMEAint (&str);
if(gi->sat[satno].snratio)
{
g->sigctr++;
}
gi->sat[satno].inview =1;
gi->sat[satno].lastutc =gp->utc;
gi->sat[satno].lastdate=gp->date;
}
}
}
indecodeGPGSV=0;
return 0;
}
SL decodePGRMZ(GPS* g,CH* str)
{
//brk
GPSNAP* gp=&g->gp;
gp->alt =NMEAreal(&str);
g->etrex=1;
return 0;
}
SL decodeHCHDG(GPS* g,CH* str)
{
//brk
GPSNAP* gp=&g->gp;
gp->mhdg= NMEAreal(&str);
while(*str==','){str++;}
gp->mvar= NMEAreal(&str);
str++;
if(*str=='W'){gp->mvar=-gp->mvar;}
g->etrex=1;
return 0;
}
SL gpssvc (DEV* d,UL service)
{
//GPS handler
GPS* g=(GPS*)d->usr;
UL n,ck,ck1,ck2;
switch(service)
{//Mandatory message support//////////////////
case DM_IDENT:
return 0; //COM DEV decides is this device is present
case DM_PREINIT:
d->usr=(GPS*)calloc(sizeof(GPS),1);
if(!d->usr){return 1;}
return 0; //device MUST support DM_PREINIT
case DM_INIT:
initbuf(d,256,1); //debug version has larger buffer
// d->flg|=DF_POLL;
// d->pollfreq=5;
return 0;
case DM_TERM:
free(d->usr);
termbuf(d);
return 0;
case DM_CHILDHANDLER:
if(d->sv0=='$')
{
d->buf[d->bufin]=0;
// clidisplay((CH*)d->buf);
ck=0;ck2=0;
for(n=1;nbufin;n++)
{
if(d->buf[n]=='*'){break;}
ck^=d->buf[n];
ck2+=d->buf[n];
}
ck1= hexchar(d->buf[n+1])<<4;
ck1+=hexchar(d->buf[n+2]);
if(ck==ck1)
{//NMEA strings interpreted only if valid checksum
//see gpsdebug.htm to watch NMEA strings
if(!memicmp((CH*)d->buf,"$GPRMC",6))
{
decodeGPRMC(g,(CH*)d->buf+0x06);
}
else if(!memicmp((CH*)d->buf,"$GPGGA",6))
{
decodeGPGGA(g,(CH*)d->buf+0x06);
}
else if(!memicmp((CH*)d->buf,"$GPGSA",6))
{
decodeGPGSA(g,(CH*)d->buf+0x06);
}
else if(!memicmp((CH*)d->buf,"$GPGSV,3,1",10))
{
decodeGPGSV(g,(CH*)d->buf+0x06);
}
else if(!memicmp((CH*)d->buf,"$GPGSV,3,2",10))
{
decodeGPGSV(g,(CH*)d->buf+0x06);
}
else if(!memicmp((CH*)d->buf,"$GPGSV,3,3",10))
{
decodeGPGSV(g,(CH*)d->buf+0x06);
}
else if(!memicmp((CH*)d->buf,"$PGRMZ",6))
{
decodePGRMZ(g,(CH*)d->buf+0x06);
}
else if(!memicmp((CH*)d->buf,"$HCHDG",6))
{
decodeHCHDG(g,(CH*)d->buf+0x06);
}
// else
// {//future extra decodes go here
// }
}
d->bufin=0;memset(d->buf,0,d->buflen);
}
writebuf(d,(UC*)&d->sv0,1);
return 0;
case DM_POLL:
//debug version only:
//examine parsing buffer at buf+0x80 for NMEA strings we want
return 0;
case DM_CLIDISPINFO:
GPSNAP* gp=&g->gp;
GPSINFO* gi=&g->gi;
CH* ptr1;
switch(gp->fixt)
{
default:
case 1:ptr1="(no fix)";break;
case 2:ptr1="(2D fix)";break;
case 3:ptr1="(3D fix)";break;
}
clidisplay("GPS %s> Lat[%10.4d%1s]Long[%10.4d%1s][%8.2d]m %1l",ptr1,&gp->lat,&gp->NS,&gp->lng,&gp->EW,&gp->amsl,&gp->fix);
clidisplay("Sats %2l,%2l,%2l,%2l,%2l,%2l,%2l,%2l,%2l,%2l,%2l,%2l,pDOP %+6.2d hDOP %+6.2d vDOP %+6.2d",g->sats,g->sats+1,g->sats+2,g->sats+3,g->sats+4,g->sats+5,g->sats+6,g->sats+7,g->sats+8,g->sats+9,g->sats+10,g->sats+11,g->sats+12,&gi->pDOP,&gi->hDOP,&gi->vDOP);
clidisplay("SATS (%2l) [%06l] at [%10.3d] [%8.2d]knots [Trk%8.2d]",&gp->sats,&gp->date,&gp->utc,&gp->gspd,&gp->trk);
clidisplay("SatNo Elev Azim S/n ");
for(n=0;n<12;n++)
{
SATELLITE* s=&gi->sat[g->sats[n]];
clidisplay("(%2l) %3l %3l %3l ",g->sats+n,&s->elevation,&s->azimuth,&s->snratio);
}
return 0;
}
}