esrf

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

#%TITLE% millimarC1210.MAC
#%NAME% 
# Macros to control a MILLIMAR C 1210 or 1216
#%DESCRIPTION%
#  This macro file allows to connect a millimar micrometer as a macro counter in SPEC.
#%DL%
#%DT%  History:
#%DD%  
#%DD%  
#%XDL%
#
#%SETUP%
#%DL%  
#%DT%  Controller 1210 or 1216
#%DD%  The Millimar controller has to be configured before using it with this macros. 
#%DD%  Press the \"MENU\" press-button (on the front panel), then go to:
#%UL%
#%LI% -> SETUP
#%LI%	-> PARCOM
#%LI%		-> PROTOCOL = M1240
#%LI%		-> FORMAT = 8-N-1 (8bit,no-paritiy, 1 stop bit)
#%LI%		-> HANDSHK = SANS
#%LI%		-> BAUD = 9600 or 19200
#%LI%		-> ENVOYER = MANUELL 
#%XUL%
#%DT%  SPEC
#%DD%  configure a ESRF serial device with baud rate set to 9600 or 19200 and with \"raw\" mode.
#%DT%  SerialLine dserver. Default resources are enough.
#%DT%  You can also use a serial port without server (e.g. /dev/ttyS0)
#%XDL%
#  In order to configure a macro counter:
#  %DL%
#    %DT% 1)
#         You must have a "SCALERS" defined with:
#         %BR%
#         %DL%
#           %DT% DEVICE
#           set to "milc1210"
#           %DT% ADDR
#           set to the SPEC serial address (e.g. 0)
#           %DT% TYPE
#           set to "Macro Counter"
#           %DT% NUM
#           must be set also according to the number of sensor you use. Max is 2.
#         %XDL%
#    %DT% 2)
#         You must define a counter with:
#         %BR%
#         %DL%
#           %DT% Device
#           set to "MAC_CNT"
#           %DT% Mnemonic
#           as you want
#           %DT% Unit
#           must correspond to the milc1210 macro scaler you choose
#           %DT% Chan
#           channel number in the micc1210 controller, 0 or 1
#         %XDL%
#END%

constant MILC1210_HEAD "MIL C1210: "
global MILC1210_LIST MILC1210_CNT_LIST

#  list_init MILC1210_LIST
#  list_init MILC1210_CNT_LIST

def milc1210_config (num, type, p1, p2, p3) '{
  local unit 
  list_test MILC1210_LIST
  list_test MILC1210_CNT_LIST

  if (type=="ctrl") {

  # p1: unit number of the controller
  # p2: number of channels
   if (ser_par(milc1210_ADDR,"device_id") == -1) {
     print MILC1210_HEAD"ERROR: no serial device found at address "milc1210_ADDR
     return ".error."
   }
   if (p2 != 1 && p2 !=2) {
     print MILC1210_HEAD"ERROR: invalid number of channels, range is 1-2" 
     return ".error."
   }
   unit = "unit"p1

   list_add(MILC1210_LIST, unit)
   list_setpar(MILC1210_LIST, unit, "serial_dev", milc1210_ADDR)
   list_setpar(MILC1210_LIST, unit, "chans", p2)
   list_setpar(MILC1210_LIST, unit, "on", 1)
   list_setpar(MILC1210_LIST, unit, "data", "")
   return
  }

  if (type == "cnt") {
    local mne unit chan
  # num: counter mnemonic
  # p1: unit number of the associated ctrler
  # p2: unused
  # p3: channel number
    mne = cnt_mne(num)
    unit = "unit"p1; chan = p3
    if (list_check(MILC1210_LIST,unit) == 0) {
      print MILC1210_HEAD"ERROR: macro counter "mne" has an invalid unit number, "p1
      return ".error."
    }
    if (chan >= list_getpar(MILC1210_LIST,unit,"chans")) {
      print MILC1210_HEAD"ERROR: macro counter "mne" has an invalid channel number, "chan
      return ".error."
    }
    if (chan == 0) {
      list_setpar(MILC1210_LIST,unit,"chan0_mne",mne)
    }else{
      list_setpar(MILC1210_LIST,unit,"chan1_mne",mne)
    } 
    list_add(MILC1210_CNT_LIST,mne)
    list_setpar(MILC1210_CNT_LIST,mne,"unit",unit)
    list_setpar(MILC1210_CNT_LIST,mne,"chan",chan)
  }
  return 
}'

