'' ***************************** '' GPS routines '' (c) 2007 Perry James Mole '' pjm@ridge-communications.ca '' ***************************** '' 05-13-2009 - JMH - Modified to accept input pin number assignments '' 05-14-2009 - JMH - Added functions to seperate the deg/min from lat/long ' PVH Comment - Excellent small GPS reader routines. ' $GPRMC Recommended minimum data ie: $GPRMC,081836,A,3751.6565,S,14507.3654,E,000.0,360.0,130998,011.3,E*62 ' $GPGGA GPS Fix Data ie: $GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75 ' $PGRMZ eTrex proprietary barametric altitude ft ie: $PGRMZ,453,f,2*18 CON CR = 13 ' ASCII LF = 10 ' ASCII serXmit = 0 ' Serial Transmit for UART - not used VAR long gps_stack[32] byte GPRMCb[68],GPGGAb[80],PGRMZb[40],GPGSAb[80] long GPRMCa[20],GPGGAa[20],PGRMZa[20],GPGSAa[20] byte gps_buff[80],Rx',cksum long cog,cptr,ptr,arg,j long Null[1] byte latlong_buf[10] OBJ uart : "FullDuplexSerial_mini" PUB start(serRecvPin, baudRate) : okay '' Starts uart object (at baud specified) in a cog '' -- returns false if no cog available okay := uart.start(serRecvPin,serXmit,0,baudRate) return cog := cognew(readNEMA,@gps_stack) + 1 PUB readNEMA Null[0] := 0 repeat bytefill(@gps_buff{0}, 0, 80) repeat ' wait for the $ to insure we are starting with while (Rx := uart.rx) <> "$" cptr := 0 repeat ' continue to collect data until the end of the NMEA sentence Rx := uart.rx ' get character from Rx Buffer if Rx == "," gps_buff[cptr++] := 0 ' If "," replace the character with 0 else gps_buff[cptr++] := Rx ' else save the character while Rx <> CR next if gps_buff[2] == "G" if gps_buff[3] == "G" if gps_buff[4] == "A" copy_buffer(@GPGGAb, @GPGGAa) if gps_buff[2] == "R" if gps_buff[3] == "M" if gps_buff[4] == "C" copy_buffer(@GPRMCb, @GPRMCa) if gps_buff[0] == "P" if gps_buff[1] == "G" if gps_buff[2] == "R" if gps_buff[3] == "M" if gps_buff[4] == "Z" copy_buffer(@PGRMZb, @PGRMZa) if gps_buff[0] == "G" if gps_buff[1] == "P" if gps_buff[2] == "G" if gps_buff[3] == "S" if gps_buff[4] == "A" copy_buffer(@GPGSAb, @GPGSAa) pub copy_buffer ( buffer,args) bytemove(buffer,@gps_buff,cptr) ' copy received data to buffer ptr := buffer arg := 0 repeat j from 0 to 78 ' build array of pointers if byte[ptr] == 0 ' to each if byte[ptr+1] == 0 ' record long[args][arg] := Null ' in else ' the long[args][arg] := ptr+1 ' data buffer arg++ ptr++ ' now we just need to return the pointer to the desired record pub altitude return PGRMZa[0] pub valid return GPRMCa[1] pub speed return GPRMCa[6] pub heading return GPRMCa[7] pub date return GPRMCa[8] pub GPSaltitude return GPGGAa[8] pub time return GPGGAa[0] pub latitude return GPGGAa[1] pub latitude_degpart | byte_ptr byte_ptr := GPGGAa[1] latlong_buf[0] := byte[byte_ptr++] latlong_buf[1] := byte[byte_ptr++] latlong_buf[2] := 0 return @latlong_buf pub latitude_minpart | byte_ptr, i, numchars byte_ptr := GPGGAa[1] + 2 numchars := strsize(byte_ptr) repeat i from 0 to (numchars-1) latlong_buf[i] := byte[byte_ptr++] 'Null terminate latlong_buf[i] := 0 return @latlong_buf pub N_S return GPGGAa[2] pub longitude return GPGGAa[3] pub longitude_degpart | byte_ptr byte_ptr := GPGGAa[3] latlong_buf[0] := byte[byte_ptr++] latlong_buf[1] := byte[byte_ptr++] latlong_buf[2] := byte[byte_ptr++] latlong_buf[3] := 0 return @latlong_buf pub longitude_minpart | byte_ptr, i, numchars byte_ptr := GPGGAa[3] + 3 numchars := strsize(byte_ptr) repeat i from 0 to (numchars-1) latlong_buf[i] := byte[byte_ptr++] 'Null terminate latlong_buf[i] := 0 return @latlong_buf pub E_W return GPGGAa[4] pub satellites return GPGGAa[6] pub hdop return GPGGAa[7] pub vdop return GPGSAa[15]