esrf

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

#%TITLE% OMU408.MAC 
#
#%NAME%
# Macros to control and read OMU 408 temperature controler device.
#
#%CATEGORY% Temperature, Isg
#
#%DESCRIPTION%
#%DL%
#
#%DT%Configuring macro counters to read a single channel %DD%
# %DL%
#  %DT% 1)
#       You must have a "SERIAL" entry with:
#       %DL%
#         %DT% -
#         The "DEVICE" can be set for instance to "/dev/ttyS1"
#         %DT% -
#         The "BAUD" must be set to 9600
#         %DT% -
#         The "MODE" must be set to "raw"
#       %XDL%
#  %DT% 2)
#       You must have a "SCALER" entry with:
#       %DL%
#         %DT% -
#         The "DEVICE" must be set to the string "omu"
#         %DT% -
#         The "ADDR" must be set to the above config SERIAL entry to use
#         %DT% -
#         The "NUM" must be set to the value 9
#         %DT% -
#         The "TYPE" must be set to "Macro Counter"
#       %XDL%
#  %DT% 3)
#       You must define a counter with "MAC_CNT" as "Device". 
#       %DL%
#         %DT% -
#         The "Unit" field must be set to the SCALER entry.
#         %DT% -
#         The "Chan" field must be set to the channel (from 1 to 8)
#       %XDL%
# %XDL%
#
#%XDL%
#
#%END%
#


#
# ----------------------- Constant defintions -----------------------
#

# Prompt for print out messages
constant OMU "OMU:"

# Warning the order does mater as it will give the command argument 
# value that will be used by OMU408 commands
constant _OMU408_TYPE "DC PM OHM RTD-Pt RTD-Ni TC DU RTD-Cu"

constant _OMU408_MODE "60mV 150mV 300mV 1200mV \
0-5mA 0-20mA 4-20mA \
0-2V 0-5V 0-10V 0-40V \
R100 R1K R10K R100K \
Pt100/3.85 Pt500/3.85 Pt1K/3.85 Pt100/3.92 \
Ni1K/5.0 Ni1K/6.18 Ni10K/5.0 Ni10K/6.18 \
TC/B TC/E TC/J TC/K TC/N TC/R TC/S TC/T \
LinPot \
Pt50/3.91 Pt100/3.91 \
Cu50/4.28 Cu100/4.28 Cu50/4.26 Cu100/4.26 \
TC/L \
Er4-20mA"

constant _OMU408_WIRE "Int1TC Int2TC Ext1TC Ext2TC Wire2 Wire3 Wire4"

constant _OMU408_MAX "60.0 150.0 300.0 1.20 5.0 20.0 20.0 2.0 5.0 10.0 \
40.0 100.0 1000.0 10.0 100.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100.0 \
0 0 0 0 0 0 0 20.0"



#
# ----------------------- MACRO COUNTER implementation -----------------------
#


#%IU%
#%MDESC%
# Macro counter: called by spec after reading the config file
#
def omu_config(num,type,p1,p2,p3) '{
 global OMU_CNT[]
 local mne
 local dev

 # p1 is the unit
 # p2 is the number of maximum channels
 if(type=="ctrl") {
  local sl

  # Get the serial line to use for communication
  sl =  omu_ADDR

  # The serial line must be already configured in spec 
  if(ser_par(sl,"device_id") == -1) 
  {
   p OMU,"ERROR: missing serial line in config ADDR field"
   return ".error"
  }

  # The OMU is quite slow to execute some commands
  ser_par(sl,"timeout",2)

  # Check that the OMU is there
  ans = _omu_query(sl,"1Y") 
  if(ans == "")
  {
   p OMU,"ERROR: no answer from controller"
   return ".error"
  }
  p OMU,"found device: "ans

  # Memorize the serial line to use
  OMU_CNT[p1]["address"] = sl

  # The OMU is quite slow to execute some commands
  ser_par(sl,"timeout",15)

  # Normal end
  return
 }


 # p1 is the unit
 # p2 is always 0
 # p3 is the channel which is the two digits address
 if(type=="cnt") {
  # Get the serial line to use for communication
  sl =  OMU_CNT[p1]["address"]
  counter_par(num,"address",sl,"add")
 }
}'