def milc1210_cmd (num, key, p1, p2, p3) '{
  local item ctrl_num rawval vals[]

  ctrl_num = list_n(MILC1210_LIST)
  if (key=="prestart_all") {
    # reset the string data before the count
    for (item=1;item != ctrl_num+1; item++) list_setpar(MILC1210_LIST,item,"data","")
  }
  if (key == "counts") {

    local mne unit serial_dev data val chan
    mne = cnt_mne(num) 
    unit = list_getpar(MILC1210_CNT_LIST,mne,"unit")
    chan = list_getpar(MILC1210_CNT_LIST,mne,"chan")
    #only ask one readout to the controller for both channels
    if (list_getpar(MILC1210_LIST,unit,"data") == "")  {
      serial_dev = list_getpar(MILC1210_LIST,unit,"serial_dev")  
      ser_put(serial_dev,"M\r")
      data = ser_get(serial_dev, "\r")
      list_setpar(MILC1210_LIST,unit,"data",data)
    }
    
    data = list_getpar(MILC1210_LIST,unit,"data")
    
    split(data, vals, ";")
    if (chan == 1) {
      rawval= vals[1]
    } else {
      rawval= vals[0]
    }
    split(rawval, vals, ",")
    return vals[1]+0
  }
}'

#%UU% [No of mils] [mil1 motor name] [mil1 device name] ...
#%MDESC% Adds the given mils to the already defined mils 
#

#%IU% mil-mnemonic serial_id channel_nr
#%MDESC%
#   Add definitions for a millitron micrometer pseudocounter
def miladd  'mil_add("$1", "$2", "$3")'

#%IU% (mil-mnemonic, serial_id, channel_nr)
#%MDESC%
#   Add definitions for a millitron micrometer pseudocounter
def mil_add(mne, dev, nr) '{
   local device angle hlim llim

   if (cnt_num(mne) == -1) {
     printf("Counter \"%s\" does not exist, exit\n", mne)
     exit
   }

   if (nr != 1 && nr != 2) {
     printf("Wrong Channel number for %s, choose 1 or 2, exit\n", mne)
     exit
   }
   list_add(MIL_LIST, mne)
   list_setpar(MIL_LIST, mne, "dev", dev)
   list_setpar(MIL_LIST, mne, "nr", nr)

   if (whatis("blmenu") & 0x2 )
     milblon() 

   setup_tail("mil", sprintf("mil_%s %s", mne, mne))
}'

def milblon() '{
  blmenuadd("Millitron counters", "Millitron Info", "milbody", "mil")
}'

def milbody(mode) '{

  if ( mode == 1 ) {
    if (MILON) {
      miloff
    } else {
      milon
    }
  }
  if (mode == 2) {
    milshow
  }
  return(MILON?"On":"Off")
}'

#%IU% (mil-mnemonic)
#%MDESC%
#   Delete definitions for one MILLI mnemonic
#
def milunsetup '{
   mildel($1)
}'

#%IU% (mil-mnemonic)
#%MDESC%
#   Delete definitions for one MIL mnemonic
#
def mildel(mne) '{
   list_remove(MIL_LIST,mne)
   cdef("", "", mne, "delete")
   S[cnt_num(mne)]=0

}'

