chiark / gitweb /
wip, speed stuff
authorian <ian>
Fri, 6 Jun 2008 20:57:52 +0000 (20:57 +0000)
committerian <ian>
Fri, 6 Jun 2008 20:57:52 +0000 (20:57 +0000)
hostside/gui
hostside/gui-plan-testdata

index 8045697e50be8c99bf21f96aa3176a44696a114d..afcfb303276a18f1bd9e66880f407c6698134223 100755 (executable)
@@ -2,12 +2,16 @@
 
 #---------- general utilities ----------
 
+set tk_strictMotif 1
+
 source lib.tcl
 
 proc pagew {page} { return ".picture-$page" }
 
 proc debug {m} { puts $m }
 
+proc warning {m} { puts stderr $m }
+
 proc sconn {m} {
     global sconn
     debug "=> $m"
@@ -36,7 +40,9 @@ proc bgerror {emsg} {
 
 #---------- train set event registraton ----------
 
-set event_dispatch_body {}
+set event_dispatch_body {
+    append l " "
+}
 set event_selections {}
 
 proc register-event {selections args re body} {
@@ -196,6 +202,186 @@ proc layout-data {} {
     }
 }
 
+#---------- speed ----------
+
+# variables:
+#   $train_commanded($train)    $speed_step
+#   $speed_commanding           $w of the one we're commanding, or unset
+#   $speedws                    [list $w ...]
+#
+# speed/${w}(...) aka s(...):
+#   $s(train)                   train selected, or something not \w+
+#   $s(optionmenu)              optionmenu widget name
+#   $s(queuedupdown)            integer, always set
+#   $s(lastproblem)             [clock clicks -milliseconds]
+#
+# We don't worry too much about races: in particular, we don't mind
+# racing with other things trying to command the speed, and losing
+# the odd increment/decrement.  But since we thread the requested
+# speed via realtime, we do queue up our own increments/decrements
+# while we're executing a speed command, to avoid loss of steps during
+# quick motions.
+
+proc speedw-new {w} {
+    upvar #0 speed/$w s
+    global speedws
+
+    lappend $speedws $w
+    set s(queuedupdown) 0
+
+    frame $w -relief groove
+    set s(optionmenu) [tk_optionMenu $w.train speed/${w}(train) {}]
+    $w.train configure -textvariable {}
+    label $w.speed -width 100
+    label $w.problem -width 300
+    pack $w.problem -side bottom
+    pack $w.speed -side right
+    pack $w.train
+    
+    speedw-disable $w "starting"
+}
+
+proc speedw-disable {w whystr} {
+    $w.train configure -state disabled
+    speedw-train-noneselected $w $whystr
+}
+
+proc speedw-train-noneselected {w whystr} {
+    upvar #0 speed/$w s
+    set s(train) {}
+    set s(lastproblem) [clock clicks -milliseconds]
+    $w.train configure -text "($whystr)"
+    $w.speed configure -textvariable {} -text -
+    $w.problem configure -text {}
+}
+proc speedw-train-selected {w t} {
+    upvar #0 speed/$w s
+    set s(queuedupdown) 0
+    $w.train configure -text $t
+    $w.speed configure -text {} -textvariable train_commanded($t)
+    $w.problem configure -text {}
+}
+
+proc speedw-trains-available {w l} {
+    upvar #0 speed/$w s
+    if {![llength $l]} { speedw-set-disabled $w "no trains"; return }
+    $s(optionmenu) delete 0 end
+    $s(optionmenu) add radiobutton -label "(none)" -value {} \
+           -command [list speedw-train-noneselected $w "(no train selected)"]
+    set l [lsort $l]
+    foreach t $l {
+       $s(optionmenu) add radiobutton -label $t -value $t \
+               -command [list speedw-train-selected $w $t]
+    }
+    $w.train configure -state normal
+    if {[llength $l]==1} {
+       $s(optionmenu) invoke 1
+    } elseif {[set ix [lsearch -exact $l $s(train)] >= 0]} {
+       $s(optionmenu) invoke [expr {$ix+1}]
+    } elseif {![string length $s(train)]} {
+       $s(optionmenu) invoke 0
+    } else {
+       $w.train configure -text "$s(train) (not present)"
+    }
+}
+
+proc speedw-report-problem {w message} {
+    upvar #0 speed/$w s
+
+    set s(lastproblem) [clock clicks -milliseconds]
+    $w problem configure -text $message
+}
+
+proc speed-check-sendcommand {} {
+    global speed_commanding speedws
+    if {[info exists speed_commanding]} return
+    for {set i 0} {$i < [llength $speedws]} {incr i} {
+       set w [lindex $speedws $i]
+       upvar #0 speed/$w s
+       if {!$s(queuedupdown)} continue
+       # right:
+       set speedws [lreplace $speedws $i $i]
+       lappend speedws $w
+fixme
+       set newspeed [speedud-calc-newspeed ]
+
+       sconn "speed $s(train) 4"
+    }
+}
+
+proc speed-command-ack {message} {
+    global speed_commanding problemdisplayms
+    
+    if {![info exists speed_commanding]} {
+       warning "unexpected ack speed when not commanding"
+       return
+    }
+    set w $speed_commanding
+    unset speed_commanding
+    speed-check-sendcommand
+
+    upvar #0 speed/$w s
+    if {[string compare $train $s(train)]} {
+       warning "unexpected train $train, expected $s(train)"
+       return
+    }
+    if {[string length $message]} {
+       speedw-report-problem $w $message
+    } elseif {[clock clicks -milliseconds] - $s(lastproblem) \
+           > $problemdisplayms} {
+       $w problem configure -text {}
+    }
+}
+
+proc speedws-forall {command args} {
+    global speedws
+    foreach w $speedws { eval [list $command $w] $args }
+}
+
+register-event stastate {state} \
+       {^stastate (\w+|\-) } {
+    global ctrain trains statstate
+
+    set stastate $state
+
+    switch -exact $stastate {
+       Run {
+           set trainsl [array names trains]
+           speedws-forall speedw-trains-available $trainsl
+       }
+       default {
+           catch { unset trains }
+           speedws-forall speedw-disable "($stastate)"
+       }
+    }
+}
+
+register-event ?train_*_speed_commanded {train speed} \
+       {^.train (\w+) speed commanded (\d+) } {
+    upvar #0 train_commanded($train) cmd
+    set cmd $speed
+}
+
+register-event {} {} {^\+ack \S+ speed ok } { speed-command-ack "" }
+register-event {} {train segment message} \
+    {^\+ack \S+ speed \S+ SignallingPredictedProblem (\S+) (\S+) \: (.*) $} {
+    speed-command-ack "$segment $message"
+}
+register-event {} {ecode message} {^\+ack (\S+) speed (.*) $} {
+    speed-command-ack "$ecode: $message"
+}
+
+register-event &train_*_signalling-problem {train problem} \
+       {^\&train (\w+) signalling-problem (.*)$} {
+    global speedws
+    foreach w $speedws {
+       upvar #0 speed/$w s
+       if {![string compare $s(train) $train]} {
+           speedw-report-problem $w $problem
+       }
+    }
+}
+
 #---------- plan background (gui-plan subprocess) ----------
 
 proc gui-pipe-readable {args} {
@@ -215,7 +401,7 @@ proc train-event-eof {} {
     error "lost connection to train set"
 }
 
-register-event {} {} {^=connected} {
+register-event {} {} {^=connected } {
     global pages gui_pipe server port event_selections
 
     sconn "select-replay [concat $event_selections]"
@@ -234,9 +420,9 @@ register-event {} {} {^=connected} {
     }
 }
 
-register-event {} {} {^=failed} { error "multiplexer failed: $l" }
-register-event {} {} {^=denied} { error "multiplexer denied us: $l" }
-register-event {} {} {^\+nack} { error "multiplexer does not understand" }
+register-event {} {} {^=failed } { error "multiplexer failed: $l" }
+register-event {} {} {^=denied } { error "multiplexer denied us: $l" }
+register-event {} {} {^\+nack } { error "multiplexer does not understand" }
 
 #---------- main program ----------
 
@@ -262,6 +448,7 @@ proc main {} {
     setting geometry {} {[-+]\d+[-+]\d+}
     setting posdeviation 10 {\d+}
     setting movfeatcommand {movfeat++} {(?:!movfeat|movfeat\+?\+?)}
+    setting problemdisplayms 1000 {\d+}
     uplevel #0 source gui-config
     parse-argv {}
     foreach cpage $pages {
index 58fb7f3cb9f434b5d42299027ccfb29ce2c39de5..27db520f3537a0b4de1b80f5b9b2be3a1bb48fe5 100644 (file)
@@ -1,3 +1,4 @@
+stastate -
 train shinkansen has X7/P0. X5. X6. Q1. X8/P0.! X10* X12 Q2 A6/P0
 picio out on
 detect X8 1
@@ -11,3 +12,4 @@ movpos Q0 feat Q 0 two
 movpos X8 feat P 0 three
 picio out polarity <X2,X3,X4,Q3>
 train shinkansen speed commanded 100
+stastate Run