#!/usr/bin/tclsh8.2 set testonly 0 #set testonly 1 set port /dev/ttya0 set ch(funcsevery) 10 set ch(speeddirnevery) 15 set ch(scale) 1 set ch(minint) 5000 # unset always set always 0 set nmrawhich 0 set polarity 908000 set pname l set m {} set segs {xx yy} set segsasgot {xx yy} set pq {} ;# unset: cdu charged and waiting set speeddirn ff7f set speeddirn_fixed {speed126 2 60 0} set funcs ff7f # 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" } gui_polarity 0x$polarity foreach seg [array names segdetect] { gui "D1 $seg" } } proc debug {m} { puts $m } proc tellpic_q {m} { global p testonly if {$testonly} return set b [binary format H* $m] puts -nonewline $p $b } proc tellpic {m} { puts ">> $m" tellpic_q $m } 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 9801 ;# 16ms after 2000 fail_now fileevent $p readable {} } proc gui_polarity {diff} { set l {} if {$diff & 0x06} { lappend l X10 X9 } if {$diff & 0x09} { lappend l X8 X1 X2 X3 X4 X5 X6 X7 } foreach seg $l { gui "R $seg" } } proc polarity {newpname m} { global pname polarity debug "polarising $m" if {![string compare $m $polarity]} return tellpic $m set pname $newpname gui_polarity [expr "0x$m ^ 0x$polarity"] set polarity $m } proc polarity_l {} { polarity l 908000 } proc polarity_p {} { polarity p 97ff79 } proc polarity_x {} { polarity x 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 randbyte {} { global rand set c [read $rand 1]; if {![string length $c]} { error "eof on rand" } binary scan $c H* x return $x } proc pt_maybe {point oneisright} { global always if {[info exists always]} { set pos $always } else { set x [randbyte] 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 pname segsasgot if {[string compare $seg [lindex $segsasgot 1]]} { set segsasgot [list [lindex $segsasgot 1] $seg] } if {[lsearch -exact $segs $seg] < 0} { set segs $segsasgot } debug "pm_detect $seg ($segsasgot) ($segs) $pname$seg" switch -exact $pname$seg { p07 - p06 { polarity_l } p02 - p09 { polarity_x } l16 - l1c - l10 - l1a { polarity_p } l03 - l05 - l08 - l0b { polarity_x } x07 - x06 { polarity_l } x14 - x16 - x1c - x20 - x1c - x10 { polarity_p } } switch -exact $seg { 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 } } switch -exact [join $segs -] { 14-20 { pt_must "42 43 A6" 1 } 20-14 { pt_must "02 03 A5" 1 } } switch -exact [join $segs -] { 07-02 { pt_maybe "00 01 X7" 0 } 02-07 { pt_maybe "02 03 A5" 1 } 06-09 { pt_maybe "40 41 X8" 1 } 09-06 { pt_maybe "42 43 A6" 0 } } } proc tellnmra {m} { global nmrawhich speeddirn funcs set m 0x$m for {set i 0} {$i < $m} {incr i} { tellpic_q [lindex [list $speeddirn $funcs] $nmrawhich] set nmrawhich [expr {!$nmrawhich}] } } proc watchdog {} { global watchdog testonly catch { after cancel $watchdog } set watchdog [after 50 watchdog] tellpic_q 9808 ;# 128ms } proc pm_hello {} { debug "got hello, starting up" tellpic 21 gui "P 1" watchdog changewhat tellnmra 01 } proc fp {m} { debug "<< $m" } proc frompic {m} { switch -glob [lindex $m 0] { 01 - 02 { tellnmra $m } 09 { fp $m; pm_hello } 07 { puts "short circuit"; exit 1 } 28 { fp $m; pm_charged } 9[0-7] { fp $m; pm_maydetect 0 [lindex $m 1] } 9? { fp $m; pm_detect [lindex $m 1]; pm_maydetect 1 [lindex $m 1] } 0a - [234567]? { puts "pic debug $m" } * { fp $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 length $c]} { if {[eof $p]} { error "eof on device" } return } binary scan $c H* x lappend m $x if {[regexp {^[0-7]} $x]} { if {![regexp {^x} $m]} { frompic $m } set m {} } } } proc newspeeddirn {} { set b1 0x[randbyte] set speed [expr {($b1 * $b1) / 516}] set b2 0x[randbyte] set dirn [expr {$b2 / 128}] debug "speeddirn b1=$b1 speed=$speed b2=$b2 dirn=$dirn" return "speed126 2 $speed $dirn" } proc newfuncs {} { set b3 0x[randbyte] set value [expr {($b3 & 127) * 16}] debug "funcs b3=$b3 value=[format %x $value]" return "funcs5to8 2 $value" } proc maybechange {thing} { global $thing ch upvar #0 ${thing}_fixed fixed if {![info exists fixed]} { set rb 0x[randbyte][randbyte] if { $rb / 65536.0 > 1.0 / (($ch(${thing}every) - $ch(minint)*0.001) * $ch(scale)) } { debug "maybechange $thing rb=$rb no" return 0 } debug "maybechange $thing rb=$rb yes ..." set l [new$thing] } else { debug "fixed $thing $fixed" set l $fixed } set bin [eval exec ./hostside-old -s/dev/stdout $l] binary scan $bin H* x debug "changed $thing=$x" set $thing ff$x return 1 } proc changewhat {} { global ch chwa catch { after cancel $chwa } if {[maybechange speeddirn] || [maybechange funcs]} { set interval $ch(minint) } else { set interval 1000 } set chwa [after $interval changewhat] } 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