esrf

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

#%NAME%
# nd287cnt.mac 
# 
#%DESCRIPTION%
#  Macrocounter for reading the ND287 Heidenhain controller, via ethernet
#%BR% Spec configuration:
#%BR% The controller nd287 must be declared in the SCALERS part
#%BR%- When the device has two interfaces X1 & X2 use the controller nd287x2
#%BR%\0
#%BR%SCALERS\0\0\0\0\0\0DEVICE\0\0\0\0ADDR\0\0<>MODE\0\0NUM\0\0\0\0<>TYPE
#%BR%\0\0\0\0YES\0\0\0\0\0\0\0nd287\0\0\0\0nd2-28710\0\0\0\0\0\0\01\0\0\0\0\0\0Macro Counter   (for 1 interface)
#%BR%\0
#%BR%\0\0\0\0YES\0\0\0\0\0\0\0nd287x2\0\0nd287id011\0\0\0\0\0\01\0\0\0\0\0\0Macro Counter  (for 2 interfaces)
#%BR% 
#%BR%- ADDR: controller IP (host)
#%BR%\0
#%BR%The device is defined in the Scaler (Counter) Configuration
#%BR%\0
#%BR%Number\0\0\0\0\0\0Name\0\0\0Mnemonic\0\0<>Device\0\0Unit\0\0Chan\0\0<>Use\0As\0\0Scale\0Factor
#%BR%\0\0\0\010\0\0\0\0\0\0enc1\0\0\0\0\0\0\0enc1\0\0\0MAC_CNT\0\0\0\00\0\0\0\00\0\0\0\0\0counter\0\0\0\0\0\0\0\0\0\01   (for 1 interface)
#%BR% 
#%BR%\0\0\0\010\0\0\0\0\0\0enc1\0\0\0\0\0\0\0enc1\0\0\0MAC_CNT\0\0\0\00\0\0\0\01\0\0\0\0\0counter\0\0\0\0\0\0\0\0\0\01   (for 2 interfaces)
#%BR%\0\0\0\011\0\0\0\0\0\0enc2\0\0\0\0\0\0\0enc2\0\0\0MAC_CNT\0\0\0\00\0\0\0\02\0\0\0\0\0counter\0\0\0\0\0\0\0\0\0\01   (for 2 interfaces)
#%BR% 
#%BR%- Unit refers to the macrocounter index in the SCALERS part
#%BR% 

#%END%

#==================================================================
#==================================================================q
# 2017/05/04 rh
#   - added macrocounter nd287x2 for 2 interfaces
#   - fixed bug in decoding of position/channel (cmd 0-x501)
#   - some cosmetics in debug
#==================================================================
#==================================================================q
global nd287_SIMUL nd287_DEBUG    
global ND287_ARR[]
global nd287_PORT ; nd287_PORT = 1050

#==================================================================
#==================================================================
#%UU%
#%MDESC% toggle the debug mode
if (!(whatis("__nd287_debug")  & 2)) rdef __nd287_debug \'#$*\'
def nd287_debug '{
  if ((whatis("__nd287_debug")>>16) <= 3) { # macro length is 3 bytes: comment
     rdef __nd287_debug "eprint"
     print "nd287 macro debug mode is ON"
     nd287_DEBUG = 1
  }
  else {
     rdef __nd287_debug \'#\$*\'
     print "nd287 macro debug mode is OFF"
     nd287_DEBUG = 0
  }
}'

