diff --git a/site_ansto/hardsup/sct_ansrfamp.c b/site_ansto/hardsup/sct_ansrfamp.c new file mode 100644 index 00000000..fe109263 --- /dev/null +++ b/site_ansto/hardsup/sct_ansrfamp.c @@ -0,0 +1,193 @@ +/** @file Protocol handler for Aviatronic 35V 7A AC RF amplifier. + * Ferdi Franceschini July 2009 + * + * Create with + * makesctcontroller sct_rfamp ansrfamp IP:PORT + * + * TODO Handle control commands + */ +#include +#include +#include +#include +#include + +#define STARTSIG 2 +#define ENDSIG 3 +#define ERRMSGLEN 127 +#define MAXRETRY 3 + +/** @brief Enclose command with start and send signals + * before sending + */ +int AnsfrWriteStart(Ascon *a) { + char startSignal[2] = {STARTSIG,'\0'}, endSignal = ENDSIG; + + DynStringInsert(a->wrBuffer, startSignal, 0); + DynStringConcatChar(a->wrBuffer, endSignal); + a->state = AsconWriting; + a->wrPos = 0; + return 1; +} + +int AnsfrReading(Ascon *a) { + int ret, i; + static int retries = MAXRETRY; + unsigned char reply[11]; + char chr, errmsg[ERRMSGLEN]; + char startSignal = STARTSIG, endSignal = ENDSIG; + unsigned char OutputOn, C1on, C2on, C3on, OH, CV, CC; + + OutputOn = 1 << 7; + C1on = 1 << 6; + C2on = 1 << 5; + C3on = 1 << 4; + + OH = 1 << 7; + CV = 1 << 6; + CC = 1 << 5; + + + ret = AsconReadChar(a->fd, &chr); + if (ret > 0 && chr != startSignal && retries > 0) { + AsconReadGarbage(a->fd); + a->state = AsconWriting; + a->wrPos = 0; + retries--; + return 0; + } else if (retries <= 0) { + a->state = AsconReadDone; + AsconError(a, "Failed to get start signal", 0); + retries = MAXRETRY; + return 0; + } + ret = AsconReadChar(a->fd, &chr); + retries = MAXRETRY; + for (i=0; ret > 0; i++) { + a->start = DoubleTime(); + + if (chr == endSignal) { + a->state = AsconReadDone; + break; + } else { + if (i >= 11) { + a->state = AsconReadDone; + AsconError(a, "Corrupt reply", ENOMEM); + return 1; + } + reply[i] = chr; + ret = AsconReadChar(a->fd, &chr); + } + } + + if (a->state != AsconReadDone) { + if (a->timeout > 0) { + if (DoubleTime() - a->start > a->timeout) { + AsconError(a, "read timeout", 0); + a->state = AsconTimeout; + return 1; + } else { + return 1; + } + } + } + DynStringConcatChar(a->rdBuffer, reply[0]); + DynStringConcatChar(a->rdBuffer, ' '); + DynStringConcatChar(a->rdBuffer, reply[1]); + DynStringConcatChar(a->rdBuffer, ' '); + DynStringConcatChar(a->rdBuffer, reply[2]); + DynStringConcatChar(a->rdBuffer, reply[3]); + DynStringConcatChar(a->rdBuffer, ' '); + DynStringConcatChar(a->rdBuffer, reply[4]); + DynStringConcatChar(a->rdBuffer, reply[5]); + DynStringConcatChar(a->rdBuffer, reply[6]); + DynStringConcatChar(a->rdBuffer, ' '); + DynStringConcatChar(a->rdBuffer, reply[7]); + DynStringConcatChar(a->rdBuffer, reply[8]); + DynStringConcatChar(a->rdBuffer, ' '); + if (C3on & reply[9]) { + DynStringConcatChar(a->rdBuffer, '1'); + DynStringConcatChar(a->rdBuffer, ' '); + } else { + DynStringConcatChar(a->rdBuffer, '0'); + DynStringConcatChar(a->rdBuffer, ' '); + } + if (C2on & reply[9]) { + DynStringConcatChar(a->rdBuffer, '1'); + DynStringConcatChar(a->rdBuffer, ' '); + } else { + DynStringConcatChar(a->rdBuffer, '0'); + DynStringConcatChar(a->rdBuffer, ' '); + } + if (C1on & reply[9]) { + DynStringConcatChar(a->rdBuffer, '1'); + DynStringConcatChar(a->rdBuffer, ' '); + } else { + DynStringConcatChar(a->rdBuffer, '0'); + DynStringConcatChar(a->rdBuffer, ' '); + } + if (OutputOn & reply[9]) { + DynStringConcatChar(a->rdBuffer, '1'); + DynStringConcatChar(a->rdBuffer, ' '); + } else { + DynStringConcatChar(a->rdBuffer, '0'); + DynStringConcatChar(a->rdBuffer, ' '); + } + if (CC & reply[10]) { + DynStringConcatChar(a->rdBuffer, '1'); + DynStringConcatChar(a->rdBuffer, ' '); + } else { + DynStringConcatChar(a->rdBuffer, '0'); + DynStringConcatChar(a->rdBuffer, ' '); + } + if (CV & reply[10]) { + DynStringConcatChar(a->rdBuffer, '1'); + DynStringConcatChar(a->rdBuffer, ' '); + } else { + DynStringConcatChar(a->rdBuffer, '0'); + DynStringConcatChar(a->rdBuffer, ' '); + } + if (OH & reply[10]) { + DynStringConcatChar(a->rdBuffer, '1'); + DynStringConcatChar(a->rdBuffer, ' '); + } else { + DynStringConcatChar(a->rdBuffer, '0'); + DynStringConcatChar(a->rdBuffer, ' '); + } + return 1; +} + +/** brief ANSFR RF amplifier protocol handler. + * This handler formats commands (ie adds cr line terminator) and + * sorts replies into standard responses of + * + * OK + * ASCERR:... + */ +int AnsfrProtHandler(Ascon *a) { + int ret; + + switch(a->state){ + case AsconWriteStart: + ret = AnsfrWriteStart(a); + return ret; + break; + case AsconReading: + ret = AnsfrReading(a); + return ret; + break; + default: + return AsconStdHandler(a); + } + return 1; +} + +void AddAnsfrProtocol(){ + AsconProtocol *prot = NULL; + + prot = calloc(sizeof(AsconProtocol), 1); + prot->name = strdup("ansrfamp"); + prot->init = AsconStdInit; + prot->handler = AnsfrProtHandler; + AsconInsertProtocol(prot); +} diff --git a/site_ansto/instrument/hrpd/config/environment/temperature/west400.tcl b/site_ansto/instrument/hrpd/config/environment/temperature/west400.tcl new file mode 100644 index 00000000..eb9d1e3c --- /dev/null +++ b/site_ansto/instrument/hrpd/config/environment/temperature/west400.tcl @@ -0,0 +1,53 @@ +# $Revision: 1.2 $ +# $Date: 2009-12-11 02:08:43 $ +# Author: Ferdi Franceschini (ffr@ansto.gov.au) +# Last revision by: $Author: ffr $ + +namespace eval ::environment::temperature { } + +# @brief Make a simulated temperature controller object. +# +# @param temp_sobj, name for temperature controller object. +proc ::environment::temperature::mkwest400sim {temp_sobj} { + EvFactory new $temp_sobj sim + sicslist setatt $temp_sobj numsensors 1 + sicslist setatt $temp_sobj controlsensor sensora + sicslist setatt $temp_sobj sensorlist sensora + sicslist setatt $temp_sobj units kelvin + sicslist setatt $temp_sobj klass @none +} + +#WEST4100 tempcontroller creation +proc ::environment::temperature::mkwest400 {temp_sobj IP } { +MakeRS232Controller sertemp $IP 502 +sertemp timeout 300 +sertemp sendterminator 0x0 +sertemp replyterminator 0x0 +EvFactory new tc1 west4100 sertemp 1 2 + +sicslist setatt tc1 units kelvin +sicslist setatt tc1 klass @none +} + +# @brief Adds a west400 temperature controller object. +# +# This must be called when the instrument configuration is loaded and before\n +# the buildHDB function is called. Currently there is no way to add and remove\n +# environment controllers and their hdb paths at runtime. +proc ::environment::temperature::add_west400 {IP} { + set sim_mode [SplitReply [environment_simulation]] + if {$sim_mode == "true"} { + ::environment::temperature::mkwest400sim tc1 + } else { + ::environment::temperature::mkwest400 tc1 $IP + tc1 Upperlimit 1500 + tc1 Lowerlimit 0 + tc1 tolerance 10 + } + + sicslist setatt tc1 environment_name tempone + sicslist setatt tc1 long_name control_sensor_reading +::environment::mkenvinfo tc1 {ramprate {priv user} powerlimit {priv manager} } +#::environment::mkenvinfo tc1 {heateron {priv user} range {priv manager} } + +} diff --git a/site_ansto/instrument/reflectometer/config/motors/sct_batmotor.tcl b/site_ansto/instrument/reflectometer/config/motors/sct_batmotor.tcl new file mode 100644 index 00000000..be46fe67 --- /dev/null +++ b/site_ansto/instrument/reflectometer/config/motors/sct_batmotor.tcl @@ -0,0 +1,193 @@ +# $Revision: 1.2 $ +# $Date: 2009-12-11 02:09:56 $ +# Author: Ferdi Franceschini (ffr@ansto.gov.au) +# Last revision by: $Author: ffr $ + +## +# @file Platypus Beam Attenuator control and status. +namespace eval ::scobj::galil { + variable sim_mode + variable bat_state + array set bat_state [list OUT -1 IN 0 OSC 1] + + set NS ::scobj::galil + set batObjName scbat + set batpath /sics/$batObjName + + set sim_mode [SplitReply [motor_simulation]] +# set sim_mode "false" + + if {$sim_mode == "false"} { + makesctcontroller sct_mc1 galil mc1-platypus:1034 + } + MakeSICSObj $batObjName SCT_OBJECT + + ## + # @brief Send a command which returns a value + # @param nextState, State which handles the reply + # @param cmd, Galil command + # @return The next state + proc getValue {nextState cmd} { + sct send $cmd + return $nextState + } + + ## + # @brief Check that a command has been acknowledged + proc ackCmd {} { + set reply [sct result] + switch -glob -- $reply { + "ASCERR:*" { + sct geterror $reply + } + "OK" { + return idle + } + default { + sct geterror "Unhandled reply: $reply" + } + } + return idle + } + + ## + # @brief Simply reports a reply to the user by setting the hipadaba node + # which this proc is associated with. + proc rdValue {} { + set data [sct result] + switch -glob -- $data { + "ASCERR:*" { + sct geterror $data + } + default { + if {$data != [sct oldval]} { + sct oldval $data + sct update $data + sct utime readtime + } + } + } + return idle + } + + ## + # @brief Translates BAT state to English and reports it via the hdb node. + proc rdBatAction {} { + variable bat_state + set oscd [expr int([sct result])] + switch -- $oscd [subst { + $bat_state(OUT) {set msg "out"} + $bat_state(IN) {set msg "in"} + $bat_state(OSC) {set msg "osc"} + default { + sct geterror "Illegal value $oscd for beam attenuator state" + return idle + } + } ] + if {$msg != [sct oldval]} { + sct oldval $msg + sct update $msg + sct utime readtime + } + return idle + } + + ## + # @brief Sets the BAT to the state set in the target property + # of the hdb node. + # @param nextState, The script context state which handles the galil reply. + proc setBatAction {nextState} { + variable bat_state + set par [sct target] + switch $par { + "out" {sct send "OSCD=$bat_state(OUT)"} + "in" {sct send "OSCD=$bat_state(IN)"} + "osc" {sct send "OSCD=$bat_state(OSC)"} + default { + error "ERROR: illegal action $par for beam attenuator, try 'in', 'out' or 'osc'" + } + } + return $nextState + } + + ## + # @brief Send a status request to the Galil + # + # NOTE: If you change the status command you must also + # update the rdStatus procedure + proc getStatus {} { + sct send "MG OSCD,POS,_TPA,DBAND" + return rdStatus + } + + ## + # @brief Parse the status reply from the Galil and set + # the abstract status. + proc rdStatus {} { + variable bat_state + + set data [sct result] + switch -glob -- $data { + "ASCERR:*" { + sct geterror $data + } + default { + if {$data != [sct oldval]} { + sct oldval $data + foreach {OSCD POS TPA DBAND} $data {} + if [expr $OSCD == $bat_state(OSC)] { + set newStatus "busy" + } elseif [expr abs($TPA - $POS) < $DBAND] { + set newStatus "idle" + } else { + set newStatus "busy" + } + if {[sct oldStatus] != $newStatus} { + sct oldStatus $newStatus + sct update $newStatus + sct utime readtime + } + } + } + } + return idle + } + + # Read and set the BAT state, ie in, out, oscillating + hfactory $batpath/action plain user text + hsetprop $batpath/action read ${NS}::getValue rdBatAction "MG OSCD" + hsetprop $batpath/action rdBatAction ${NS}::rdBatAction + hsetprop $batpath/action write ${NS}::setBatAction ${NS}::ackCmd + hsetprop $batpath/action ackCmd ${NS}::ackCmd + hsetprop $batpath/action oldval UNKNOWN + + # Report the abstract status to GumTree + hfactory $batpath/status plain user text + hsetprop $batpath/status read ${NS}::getStatus + hsetprop $batpath/status rdStatus ${NS}::rdStatus + hsetprop $batpath/status values busy,idle + hsetprop $batpath/status oldval UNKNOWN + hsetprop $batpath/status oldStatus UNKNOWN + hset $batpath/status idle + + # Report the current position in encoder counts + # Useful as an activity monitor and troubleshooting. + hfactory $batpath/pos plain user int + hsetprop $batpath/pos read ${NS}::getValue rdValue "TPA" + hsetprop $batpath/pos rdValue ${NS}::rdValue + hsetprop $batpath/pos oldval UNKNOWN + + if {$sim_mode == "false"} { + sct_mc1 poll $batpath/pos + sct_mc1 poll $batpath/action + sct_mc1 poll $batpath/status + sct_mc1 write $batpath/action + } + + # Set hipadaba properties for GumTree interface + # and NeXus data file. + hsetprop $batpath klass NXaperture + ::scobj::hinitprops $batObjName + hsetprop $batpath/action mutable "false" + ::scobj::hinitprops $batObjName action +}