diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 19:39:39 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 19:39:39 (GMT) |
commit | ea28451286d3ea4a772fa174483f9a7a66bb1ab3 (patch) | |
tree | 6ee9d8a7848333a7ceeee3b13d492e40225f8b86 /tcllib/modules/nmea | |
parent | b5ca09bae0d6a1edce939eea03594dd56383f2c8 (diff) | |
parent | 7c621da28f07e449ad90c387344f07a453927569 (diff) | |
download | blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.zip blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.gz blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.bz2 |
Merge commit '7c621da28f07e449ad90c387344f07a453927569' as 'tcllib'
Diffstat (limited to 'tcllib/modules/nmea')
-rw-r--r-- | tcllib/modules/nmea/ChangeLog | 101 | ||||
-rw-r--r-- | tcllib/modules/nmea/nmea.man | 102 | ||||
-rwxr-xr-x | tcllib/modules/nmea/nmea.tcl | 197 | ||||
-rw-r--r-- | tcllib/modules/nmea/pkgIndex.tcl | 2 |
4 files changed, 402 insertions, 0 deletions
diff --git a/tcllib/modules/nmea/ChangeLog b/tcllib/modules/nmea/ChangeLog new file mode 100644 index 0000000..2b93864 --- /dev/null +++ b/tcllib/modules/nmea/ChangeLog @@ -0,0 +1,101 @@ +2013-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.15 ======================== + * + +2011-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.14 ======================== + * + +2011-01-24 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.13 ======================== + * + +2009-12-07 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.12 ======================== + * + +2009-02-11 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * nmea.man: Added category information to manpage, put into + 'Networking'. Regenerated support/devel/sak/doc/toc.txt. + +2009-01-09 Andreas Kupries <andreask@activestate.com> + + * nmea.man: Fixed manpage problems reported by 'sak.tcl doc + validate nmea'. + +2009-01-08 Aaron Faupell <afaupell@users.sourceforge.net> + + nmea.tcl: lots of changes, bumped major ver to 1.0.0 + - close_port and close_file become close + - fixed some problems with automatic file reading + - switched to registered events instead of specially named procs + - added default and eof events + - added configure command + nmea.man: updated for new commands and clarity + +2008-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.11.1 ======================== + * + +2008-10-16 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.11 ======================== + * + +2007-11-15 Aaron Faupell <afaupell@users.sourceforge.net> + + * nmea.tcl: added return values to do_line, new input command + bumped minor rev + * nmea.man: updated for do_line, input, new intro paragraph + +2007-09-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.10 ======================== + * + +2007-08-20 Andreas Kupries <andreask@activestate.com> + + * nmea.man: Bumped package version to 0.1.1. + * nmea/tcl: + * pkgIndex.tcl: + +2007-08-16 Aaron Faupell <afaupell@users.sourceforge.net> + + * nmea.tcl fixed bug in read_port when using logging, + bug id 1765388 + +2007-05-28 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * nmea.man: Added title, extended set of keywords. + +2007-03-21 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * nmea.man: Fixed all warnings due to use of now deprecated + commands. Added a section about how to give feedback. + +2006-10-03 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.9 ======================== + * + +2006-06-30 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * nmea.man: Fixed syntax errors in the documentation. + +2006-06-30 Aaron Faupell <afaupell@users.sourceforge.net> + + * New module for handling NMEA protocol diff --git a/tcllib/modules/nmea/nmea.man b/tcllib/modules/nmea/nmea.man new file mode 100644 index 0000000..cba215b --- /dev/null +++ b/tcllib/modules/nmea/nmea.man @@ -0,0 +1,102 @@ +[manpage_begin nmea n 1.0.0] +[keywords gps] +[keywords nmea] +[copyright {2006-2009, Aaron Faupell <afaupell@users.sourceforge.net>}] +[moddesc {NMEA protocol implementation}] +[titledesc {Process NMEA data}] +[category Networking] +[require Tcl 8.4] +[require nmea [opt 1.0.0]] +[description] +[para] + +This package provides a standard interface for writing software which recieves +NMEA standard input data. It allows for reading data from COM ports, files, +or programmatic input. It also supports the checksumming and logging of incoming data. +After parsing, input is dispatched to user defined handler commands for processing. +To define a handler, see the [cmd event] command. There are no GPS specific functions +in this package. NMEA data consists of a sentence type, followed by a list of data. + +[section COMMANDS] +[list_begin definitions] + +[call [cmd ::nmea::input] [arg sentence]] +Processes and dispatches the supplied sentence. If [arg sentence] contains no commas it is treated as a Tcl list, otherwise it must be standard comma delimited NMEA data, with an optional checksum and leading [const \$]. + +[example { +nmea::input {$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39} +nmea::input [list GPGSA A 3 04 05 09 12 "" "" 24 "" "" "" 2.5 1.3 2.1] +}] + +[call [cmd ::nmea::open_port] [arg port] [opt speed]] +Open the specified COM port and read NMEA sentences when available. Port speed is set to +4800bps by default or to [arg speed]. + +[call [cmd ::nmea::close_port]] +Close the com port connection if one is open. + +[call [cmd ::nmea::configure_port] [arg settings]] +Changes the current port settings. [arg settings] has the same format as fconfigure -mode. + +[call [cmd ::nmea::open_file] [arg file] [opt rate]] +Open file [arg file] and read NMEA sentences, one per line, at the rate specified by [opt rate] in milliseconds. +The file format may omit the leading [const \$] and/or the checksum. If rate is <= 0 (the default) then lines +will only be processed when a call to [cmd do_line] is made. + +[call [cmd ::nmea::close_file]] +Close the open file if one exists. + +[call [cmd ::nmea::do_line]] +If there is a currently open file, this command will read and process a single line from it. +Returns the number of lines read. + +[call [cmd ::nmea::rate]] +Sets the rate at which lines are processed from the open file, in milliseconds. The rate remains +consistant across files, there does not need to be a file currently open to use this command. +Set to 0 to disable automatic line processing. + +[call [cmd ::nmea::log] [opt file]] +Starts or stops input logging. If a file name is specified then all NMEA data recieved on +the open port will be logged to the [opt file] in append mode. If file is an empty string then +any logging will be stopped. If no file is specified then returns a boolean value indicating +if logging is currently enabled. Data written to the port by [cmd write], + data read from files, or input made using [cmd input], is not logged. + +[call [cmd ::nmea::checksum] [arg data]] +Returns the checksum of the supplied data. + +[call [cmd ::nmea::write] [arg sentence] [arg data]] +If there is a currently open port, this command will write the specified sentence and data to the port +in proper NMEA checksummed format. + +[call [cmd ::nmea::event] [arg setence] [opt command]] +Registers a handler proc for a given NMEA [arg sentence]. There may be at most one handler per +sentence, any existing handler is replaced. +If no command is specified, returns the name of the current handler for the given [arg setence] +or an empty string if none exists. In addition to the incoming sentences there are 2 builtin types, +EOF and DEFAULT. The handler for the DEFAULT setence is invoked if there is not a specific handler +for that sentence. The EOF handler is invoked when End Of File is reached on the open file or port. +[para] +The handler procedures, with the exception of the builtin types,must take exactly one argument, +which is a list of the data values. +The DEFAULT handler should have two arguments, the sentence type and the data values. +The EOF handler has no arguments. + +[example { +nmea::event gpgsa parse_sat_detail +nmea::event default handle_unknown + +proc parse_sat_detail {data} { + puts [lindex $data 1] +} + +proc handle_unknown {name data} { + puts "unknown data type $name" +} +}] + +[list_end] + +[vset CATEGORY nmea] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/nmea/nmea.tcl b/tcllib/modules/nmea/nmea.tcl new file mode 100755 index 0000000..884b4a5 --- /dev/null +++ b/tcllib/modules/nmea/nmea.tcl @@ -0,0 +1,197 @@ +# nmea.tcl -- +# +# NMEA protocol implementation +# +# Copyright (c) 2006-2009 Aaron Faupell +# +# RCS: @(#) $Id: nmea.tcl,v 1.5 2009/01/09 06:49:25 afaupell Exp $ + +package require Tcl 8.4 +package provide nmea 1.0.0 + +namespace eval ::nmea { + array set ::nmea::nmea [list checksum 1 log {} rate 0] + array set ::nmea::dispatch "" +} + +proc ::nmea::open_port {port {speed 4800}} { + variable nmea + if {[info exists nmea(fh)]} { ::nmea::close } + set nmea(fh) [open $port] + fconfigure $nmea(fh) -mode $speed,n,8,1 -handshake xonxoff -buffering line -translation crlf + fileevent $nmea(fh) readable [list ::nmea::read_port $nmea(fh)] + return $port +} + +proc ::nmea::open_file {file {rate {}}} { + variable nmea + if {[info exists nmea(fh)]} { ::nmea::close } + set nmea(fh) [open $file] + if {[string is integer -strict $rate]} { + if {$rate < 0} { set rate 0 } + set nmea(rate) $rate + } + fconfigure $nmea(fh) -buffering line -blocking 0 -translation auto + if {$nmea(rate) > 0} { + after $nmea(rate) [list ::nmea::read_file $nmea(fh)] + } + return $file +} + +proc ::nmea::configure_port {settings} { + variable nmea + fconfigure $nmea(fh) -mode $settings +} + +proc ::nmea::close {} { + variable nmea + catch {::close $nmea(fh)} + unset -nocomplain nmea(fh) + foreach x [after info] { + if {[lindex [after info $x] 0 0] == "::nmea::read_file"} { + after cancel $x + } + } +} + +proc ::nmea::read_port {f} { + if {[catch {gets $f} line] || [eof $f]} { + if {[info exists ::nmea::dispatch(EOF)]} { + $::nmea::dispatch(EOF) + } + nmea::close + } + if {$::nmea::nmea(log) != ""} { + puts $::nmea::nmea(log) $line + } + ::nmea::parse_nmea $line +} + +proc ::nmea::read_file {f {auto 1}} { + variable nmea + set line [gets $f] + if {[eof $f]} { + if {[info exists ::nmea::dispatch(EOF)]} { + $::nmea::dispatch(EOF) + } + nmea::close + return 0 + } + if {[string match {$*} $line]} { + ::nmea::parse_nmea $line + } else { + ::nmea::parse_nmea \$$line + } + if {$auto} { + after $nmea(rate) [list ::nmea::read_file $f] + } + return 1 +} + +proc ::nmea::do_line {} { + variable nmea + if {![info exists nmea(fh)]} { return -code error "there is no currently open file" } + return [::nmea::read_file $nmea(fh) 0] +} + +proc ::nmea::configure {opt {val {}}} { + variable nmea + switch -exact -- $opt { + rate { + if {$val == ""} { return $nmea(rate) } + if {![string is integer $val]} { return -code error "rate must be an integer value" } + if {$val <= 0} { + foreach x [after info] { + if {[lindex [after info $x] 0 0] == "::nmea::read_file"} { + after cancel $x + } + } + set val 0 + } + if {$nmea(rate) == 0 && $val > 0} { + after $val [list ::nmea::read_file $nmea(fh)] + } + set nmea(rate) $val + return $val + } + checksum { + if {$val == ""} { return $nmea(checksum) } + if {![string is bool $val]} { return -code error "checksum must be a boolean value" } + set nmea(checksum) $val + return $val + } + default { + return -code error "unknown option $opt" + } + } +} + +proc ::nmea::input {sentence} { + if {![string match "*,*" $sentence]} { set sentence [join $sentence ,] } + if {[string match {$*} $sentence]} { + ::nmea::parse_nmea $sentence + } else { + ::nmea::parse_nmea \$$sentence + } +} + +proc ::nmea::log {{file _X}} { + variable nmea + if {$file == "_X"} { return [expr {$nmea(log) != ""}] } + if {$file != ""} { + if {$nmea(log) != ""} { ::nmea::log {} } + set nmea(log) [open $file a] + } else { + catch {::close $nmea(log)} + set nmea(log) "" + } + return $file +} + +proc ::nmea::parse_nmea {line} { + set line [split $line \$*] + set cksum [lindex $line 2] + set line [lindex $line 1] + if {$cksum == "" || !$::nmea::nmea(checksum) || [checksum $line] == $cksum} { + set line [split $line ,] + set sentence [lindex $line 0] + set line [lrange $line 1 end] + if {[info exists ::nmea::dispatch($sentence)]} { + $::nmea::dispatch($sentence) $line + } elseif {[info exists ::nmea::dispatch(DEFAULT)]} { + $::nmea::dispatch(DEFAULT) $sentence $line + } + } +} + +proc ::nmea::checksum {line} { + set sum 0 + binary scan $line c* line + foreach char $line { + set sum [expr {$sum ^ ($char % 128)}] + } + return [format %02X [expr {$sum % 256}]] +} + +proc ::nmea::write {type args} { + variable nmea + set data $type,[join $args ,] + puts $nmea(fh) \$$data*[checksum $data] +} + +proc ::nmea::event {sentence {command _X}} { + variable dispatch + set sentence [string toupper $sentence] + if {$command == "_X"} { + if {[info exists dispatch($sentence)]} { + return $dispatch($sentence) + } + return {} + } + if {$command == ""} { + unset -nocomplain dispatch($sentence) + return {} + } + set dispatch($sentence) $command + return $command +} diff --git a/tcllib/modules/nmea/pkgIndex.tcl b/tcllib/modules/nmea/pkgIndex.tcl new file mode 100644 index 0000000..200dd5d --- /dev/null +++ b/tcllib/modules/nmea/pkgIndex.tcl @@ -0,0 +1,2 @@ +if {![package vsatisfies [package provide Tcl] 8.2]} {return} +package ifneeded nmea 1.0.0 [list source [file join $dir nmea.tcl]] |