#%IU%
#%MDESC%
# Macro counter: called by spec on counter operations
#
def omu_cmd(num,key,p1,p2) '{
 global OMU_CNT[]
 local mne
 local ch
 local sl
 local ans


 if (num != "..") 
 {
  mne = cnt_mne(num)
 }


 if (key == "counts") 
 {
  ch  = counter_par(num,"channel") 
  sl  = counter_par(num,"address")
  ans = _omu_query(sl,sprintf("%dx",ch))
  if(ans != "00") 
  {
   p OMU,"ERROR: on compter ",mne,": unable to select channel: ",ch
   return 0 
  }
  ans = _omu_query(sl,"")
  return ans
 }

}'



#
# ----------------------- Direct access macros -----------------------
#


#%UU% sl channel [type mode wire]
#%MDESC%
# Set or print the configuration of the specified channel.
# Channel are numbered from 1
#
def omu_ch '{
 local sl
 local ch
 local t tt
 local m mt
 local w wt
 local found

 # Online documentation
 if((!$#) || (($#>2) && ($#!=5)))
 {
  print "Usage: $0 sl channel [type mode wire]"
  _omu_printdocch()
  exit
 }

 # Get the serial line to use for communication
 _omu_checksl $*

 # Get the channel to play with
 _omu_checkch $*


 # Configure a channel
 if($#==5)
 {
  tt="$3"
  mt="$4"
  wt="$5"

  found =0
  for(t in OMU408_TYPE) { if(OMU408_TYPE[t] == tt) {found=1; break;} }
  if(!found) 
  {
   p OMU,"ERROR: invalid channel type, hint: use _omu_printdocch()"
   exit
  }

  found =0
  for(m in OMU408_MODE) { if(OMU408_MODE[m] == mt) {found=1; break;} }
  if(!found) 
  {
   p OMU,"ERROR: invalid channel mode, hint: use _omu_printdocch()"
   exit
  }

  found =0
  for(w in OMU408_WIRE) { if(OMU408_WIRE[w] == wt) {found=1; break;} }
  if(!found) 
  {
   p OMU,"ERROR: invalid channel wire, hint: use _omu_printdocch()"
   exit
  }

  _omu_configch(sl,ch,t,m,w)
 }



 # Select the channel
 _omu_selectch(sl,ch)



 # Get the channel type
 if((t = _omu_getchtype(sl)) == -1) { exit }
 tt = (t in OMU408_TYPE)?OMU408_TYPE[t]:"?????"
 print "Current Type.........",tt


 # Get the channel mode
 if((m = _omu_getchmode(sl)) == -1) { exit }
 mt = (m in OMU408_MODE)?OMU408_MODE[m]:"?????"
 print "Current Mode.........",mt


 # Not documented but it seems that the wiring config is not for all cases
 # Works only with OHM RTD-Pt RTD-Ni TC RTD-Cu
 if((t==2) || (t==3) || (t==4) || ((t==5)&&(ch==1)) || (t==7))
 {
  # Get the channel wiring
  if((w = _omu_getchwire(sl)) == -1) { exit }
  wt = (w in OMU408_WIRE)?OMU408_WIRE[w]:"?????"
 }
 else
 {
  wt = "standard"
 }
 print "Current Wire.........",wt
}'





#%IU%(sl,ch,type,mode,wire)
#%MDESC%
# Activate and configure the specified channel.
# Returns -1 if failed, otherwise returns 0
#
def _omu_configch(sl,ch,t,m,w) '{
 local ans

 # Activate channel
 printf("Activating channel...")
 # MP 2009/11/17: it is not a single channel activation command
 # but a zero to n channel, therefore activate all channels
 # MP 2009/11/17: activating an already configured channel seems
 # to not erase its configuration
 # ans = _omu_query(sl,sprintf("1o%02d",(ch-1)))
 ans = _omu_query(sl,"1o07")
 printf(" %s\n",(ans==""?"failed":"done"))
 if(ans=="") { exit }

 # Select the channel
 _omu_selectch(sl,ch)

 # Configure channel
 printf("Setting type.........")
 ans = _omu_query(sl,sprintf("3Z%02d",t))
 printf(" %s\n",(ans==""?"failed":"done"))
 if(ans=="") { exit }




 # Configure channel
 printf("Setting mode.........")

 # Not documented but it seems that the wiring config is not for all cases
 # Works with DU but only if mode is LinPot
 if((t==6) && (m!=31))
 { 
  printf(" invalid mode, only \"LinPot\" possible\n")
  exit
 }
 ans = _omu_query(sl,sprintf("4Z%02d",m))
 printf(" %s\n",(ans==""?"failed":"done"))
 if(ans=="") { exit }




 # Configure channel
 printf("Setting wiring.......")

 # Not documented but it seems that the wiring config is not for all cases
 # Works only with OHM RTD-Pt RTD-Ni TC RTD-Cu
 if((t==2) || (t==3) || (t==4) || ((t==5)&&(ch==1)) || (t==7))
 {
  ans = _omu_query(sl,sprintf("8Z%02d",w))
  printf(" %s\n",(ans==""?"failed":"done"))
  if(ans=="") { exit }
 }
 else
 {
  printf(" skipped\n")
 }



 # Configure display format
 printf("Setting display......")
 ans = _omu_query(sl,"7I04")
 printf(" %s\n",(ans==""?"failed":"done"))
 if(ans=="") { exit }



 # Configure display factor convertion
 printf("Setting min..........")

 # Not documented but it seems that the wiring config is not for all cases
 # Works only with DC PM OHM DU
 if((t==0) || (t==1) || (t==2) || (t==6))
 {
  ans = _omu_query(sl,"1I00")
  printf(" %s\n",(ans==""?"failed":"done"))
  if(ans=="") { exit }
 }
 else
 {
  printf(" skipped\n")
 }



 # Configure display factor convertion
 printf("Setting max..........")

 # Not documented but it seems that the wiring config is not for all cases
 # Works only with DC PM OHM DU
 if((t==0) || (t==1) || (t==2) || (t==6))
 {
  ans = _omu_query(sl,sprintf("2I%.1f",OMU408_MAX[m]))
  printf(" %s\n",(ans==""?"failed":"done"))
  if(ans=="") { exit }
 }
 else
 {
  printf(" skipped\n")
 }


}'


#%IU%(sl,ch)
#%MDESC%
# Select the specified channel that will be used for other commands.
# Returns -1 if failed, otherwise returns 0
#
def _omu_selectch(sl,ch) '{
 local ans
 ans = _omu_query(sl,sprintf("1P%02d",(ch-1)))
 return (ans==""?-1:0)
}'


