esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%TITLE% WCINTLCK.MAC
#%NAME%
#  Macros for handling interlock systems running on the  WAGO Controller

def _wc_loadtype '{
   WC_TYPE["HT"] = 0
   WC_TYPE["HT"]["desc"] = "High Temperature"
   WC_TYPE["HT"]["scale"] = 0.1
   WC_TYPE["HT"]["offset"] = 0
   WC_TYPE["LN"] = 1
   WC_TYPE["LN"]["desc"] = "Cryogenic T (-200, 30) deg "
   WC_TYPE["LN"]["scale"] = (230 * 1.25) / (0x7FFF / 2)
   WC_TYPE["LN"]["offset"] = -257.5
}'


#%UU%
#%MDESC%
#  Edit and upload the configuration file into the controller
#
def wc_init '{
   local nres res[] silent

   if ($# != 1) {
      print "Usage: $0 wc_name"
      exit
   }
   _wc_init("$1")

   _wc_loadtype

   _wccomm WC_U 0x0002 0x0100
   # --- check that interlock instance exist
   if (res[0]) {
      _wccomm WC_U 0x0105 1
      WC[WC_U]["nchan"] = nres > 0? res[1] : 0
   }
   else {
      printf("Wago controller <%s> has no interlock instance configured\n", wcname)
      printf("Hint: Use wcconfig.\n")
      WC[WC_U]["nchan"] = -1
   }
   
}'

#%UU% 
#%MDESC%
#  Edit and upload the configuration file into the controller
#  
def wcconfig '{
   local file

   wc_get_unit($1)
   if (whatis("BLISSADM") & 0x04000000) {
      file = BLISSADM "/local/spec/userconf/" WC[WC_U]["name"] ".intlck"
   } else {
      file = "~specadm/local/userconf/" WC[WC_U]["name"] ".intlck"
   }

   unix(sprintf("%s %s", SEDITOR, file))
   wc_loadcfg(WC_U, file)
}'

#%UU% 
#%MDESC%
#  Edit and upload the configuration file into the controller
#  
def wclistunits '{
   local unit

   print "\nWAGO Unit\tName"

   for (unit = 1; unit <= WC_NRUNIT; unit++) {
      printf("%5d\t\t%s\n", unit, WC[unit]["name"])
   }
}'

def wc_loadcfg(unit, file) '{
   local line 
   local relay n c chan loth hith flags type
   local scale offset
   short array wc_config[20][5]

   if (!file_info(file, "-r")) {
      print " WC: Can not access configuration file ", file
      return (-1)
   }

   printf("Reading file \"%s\"\n", file)

   getline(file, "close")
   n = 0
   relay = -1
   while ((line = getline(file)) != -1) {
      if (sscanf(line, "%s", c) != 1 || substr(c, 1, 1) == "#")
         continue

      if (c == "relay") {
         if (sscanf(line, " relay %d", relay) != 1) {
            printf("  Bad line in \"%s\": %s\n", file, line)
            return(-1)
         }
         continue
      }
      flags = ""
      if (sscanf(line, " %d %g %g %s %s", chan, loth, hith, type, flags) < 4 \
          || !(type in WC_TYPE)) {
         printf("  Bad line in \"%s\": %s\n", file, line)
         return(-1)
      } 
      scale  = WC_TYPE[type]["scale"]
      offset = WC_TYPE[type]["offset"]
      wc_config[n][0] = (flags == "S" or flags == "s")? 0x08 : 0
      wc_config[n][1] = chan
      wc_config[n][2] = (loth - offset) / scale
      wc_config[n][3] = (hith - offset) / scale
      wc_config[n][4] = asc(substr(type,1,1)) << 8 | asc(substr(type,2,1))
      n++
   }
   getline(file, "close")

   print n " TC channels loaded from " file "."
   if (relay < 0) {
      relay = 0
      print "WARNING: No relay output specified. Default is channel 0."
   }
   wc_load(unit, relay, n, wc_config)

   return(n)
}'

def wc_load(unit, outrelay, n, data) '{
   local nres res[] err
   local short array par[6]
   local name silent

   if (WC[unit]["mode"]=="spec") {
      name = MODBUS[WC[unit]["id"]]["dev"]
   }
   else {
      name = WC[unit]["name"]
   }
   print "Uploading data into \`" name "\'"
   if(wc_ipcheck(name) != 1) exit

   silent= -1
   # --- check that interlock instance exist
   _wccomm WC_U 0x0002 0x0100
   if (res[0]) {
      # Delete previous instance
      par[0] = 1
      send_wccomm(unit, 0x0102, 1, par, res)
   }

   #Create a new instance on relay 0  (par[0])
   par[0] = outrelay
   if ((nres = send_wccomm(unit, 0x0101, 1, par, res)) < 0) {
      printf("ERROR %d: %s.\n", -nres, WC_ERR[-nres])
      exit
   }

   err = 0
   for (i = 0; i < n; i++) {
      par[0] = 1
      par[1:5] = data[i][]
      if ((nres = send_wccomm(unit, 0x0103, 6, par, res)) < 0) {
         printf("ERROR %d: %s.\n", -nres, WC_ERR[-nres])
         err = 1
      }
   }
   if (!err) {
      print "WAGO controller", unit, "configured succesfully."
      WC[unit]["nchan"] = n
   } else
      print "Check current configuration."

   print
   wcshow unit
}'

