NMEA
NMEA is the communication standard used with GPS devices. A websearch for 'NMEA'
will find the complete protocol. Here only a part of it is implemented. Though
this application uses a realtime kernel, just a serial receiver will do.
program Graminreceiver;
uses opstring,opcrt,RTKERNEL,NMEA;
var s:string;
i:integer;
begin
signal(nmeastart);
repeat
rtkernel.delay(50);
s:=NMEAStrings.rec+' '+NMEAStrings.time+' '+NMEAStrings.date+' '+
NMEAStrings.latitude+' '+NMEAStrings.longitude+' '+
NMEAStrings.speed+' '+NMEAStrings.magnetic;
wait(screensema);
writeln(s);
writeln(NMEAData.latitude,' ',NMEAData.longitude);
signal(screensema);
until keypressed;
i:=0;
end.
and the NMEA unit :
unit nmea;
interface
uses RTKernel,RTCom;
type
NMEAstr=record
time:string[10];
date:string[10];
latitude:string[10];
longitude:string[10];
speed:string[10];
magnetic:string[10];
madegood:string[10];
rec:string[10];
fixq:char;
satcnt:char;
hdil:string[10];
altitude:string[10];
geodelta:string[10];
hpe,vpe,spe:string[10];
end;
NMEARData=record
latitude,
longitude,speed:extended;
end;
var nmeastart:RTKERNEL.Semaphore;
nmeaaccess:RTKernel.Semaphore;
nmeadtaskhandle:RTKERNEL.Taskhandle;
NMEAStrings:NMEAStr;
NMEAData:NMEARData;
rs:string;
ScreenSema:RTKernel.Semaphore;
implementation
const NMEAPort=COM2;
procedure initnmea;
begin
if RTCOM.portinstalled(NMEAPort) then
begin
RTCOM.InitPort(NMEAPort,4800,none,1,8);
RTCOM.EnableCOMInterrupt(NMEAPort,1000);
end;
NMEAStrings.rec:='no msg ';
end;
{$F+}
procedure nmeatask;
var currentstr,s:string;
data:RTCOM.V24Data;
strcomplete,next,success:boolean;
index:byte;
deg:integer;
min:single;
function nextcomma(s:string;var index:byte;var sub:string):boolean;
var j:byte;
begin
j:=index;sub:='';
while(s[j]<>',')and(s[j]<>'*')do begin
sub:=sub+s[j]; inc(j);
end;
nextcomma:=(index=j);
index:=j+1;
end;
begin
ProtectCoprocessor(TRUE);
initnmea;
wait(nmeastart);
currentstr:='';
while true do
begin
strcomplete:=false;currentstr:='';
repeat
RTCOM.GetTimed(RTCOM.ReceiveBuffer[NMEAPort],data,90,success);
if (not success) then NMEAStrings.rec:='no msg '
else
begin
strcomplete:=(data.ch=chr(10)); { linefeed }
{strcomplete:=(length(currentstr)>200);}
currentstr:=currentstr+data.ch;
end;
until strcomplete;
rs:=currentstr;
{ wait(screensema);
writeln(rs);
signal(screensema);}
s:=copy(currentstr,1,6); next:=false;
if (s='$GPRMC') then
begin
{ wait(screensema); writeln(currentstr); signal(screensema);}
index:=8;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.time:=s;
end;
if not nextcomma(currentstr,index,s) then
begin
if s='A'then NMEAStrings.rec:='ok ';
if s='V'then NMEAStrings.rec:='warning ';
end;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.latitude:=s;
deg:=10*(ord(s[1])-$30)+(ord(s[2])-$30);
min:=10*(ord(s[3])-$30)+(ord(s[4])-$30)
+0.1*(ord(s[6])-$30)+0.01*(ord(s[7])-$30)
+0.001*(ord(s[8])-$30);
NMEAData.latitude:=pi*(deg+(min/60))/180.0;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.latitude:=NMEAStrings.latitude+s;
if s='S' then NMEAData.latitude:=-NMEAData.latitude;
end;
end;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.longitude:=s;
deg:=100*(ord(s[1])-$30)+10*(ord(s[2])-$30)+(ord(s[3])-$30);
min:=10*(ord(s[4])-$30)+(ord(s[5])-$30)+0.1*(ord(s[7])-$30)
+0.01*(ord(s[8])-$30)+0.001*(ord(s[9])-$30);
NMEAData.longitude:=pi*(deg+(min/60))/180.0;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.longitude:=NMEAStrings.longitude+s;
if s='W' then NMEAData.longitude:=-NMEAData.longitude;
end;
end;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.speed:=s;
end;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.madegood:=s;
end;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.date:=s;
end;
if not nextcomma(currentstr,index,s) then
begin
NMEAStrings.magnetic:=s;
if not nextcomma(currentstr,index,s) then
NMEAStrings.magnetic:=NMEAStrings.magnetic+s;
end;
next:=true;
end;
if (not next)and(s='$GPRMB') then
begin
next:=true;
end;
if (not next)and(s='$GPGGA') then
begin
next:=true;
end;
if (not next)and(s='$GPGSA') then
begin
next:=true;
end;
if (not next)and(s='$GPGSV') then
begin
next:=true;
end;
if (not next)and(s='$PGRME') then
begin
next:=true;
end;
if (not next)and(s='$GPGLL') then
begin
next:=true;
end;
if (not next)and(s='$PGRMZ') then
begin
next:=true;
end;
if (not next)and(s='$PGRMM') then
begin
next:=true;
end;
if (not next)and(s='$GPBOD') then
begin
next:=true;
end;
end; { while true loop }
end; {nmeatask}
begin
initsemaphore(nmeastart,binary,0,'nmeastart');
initsemaphore(nmeaaccess,resource,1,'nmeaaccess');
initsemaphore(ScreenSema,resource,1,'screensema');
createtask(nmeatask,mainpriority-1,2000,'NMEA',nmeadtaskhandle);
{ signal(screensema);}
end.
home
last updated: 26.jan.00
Copyright (99,2000) Ing.Büro R.Tschaggelar