chiark / gitweb /
stopgap controller program
authorian <ian>
Sat, 31 Dec 2005 04:40:49 +0000 (04:40 +0000)
committerian <ian>
Sat, 31 Dec 2005 04:40:49 +0000 (04:40 +0000)
hostside/stopgap-controller [new file with mode: 0755]

diff --git a/hostside/stopgap-controller b/hostside/stopgap-controller
new file mode 100755 (executable)
index 0000000..24f3cb7
--- /dev/null
@@ -0,0 +1,300 @@
+#!/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