esrf

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

#%TITLE% MADC.MAC
#%NAME%
#  macro to read the ICV150 (ADC) card
#%CATEGORY% Generic I/O
#%DESCRIPTION%
#  This macro set provides an interface to work with the ADAS ICV150 (ADC)
#  VME card. You can configure the ADC as a counter or monitor and use the
#  startdar SPEC macros like %B%ct%B% for reading.
#%SETUP%
#  The communication is done using a "device server" MAdc150, which should
#  run in the VME crate. The configuration of the "server" can be found in
#  a resource file xxxMAdc150_y.res, where xxx is the name of the crate
#  (e.g d291, id011 ...) and y is the number of the ICV150 card as form the
#  device descriptor (e.g. for adc1 the UNIT is 1) %BR%
# %BR%
# The %B%config%B% parameters for an ADC channel as a pseudo counter are:%BR%
#	NAME - the name which appears when executing %B%ct%B% %BR%
#	MNEMONIC - the name which is used by %B%madcsetup%B% %BR%
#	UNIT - the ADC card number as from the device descriptor %BR%
#			(e.g. for card 1 (or adc1) the UNIT is 1) %BR%
#	CHAN - the ADC channel number as cabled (0 - 31) %BR%
#
#%LOG%
#$Log: madc.mac,v $
#Revision 2.2  2008/07/31 06:51:36  rey
#documentation changes
#
#Revision 2.1  2007/01/19 12:26:49  beteva
#fixed bug in madcsetupf
#
#Revision 2.0  2007/01/11 15:17:52  beteva
#replaced signal_name by counter_mne,signal_name couple in the madcsetup, to be able to read wago ADCs. Added madcthcsetup for thermocouples reading.
#
#Revision 1.1  1999/02/23 15:14:19  beteva
#Initial revision
#
#%END%

# MADC_NBCH  - nb of channels exported from the device server
# MADC_CONFIG  - array of doubles to keep the device server configuration
# MADC_ON - flag to define if pseudo counters defined for the ct
# MADC_NREAD - nb of read per channel
# MADC_AVER - average value for a channel

#%UU% [device] [counter_mnem,signal_name(,counter_mnem2, ...)]
#%MDESC%
#setup the reading of the ADC channels. Each channel is configured as
#a pseudo counter.%BR%
#%B%device%B% is the device name, as for the "device server",
#assosiated with the pseudo counters (e.g. d29/madc150_d292/1).%BR%
#%B%counter_mnem%B% is the mnemonics of the pseudo counter.
#%B%signal_name%B% is the one configured in the device server.
#If more than one counters, they are comma separated, no blancs.
#There is always a couple counter mnemonic - signal name. If ICV150 card
#used, the signal name is %B%none%B%. Else the signal name corresponds to
#the one configures in the device server resource.
def madcsetup '{
local dev cntlist siglist 

  if ($# < 2) {
    printf ("Counter mnemonic/signal name list (comma separated)\n")
    cntlist = getval("(e.g. cnt1_mne,sig1_name or cnt1_mne,none", cntlist)
    dev = getval(sprintf("Device name for %s ", cntlist), dev)
  } else {
    dev = "$1"
    cntlist="$2"
  }

  split (cntlist,siglist,",")
  if (siglist[1] == "none")
    madcsetupf (dev, cntlist)
  else
    wagomadcsetupf (dev, cntlist)
}'

def madcthcsetup '{
local dev cntlist siglist
    if ($# < 2) {
    printf ("Counter mnemonic/signal name list (comma separated)\n")
    cntlist = getval("(e.g. cnt1_mne,sig1_name or cnt1_mne,none", cntlist)
    dev = getval(sprintf("Device name for %s ", cntlist), dev)
  } else {
    dev = "$1"
    cntlist="$2"
  }
  thcmadcsetupf (dev, cntlist)
}'
#%UU% (device, counters_list)
#%MDESC%
# Same as madcsetup, but defined as a function, so it can be used by
# other macros.%BR%
#%B%device%B% is the device name , as for the "device server",
# assosiated with the pseudo counters (e.g. d29/madc150_d292/1).%BR%
#%B%counters_list%B% is a string, containing the mnemonics of the pseudo
# counters, comma separated, no blancs.

def madcsetupf (dev, cntlist)    '{
global MADC_ON MADC_NREAD MADC_AVER 
global MADC_LIST MADC_CTLIST

