#!/bin/bash
#\
exec wish8.2 "$0" ${1+"$@"}

set SRLPORT /dev/cuau0
set BaudRate 4800
set Hours "0"
set Minutes "0"
set Seconds "0"
set Interval 2000
set LatDeg 27
#set LatMin 30.000
set LatMin 54.30
set LatSign S
set LongDeg 153
#set LongMin 30.000
set LongMin 19.334
set LongSign E
#set LatIncr 0.00
#set LongIncr -0.05
set LatIncr 0.03
set LongIncr 0.01
set SendDummies 0
array set Dummies {
	S01 GPRMC,172819,A,4110.736,N,00836.659,W,000.0,360.0,091000,005.4,W*7F
	S02 GPRMB,A,,,,,,,,,,,,V*71
	S03 GPGSA,A,3,,,,,,,,,,,,,2.0,2.0,3.0*31
	S05 GPGSV,2,1,08,05,82,288,54,07,17,042,43,09,56,080,51,21,22,273,45*7C
	S06 GPGSV,2,2,08,23,15,223,42,26,19,153,43,29,38,308,48,30,46,242,49*72
	S07 PGRME,15.0,M,22.5,M,15.0,M*1B
	S08 GPGLL,4110.736,N,00836.659,W,172820,A*37
	S09 PGRMZ,507,f,3*19
	S10 PGRMM,WGS_72*0F
	S11 GPBOD,,T,,M,,*47
	S12 GPRTE,1,1,c,0*07
} 
proc SetSerial {} {

global SRLPORT BaudRate OutputFile

    set OutputFile [open $SRLPORT r+]
    fconfigure $OutputFile -blocking 0 -mode $BaudRate,n,8,1
    Clock
} 

proc Clock {} {

global Interval Hours Minutes Seconds

    
    set Seconds [expr $Seconds + 2]
    if {$Seconds >= 60} {
	set Seconds [expr $Seconds - 60]
	set Minutes [incr Minutes]
    }
    if {$Minutes >= 60} {
	set Minutes [expr $Minutes - 60]
	set Hours [incr Hours]
    }
    set secs $Seconds
    set mins $Minutes
    set hrs $Hours
    if {[string length $Seconds] == 1} {
	set secs ""
	append secs "0" $Seconds
    }
    if {[string length $Minutes] == 1} {
	set mins ""
	append mins "0" $Minutes
    }
    if {[string length $Hours] == 1} {
	set hrs ""
	append hrs "0" $Hours
    }
    Sentence [join [list $hrs $mins $secs] ""]
    after $Interval Clock
}

proc Sentence {time} {

# Creates a valid NMEA GGA sentence.
# Lat and Long are lists of "NSEW" "Deg "DecMin"

global OutputFile LatDeg LatMin LatSign LongDeg LongMin LongSign \
		LatIncr LongIncr Dummies SendDummies 

    set LatMin [expr $LatMin + $LatIncr]
    set LongMin [expr $LongMin + $LongIncr]
    if {$LatMin > 60} {
	set LatMin [expr $LatMin - 60]
	set LatDeg [incr LatDeg]
    }
    if {$LatMin < 0} {
	set LatMin [expr $LatMin + 60]
	set LatDeg [incr LatDeg -1]
    }
    if {$LongMin > 60} {
	set LongMin [expr $LongMin - 60]
	set LongDeg [incr LongDeg]
    }
    if {$LongMin < 0} {
	set LongMin [expr $LongMin + 60]
	set LongDeg [incr LongDeg -1]
    }
    set LatDeg [CheckDeg $LatDeg 0]
    set LongDeg [CheckDeg $LongDeg 1]
    set LatMin [CheckMin $LatMin]
    set LongMin [CheckMin $LongMin]
    set sentence [list "GPGGA" "," $time , $LatDeg $LatMin , $LatSign , \
	$LongDeg $LongMin , $LongSign , "1" , "5" , "0.9" , \
	"100" , "M" , "50" , "M" , ,]  
    set sentence [join $sentence ""]
    set sentence [split $sentence ""]
    set sum [Checksum $sentence]
    set sentence [linsert $sentence end "*"]
    set sentence [linsert $sentence end $sum]
    set sentence [join $sentence ""]
    puts -nonewline $OutputFile \$
    puts $OutputFile $sentence
    flush $OutputFile
# puts $sentence
    if { $SendDummies } { PutArray Dummies }
    return
}

proc PutArray {name} {

    global OutputFile

    upvar $name a
    foreach el [array names a] {
	puts $OutputFile "\$$a($el)"
puts "\$$a($el)"
    }
    return
}

proc CheckMin {num} {
 
    set num [split $num "."]
    set intgr [lindex $num 0]
    set len [string length $intgr]
    switch $len {
	0 {
	    set intgr "00"
	}
	1 { 
	    set num2 $intgr ; set intgr "0"
	    set intgr [append intgr $num2]
	}
    }
    return [join [list $intgr [lindex $num 1]] "."]
}       

proc CheckDeg {num type} {
 
    set len [string length $num]
    if {$type == 0} {set len [expr $len + 1]}
    switch $len {
	0 {
	    set num "000"
	}
	1 { 
	    set num2 $num ; set num "00"
	    set num [append num $num2]
	}
	2 {
	    set num2 $num ; set num "0"
	    set num [append num $num2]
	}
    }
    return $num
}       


proc Checksum {str} {

    set start [lindex $str 0]
    binary scan $start c first 
    set str [lreplace $str 0 0]
    foreach ch $str {
	binary scan $ch c next
	set first [expr $first ^ $next]
    }
    set hex [Dec2Hex $first] 
    return $hex
}

proc Dec2Hex {dec} {

    set lookup {0 1 2 3 4 5 6 7 8 9 A B C D E F}
    set major [expr $dec/16]
    set major [expr int($major)]
    set minor [expr $dec - ($major * 16)]
    set major [lindex $lookup $major]
    set minor [lindex $lookup $minor]
    set hex [list $major $minor]
    set hex [join $hex ""]
    return $hex
}

SetSerial
