#!/usr/local/bin/perl # # -------------------------------------------------------------------- # xgps --- FreeBSD GPS-card utility for X11 # Copyright (C) 1996 by Tatsumi Hosokawa # -------------------------------------------------------------------- # # This utility requires # # o Perl 5.002 or later # o pTk-b10 or later # # You can install them from FreeBSD ports/packages collections. # # ----------------------------------------------------------------- require 5.002; use Getopt::Long; use Socket; use Tk; use Text::ParseWords; # ----------------------------------------------------------------- sub fixlng($); sub fixlat($); sub drawrad(); sub drawsat($$); sub statchanged(); my $pi = 3.141592653569; my $gpsdev = '/dev/cuaa3'; my @dows = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); my $radius = 60; my $satrad = 8; my %sname; $sname{'A'} = "SV1"; $sname{'B'} = "SV2"; $sname{'C'} = "SV3"; $sname{'D'} = "SV4"; $sname{'E'} = "SV5"; $sname{'F'} = "SV6"; $sname{'G'} = "SV7"; $sname{'H'} = "SV8"; $sname{'I'} = "SV9"; $sname{'J'} = "SV10"; $sname{'K'} = "SV11"; $sname{'L'} = "SV12"; $sname{'M'} = "SV13"; $sname{'N'} = "SV14"; $sname{'O'} = "SV15"; $sname{'P'} = "SV16"; $sname{'Q'} = "SV17"; $sname{'R'} = "SV18"; $sname{'S'} = "SV19"; $sname{'T'} = "SV20"; $sname{'U'} = "SV21"; $sname{'V'} = "SV22"; $sname{'W'} = "SV23"; $sname{'X'} = "SV24"; $sname{'a'} = "SV25"; $sname{'b'} = "SV26"; $sname{'c'} = "SV27"; $sname{'d'} = "SV28"; $sname{'e'} = "SV29"; $sname{'f'} = "SV30"; $sname{'g'} = "SV31"; $sname{'h'} = "SV32"; my %elev; $elev{'A'} = 0; $elev{'B'} = 10; $elev{'C'} = 20; $elev{'D'} = 30; $elev{'E'} = 40; $elev{'F'} = 50; $elev{'G'} = 60; $elev{'H'} = 70; $elev{'I'} = 80; $elev{'J'} = 90; $elev{'a'} = 0; $elev{'b'} = -10; $elev{'c'} = -20; $elev{'d'} = -30; $elev{'e'} = -40; $elev{'f'} = -50; $elev{'g'} = -60; $elev{'h'} = -70; $elev{'i'} = -80; $elev{'j'} = -90; my %drct; $drct{'A'} = 0; $drct{'B'} = 10; $drct{'C'} = 20; $drct{'D'} = 30; $drct{'E'} = 40; $drct{'F'} = 50; $drct{'G'} = 60; $drct{'H'} = 70; $drct{'I'} = 80; $drct{'J'} = 90; $drct{'K'} = 100; $drct{'L'} = 110; $drct{'M'} = 120; $drct{'N'} = 130; $drct{'O'} = 140; $drct{'P'} = 150; $drct{'Q'} = 160; $drct{'R'} = 170; $drct{'a'} = -10; $drct{'b'} = -20; $drct{'c'} = -30; $drct{'d'} = -40; $drct{'e'} = -50; $drct{'f'} = -60; $drct{'g'} = -70; $drct{'h'} = -80; $drct{'i'} = -90; $drct{'j'} = -100; $drct{'k'} = -110; $drct{'l'} = -120; $drct{'m'} = -130; $drct{'n'} = -140; $drct{'o'} = -150; $drct{'p'} = -160; $drct{'q'} = -170; $drct{'r'} = 180; my %stat; $stat{'A'} = "SCAN"; $stat{'B'} = "LOCK"; $stat{'C'} = "RDY "; $stat{'D'} = "HOLD"; $stat{'E'} = "ILL "; $stat{'F'} = "OK "; my %statc; $statc{'A'} = "red"; $statc{'B'} = "yellow"; $statc{'C'} = "green"; $statc{'D'} = "red"; $statc{'E'} = "black"; $statc{'F'} = "blue"; my @sats; my @satsx; my @satsy; my $ok = 0; open(GPS, $gpsdev) || die 'Can\'t open $gpsdev'; my $main = new MainWindow; my $ftim = $main -> Frame -> pack(-side => 'top'); my $vtim = $ftim -> Label( -text => '', -width => 22, -anchor => 'w', -relief => 'sunken') -> pack( -side => 'right'); my $ltim = $ftim -> Label( -text => 'Time (GMT)', -anchor => 'w', -width => 11) -> pack( -side => 'right'); my $flat = $main -> Frame -> pack(-side => 'top'); my $vlat = $flat -> Label( -text => '', -width => 22, -anchor => 'w', -relief => 'sunken') -> pack( -side => 'right'); my $llat = $flat -> Label( -text => 'Latitude', -anchor => 'w', -width => 11) -> pack( -side => 'right'); my $flng = $main -> Frame -> pack(-side => 'top'); my $vlng = $flng -> Label( -text => '', -width => 22, -anchor => 'w', -relief => 'sunken') -> pack( -side => 'right'); my $llng = $flng -> Label( -text => 'Longtitude', -anchor => 'w', -width => 11) -> pack( -side => 'right'); my $falt = $main -> Frame -> pack(-side => 'top'); my $valt = $falt -> Label( -text => '', -width => 22, -anchor => 'w', -relief => 'sunken') -> pack( -side => 'right'); my $lalt = $falt -> Label( -text => 'Altitude', -anchor => 'w', -width => 11) -> pack( -side => 'right'); my $fvel = $main -> Frame -> pack(-side => 'top'); my $vvel = $fvel -> Label( -text => '', -width => 22, -anchor => 'w', -relief => 'sunken') -> pack( -side => 'right'); my $lvel = $fvel -> Label( -text => 'Velocity', -anchor => 'w', -width => 11) -> pack( -side => 'right'); my $fdim = $main -> Frame -> pack(-side => 'top'); my $vdim = $fdim -> Label( -text => '', -width => 22, -anchor => 'w', -relief => 'sunken') -> pack( -side => 'right'); my $ldim = $fdim -> Label( -text => 'Dimension', -anchor => 'w', -width => 11) -> pack( -side => 'right'); my $fcam = $main -> Frame -> pack(-side => 'top'); my $ccam = $main -> Canvas( -width => $radius * 2 + 10, -height => $radius * 2 + 10, -background => 'dim gray') -> pack( -side => 'top'); drawrad; $main->fileevent(GPS, 'readable', \&statchanged); MainLoop; sub statchanged { $gpsdata = ; if ($gpsdata =~ /^SONY\d\d/) { $t = substr($gpsdata, 6, 13); $year = substr($t, 0, 2); $month = substr($t, 2, 2); $date = substr($t, 4, 2); $dow = $dows[substr($t, 6, 1)]; $hour = substr($t, 7, 2); $min = substr($t, 9, 2); $sec = substr($t, 11, 2); $lat = fixlat(substr($gpsdata, 19, 8)); $lng = fixlng(substr($gpsdata, 27, 9)); $alt = substr($gpsdata, 36, 5); $vel = substr($gpsdata, 41, 3); $dir = substr($gpsdata, 44, 3); $dop = substr($gpsdata, 60, 1); $dim = substr($gpsdata, 61, 1); if ($ok) { $stt = 'OK'; } else { $stt = 'NG'; } for ($i = 0; $i < 8; $i++) { $sat[$i] = substr($gpsdata, 63 + $i * 5, 5); } $tim = sprintf("$year/$month/$date($dow) $hour:$min:$sec"); $vtim -> configure( -text => $tim); $vlat -> configure( -text => $lat); $vlng -> configure( -text => $lng); $valt -> configure( -text => ($alt . 'm')); $vvel -> configure( -text => ($vel . 'km/h')); if ($dim == 3) { $vdim -> configure( -text => "two dimensional"); $valt -> configure( -foreground => 'dim gray'); $lalt -> configure( -foreground => 'dim gray'); } elsif ($dim == 4) { $vdim -> configure( -text => "three dimensional"); $valt -> configure( -foreground => 'black'); $lalt -> configure( -foreground => 'black'); } else { $vdim -> configure( -text => ""); } if ($ok) { $vlat -> configure( -foreground => 'black'); $vlng -> configure( -foreground => 'black'); $vvel -> configure( -foreground => 'black'); $llat -> configure( -foreground => 'black'); $llng -> configure( -foreground => 'black'); $lvel -> configure( -foreground => 'black'); } else { $vlat -> configure( -foreground => 'dim gray'); $vlng -> configure( -foreground => 'dim gray'); $vvel -> configure( -foreground => 'dim gray'); $llat -> configure( -foreground => 'dim gray'); $llng -> configure( -foreground => 'dim gray'); $lvel -> configure( -foreground => 'dim gray'); } for ($i = 0; $i < 8; $i++) { drawsat($sat[$i], $i); } } } sub fixlng { my($s) = shift; my($dir, $deg, $min, $sec, $ssec) = (substr($s, 0, 1), substr($s, 1, 3), substr($s, 4, 2), substr($s, 6, 2), substr($s, 8, 1)); sprintf("%s %03dd %02dm %02d.%1ds", $dir, $deg, $min, $sec, $ssec); } sub fixlat { my($s) = shift; my($dir, $deg, $min, $sec, $ssec) = (substr($s, 0, 1), substr($s, 1, 2), substr($s, 3, 2), substr($s, 5, 2), substr($s, 7, 1)); $ok = ($dir eq 'N' || $dir eq 'S'); $dir = 'N' if ($dir eq 'n'); $dir = 'S' if ($dir eq 's'); sprintf("%s %02dd %02dm %02d.%1ds", $dir, $deg, $min, $sec, $ssec); } sub drawrad { $ccam -> create ('oval', (5, 5), (5 + $radius * 2, 5 + $radius * 2), -width => 2); $ccam -> create ('oval', (5 + $radius / 2, 5 + $radius / 2), (5 + $radius * 3 / 2, 5 + $radius * 3 / 2), -width => 2); $ccam -> create ('line', (5 + $radius, 5), (5 + $radius, 5 + $radius * 2), -width => 2); $ccam -> create ('line', (5, 5 + $radius), (5 + $radius * 2, 5 + $radius), -width => 2); my $i; foreach $i (0 .. 7) { my $tag = sprintf("ov%d", $i); $satsx[$i] = 5 + $radius - $satrad; $satsy[$i] = 5 + $radius - $satrad; $sats[$i] = $ccam -> create ('oval', ($satsx[$i], $satsy[$i]), ($satsx[$i] + $satrad * 2, $satsy[$i] + $satrad * 2), -fill => 'white', -width => 1, -tag => $tag); } } sub drawsat { my($str) = shift; my($num) = shift; my($name, $elv, $dir); if (substr($str, 1, 1) cmp '_') { my $tag = sprintf("ov%d", $i); my $x = 0; my $y = 0; my $s; my $rad; my $ang; $name = $sname{substr($str, 0, 1)}; $elv = $elev{substr($str, 1, 1)}; $dir = $drct{substr($str, 2, 1)}; $s = substr($str, 3, 1); $st = $stat{$s}; $lvl = ord(substr($str, 4, 1)) - ord('D'); $rad = (90 - $elv); $rad = 95 if ($rad > 90); $rad = $radius * $rad / 90; $ang = ($dir - 90) * $pi / 180.0; $x = int($rad * cos($ang) - $satrad / 2 + $radius); $y = int($rad * sin($ang) - $satrad / 2 + $radius); $color = $statc{$s}; $ccam -> move ($tag, $x - $satsx[$num], $y - $satsy[$num]); $ccam -> itemconfigure ($tag, -fill => $color); $satsx[$num] = $x; $satsy[$num] = $y; } }