#%IU%(sl)
#%MDESC%
# Read the type of the current select channel.
# Returns -1 if failed, otherwise returns the corresponding number.
#
def _omu_getchtype(sl) '{
 local ans
 local ret

 # Request 
 ans = _omu_query(sl,"3Y")
 if(ans=="")
 {
  p OMU,"ERROR: failed to get channel type, hint: configured one?"
  return -1
 }

 # Get the answer
 ans = _omu_query(sl,"")
 sscanf(ans,"%d",ret)
 return (ans==""?-1:ret)
}'



#%IU%(sl)
#%MDESC%
# Read the mode of the current select channel.
# Returns -1 if failed, otherwise returns the corresponding number.
#
def _omu_getchmode(sl) '{
 local ans
 local ret

 # Request 
 ans = _omu_query(sl,"4Y")
 if(ans=="")
 {
  p OMU,"ERROR: failed to get channel mode, hint: configured one?"
  return -1
 }

 # Get the answer
 ans = _omu_query(sl,"")
 sscanf(ans,"%d",ret)
 return (ans==""?-1:ret)
}'



#%IU%(sl)
#%MDESC%
# Read the wire of the current select channel.
# Returns -1 if failed, otherwise returns the corresponding number.
#
def _omu_getchwire(sl) '{
 local ans
 local ret

 # Request 
 ans = _omu_query(sl,"8Y")
 if(ans=="")
 {
  p OMU,"ERROR: failed to get channel wire, hint: configured one?"
  return -1
 }

 # Get the answer
 ans = _omu_query(sl,"")
 sscanf(ans,"%d",ret)
 return (ans==""?-1:ret)
}'