local npars nbcha
local cntunit cntcha
local cnum dscons

  _madcprecount()   # clears counter values

  list_test MADC_LIST
  list_test MADC_CTLIST

  nbcha = esrf_io(dev,"DevGetDsConfig",dsconf)

  if (nbcha == -1 ) {
    printf("Error reading config from ADC.\n")
    printf("Maybe the device server is not running.\n")
    exit
  }
  nbcha = (nbcha - 1)/dsconf[0]
  npars = dsconf[0]

  list_add(MADC_LIST,dev)
  list_setpar(MADC_LIST,dev,"cntlist",cntlist)
  list_setpar(MADC_LIST,dev,"used",0)
  list_setpar(MADC_LIST,dev,"nbcha",nbcha) 

  ncnt=split(cntlist,cntarr,",")

  # Assign param for each counter in cntlist
  #  Param are:  dev, unit, channel and idx
  for (jj=0;jj<ncnt;jj+=2) {
    list_add(MADC_CTLIST,cntarr[jj])
    list_setpar(MADC_CTLIST,cntarr[jj],"dev",dev)

    if ((cnum = cnt_num(cntarr[jj])) != -1 ) {
      list_setpar(MADC_LIST,dev,"used",1)
      cntunit = counter_par(cnum,"unit")
      cntcha  = counter_par(cnum,"channel")
      list_setpar(MADC_CTLIST,cntarr[jj],"unit",cntunit)
      list_setpar(MADC_CTLIST,cntarr[jj],"chan",cntcha)
      for (kk=0; kk<nbcha; kk++) {
        if ((cntunit == dsconf[kk*npars +2]) && \
	    (cntcha  == dsconf[kk*npars +1])) {
          list_setpar(MADC_CTLIST,cntarr[jj],"idx",kk)
          break
        }
      }
      if (kk == nbcha) {
        printf("Counter %s (un: %d; ch: %d) not served by %s\n", \
		cntarr[jj],cntunit,cntcha,dev)
        list_setpar(MADC_CTLIST,cntarr[jj],"idx",-1)
      }
    }
  }
  madcon(MADC_LIST[MADC_LIST[list_n(MADC_LIST)]])

  _madcmiscsetup(dev)
}'

def wagomadcsetupf (dev, cntlist) '{
global MADC_ON MADC_NREAD MADC_AVER 
global MADC_LIST MADC_CTLIST

local npars nbcha
local cnum cntunit cntcha
local signam dsconf
local ind jj

  _madcprecount()   # clears counter values

  list_test MADC_LIST
  list_test MADC_CTLIST

  nbcha = esrf_io(dev,"DevReadAll",dsconf)
  if (nbcha == -1 ) {
    printf("Error reading config from ADC.\n")
    printf("Maybe the device server is not running.\n")
    exit
  }

  list_add(MADC_LIST,dev)
  ind = list_check(MADC_LIST,dev)
  list_setpar(MADC_LIST,dev,"cntlist",cntlist)
  list_setpar(MADC_LIST,dev,"used",0) 
  list_setpar(MADC_LIST,dev,"nbcha",nbcha)
  list_setpar(MADC_LIST,dev,"type","wagods")

  ncnt=split(cntlist,cntarr,",")
  # Assign param for each counter in cntlist
  # Param are: dev and idx
  for (jj=0;jj<ncnt;jj+=2) {
    list_add(MADC_CTLIST,cntarr[jj])
    list_setpar(MADC_CTLIST,cntarr[jj],"type","wagods")
    list_setpar(MADC_CTLIST,cntarr[jj],"dev",dev)

    if (cnt_num(cntarr[jj]) != -1 ) {
      list_setpar(MADC_LIST,dev,"used",1)
      signam = esrf_io(dev,"DevName2Key",cntarr[jj+1])
      if (signam == -1) {
        printf("Counter %s not served by %s\n", cntarr[jj], dev)
        madcoff(ind)
      } else
        madcon(ind)
      list_setpar(MADC_CTLIST,cntarr[jj],"idx",signam)
    }
  }
  _madcmiscsetup(dev)
}'

def thcmadcsetupf (dev, cntlist) '{
global MADC_ON MADC_NREAD MADC_AVER 
global MADC_LIST MADC_CTLIST

