#!/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 lastptchosen xx set polmsg(l) 908000 set polmsg(x) 90f802 set polmsg(y) 90807c 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 80 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 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 {} { global pname set 1 {} switch -exact $pname { l { lappend 0 X1 X3 X5 X7 X9; lappend 0 X2 X4 X6 X8 X10 } x { lappend 1 X1 X3 X5 X7 X9; lappend 0 X2 X4 X6 X8 X10 } y { lappend 0 X1 X3 X5 X7 X9; lappend 1 X2 X4 X6 X8 X10 } } foreach v {0 1} { foreach seg [set $v] { gui "R $v $seg" } } } proc polarity {newpname} { global pname polmsg debug "polarising $newpname" if {![string compare $pname $newpname]} return tellpic $polmsg($newpname) set pname $newpname gui_polarity } 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 pt_ifthenmust {ifpoint ifposwant thenpoint thenpos} { upvar #0 pointpos($ifpoint) ifpos if {![info exists ifpos] || $ifpos != $ifposwant} return pt_must $thenpoint $thenpos } 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 lastptchosen if {[info exists always]} { set pos $always } else { if {![string compare $point $lastptchosen]} return set lastptchosen $point 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 { l16 - l1c - l08 - l0b { polarity y } l10 - l1a - l03 - l05 { polarity x } x07 - x04 - x0a { polarity l } x16 - x1c - x14 - x0b { polarity y } y06 - y04 - y0a { polarity l } y20 - y10 - y1a - y05 { polarity x } } switch -exact $seg { 04 - 0a { pt_must "00 01 X7" 1; pt_must "40 41 X8" 1 } 05 { pt_must "00 01 X7" 0 } 0b { pt_must "40 41 X8" 0 } 16 - 1c { pt_must "02 03 A5" 0 } 1a - 10 { pt_must "42 43 A6" 0 } 14 { pt_ifthenmust "02 03 A5" 1 "42 43 A6" 1 } 20 { pt_ifthenmust "42 43 A6" 1 "02 03 A5" 1 } } switch -exact [join $segs -] { 02-07 { pt_maybe "00 01 X7" 0 } 07-02 { pt_maybe "02 03 A5" 1 } 09-06 { pt_maybe "40 41 X8" 1 } 06-09 { 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