#%IU%
#%MDESC%
# Internal initialization of macros
#
def _omu_internals() '{
 global OMU408_TYPE[]
 global OMU408_MODE[]
 global OMU408_WIRE[]
 global OMU408_MAX[]
 local  i
 local  n
 local  args[]


 n = split(_OMU408_TYPE,args)
 for(i=0;i<n;i++) { OMU408_TYPE[i] = args[i] }

 n = split(_OMU408_MODE,args)
 for(i=0;i<n;i++) { OMU408_MODE[i] = args[i] }

 n = split(_OMU408_WIRE,args)
 for(i=0;i<n;i++) { OMU408_WIRE[i] = args[i] }

 n = split(_OMU408_MAX,args)
 for(i=0;i<n;i++) { OMU408_MAX[i]  = args[i] }
}'



# Ensure that everything is well initialized, sorry for the waste of memory
unglobal OMU408_TYPE
unglobal OMU408_MODE
unglobal OMU408_WIRE
_omu_internals()



#%IU%
#%MDESC%
# Get a serial line from the 1st argument
#
def _omu_checksl '{
 if($#<1) 
 {
  p OMU,"ERROR: missing serial line"
  exit
 }

 # Get the serial line to use for communication
 sl = $1

 # The serial line must be already configured in spec 
 if(ser_par(sl,"device_id") == -1) 
 {
  p OMU,"ERROR: serial line not in config"
  exit
 }

 # The OMU is quite slow to execute some commands
 ser_par(sl,"timeout",15)

}'


#%IU%
#%MDESC%
# Get a valid channel from the 2nd argument
#
def _omu_checkch '{
 if($#<2) 
 {
  p OMU,"ERROR: missing channel"
  exit
 }

 # Get the channel to play with
 ch = $2

 # Minimum check for OMU408
 if((ch<1) || (ch>8)) 
 {
  p OMU,"ERROR: bad channel value, allowed from 1 to 8"
  exit
 }

 # Check that the channel is activated on the OMU
 # TODO
}'



#%UU% sl [channel]
#%MDESC%
# Select or return the channel displayed on the OMU device.
# Channel are numbered from 1
#
def omu_display '{
 local ch
 local sl
 local ans
 local ret
 local filt
 

 # Get the serial line to use for communication
 _omu_checksl $*

 if($#>=2)
 {
  # Get the channel to play with
  _omu_checkch $*

  if(_omu_setdisplay(sl,ch) == -1)
  {
   p OMU,"ERROR: failed to change channel, hint: configured one?"
   exit
  }
 }

 ch = _omu_getdisplay(sl)
 filt=(int(ch)!=ch)?"filtered":""
 p OMU,"current displayed channel: ", int(ch),filt
}'


#%IU%(sl,ch)
#%MDESC%
# Set the displayed channel.
# Returns -1 if failed, otherwise returns 0
#
def _omu_setdisplay(sl,ch) '{
 local ans
 ans = _omu_query(sl,sprintf("2r%02d",1+(ch-1)*2))
 return (ans==""?-1:0)
}'


#%IU%(sl)
#%MDESC%
# Return the current displayed channel as a number
#
def _omu_getdisplay(sl) '{
 local ans
 local ch

 # Request the current permanent channel
 ans = _omu_query(sl,"2s")

 # Get the answer
 ans = _omu_query(sl,"")
 sscanf(ans,"%d",ch)
 ch = ((ch-1)/2)+1 
 return ch
}'