def wc_ipcheck(name) '{
   local subnetwork

   if ((subnet = get_subnet("`hostname`")) > 0 && \
       subnet == get_subnet(name))
      return(1)
   else {
      print "ERROR. This only works from the local network."
      return(-1)
   }
}'

def get_subnet(computer) '{
   local comm aux aux0 aux1 aux2 

   comm = "nslookup " computer " | grep Address: | tail -1"
   unix(comm, aux)
   if (sscanf(aux, "%s 160.103.%d.%d", aux0, aux1, aux2) == 3)
      return(aux1)
   else
      return(-1)
}'

#%UU% 
#%MDESC%
#  Resets the controller (in case of sticky channels)
#  
def wcreset '{
   wc_get_unit($1)
   wccomm WC_U 0x010c 1
}'

#%UU% 
#%MDESC%
#  Displays the current configuration
#  
def wcshow '{
   local nres res[] silent
   local n_inst n_chan inst chan
   local flags lbl type scale offset
   local c

   wc_get_unit($1)

   silent = 1

   _wccomm WC_U 0x0002 0x0100
   if (nres != 2)
      exit

   printf("WAGO Controller %d: %d interlock instance(s) found.\n", WC_U, res[0])
   n_inst = res[0]
   for (inst = 1; inst <= n_inst; inst++) {
      silent = -1
      _wccomm WC_U 0x0105 inst
      silent = 1
      if (nres < 0) continue
      printf("  Instance #%d\n", inst)
      printf("    Alarm relay = %d\n", res[0])
      n_chan = res[1]

      _wccomm WC_U 0x0108 inst
      printf("    State = %s\n", res[0]? "TRIPPED" : "NOT TRIPPED")

      printf("    %d channels configured:\n", n_chan)
      for (chan = 1; chan <= n_chan; chan++) {
         _wccomm WC_U 0x0105 inst chan
         flags = res[0]
         lbl = ""
         c = flags & 0x0800? "H":"."; lbl = lbl c
         c = flags & 0x0400? "C":"."; lbl = lbl c
         c = flags & 0x0200? "A":"."; lbl = lbl c
         c = flags & 0x0100? "T":"."; lbl = lbl c
         lbl = lbl " - "
         c = flags & 0x0010? "D":"E"; lbl = lbl c
         c = flags & 0x0008? "S":"."; lbl = lbl c
         c = flags & 0x0004? "I":"N"; lbl = lbl c
         printf("       [%2d] ", chan)
         if (flags & 0x0001) {
            printf("%sD  %2d\n", lbl, res[1])
         } else {
            c = flags & 0x0002? "U":"."; lbl = lbl c

            type = sprintf("%c%c", res[4] >> 8, res[4] & 0xff)
            if (type in WC_TYPE) {
               scale  = WC_TYPE[type]["scale"]
               offset = WC_TYPE[type]["offset"]
               res[2] = scale * res[2] + offset
               res[3] = scale * res[3] + offset
               res[5] = scale * res[5] + offset
            } else {
               scale  = 1
               offset = 0
               type = "??(" type ")"
            }
            printf("%s  %2d %s LO=%.0f HI=%.0f [%g]\n", lbl, res[1], type, \
                        res[2], res[3], res[5])
         }
      }
      print
   }
}'


#%UU% 
#%MDESC%
#  Displays the temperatures
#  
def wcreadT '{
   local n t
   local res[] addr[] silent chan

   wc_get_unit($1)
   n = WC[WC_U]["nchan"]

   while (1) {
      silent = -1
      for (i = 0; i < n; i++) {
         chan = i+1
         printf("  %2d ", chan)
         _wccomm WC_U 0x0105 1 chan
         addr[i] = res[1]
         t = res[5]
         if (t == 32767)
               printf("  ---")
            else
               printf(" %3.1f", t/10)
      }
      printf("\r")
      sleep(.5)
   }

}'

#%MACROS%
#%SETUP%
#  The %B%wc_init%B% macro has to be executed with the proper parameters.

#%AUTHOR% P.Fajardo, (Original 1/2002).
#  $Revision: 1.4 $ / $Date: 2004/09/10 13:17:46 $
#%TOC%