#!/usr/bin/tclsh8.4 set testonly 1 set port /dev/ttya0 # unset always set m xx set segs xx set polarity 908000 set pq {} ;# unset: cdu charged and waiting # unset pointpos($point) # unset segdetect($seg) ;# unset: shown D0; {}: shown D1; or: after id, D1->0 proc gui {m} { puts "GUI $m" } proc gui_init {} { global watchdog polarity segdetect gui "M A2 0" gui "M A5 0 J" gui "M A6 0 J" if {[info exists watchdog]} { gui "P 1" } if {![regexp {^90} $polarity]} { gui_polarity } foreach seg [array names segdetect] { gui "D1 $seg" } } proc debug {m} { puts $m } proc tellpic {m} { global p testonly puts ">> $m" if {$testonly} return set b [binary format H* $m] puts -nonewline $p $b } proc bgerror {m} { if {[catch { global errorInfo errorCode puts stderr "$m\n$errorCode\n$errorInfo" fail "bgerror $m" } emsg]} { exit 127 } } proc fail_now {} { global p debug "failing now" fconfigure $p -blocking yes gui "P 0" tellpic 20 exit 1 } proc fail {m} { global watchdog p catch { after cancel $watchdog; unset watchdog } puts "failing $m" tellpic a001 ;# 16ms after 2000 fail_now fileevent $p readable {} } proc gui_polarity {} { foreach seg { X8 X9 X10 X1 X2 X3 X4 X5 X6 X7 } { gui "R $seg" } } proc polarity {m} { global polarity debug "polarising $m" tellpic $m if {[string compare $m $polarity]} { gui_polarity } set polarity $m } proc polarity_l {} { polarity 908000 } proc polarity_x {} { polarity 97ff7f } proc pt_now {how point pos xtra} { set msg a0[lindex $point $pos] debug "$how point $point pos=$pos msg=$msg$xtra" gui "M [lindex $point 2] [expr {!$pos}]" tellpic $msg } proc pt_must {point newpos} { upvar #0 pointpos($point) pos global pq if {[info exists pos] && $pos == $newpos} return set pos $newpos if {[info exists pq]} { lappend pq [list $point $pos] debug "queue point $point pos=$pos l=[llength $pq]" return } pt_now immed $point $pos {} set pq {} } proc pm_charged {} { global pq if {[llength $pq]} { set v [lindex $pq 0] set pq [lrange $pq 1 end] pt_now nowdo [lindex $v 0] [lindex $v 1] " l=[llength $pq]" } else { debug "cdu-charged" unset pq } } proc pt_maybe {point} { global always rand if {[info exists always]} { set pos $always } else { set c [read $rand 1]; if {![string length $c]} { error "eof on rand" } binary scan $c H* x set pos [expr [regexp {^[89a-f]} $x] ? 1 : 0] debug "chose point $point pos=$pos (x=$x)" } pt_must $point $pos } proc s0 {seg} { upvar #0 segdetect($seg) segd if {![info exists segd]} { debug "segment $seg = already" } elseif {[string length $segd]} { debug "segment $seg = pending already" } else { debug "segment $seg = soon" set segd [after 100 s0t $seg] } } proc s0t {seg} { upvar #0 segdetect($seg) segd debug "segment $seg = now" unset segd gui "D0 $seg" } proc s1 {seg} { upvar #0 segdetect($seg) segd if {![info exists segd]} { debug "segment $seg ! (overwrites =)" } elseif {[string length $segd]} { debug "segment $seg ! (cancels =)" after cancel $segd } else { debug "segment $seg ! already" return } gui "D1 $seg" set segd {} } proc pm_maydetect {d seg} { switch -exact $seg { 06 { s$d X10 } 09 { s$d X8 } 0a { s$d X6 } 04 { s$d X5 } 02 { s$d X7 } 07 { s$d X9 } 14 { s$d A5 } 20 { s$d A6 } 1a { s$d A4 } 10 { s$d A2 } 03 { s$d X1 } 05 { s$d X3 } 16 { s$d A3 } 1c { s$d A1 } 08 { s$d X2 } 0b { s$d X4 } } } proc pm_detect {seg} { global segs switch -exact $seg { 07 - 06 { polarity_l } 16 - 1c - 1a - 10 - 03 - 05 - 08 - 0b { polarity_x } } switch -exact $seg { 14 - 20 { pt_must "02 03 A5" 1; pt_must "42 43 A6" 1 } 04 - 0a { pt_must "00 01 X7" 1; pt_must "40 41 X8" 1 } 03 - 05 { pt_must "00 01 X7" 0 } 08 - 0b { pt_must "40 41 X8" 0 } 16 - 1c { pt_must "02 03 A5" 0 } 1a - 10 { pt_must "42 43 A6" 0 } } if {[lsearch -exact $segs $seg] < 0} { set segs [list [lindex $segs end] $seg] } switch -exact [join $segs -] { 07-02 { pt_maybe "00 01 X7" } 02-07 { pt_maybe "02 03 A5" } 06-09 { pt_maybe "40 41 X8" } 09-06 { pt_maybe "42 43 A6" } } } proc watchdog {} { global watchdog testonly if {$testonly} return catch { after cancel $watchdog } set watchdog [after 50 watchdog] tellpic 9808 ;# 128ms } proc pm_hello {} { debug "got hello, starting up" tellpic 21 gui "P 1" watchdog } proc frompic {m} { debug "<< $m" switch -glob [lindex $m 0] { 09 { pm_hello } 28 { pm_charged } 9[0-7] { pm_maydetect 0 [lindex $m 1] } 9? { pm_detect [lindex $m 1]; pm_maydetect 1 [lindex $m 1] } 0a - [234567]? { puts "pic debug $m" } * { fail "pic unknown $m" } } } proc onreadp_test {} { if {![gets stdin m]} { return } frompic $m } proc onreadp {} { global p m while 1 { set c [read $p 1] if {![string llength $c]} { if {[eof $p]} { error "eof on device" } return } binary scan $c H* x lappend m $x if {[regexp {^[89a-f]} $x]} { if {![regexp {^x} $m]} { frompic $m } set m {} } } } proc setup {} { global port p rand testonly if {!$testonly} { set p [open $port {RDWR NONBLOCK} 0] exec stty -F $port min 1 time 0 -istrip -ocrnl -onlcr -onocr -opost \ -ctlecho -echo -echoe -echok -echonl -iexten -isig \ -icanon -icrnl \ 9600 clocal cread crtscts -hup -parenb cs8 -cstopb \ -ixoff bs0 cr0 ff0 nl0 -ofill -olcuc fconfigure $p -encoding binary -translation binary \ -blocking false -buffering none fileevent $p readable onreadp } else { set p stdin fconfigure stdin -blocking false fileevent stdin readable onreadp_test } set rand [open /dev/urandom {RDONLY} 0] fconfigure $rand -encoding binary -translation binary } setup gui_init vwait end