#%IU%(sl, cmd)
#%MDESC%
# Send over the specified serial line a command, waits for
# the answer and return a string. In case of error, a null string
# is returned.
#
def _omu_query(sl,cmd) '{
 local ans
 local cr
 local ack
 
 # Check for terminator
 if(substr(cmd,length(cmd)) != "\r") { cr = "\r" } else { cr="" }

 # Add instrument address which "00" by default
 cmd=sprintf("#00%s%s",cmd,cr)

 # Send the command
 ser_put(sl,cmd)

 # Wait for the answer
 ans = ser_get(sl,"\r")

 # Check for timeout
 if(ans=="") 
 {  
  p OMU,"ERROR: timeout waiting for answer" 
  return ""
 }

 # Check for error
 ack = substr(ans,1,1) 
 if(ack == "?")
 {  
  p OMU,"ERROR: command failed" 
  return ""
 }

 # Remove acknowledge character
 if ((ack == ">") || (ack == "!"))
 {
  ans = substr(ans,2)
 }

 # Remove terminator character
 ans = substr(ans,1,length(ans)-1)

 # Normal end
 return ans
}'


#%IU%
#%MDESC%
# Documentation of OMU408 commands
#
def _omu_printdoc '{

 print "
Read all active channels:
	p _omu_query(0,\"7W\")
	-25.001;-25.000;;;;;;;
	or
	------.;------.;;;;;;;

Read one channel:
   Select the channel to read (the 5th channel):
	p _omu_query(0,\"5x\")
   Read the value:
	p _omu_query(0,\"\")
   Read another value (no need to give again the channel):
	p _omu_query(0,\"\")


Activate channels (several seconds)
   For 1 channel:
	p _omu_query(0,\"1o00\")

   For 2 channel:
	p _omu_query(0,\"1o01\")


Configure a channel:
   Select the channel to configure (the 8th):
	p _omu_query(0,\"1P07\")
   Select type (thermocouple):
	p _omu_query(0,\"3Z05\")
   Sekect mode (type K):
	p _omu_query(0,\"4Z26\")
   Select connection (internal 1TC):
	p _omu_query(0,\"8Z00\")



Change the channel displayed:
   Select the channel or value (the 4th channel):
	p _omu_query(0,\"2r07\")
   Read was is displayed (coded value):
	p _omu_query(0,\"2s\")
	p _omu_query(0,\"\")




Print out a message on the display (for 2 seconds):
	p _omu_query(0,\"9dHELLO\")


Display brightness:
   For 100%:
	p _omu_query(0,\"8W04\")
	or
	p _omu_query(0,\"8r04\")
   For 25%:
	p _omu_query(0,\"8W01\")
   For switching off display after 10 seconds:
	p _omu_query(0,\"8W00\")


Channel displayed:
   For displaying the channel as a number:
	p _omu_query(0,\"6M1\")
   For displaying the channel as a letter
	p _omu_query(0,\"6M2\")
   For not displaying the channel:
	p _omu_query(0,\"6M0\")
 "
}'

#%IU%(expert)
#%MDESC%
# If expert is set, some extra values are printed out
#
def _omu_printdocch(expert) '{
 local n
 local i
 local t m w 

 print "Possible parameters for an OMU408 channel configuration:"

 # Size of each column
 n = 15

 # Column heads
 t = "Type"
 m = "Mode"
 w = "Wire"
 tty_cntl("md")
 printf("%*s %*s %*s\n",n,t,n,m,n,w)
 tty_cntl("me")

 # List everything known
 for(i=0;i<40;i++)
 {
  t=(i in OMU408_TYPE)?(expert?sprintf("%s.%02d",OMU408_TYPE[i],i):\
    OMU408_TYPE[i]):""
  m=(i in OMU408_MODE)?(expert?sprintf("%s.%02d",OMU408_MODE[i],i):\
    OMU408_MODE[i]):""
  w=(i in OMU408_WIRE)?(expert?sprintf("%s.%02d",OMU408_WIRE[i],i):\
    OMU408_WIRE[i]):""
  printf("%*s %*s %*s\n",n,t,n,m,n,w)
 }
}'


#%MACROS%
#%IMACROS%
#%AUTHOR% MP BLISS (Original 11/2009).
# %BR%$Revision: 1.0 $ / $Date: 2009/11/24 15:16:18 $
#%TOC%