# some programmer help
#%UU%
#%MDESC% toggle simul mode for the present macros.
def nd287_simul '{
  if (nd287_SIMUL) { # if present should be true
      nd287_SIMUL = 0
    print "nd287 simulation is OFF"
  } else {
    nd287_SIMUL      = 1
    print "nd287 simulation is ON"
  }
}
'
#==================================================================
#==================================================================
#%IU%(mne,type,p1,p2,p3)
#%MDESC%Macro counter mechanism (1 encoder): config
def nd287_config(mne,type,p1,p2,p3)'{
   local lcmd
   
   # .. ctrl or mne cnt
   __nd287_debug ">>> nd287:    ",mne, type, p1, p2, p3
   if (type == "ctrl") {
     __nd287_debug ">>>                   new controller "
     lcmd = sprintf ("ping %s -c 1", nd287_ADDR)
     if (unix(lcmd) != 0) {
       eprintf ("Controller %s not responding, disabling its motors\n", \
		nd287_ADDR)
       return ".error."
     }
     #removed as it takes a long time
     #nd287_flush(nd287_ADDR)
     return 0
   }
   
   if (type == "cnt") {
     # add a new parameter, to store the value when read
     counter_par(cnt_num(mne),    "mypos",  0,       "add")
     
     return   0
   }
   
}'

#%IU%(mne,type,p1,p2,p3)
#%MDESC%Macro counter mechanism (1 encoder): cmd
def nd287_cmd(mne,key,p1,p2,p3)'{
   local resp myval 
   
   __nd287_debug ">>> nd287:    ",mne, key, p1, p2, p3
      
   if (key == "halt_one") {
         resp = _nd287_dispos(nd287_ADDR)
         __nd287_debug ">>> nd287:     returns", resp        
         counter_par(cnt_num(mne),"mypos",resp)         
         return 0
   }
   
   if (key == "counts"){
        local mypos
        mypos = counter_par(cnt_num(mne),"mypos")
        return mypos   
   }

#  returns .error. if an error
}'

#==================================================================
#==================================================================
#%IU%(mne,type,p1,p2,p3)
#%MDESC%Macro counter mechanism (2 encoders): config
def nd287x2_config(mne,type,p1,p2,p3)'{
   local lcmd
   local fnId ; fnId = "nd287x2_config"  
   
   # .. ctrl or mne cnt
   __nd287_debug ">>> nd287:    ",fnId, mne, type, p1, p2, p3
   if (type == "ctrl") {
     __nd287_debug ">>>                   new controller ", fnId
     lcmd = sprintf ("ping %s -c 1", nd287x2_ADDR)
     if (unix(lcmd) != 0) {
       eprintf ("Controller %s not responding, disabling its motors\n", \
		nd287x2_ADDR)
       return ".error."
     }
     #removed as it takes a long time
     #nd287_flush(nd287_ADDR)
     return 0
   }
   
   if (type == "cnt") {
     # add a new parameter, to store the value when read
     counter_par(cnt_num(mne),    "mypos",  0,       "add")
     
     return 0  
   }
   
}'


#%IU%(mne,type,p1,p2,p3)
#%MDESC%Macro counter mechanism (2 encoders): cmd
def nd287x2_cmd(mne,key,p1,p2,p3)'{
   local fnId ; fnId = "nd287x2_cmd"  

   local resp myval 
   
   __nd287_debug ">>> nd287:    ",fnId, mne, key, p1, p2, p3
      
   local _addr
   _addr = nd287x2_ADDR
  
   if (key == "halt_all") {
        ND287_ARR[_addr][1]=nd287_posbytes(_addr,1)
        ND287_ARR[_addr][2]=nd287_posbytes(_addr,2)
         return 0
   }

   if (key == "counts"){
        local mypos ch
        ch = counter_par(cnt_num(mne),"channel")
        return ND287_ARR[_addr][ch]   
   }

#  returns .error. if an error
}'


#==================================================================
#==================================================================

#%UU% (host)
#%MDESC% flushes 
def nd287_flush(host) '{
   local val
   p  sock_get(sprintf("%s:%d",host,nd287_PORT))
}'

#%UU% (host)
#%MDESC% flushes one byte
def nd287_flushbytes(host) '{
   local val
   val =  sock_get(sprintf("%s:%d",host,nd287_PORT),"byte")
   printf("%x %d\n",val,val)
}'

#%IU% (host,cmd,framework_length,command_number)
#%MDESC% send a command without arguments (not verbose)
def nd287_put(host,cmd,nb,id)'{
   local long array aa[3]
   # command
   aa[0]=cmd
   # framework lenght in bytes
   aa[1]=nb
   # command number
   aa[2]=id
     
   sock_put(sprintf("%s:%d",host,nd287_PORT),aa,3) 
}'

