esrf

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

#%TITLE% CaenV462.mac
#%NAME% 
#   Caen V462 counter timer via macro counters and vmeds
#%CATEGORY% Detection, Counting
#%DESCRIPTION%
# Use this macro set to control a Caen V462 counter/timer card by the use of
# macro counters.
# %BR%
# For the internals:
# %BR%
# %BR%
# the channels are cleared before starting the counter; signal "prestart_all".
# %BR%
# all channels are read only once at the signal "halt_all".
# %BR%
# then each channel receives its value, signal "counts".
#%SETUP%
# The macro set needs the vmeds.mac file.
# %BR%
# %BR%
# In the config editor:
# %BR%    
# create a scaler controller like follows:
# %BR%
# YES          V462  IDXX/V462/0      2             Macro Counter/Timer
# %BR% 
# then create up to 2 timers/counters:
# %BR%
# 1      V462_1    V462_1   MAC_CNT     0     0(or 1)    counter         1
#
#%LOG%
#
# Information about the card addresses and their contents have been taken from
# the OS9 device server sources and with friendly help of F. Epaud.
# /segfs/os9/drv/cnttim/v462 and /segfs/dserver/classes/das/cnttim
#%BR% %BR%
# Modifications history:
# 02/04/2007 Creation 
#$Revision: 1.4 $
#%END%

need vmeds

def V462_config(mne,type,unit,mod,chan) '{
  local manufacturer, nm
  global V462[]

  if (mne != "..") {
    if (DEBUG & 128) print "Configuring \"" cnt_mne(mne) "\" as a Caen V462 channel on " V462_ADDR
    gates = list_getpar(V462, V462_ADDR, "gates")
    list_setpar(V462, V462_ADDR, "gates", ++gates)
    
  } else {
    if (type == "ctrl" && unit == 0) {
      list_init V462 #make sure there are no residues
    }
    # Try to read the manufacturer code, offset 0xfc, short
    if ((manufacturer = (vmeds_get(V462_ADDR, 0xfc, "D16") & 0xfe00) >> 10) != 2) {
      eprint "Card with server name", V462_ADDR, "does not seem to be a"
      eprint "Caen V462! Macro counter disabled!"
      return ".error."
    } else
    # Try to read the moduletype 
    if (manufacturer = (vmeds_get(V462_ADDR, 0xfc, "D16") & 0x01ff) != 0x0a) {
      eprint "Card with server name", V462_ADDR, "does not seem to be a"
      eprint "Caen V462! Macro counter disabled!"
      return ".error."
    } else if ((vmeds_get(V462_ADDR, 0x00, "D16") & (0x2000<<chan)) == (0x2000<<chan)) {
      eprint "Caen V462 with name", V462_ADDR, "seems to be set to local."
      eprint "Macro counter disabled!"
      return ".error."
    }
    local gates
    list_add(V462, V462_ADDR)
    
  }
}'

def V462_cmd(mne, cmd, p1, p2) '{
  V462_info "V462_cmd(" mne, cmd, p1, p2")"
  local dsname, dings, n, digit, maxt, zz, ii, ctime
  global V462_ctime
  global V462_loops