local npars nbcha
local cntunit cntcha
local signam dsconf
local ind jj kk

  _madcprecount()   # clears counter values

  list_test MADC_LIST
  list_test MADC_CTLIST

  nbcha = esrf_io(dev,"DevGetSigConfig",dsconf)

  if (nbcha == -1 ) {
    printf("Error reading config from ADC.\n")
    printf("Maybe the device server is not running.\n")
    exit
  }
  nbcha = (nbcha - 1)/dsconf[0]
  npars = dsconf[0]

  list_add(MADC_LIST,dev)
  ind = list_check(MADC_LIST,dev)
  list_setpar(MADC_LIST,dev,"cntlist",cntlist)
  list_setpar(MADC_LIST,dev,"used",0) 
  list_setpar(MADC_LIST,dev,"nbcha",nbcha) 

  ncnt=split(cntlist,cntarr,",")
  # Assign param for each counter in cntlist
  # Param are: dev and idx
  for (jj=0;jj<ncnt;jj+=2) {
    list_add(MADC_CTLIST,cntarr[jj])
    list_setpar(MADC_CTLIST,cntarr[jj],"dev",dev)
    if (cnt_num(cntarr[jj]) != -1 ) {
      list_setpar(MADC_LIST,dev,"used",1) 
      for (kk=0; kk<nbcha; kk++) {
        split(dsconf[kk*npars + 1],signam,"/")
        if (cntarr[jj+1] == signam[3]) {
          list_setpar(MADC_CTLIST,cntarr[jj],"idx",kk)
          break
        }
      }
      if (kk == nbcha) {
        printf("Counter %s not served by %s\n", cntarr[jj], dev)
        list_setpar(MADC_CTLIST,cntarr[jj],"idx",-1)
      }
    }
    if (list_getpar(MADC_CTLIST,cntarr[jj],"idx") == -1)
      madcoff(ind)
    else
      madcon(ind)
  }

  _madcmiscsetup(dev)
}'

def _madcmiscsetup(dev) '{
local i

  setup_tail("madc",dev)

  # Dimension for DATA array
  nbdev  = list_n(MADC_LIST)
  maxcha = 0
  for (i=1;i<=nbdev;i++) {
    if ((nbcha = list_getpar(MADC_LIST,i,"nbcha")) > maxcha)
      maxcha = nbcha
    if (whatis("blmenu") & 0x2 )
      madcblon(i)
  }
  double array MADC_DATA[nbdev][maxcha]
}'

#%IU%
#%MDESC%
# add to blmenu
def madcblon(ind)  '{
  blmenuadd(sprintf("MADC (%s) counters",MADC_LIST[ind]),\
	sprintf("%s info",MADC_LIST[ind]), "madcbody",sprintf("_madc_%d",ind))
}'

#%IU%
#%MDESC%
# Enable the counting for the MADC pseudo counters.
def madcon(ind) '{
  MADC_ON[ind]=1
  list_setpar(MADC_LIST,ind,"used",1)
  # MCD+MP: Fri Sep  1 15:14:03 CEST 2006
  # change the key of cdef to avoid overwrite
  cdef("user_prepcount", sprintf("_madcprecount(%d);",ind), sprintf("madc%d",ind))
  cdef("user_pollcounts", "_madcgetcounts()\n", "madc")
  cdef("user_getcounts",  "_madcgetcounts()\n", "madc")
}'

#%UU%
#%MDESC%
# Remove the MADCs from the setup.
def madcunsetup '{
local i list_nb
local ind
  
  if ($# == 0) {
    list_nb = list_n(MADC_LIST)
    for (i=list_nb; i>0; i--) {
      madcoff(i)
      list_remove(MADC_LIST,MADC_LIST[1])
    }
    cdef("","","madc","delete")
  } else {
    ind = MADC_LIST[MADC_LIST["$1"]]
    madcoff(ind)
    list_remove(MADC_LIST,"$1")
  }
}'

#%IU%
#%MDESC%
# Disable the counting for the MADC pseudo counters.
def madcoff(ind) '{

  p "madcoff"
  MADC_ON[ind]=0
  _madcprecount(ind)
  list_setpar(MADC_LIST,ind,"used",0)
  cdef("","",sprintf("madc%d",ind),"delete")
}'