#%IU% (host,cmd,framework_length,command_number,argument)
#%MDESC%send a command with arguments (not verbose)
def nd287_putarg(host,cmd,nb,id,arg)'{
   long array aa[4]
   # command
   aa[0]=cmd
   # framework lenght in bytes
   aa[1]=nb
   # command number
   aa[2]=id
   # argument 
   aa[3] = arg
   
   sock_put(sprintf("%s:%d",host,nd287_PORT),aa,4) 
}'

#==================================================================
#==================================================================
#%IU% (host)
#%MDESC% reads the header of a response
#%BR%- return the theoretical number of remaining bytes (verbose)
def nd287_getheader(host)'{
   local rcmd, rlen, rid  rnbytes
   local fnId ; fnId = "nd287_getheader"  

   # response code
   rcmd = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")
   # length in bytes
   rlen = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")
   # command number
   rid  = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")

   __nd287_debug ">>> nd287:    ", fnId, sprintf("response code  : %x\n",rcmd)
   __nd287_debug ">>> nd287:    ", fnId, sprintf("length in bytes: %d\n",rlen)
   __nd287_debug ">>> nd287:    ", fnId, sprintf("command number : %d\n",rid)
   
   rnbytes = rlen - 12
   
   return rnbytes

}'


#%IU% (host)
#%MDESC% reads the header of a response (not verbose)
#%BR%- return the theoretical number of remaining bytes
def _nd287_getheader(host)'{
   local rcmd, rlen, rid  rnbytes  

   # response code
   rcmd = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")
   # length in bytes
   rlen = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")
   # command number
   rid  = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")

   rnbytes = rlen - 12
   
   return rnbytes

}'

#%IU% (host,cmd,framework_lengh, command_number)
#%MDESC%sends a command without arguments,
# reads the header
# and the remaining bytes. verbose
def nd287_putget(host,cmd,nb,id)'{
   local rbytes mb

   nd287_put(host,cmd,nb,id)

   rbytes = nd287_getheader(host)
   printf("%d remaining bytes: \n",rbytes)

   # data:
   for (ii=0; ii<rbytes; ii++) {
      mb =  sock_get(sprintf("%s:%d",host,nd287_PORT),"byte")      
	  printf("byte %d: 0x%x (%d)\n",ii,mb,mb)
   }
}'

#%IU% (host,cmd,framework_length,command_number,argument)
#%MDESC% sends a command with argument,
# reads the header
# and the remaining bytes. verbose
def nd287_putgetarg(host,cmd,nb,id,arg)'{
   local rbytes mb

   nd287_putarg(host,cmd,nb,id,arg)

   rbytes = nd287_getheader()
   printf("%d remaining bytes: \n",rbytes)

   # data:
   for (ii=0; ii<rbytes; ii++) {
      mb =  sock_get(sprintf("%s:%d",host,nd287_PORT),"byte")      
	  printf("byte %d: 0x%x (%d)\n",ii,mb,mb)
   }
}'

#%IU% (host)
#%MDESC% read nn bytes
def nd287_get(host,nn)'{
   local ii val
   
   for (ii=0; ii<nn; ii++) {
      val =  sock_get(sprintf("%s:%d",host,nd287_PORT),"byte")
      printf("%d: 0x%x (%d)\n",ii,val,val)   
   }
}'

#%UU% (host)
#%MDESC% get version reading long words
def nd287_ver(host)'{
   local rdata rbytes

   nd287_put(host,0x401,12,1)

   rbytes = _nd287_getheader(host)
   
   # data: we know it is 4 bytes
   # read it as an integer
   rdata  = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")
   printf("version           : %x\n",rdata)

}'

#%IU% (host)
#%MDESC% get version reading bytes
def nd287_verbytes(host)'{

   nd287_putget(host,0x401,12,1)

}'

