#%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%
|