From 54e217af783040d76c5a50e589b3419ac172672c Mon Sep 17 00:00:00 2001 From: Douglas Clowes Date: Wed, 19 Feb 2014 14:33:19 +1100 Subject: [PATCH] Bilby Script Context drivers for galil-attached devices --- .../config/motors/motor_configuration.tcl | 6 +- .../bilby/config/motors/sct_shutters.tcl | 245 ++++++++++++++++++ .../bilby/config/motors/sct_tank.tcl | 208 +++++++++++++++ .../bilby/config/motors/shutters.sct | 93 +++++++ .../instrument/bilby/config/motors/tank.sct | 70 +++++ 5 files changed, 621 insertions(+), 1 deletion(-) create mode 100644 site_ansto/instrument/bilby/config/motors/sct_shutters.tcl create mode 100644 site_ansto/instrument/bilby/config/motors/sct_tank.tcl create mode 100644 site_ansto/instrument/bilby/config/motors/shutters.sct create mode 100644 site_ansto/instrument/bilby/config/motors/tank.sct diff --git a/site_ansto/instrument/bilby/config/motors/motor_configuration.tcl b/site_ansto/instrument/bilby/config/motors/motor_configuration.tcl index eae91283..38e8926b 100644 --- a/site_ansto/instrument/bilby/config/motors/motor_configuration.tcl +++ b/site_ansto/instrument/bilby/config/motors/motor_configuration.tcl @@ -1,11 +1,15 @@ # @file Loads the generated_motor_configuration.tcl file which is created by util/genmotconf.tcl from CSV files. fileeval config/motors/generated_motor_configuration.tcl +fileeval config/motors/sct_shutters.tcl +fileeval config/motors/sct_tank.tcl +add_shutters shutters aqadapter mc4 +add_tank tank aqadapter mc8 # Motors which should not be driven should be set as "fixed" here. # Configurable virtual motors can be defined here. # Eg, mot fixed 1 # Define "proc motor_set_sobj_attributes {}" if we need to define extra sicslist attributes for some motors. -for {set n 1} {$n < 8} {incr n} { +for {set n 1} {$n <= 8} {incr n} { make_coll_motor_1 c$n c$n col$n count make_coll_motor_1 a$n a$n ap$n count } diff --git a/site_ansto/instrument/bilby/config/motors/sct_shutters.tcl b/site_ansto/instrument/bilby/config/motors/sct_shutters.tcl new file mode 100644 index 00000000..46df0f3b --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/sct_shutters.tcl @@ -0,0 +1,245 @@ +# Generated driver for shutters +# vim: tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent +# + +namespace eval ::scobj::shutters { + set debug_threshold 0 +} + +proc ::scobj::shutters::debug_log {debug_level debug_string} { + if {${debug_level} >= ${::scobj::shutters::debug_threshold}} { + set fd [open "/tmp/shutters.log" "a"] + set line "[clock format [clock seconds] -format "%T"] ${debug_string}" + puts ${fd} "${line}" + close ${fd} + } +} + +# check function for hset change +proc ::scobj::shutters::checkrange {tc_root} { + debug_log 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK +} + +# function to request the read of a parameter on a device +proc ::scobj::shutters::getValue {tc_root nextState cmd_str} { + debug_log 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" + debug_log 1 "getValue sct send ${cmd}" + sct send "${cmd}" + return ${nextState} +} + +# function to check the write parameter on a device +proc ::scobj::shutters::noResponse {tc_root} { + debug_log 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]" + return "idle" +} + +# function to parse the read of a parameter on a device +proc ::scobj::shutters::read_switch_pair {tc_root} { + debug_log 1 "read_switch_pair tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + return -code error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 1 "${data}" "?"] } { + sct geterror "Galil error in: '${data}'" + } else { + set data_list [split [string trim "${data}"]] + if { [llength ${data_list}] > 2 && [lindex ${data_list} end] == ":" } { + set data_list [lrange ${data_list} 0 1] + } + if { [llength ${data_list}] == 2 } { + set left [expr [lindex ${data_list} 0]] + set right [expr [lindex ${data_list} 1]] + if { ${left} == 1 && ${right} == 0 } { # open + set data "out" + } elseif { ${left} == 0 && ${right} == 1 } { # closed + set data "in" + } else { # indeterminate + set data "moving" + } + } else { + sct geterror "Syntax error in: '${data}'=>'${data_list}'" + } + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + return -code error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} +} + +# function to write a parameter value on a device +proc ::scobj::shutters::setValue {tc_root nextState cmd_str} { + debug_log 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" + debug_log 1 "setValue sct send ${cmd}" + sct send "${cmd}" + return ${nextState} +} + +# function to write a parameter value on a device +proc ::scobj::shutters::write_switch {tc_root nextState cmd_str} { + debug_log 1 "write_switch tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code starts + if { [string equal -nocase -length 2 "${par}" "in"] } { + set cmd "SB${cmd_str}" + } elseif { [string equal -nocase -length 2 "${par}" "out"] } { + set cmd "CB${cmd_str}" + } else { + sct geterror "Value error: '${par}' not in ('in', 'out')" + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + return -code error "[sct geterror]" + } + debug_log 1 "write_switch sct send ${cmd}" + sct send "${cmd}" + return ${nextState} +} + +proc ::scobj::shutters::mk_sct_shutters { sct_controller name } { + debug_log 1 "mk_sct_shutters for ${name}" + set ns "[namespace current]" + set catch_status [ catch { + + MakeSICSObj ${name} SCT_OBJECT + + sicslist setatt ${name} klass collimator + sicslist setatt ${name} long_name ${name} + + set scobj_hpath /sics/${name} + + hfactory ${scobj_hpath}/fast_shutter plain user text + hsetprop ${scobj_hpath}/fast_shutter read ${ns}::getValue ${scobj_hpath} read_switch_pair {MG @IN[5], @IN[6]} + hsetprop ${scobj_hpath}/fast_shutter read_switch_pair ${ns}::read_switch_pair ${scobj_hpath} + hsetprop ${scobj_hpath}/fast_shutter control true + hsetprop ${scobj_hpath}/fast_shutter data true + hsetprop ${scobj_hpath}/fast_shutter mutable false + hsetprop ${scobj_hpath}/fast_shutter nxsave true + hsetprop ${scobj_hpath}/fast_shutter oldval UNKNOWN + hsetprop ${scobj_hpath}/fast_shutter klass "collimator" + hsetprop ${scobj_hpath}/fast_shutter nxalias "fast_shutter" + hsetprop ${scobj_hpath}/fast_shutter sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/fast_shutter type "part" + + hfactory ${scobj_hpath}/rough_20 plain user text + hsetprop ${scobj_hpath}/rough_20 read ${ns}::getValue ${scobj_hpath} read_switch_pair {MG @IN[15], @IN[16]} + hsetprop ${scobj_hpath}/rough_20 read_switch_pair ${ns}::read_switch_pair ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_20 write ${ns}::write_switch ${scobj_hpath} noResponse {11} + hsetprop ${scobj_hpath}/rough_20 noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_20 check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_20 control true + hsetprop ${scobj_hpath}/rough_20 data true + hsetprop ${scobj_hpath}/rough_20 mutable false + hsetprop ${scobj_hpath}/rough_20 nxsave true + hsetprop ${scobj_hpath}/rough_20 values in,out + hsetprop ${scobj_hpath}/rough_20 oldval UNKNOWN + hsetprop ${scobj_hpath}/rough_20 klass "collimator" + hsetprop ${scobj_hpath}/rough_20 nxalias "rough_20" + hsetprop ${scobj_hpath}/rough_20 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/rough_20 type "part" + + hfactory ${scobj_hpath}/rough_40 plain user text + hsetprop ${scobj_hpath}/rough_40 read ${ns}::getValue ${scobj_hpath} read_switch_pair {MG @IN[13], @IN[14]} + hsetprop ${scobj_hpath}/rough_40 read_switch_pair ${ns}::read_switch_pair ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_40 write ${ns}::write_switch ${scobj_hpath} noResponse {10} + hsetprop ${scobj_hpath}/rough_40 noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_40 check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_40 control true + hsetprop ${scobj_hpath}/rough_40 data true + hsetprop ${scobj_hpath}/rough_40 mutable false + hsetprop ${scobj_hpath}/rough_40 nxsave true + hsetprop ${scobj_hpath}/rough_40 values in,out + hsetprop ${scobj_hpath}/rough_40 oldval UNKNOWN + hsetprop ${scobj_hpath}/rough_40 klass "collimator" + hsetprop ${scobj_hpath}/rough_40 nxalias "rough_40" + hsetprop ${scobj_hpath}/rough_40 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/rough_40 type "part" + + hsetprop ${scobj_hpath} data "true" + hsetprop ${scobj_hpath} nxsave "true" + + if {[SplitReply [motor_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/fast_shutter 1 + ${sct_controller} poll ${scobj_hpath}/rough_20 1 + ${sct_controller} poll ${scobj_hpath}/rough_40 1 + ${sct_controller} write ${scobj_hpath}/rough_20 + ${sct_controller} write ${scobj_hpath}/rough_40 + } + hsetprop ${scobj_hpath} klass collimator +# hook code starts +# hook code ends + } catch_message ] + handle_exception ${catch_status} ${catch_message} "in ${ns}::mk_sct_shutters" +} + +namespace eval ::scobj::shutters { + namespace export debug_log + namespace export mk_sct_shutters +} + +proc add_shutters {name IP port} { + set ns "::scobj::shutters" + ${ns}::debug_log 1 "add_shutters ${name} ${IP} ${port}" + if {[SplitReply [motor_simulation]]=="false"} { + if {[string equal -nocase "aqadapter" "${IP}"]} { + ${ns}::debug_log 1 "makesctcontroller sct_${name} aqadapter ${port}" + makesctcontroller sct_${name} aqadapter ${port} + } else { + ${ns}::debug_log 1 "makesctcontroller sct_${name} dmc2280 ${IP}:${port}" + makesctcontroller sct_${name} dmc2280 ${IP}:${port} + } + } + ${ns}::debug_log 1 "mk_sct_shutters sct_${name} ${name}" + ${ns}::mk_sct_shutters sct_${name} ${name} + close ${fd} +} + +puts stdout "file evaluation of sct_shutters.tcl" +::scobj::shutters::debug_log 1 "file evaluation of sct_shutters.tcl" diff --git a/site_ansto/instrument/bilby/config/motors/sct_tank.tcl b/site_ansto/instrument/bilby/config/motors/sct_tank.tcl new file mode 100644 index 00000000..6aa06101 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/sct_tank.tcl @@ -0,0 +1,208 @@ +# Generated driver for tank +# vim: tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent +# + +namespace eval ::scobj::tank { + set debug_threshold 0 +} + +proc ::scobj::tank::debug_log {debug_level debug_string} { + if {${debug_level} >= ${::scobj::tank::debug_threshold}} { + set fd [open "/tmp/tank.log" "a"] + set line "[clock format [clock seconds] -format "%T"] ${debug_string}" + puts ${fd} "${line}" + close ${fd} + } +} + +# check function for hset change +proc ::scobj::tank::checkrange {tc_root} { + debug_log 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK +} + +# function to request the read of a parameter on a device +proc ::scobj::tank::getValue {tc_root nextState cmd_str} { + debug_log 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" + debug_log 1 "getValue sct send ${cmd}" + sct send "${cmd}" + return ${nextState} +} + +# function to check the write parameter on a device +proc ::scobj::tank::noResponse {tc_root} { + debug_log 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]" + return "idle" +} + +# function to parse the read of a parameter on a device +proc ::scobj::tank::read_switch {tc_root} { + debug_log 1 "read_switch tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + return -code error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 1 "${data}" "?"] } { + sct geterror "Galil error in: '${data}'" + } else { + set data_list [split [string trim "${data}"]] + if { [llength ${data_list}] > 1 && [lindex ${data_list} end] == ":" } { + set data_list [lrange ${data_list} 0 0] + } + if { [llength ${data_list}] == 1 } { + set left [expr [lindex ${data_list} 0]] + if { ${left} == 1 } { # open + set data "open" + } else { # closed + set data "closed" + } + } else { + sct geterror "Syntax error in: '${data}'=>'${data_list}'" + } + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + return -code error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} +} + +# function to write a parameter value on a device +proc ::scobj::tank::setValue {tc_root nextState cmd_str} { + debug_log 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" + debug_log 1 "setValue sct send ${cmd}" + sct send "${cmd}" + return ${nextState} +} + +proc ::scobj::tank::mk_sct_tank { sct_controller name } { + debug_log 1 "mk_sct_tank for ${name}" + set ns "[namespace current]" + set catch_status [ catch { + + MakeSICSObj ${name} SCT_OBJECT + + sicslist setatt ${name} klass instrument + sicslist setatt ${name} long_name ${name} + + set scobj_hpath /sics/${name} + + hfactory ${scobj_hpath}/limits plain spy none + + hfactory ${scobj_hpath}/limits/forward plain user text + hsetprop ${scobj_hpath}/limits/forward read ${ns}::getValue ${scobj_hpath} read_switch {MG _LFH} + hsetprop ${scobj_hpath}/limits/forward read_switch ${ns}::read_switch ${scobj_hpath} + hsetprop ${scobj_hpath}/limits/forward control true + hsetprop ${scobj_hpath}/limits/forward data true + hsetprop ${scobj_hpath}/limits/forward mutable false + hsetprop ${scobj_hpath}/limits/forward nxsave true + hsetprop ${scobj_hpath}/limits/forward oldval UNKNOWN + + hfactory ${scobj_hpath}/limits/reverse plain user text + hsetprop ${scobj_hpath}/limits/reverse read ${ns}::getValue ${scobj_hpath} read_switch {MG _LRH} + hsetprop ${scobj_hpath}/limits/reverse read_switch ${ns}::read_switch ${scobj_hpath} + hsetprop ${scobj_hpath}/limits/reverse control true + hsetprop ${scobj_hpath}/limits/reverse data true + hsetprop ${scobj_hpath}/limits/reverse mutable false + hsetprop ${scobj_hpath}/limits/reverse nxsave true + hsetprop ${scobj_hpath}/limits/reverse oldval UNKNOWN + + if {[SplitReply [motor_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/limits/forward 1 + ${sct_controller} poll ${scobj_hpath}/limits/reverse 1 + } + + hfactory ${scobj_hpath}/switches plain spy none + + hfactory ${scobj_hpath}/switches/forward plain user text + hsetprop ${scobj_hpath}/switches/forward read ${ns}::getValue ${scobj_hpath} read_switch {MG @IN[5]} + hsetprop ${scobj_hpath}/switches/forward read_switch ${ns}::read_switch ${scobj_hpath} + hsetprop ${scobj_hpath}/switches/forward control true + hsetprop ${scobj_hpath}/switches/forward data true + hsetprop ${scobj_hpath}/switches/forward mutable false + hsetprop ${scobj_hpath}/switches/forward nxsave true + hsetprop ${scobj_hpath}/switches/forward oldval UNKNOWN + + hfactory ${scobj_hpath}/switches/reverse plain user text + hsetprop ${scobj_hpath}/switches/reverse read ${ns}::getValue ${scobj_hpath} read_switch {MG @IN[6]} + hsetprop ${scobj_hpath}/switches/reverse read_switch ${ns}::read_switch ${scobj_hpath} + hsetprop ${scobj_hpath}/switches/reverse control true + hsetprop ${scobj_hpath}/switches/reverse data true + hsetprop ${scobj_hpath}/switches/reverse mutable false + hsetprop ${scobj_hpath}/switches/reverse nxsave true + hsetprop ${scobj_hpath}/switches/reverse oldval UNKNOWN + + if {[SplitReply [motor_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/switches/forward 1 + ${sct_controller} poll ${scobj_hpath}/switches/reverse 1 + } + hsetprop ${scobj_hpath} klass instrument +# hook code starts +# hook code ends + } catch_message ] + handle_exception ${catch_status} ${catch_message} "in ${ns}::mk_sct_tank" +} + +namespace eval ::scobj::tank { + namespace export debug_log + namespace export mk_sct_tank +} + +proc add_tank {name IP port} { + set ns "::scobj::tank" + ${ns}::debug_log 1 "add_tank ${name} ${IP} ${port}" + if {[SplitReply [motor_simulation]]=="false"} { + if {[string equal -nocase "aqadapter" "${IP}"]} { + ${ns}::debug_log 1 "makesctcontroller sct_${name} aqadapter ${port}" + makesctcontroller sct_${name} aqadapter ${port} + } else { + ${ns}::debug_log 1 "makesctcontroller sct_${name} dmc2280 ${IP}:${port}" + makesctcontroller sct_${name} dmc2280 ${IP}:${port} + } + } + ${ns}::debug_log 1 "mk_sct_tank sct_${name} ${name}" + ${ns}::mk_sct_tank sct_${name} ${name} + close ${fd} +} + +puts stdout "file evaluation of sct_tank.tcl" +::scobj::tank::debug_log 1 "file evaluation of sct_tank.tcl" diff --git a/site_ansto/instrument/bilby/config/motors/shutters.sct b/site_ansto/instrument/bilby/config/motors/shutters.sct new file mode 100644 index 00000000..d0051a1f --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/shutters.sct @@ -0,0 +1,93 @@ +# +# Simple driver generator for the non-motor galil controls on mc4 +# vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent nocindent +# +driver shutters = { + usecreatenode = false + vendor = galil; device = mc4; protocol = dmc2280; + class = collimator + simulation_group = motor_simulation +# +# Unnamed group has variables at device level +# +# +# The named group is at the device level, variables below that +# + group = { + type = text + priv = user + group_property 'data' = 'true' + group_property 'nxsave' = 'true' + property 'type' = 'part' + property 'klass' = 'collimator' + property 'sdsinfo' = '::nexus::scobj::sdsinfo' + var fast_shutter = { + readable = 1 + read_command = 'MG @IN[5], @IN[6]' + read_function = read_switch_pair + property 'nxalias' = 'fast_shutter' + } + var rough_40 = { + readable = 1; + read_function = read_switch_pair; + read_command = 'MG @IN[13], @IN[14]' + writeable = 1 + write_function = write_switch; + write_command = '10' + allowed = 'in,out' + property 'nxalias' = 'rough_40' + } + var rough_20 = { + readable = 1; + read_function = read_switch_pair; + read_command = 'MG @IN[15], @IN[16]' + writeable = 1 + write_function = write_switch; + write_command = '11' + allowed = 'in,out' + property 'nxalias' = 'rough_20' + } + }; + +# +# Code lines start with '@' which is stripped before being emitted +# The code is emitted at the appropriate place in the given function +# + code read_function read_switch_pair = { +@ if { [string equal -nocase -length 1 "${data}" "?"] } { +@ sct geterror "Galil error in: '${data}'" +@ } else { +@ set data_list [split [string trim "${data}"]] +@ if { [llength ${data_list}] > 2 && [lindex ${data_list} end] == ":" } { +@ set data_list [lrange ${data_list} 0 1] +@ } +@ if { [llength ${data_list}] == 2 } { +@ set left [expr [lindex ${data_list} 0]] +@ set right [expr [lindex ${data_list} 1]] +@ if { ${left} == 1 && ${right} == 0 } { # open +@ set data "out" +@ } elseif { ${left} == 0 && ${right} == 1 } { # closed +@ set data "in" +@ } else { # indeterminate +@ set data "moving" +@ } +@ } else { +@ sct geterror "Syntax error in: '${data}'=>'${data_list}'" +@ } +@ } + } + code write_function write_switch = { +@ if { [string equal -nocase -length 2 "${par}" "in"] } { +@ set cmd "SB${cmd_str}" +@ } elseif { [string equal -nocase -length 2 "${par}" "out"] } { +@ set cmd "CB${cmd_str}" +@ } else { +@ sct geterror "Value error: '${par}' not in ('in', 'out')" +@ } + } +# +# This code is after database creation +# + code mkDriver = { + } +}; diff --git a/site_ansto/instrument/bilby/config/motors/tank.sct b/site_ansto/instrument/bilby/config/motors/tank.sct new file mode 100644 index 00000000..b22d752f --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/tank.sct @@ -0,0 +1,70 @@ +# +# Simple driver generator for the non-motor galil controls on mc8 +# vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent nocindent +# +driver tank = { + usecreatenode = false + vendor = galil; device = mc8; protocol = dmc2280; + class = instrument + simulation_group = motor_simulation +# +# Unnamed group has variables at device level +# +# +# The named group is at the device level, variables below that +# + group switches = { + type = text; + priv = user; + readable = 1; + read_function = read_switch; + var forward = { + read_command = 'MG @IN[5]' + } + var reverse = { + read_command = 'MG @IN[6]' + } + }; + group limits = { + type = text; + priv = user; + readable = 1; + read_function = read_switch; + var forward = { + read_command = 'MG _LFH' + } + var reverse = { + read_command = 'MG _LRH' + } + }; + +# +# Code lines start with '@' which is stripped before being emitted +# The code is emitted at the appropriate place in the given function +# + code read_function read_switch = { +@ if { [string equal -nocase -length 1 "${data}" "?"] } { +@ sct geterror "Galil error in: '${data}'" +@ } else { +@ set data_list [split [string trim "${data}"]] +@ if { [llength ${data_list}] > 1 && [lindex ${data_list} end] == ":" } { +@ set data_list [lrange ${data_list} 0 0] +@ } +@ if { [llength ${data_list}] == 1 } { +@ set left [expr [lindex ${data_list} 0]] +@ if { ${left} == 1 } { # open +@ set data "open" +@ } else { # closed +@ set data "closed" +@ } +@ } else { +@ sct geterror "Syntax error in: '${data}'=>'${data_list}'" +@ } +@ } + } +# +# This code is after database creation +# + code mkDriver = { + } +};