#%UU% (host)
#%MDESC% get displayed position reading string.
#%BR%- returns numerical value
def nd287_dispos(host)'{
   local rdata rbytes numval

   nd287_put(host,0x61b,12,2)

   rbytes = nd287_getheader(host)
   
   # read it as a string
   rdata  = sock_get(sprintf("%s:%d",host,nd287_PORT))
   printf("data           : %s\n",rdata)
   
   numval = _nd287_extractpos(rdata)
   
   return numval

}'

#%IU% (host)
#%MDESC% get displayed position reading string (without printing)
#%BR%- returns numerical value
def _nd287_dispos(host)'{
   local rdata rbytes numval

   nd287_put(host,0x61b,12,2)

   rbytes = _nd287_getheader(host)
   
   # read it as a string
   rdata  = sock_get(sprintf("%s:%d",host,nd287_PORT))

   numval = _nd287_extractpos(rdata)
   
   return numval

}'

#%IU% (host)
#%MDESC% get display position reading bytes
def nd287_disposbytes(host)'{

   nd287_putget(host,0x61b,12,2)

}'

#%UU% (host)
#%MDESC% read error messages as string
def nd287_err(host)'{
   local rbytes rdata numval
   
   nd287_put(host,0x605,12,3)
   
   rbytes = nd287_getheader(host)

   # read it as a string
   rdata  = sock_get(sprintf("%s:%d",host,nd287_PORT))
   printf("data           : %s\n",rdata)

}'

#%IU% (host)
#%MDESC% read error messages as bytes
def nd287_errbytes(host)'{
   local rbytes
   
   nd287_putget(host,0x605,12,3)

}'

#==================================================================
#==================================================================
#%IU% (host)
#%MDESC% read encoder position as integers
def nd287_posbytes(host,ch)'{
   local rbytes data1 data2 mstatus mdata posr posx globdata msg
   local fnId ; fnId = "nd287_posbytes"  
   
   nd287_putarg(host,0x501,13,4,ch)
   
   rbytes = nd287_getheader(host)
   
   __nd287_debug ">>> nd287:    ", fnId, sprintf("remaining bytes: %d\n",rbytes)

   #data: read 2 integers
   data1  = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")
   data2  = sock_get(sprintf("%s:%d",host,nd287_PORT),"long_swap")
   __nd287_debug ">>> nd287:    ", fnId, sprintf("data1: 0x%08llx\n",data1)
   __nd287_debug ">>> nd287:    ", fnId, sprintf("data2: 0x%08llx\n",data2)

   
   mstatus = data1 & 0x0ffff
   __nd287_debug ">>> nd287:    ", fnId, sprintf("status: 0x%04llx\n",mstatus)
   
   datapos = (data2 << 16) | (data1 >> 16)
   __nd287_debug ">>> nd287:    ", fnId, sprintf("datapos: 0x%012llx\n", datapos)
   
   factor = 1.0e-4
   _pos = (datapos & 0x800000000000) ? factor * (datapos - 0x1000000000000) : factor * datapos 
   __nd287_debug ">>> nd287:    ", fnId, sprintf("position : %10.4f (0x%012llx) \n", _pos, datapos)

   return _pos

}'

#%IU% (string)
#%MDESC% extracting numerical value
def _nd287_extractpos(mystr)'{
   local sign nn mya
   
   if (asc(mystr) == asc("-")) {
      #p "negative value"
	  sign = -1
   } 
   else {
      #p "positive value"
	  sign = 1
   } 
   
   nn = split(mystr,mya)
   
   return (mya[1]*sign)
   
   

}'

#%MACROS%
#%IMACROS%
#%LOG%
#$Revision: 1.2 $
#$Log: nd287cnt.mac,v $
#Revision 1.2  2017/05/04 13:50:56  homsrego
#- added macrocounter nd287x2 for 2 interfaces
#- fixed bug in decoding of position/channel (cmd 0-x501)
#- some cosmetics in debug
#
#Revision 1.1  2012/11/28 07:40:39  domingue
#Initial revision
#
#
#%AUTHOR% mcd november 2012
#%TOC%