#%UU% [mil-mne1 serial_id1 channel_nr1 [...]]
#%MDESC%
#  Sets parameters for a group of millitron micrometer pseudocounters. It can be called
#  interactively or non-interactively by giving all parameters in the
#  command line.
def milsetup '
{
   global MILON MIL_LIST MIL_LAST_CNT
   list_test MIL_LIST
   local millist i
   local params number
   local milmne mildev milno milnr
   number = 0

   if (!$#) {
      milshow
    
      if ((milno = list_n(MIL_LIST)) > 0 ) {
         _yn = yesno("Do you want to change any of this values",0)
      }

      if (_yn || !milno) {
         miloff
         print "\nEnter as mnemonic \`end\' to finish or \`delete\' to remove a millitron counter."
         list_init millist
         for(i = 1; ; i++) {
            printf("\nMILLITRON #%d:", i)
            if ((milmne = list_item(MIL_LIST, i)) == -1) {
               milmne = "end"
            }
            milmne = getval("\tMnemonic", milmne)
            if (milmne == "delete") {
               milmne = list_item(MIL_LIST, i)
               milunsetup milmne
	       i--
               continue
            }
            if (milmne == "end") {
               break
            }
            if ((mildev = list_getpar(MIL_LIST, milmne, "dev")) == -1) {
               mildev = ""
            }
            mildev = getval("\tSERIAL ID # ", list_getpar(MIL_LIST, i, "dev"))
            list_add(millist, milmne)
            milnr = getval("\tChannel (1-2)# ",  list_getpar(MIL_LIST, i, "nr"))
            list_add(millist, milnr)

            list_setpar(millist, milmne, "dev", mildev)
            list_setpar(millist, milmne, "nr",  milnr)
            number +=1
         }
         print
         milreset
         for (i = 1; i <= number; i++) {
            milmne = list_item(millist, i)
            mildev = list_getpar(millist, milmne, "dev")
            milnr  = list_getpar(millist, milmne, "nr")
            p milmne
            mil_add(milmne, mildev, milnr)
         }
      }
   } else {
      miloff
      milno = int($#/3)
      split("$*",params)
      milreset
      for (i = 0; i < milno; i++) {
         milmne = params[i*3]
         mildev = params[i*3 + 1]
         milnr  = params[i*3 + 2]
         mil_add(milmne, mildev, milnr)
      }
   }
}
'

#%UU%
#%MDESC%
#  Reset internal lists.
def milreset '
   miloff
   list_init MIL_LIST
'

#%UU%
#%MDESC%
#  Shows current MIL pseudocounters definition.
#
def milshow '{
   local milno mne

   if (milno = list_n(MIL_LIST)) {
 
      printf("\nMILLITRON pseudocounters are \"%s\"\n\n",MILON?"ACTIVE":"NOT ACTIVE")
      printf("\t   Motor              Device               Config\n") 
      printf("\t---------------------------------------------------\n") 
      for (i=1; i<=milno; i++) {
         mne =  list_item(MIL_LIST, i)
         printf("\t%8s %15s/%s", mne, list_getpar(MIL_LIST, mne, "dev"),\
                                      list_getpar(MIL_LIST, mne, "nr"))
         if (cnt_num(mne) < 0) 
            printf(" %20s\n","NOT DEFINED")
         else 
            printf(" %20s\n","OK")
      }
      printf("\n")
   } else
      printf("Nothing defined for MILLITRON\n")
}' 

#%UU% 
#%MDESC% 
#  Deactivates definitions for MIL pseudocounters.
def miloff '
{
   local milno

   milno = list_n(MIL_LIST)

   for (i = 1; i <= milno; i++) {
      cdef("", "", list_item(MIL_LIST, i), "delete")
   } 
   MILON=0
}'

#%UU% 
#%MDESC%
#  Activates definitions for MIL pseudocounters.
#
def milon '
{
   local milno num mne dev nr init

   milno = list_n(MIL_LIST)
   init=0
   for (i=1; i <= milno; i++) {
      num = cnt_num(mne = list_item(MIL_LIST, i))
      if (num != -1 ) {
         dev = list_getpar(MIL_LIST, mne, "dev")
         nr  = list_getpar(MIL_LIST, mne, "nr")
         if (init==0) {
           # first initialise the controller for computer control
           ser_put(dev, "I\r")  # Init. controller for remote ctrl
           sleep(1)
           ser_par(dev,"flush")
           ser_par(dev,"timeout",0.1)
           init=1
        }
         cdef("user_getcounts", sprintf("mil_getcounts %s\n", mne), mne, 0x02)
      }
   } 
   MILON=1

   setup_tail("mil", sprintf("mil_%s %s", mne, mne))

   # position control
   printf("MILLITRON pseudocounters are now ACTIVE\n")
}'


#%IU%
#
def mil_getcounts '
{
   local device mil_dummy mil_ct mil_val nr

   device = list_getpar(MIL_LIST, "$1", "dev")
   nr     = list_getpar(MIL_LIST, "$1", "nr")

   ser_put(device,"M\r")
#   sleep(0.1)
#   mil_ct = ""
#   mil_dummy= ser_get(device)
#   while (mil_dummy !="") {
#     mil_ct = sprintf("%s%s", mil_ct, mil_dummy)
#     mil_dummy = ser_get(device)
#   }
    mil_ct = ser_get(device,"\r")

   if (mil_ct != "") {
     split(mil_ct, mil_val,";")
     if (nr==2) {
       S[$1] = mil_val[1]+0
     }else {
       mil_dummy=mil_val[0]
       split(mil_dummy, mil_val,",")
       S[$1] = mil_val[1]+0
     }
   } else {
     S[$1] = -99999
   }
}'


#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#  To use a millitron as a counter the following conditions have to be fulfilled:
#%UL%
#%LI% The file millitron.mac has to be read in       done by: startup s.
#    (this file needs: pseudo.mac , stchanges.mac)
#%LI% the millitron counters have to be configured          done by: SPECADM
#       (Controller NONE, mnemonic as in startupscript)
#%LI% setup the mils ( with milsetup )              done by: startup s.
#%XUL%
#%AUTHOR% Laurent
#%TOC%