#%IU%
#%MDESC%
#  Reset variables to zero. 
def _madcprecount(ind) '{
local cnum i

  for (i=1; i<=list_n(MADC_CTLIST); i++) {
    if (list_getpar(MADC_CTLIST,i,"dev") == list_item(MADC_LIST,ind)) {
      cnum = cnt_num(list_item(MADC_CTLIST,i))
      if (cnum != -1 ) {
        S[cnum]=0
        MADC_NREAD[cnum]=0
        MADC_AVER[cnum]=0
      }
    }
  }
  MADC_DATA = 0
}'

#%IU% ()
#%MDESC% Do the reading. 
def _madcgetcounts() '{
local dev stat cnum idx devno
local i k

  # Read devices
  for (i=1; i<=list_n(MADC_LIST); i++) {
    if (list_getpar(MADC_LIST,i,"used") == 1) {
      list_setpar(MADC_LIST,i,"error",0)
      dev  = list_item(MADC_LIST, i)
      if (list_getpar(MADC_LIST,i,"type") != "wagods")
        stat = esrf_io(dev,"DevReadSigValues",MADC_DATA[i-1][])
      else {
        for (k=1; k<=list_n(MADC_CTLIST); k++) {
          if (list_getpar(MADC_CTLIST,k,"type") == "wagods") {
            idx = list_getpar(MADC_CTLIST,k,"idx")
            stat = esrf_io(dev,"DevReadNoCachePhys",idx,MADC_DATA[i-1][k-1])
          }
        }
      }
      if (stat == -1 || ESRF_ERR) {
	printf("Error reading %s\n",list_item(MADC_LIST,i))
        list_setpar(MADC_LIST,i,"error",1)
      }
    }
  }

  # Assign counters
  for (i=1; i<=list_n(MADC_CTLIST); i++) { 
    cnum = cnt_num(list_item(MADC_CTLIST,i))
    if (cnum == -1 ) {
      continue
    }
    idx = list_getpar(MADC_CTLIST,i,"idx")
    dev = list_getpar(MADC_CTLIST,i,"dev")
    devno = list_check(MADC_LIST,dev)

    if ((list_getpar(MADC_LIST,devno,"error") == 0)  && (idx != -1)) {
      if (list_getpar(MADC_LIST,devno,"type") != "wagods")
        MADC_AVER[cnum] += MADC_DATA[devno-1][idx]
      else {
        nb = MADC_CTLIST[list_item(MADC_CTLIST,i)] - 1
        MADC_AVER[cnum] += MADC_DATA[devno-1][nb]
      }
      MADC_NREAD[cnum]++
      S[cnum] = MADC_AVER[cnum] * counter_par(cnum,"scale") / MADC_NREAD[cnum]
    }
  }
}'

#%UU%
#%MDESC%
# Shows current configuration and state of MADCs
def madcshow '{
  local cntstr ncnt cnum sc
  printf("\n\t")

  tty_cntl("us")
  printf("Current configuration\n")
  tty_cntl("ue")

  for (it=1; it<=list_n(MADC_LIST); it++) {
      printf("\nDevice:  ")
      tty_cntl("md")
      printf("%s\n",list_item(MADC_LIST,it))
      tty_cntl("me")
      cntstr=list_getpar(MADC_LIST,it,"cntlist")
      ncnt = split(cntstr,cntlist,",")
      for (kk=0; kk<ncnt; kk+=2) {
           if (kk%3 == 0 && kk !=0 ) printf("\n")
           cnum = cnt_num(cntlist[kk]) 
           tty_cntl("md")
           printf("%7s: ", cntlist[kk])
           tty_cntl("me")
           if (cnum != -1) {
              sc = counter_par(cnum,"scale") 
              printf("%6s", sprintf("scale=%d",sc))
             }
            else
               printf("Not configured")
            printf(" |")
        }
      printf("\n")
    }
}'

#%IU%
#%MDESC%
def madcbody (mode,ind) '{
  if (mode == 1) {
    if (MADC_ON[1]) {
      madcoff(MADC_LIST[MADC_LIST[list_n(MADC_LIST)]])
    } else {
      madcon(MADC_LIST[MADC_LIST[list_n(MADC_LIST)]])
    }
  }

  if (mode == 2) {
    madcshow
  }

  return(MADC_ON[ind]?"On":"Off")
}'

#%MACROS%
#%IMACROS%
#%AUTHOR% A.Beteva / V.Rey (BLISS/ESRF)
#$Revision: 2.2 $, $Date: 2008/07/31 06:51:36 $
#%TOC%