#  V462_ctime = 0
  if (mne == "..") {
    digit = 8
    local ubyte array c_bcd[digit]
    local ushort array time_gate[4]
    maxt = 9.99999990001
    ctime = p1
    # Init power table of ten used in preset function
    local double array tab_pu_10[7]
    tab_pu_10[0]= 1.0E+7;
    tab_pu_10[1]= 1.0E+6;
    tab_pu_10[2]= 1.0E+5;
    tab_pu_10[3]= 1.0E+4;
    tab_pu_10[4]= 1.0E+3;
    tab_pu_10[5]= 1.0E+2;
    tab_pu_10[6]= 1.0E+1;

    for ( n = 0; n < list_n(V462); n ++ ) {
      if((dsname = V462[n+1]) == "") {
        eprint "Caen V462: device server name undefined."
        return(0)
      }
      if (cmd == "prestart_all") {
        # preset counting values into both gates!
        if (ctime < 0.0000001) {
          eprint "V462: \"" cnt_mne(mne) "\" counting time too short, must be bigger than 0.0000001 secs."
          return(".error.")
        }
        V462_loops = 1;
        while (ctime > maxt) {
          ctime /= 2.0;
          V462_loops <<= 1;
        }
        V462_info "suggests", V462_loops, "loops"
        ctime = ctime * 1.0E+7;
        xx = ctime;

        # BCD conversion made by dividing the ctime by decreasing tenth powers 
        # In case of small value < 9.01E+0 :  ii = 0 
        ii = 0;    
        while ( ctime > 9.01E+0 ) {
          if ( ctime < tab_pu_10[ii] ) {
            c_bcd[ii] = 0
          } else {
            c_bcd[ii] = ctime / tab_pu_10[ii]
            ctime = ctime - ( c_bcd[ii] * tab_pu_10[ii] )
            if ( ctime < 0 ) ctime = 0
          }
          ii++
        }
        if (!ii) {
          c_bcd[digit-1] = ctime
        } else {
          c_bcd[ii] = ctime
        }
        V462_info "c_bcd is", c_bcd

        # Recalculate the double time value from BCD code table to check the 
        # rounding 
        zz = 0
        for (ii = 0; ii < digit-1; ii++)   {
          if (c_bcd[ii] == 0) {
            continue
          }
          zz += c_bcd[ii] * tab_pu_10[ii]
        }
        zz +=  c_bcd[ii]
        V462_ctime = (zz * V462_loops) / 1.0E+7
        V462_info "V462_ctime:", V462_ctime
        # Move the 8 BCD values to form 4 bytes
        for ( ii = 0 ; ii < 4 ; ii ++ ) {
          time_gate[0] |=  c_bcd[ii] << (4 * (3-ii))
          time_gate[1] |=  c_bcd[ii+4] << (4 * (3-ii))
        }

        # Move them into the card
        V462_info "writing msb: ", sprintf("0x%04x", time_gate[0])
        V462_info "writing lsb: ", sprintf("0x%04x", time_gate[1])

        vmeds_put(dsname, 2, time_gate[0], "D16")
        vmeds_put(dsname, 4, time_gate[1], "D16")
        vmeds_put(dsname, 6, time_gate[0], "D16")
        vmeds_put(dsname, 8, time_gate[1], "D16")

        # start both gates regardless if theyre configured or not
        vmeds_put(dsname, 0, 0x0600, "D16")
      }
    }
  } else {
    local unit
    unit = counter_par(mne,"unit")
    if((dsname = V462[unit+1]) == "") {
      eprint "Caen V462: device server name undefined."
      return(0)
    }
    if((chan = counter_par(mne,"channel")) > 1) {
      eprint "Caen V462! not enough channels for channel", chan, "!"
      return ".error."
    }

    if (cmd == "get_status") {
      local thisstat
      # get status
      thisstat = vmeds_get(dsname, 0x00, "D16") & 0x0800
      V462_info "status:", sprintf("%x", thisstat)
      if (thisstat & (0x0800<<chan)) {
        return(1)
      } else {
        # check if more loops remain to be started.
        if (--V462_loops) {
          V462_info "V462_loops:", V462_loops
          vmeds_put(dsname, 0, 0x0600, "D16")
          return(1)
        } else {
          return(0)
        }
      }
    } else if (cmd == "start_one") {
      return(0)
    } else if (cmd == "counts") {
      return(V462_ctime)
    } else if (cmd == "halt_one") {
      # halt each gate
      vmeds_put (dsname, 0, 0, "D16")
      return(0)
    }
  }
}'

rdef V462_info \'#$*\'
def V462_debug '
{
  if ("$1" == "on" || $# == 0) rdef V462_info "print"
  if ("$1" == "off") rdef V462_info \'#$*\'
}'


#%DEPENDENCIES%
# vmeds.mac must already be read in.
#%AUTHOR% BLISS - ESRF, H. Witsch
#$Revision: 1.4 $, $Date: 2008/02/18 09:37:02 $
#%TOC%