esrf

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


#%TITLE% C111_GFD1D.MAC
#%NAME%
#  Access to C111 Card Linux Taco device server
#
#%CATEGORY% other hardware
#%SEARCH% c111setup
#
#%LOG%
#$Revision: 1.11 $
#
#%DESCRIPTION%
#  These macros implement access to C111 Linux TACO device server controlling
#  one C111/P111 C111 card designed by Christian Herve. They work with the 
#  version V1.4 of C111 device server [which in turn uses version v.0.4.8 of
#  the C111 device driver library].
#  These macro set does not cover all possible C111 configurations but is
#  written for the specific configuration which is using C111 for GFD
#  detector equipped with 1 delay line connected to X1,X2 C111 inputs. Anode
#  as usually is connected to COM C111 input.%BR%
#
#  Normally one would always program C111 in Normal mode. The test mode
#  is selected only to make delay line length estimation.
#
#  When set in test mode, where the choice of the resolution (half/full) is
#  ignored and the C111 behaves as being set in half-resolution mode, the
#  digitized channel where is the data peak (sum ~ DelayLine) must be
#  multiplied by .3 ns (300ps) to obtain the estimation of the delay line
#  length (in fact the number obtained is:
#          DelayLine + (Anode-to-X1 delay) + (Anode-to-X2 delay),
#  but since the 2 A-K delays are normally much shorter than the delay line,
#  this gives a good estimate of the DL.
#
#
#
#%SETUP%
#%DL%
#%DT%  c111setup <device> <RPC timeout> %DD%
#  (connect to C111 device and powers up ASIC if necessary)
#%DT%  c111version %DD%
#  (show the version of these macros)
#%DT%  c111
#  (menu to access all functionnalities)
#%XDL%

#%EXAMPLE%
#%BR% STATUS
#%DL%
#%DT%  c111state %DD%
#  (state of C111 - idle/running)
#%DT%  c111status %DD%
#  (Print C111 status)
#%DT%  c111show %DD%
#  (shows most essential config/status fields)
#%XDL%

#%BR% CONFIGURATION
#%DL%
#%DT%  c111config %DD%
#  (interactive menu to display/change C111 hardware config)
#%DT%  c111reconfig %DD%
#  (reconfigure with default values from database)
#%DT%  c111setconfig %DD%
#  (full interactive configuration)
#%DT%  c111tuneconfig %DD%
#  (tune main parameters of the C111 hardware)
#%XDL%

#%BR% ACQUISITION
#%DL%
#%DT%  c111on %DD%
#  (switch on C111 acq. in ct and scan; beware that when statistics counters
#   are used in ct and scan, the minimum time period is 1 seconds and must
#   be an integer number of seconds)
#%DT%  c111off %DD%
#  (switch off C111 acq. in ct and scan)
#%DT%  c111acq <n> [<donotclearflag>]%DD%
#  (make finite-time acquisition for n seconds; if second argument is passed,
#   then the memory is not cleared and data from the new acquisition are
#   cumulated with the data from the previous acq.)
#%DT%  c111statacq <n> <any> %DD%
#  (make acq. in order to get statistics info; stat timer duration = n secs;
#   acq. stops quickly after stat.timer expiration;
#   if second argument is passed, then both X and Y pileups are disabled)
#%XDL%

#%BR% SAVING
#%DL%
#%DT%  c111savemenu %DD%
#  (Menu to access all saving options)
#%DT%  c111savesetup %DD%
#  (Set saving options)
#%DT%  c111newfile %DD%
#  (Specify private directory, file prefix, run number)
#%DT%  c111saverange %DD%
#  (Specify spectrum range to be saved)
#%DT%  c111save <file> %DD%
#  (save data to file <file> or the one defined during config if no argument
#   passed -> to be used outside counting and scans or at the end of ct)
#%XDL%

#%BR% ROIS
#%DL%
#%DT%  c111roishow %DD%
#  (show the ROI(s) definitions)
#%DT%  c111roi <mnemonic> <chan_min> <chan_max> %DD%
#  (add or modify an ROI)
#%DT%  c111roimenu %DD%
#  (interactively add/remove/modify an ROI)
#%DT%  c111roiclear %DD%
#  (clear ROI counters)
#%XDL%

#%BR% Plotting
#%DL%
#%DT%  c111splotrange <xmin> <xmax> %DD%
#  (define the limit C111 digitized channels for plotting; if no parameters
#   passed, the C111_PLOTMIN = 0 and C111_PLOTMAX = C111_NBCOLS-1)
#%DT%  c111plot %DD%
#  (plots the data from channel C111_PLOTMIN to channel C111_PLOTMAX)
#%DT%  c111tolin/log %DD%
#  (changes Y-scale to linear/to logarithmic)
#%XDL%
#%END%

# $Log: c111_gfd1d.mac,v $
# Revision 1.11  2009/01/07 07:58:28  papillon
# * option to limit size of spectrum read
# * simplify plot macros
#
# Revision 1.9  2006/02/02 09:33:44  sever
# Modified _c111_cleanup (protected with C111_ON flag)
#
# Revision 1.8  2006/01/31 09:23:59  papillon
# * savemcaroi in a separate macro for id10b
#
# Revision 1.7  2005/11/09 15:31:19  papillon
# * Change the plot unit if needed
#
# Revision 1.6  2005/09/23 13:29:30  sole
# Added entries for cdef prior to saving data
#
# Revision 1.5  2005/09/20 13:38:44  sever
# made _mo_loop1 and savestdheader1 to get ALL motors in standard header like in
# scan file
# added display of elapsed time in c111acq
# changed line for filters to start with UFILTER
#
# Revision 1.4  2005/09/19 15:11:58  sever
# Corrected the macro name in comment line for _c111_handlecounts
# and enlarged comment on removal of test on NPTS.
#
# Revision 1.3  2005/09/16 09:28:35  papillon
# * Remove test on NPTS for c111save
# * Usage in c111plotrange
#
# Revision 1.2  2005/09/13 15:14:51  papillon
# * Main menu to access functionnalities
# * Saving to standard/private file revised
# * Saving in user_handlecounts
#
# Revision 1.1  2005/09/06 08:59:53  papillon
# Initial revision
#


#============================================================
#
# Initialization/Setup related macros and functions 
#
#============================================================
#
#
#-------------------------- _c111varinit() ---------------------
#%IU%
#%MDESC%
#  Internal macro to declare global variables and initialise some.
#
cdef("c111_user_presave","\n{}\n","c111")
cdef("c111_user_postsave","\n{}\n","c111")
cdef("c111_user_prescan_loop","\n{}\n","c111")
cdef("c111_user_postscan_loop","\n{}\n","c111")

def _c111varinit() '{

    global C111_VERSION     # version of these macros

    global C111_DEV         # name of C111 device (ex. ID10B/C111/01)
    global C111_RPCTIMEOUT  # RPC timeout for esrf_io() calls

    # State, Status, Configuration related
    global C111_STATE       # C111 state string (idle/running)
    global C111_STATUS[]    # complete status array of C111 device
    global C111_STA_STR     # String array for status array fields (in total 34)
                           # of which first 14 (until and including acq_bank)
                           # are configuration array fields

    # Configuration/Status fields in detail:
    global C111_DEBUGFL     # debug flag used in device server(1=debug on)
    global C111_BOOT_CONFIG # FGPA boot config = mode select:0=GFD/1=MHIT/2=MHIP
                           # for GFD (1D/2D) should be 0
    global C111_MODE_TYPE   # mode type (0=normal/1=test); always normal for MHIP
    global C111_TIMEOUT     # timeout in ns
    global C111_SKIP        # skip (0 = no skip) flag - only for MHIT
    global C111_EXTINHFC    # ext. inhibit(0)/fast clear(1) flag - only for GFD
                           # always 0 (ignored) for MHIT/P
    global C111_OFFSET_X    # X offset in ns
    global C111_OFFSET_Y    # Y offset in ns - dont care for GFD 1D(X axis used)
    global C111_PILEUP_X    # X pileup = should be 1 for GFD 1D
    global C111_PILEUP_Y    # Y pileup = should be 0 for GFD 1D
    global C111_HALF_RES    # half resolution flag (0=full resol/1=half resol);
                           # normally would use 0 = full resolution
    global C111_FP_MONITOR  # front pannel signal for monitoring 0 = gate
    global C111_MUX_SEL     # ASIC signal for monitoring (not important if gate)
    global C111_STAT_TIMER  # statistics timer enable(1)/disable(0) flag
    global C111_DURATION    # statistics timer duration in seconds
    global C111_ACQ_BANK    # index of bank selected for acq (= bank on port M)
                           # normally would start with bank 0 
    # 2 more status fields in detail:
    global C111_NBROWS      # nb of rows (Y) for data in memory = 1 for GFD 1D
    global C111_MAXCOLS     # max nb of columns
    global C111_NBCOLS      # nb of columns (X) for data in memory: 
                            # 8192 for 1/2 resolution; 16384 for full resolution
                            # (since for 1D case we never apply binning in
                            #  readout)
    global C111_ACQSTART_TIME # start UNIX time (with time() function) whihc serves
                              # to calculated current elapsed time in c111acq

 
    # String array for Status array fields
    C111_STA_STR[0] ="0/1 = server dbg flag off(0)/on(1)"
    C111_STA_STR[1] ="Boot config (0=GFD/1=MHIT/2=MHIP) "
    C111_STA_STR[2] ="Mode type (0=normal/1=test)       "
    C111_STA_STR[3] ="Timeout value (ns)                "
    C111_STA_STR[4] ="Skip (= no skip)     flag         "
    C111_STA_STR[5] ="ExtInh(0)/FastClr(1) flag         "
    C111_STA_STR[6] ="X offset value (ns)               "
    C111_STA_STR[7] ="Y offset value (ns)               "
    C111_STA_STR[8] ="X pileup disabled(0)/enabled(1)   "
    C111_STA_STR[9] ="Y pileup disabled(0)/enabled(1)   "
    C111_STA_STR[10]="Half resolution(0=full/1=half)    "
    C111_STA_STR[11]="front pannel monitor              "
    C111_STA_STR[12]="ASIC f.p. mon(0=MSB cntr/1=MASK4) "
    C111_STA_STR[13]="Stat.timer disabled(0)/enabled(1) "
    C111_STA_STR[14]="Stat.timer duration (s)           "
    C111_STA_STR[15]="Bank selected for acquisition     "
    C111_STA_STR[16]="Max Nb of Rows for data in memory "
    C111_STA_STR[17]="Max Nb of Cols for data in memory "
    C111_STA_STR[18]="CUB Low Voltage 1.8V (1=OK)       "
    C111_STA_STR[19]="CUB Low Voltage 2.5V (1=OK)       "
    C111_STA_STR[20]="CUB Low Voltage 3.3V (1=OK)       "
    C111_STA_STR[21]="CUB Low Voltage  5V  (1=OK)       "
    C111_STA_STR[22]="CUB Low Voltage +12V (1=OK)       "
    C111_STA_STR[23]="CUB Low Voltage -12V (1=OK)       "
    C111_STA_STR[24]="CUB All Low Voltages (1=OK)       "
    C111_STA_STR[25]="33 Mhz PLL Lock (1=OK)            "
    C111_STA_STR[26]="C111 Clock PLL Lock (1=OK)        "
    C111_STA_STR[27]="CUB serial number                 "
    C111_STA_STR[28]="C111 mode acknowledge             "
    C111_STA_STR[29]="C111 ASIC power (1=UP)            "
    C111_STA_STR[30]="C111 ASIC PLL Lock (1=OK)         "
    C111_STA_STR[31]="C111 State (0=Idle/1=Running)     "
    C111_STA_STR[32]="Nb of Interr. at stat timer expir."
    C111_STA_STR[33]="Nb of Interr. at stat regs OVFlow "
    C111_STA_STR[34]="Nb of Interr. at soft timer expir."
    C111_STA_STR[35]="Driver signal number              "

    # Plotting Related
    global C111_PLOTMIN     # minimal digitized channel index for spec std plot
    global C111_PLOTMAX     # maximal digitized channel index for spec std plot 
    global C111_PLOTUNIT    # plot filter number
	global C111_PLOTLOG		# plot in log scale 

    # Counting + Scanning Related
    global C111_ON          # flag to indicate if C111 acquisition is done(1) or
                           # not(0) at each scan point
    global C111_STATISTICS  # flag to indicate if use(1) C111 statistics timer
                           # or not(0) in acq. inside ct and scan

    # ROI Pseudo-counters Related
    global C111_ROI[]       # assoc. array with 2 fields for each pseudo-cntr:
                           # C111_ROI[countermnemonic]["min"]
                           # C111_ROI[countermnemonic]["max"]

    # data saving related
    # - data acquired at each scan point are saved in file DATAFILE, when it
    #   is not /dev/null. The DATAFILE is defined by running macro newfile
    # - data acquired outside scan (with c111acq macro for ex.) can be saved in
    #   a simple ASCII file which name is composed by concatenating
    #   C111_DATA_DIR and C111_FILE_PREFIX.
    #   These fields are defined by running macro c111newfile
    global C111_DATA_DIR
    global C111_FILE_PREFIX
    global C111_RUN_NUMBER
    global C111_ACQSAVE      # flag to indicate if c111save is called after
                             # c111acq in order to put right HEADING in 
                             # mca-like file (to distinguish this from 
                             # saving after simple counting with ct DeltaT)
    global C111_SAVE         # flag to indicate if save(1) or not(0) the C111
                             # data for the acquisitions OUTSIDE scan or at
                             # the end of counting
    global C111_SAVE_PADI    # flag to indicate if for acquisition OUTSIDE scan
                             # save spectrum only in MCA-like file(0) or
                             # should save data in addition in PADI-like file(1)
    global C111_SAVESPECTRUM # to save spectrum in addition to optional ROI cts
                             # at each scan pointi. When save after counting or
                             # outside counting and scanning (in tdcacq), then
                             # spectrum is always in file!!!
    global C111_SAVEINPRIVATE # to save spectrum in scan in each point in a
                             # private file. 
                             # If this flag = 0, then data are saved as now
                             # all in scan file (DATAFILE), while when = 1,
                             # data (counters+spectrum) are saved in each
                             # point in scan in a separate private file.
                             # (=> one file per scan point)
    global C111_SAVEMIN      # min chan nb for spectrum saving
    global C111_SAVEMAX      # max chan nb for spectrum saving

    # be generous
    C111_RPCTIMEOUT = 10
   
    C111_ACQSAVE = 0

}'


#------------- _c111_cleanup ------------------------------
#%IU%
#%MDESC%
#  Macro executed at cleanup(CTRL-C)
#  N.B. On the request of P.Boesecke this macro is modified
#       to avoid error: Cant import ID01/C111/01 when C111 is not
#       used. Note that this is not a 100 percent protection since
#       one can still have C111_ON left set to 1 and C111 not used.
#
def _c111_cleanup '{
    if (C111_ON) {
        C111_STATE=esrf_io(C111_DEV,"DevC111GetStateString")
        if (index(C111_STATE,"RUNNING") != 0) {
            printf("The C111 is still running, stop it.\n")
            c111stop
        }
    }
}'


#-------------------------- c111version -----------------------
#%UU%
#%MDESC%
#  Prints out the version of this software
#
def c111version '{
    C111_VERSION = "GFD 1D FS May 2004 "
    tty_cntl("md")
    print (sprintf("  C111Version %s\n",C111_VERSION));
    tty_cntl("me")
}'


#-------------------------- c111setup -----------------------
#%UU% <device_name> <rpc_timeout>
#%MDESC%
#  This macro should normally be invoked at spec session start 
#  after C111 macro set was loaded.
#  Connects to C111 device and sets RPC timeout.
#
def c111setup '{

    if ($#!=2) {
        print "Usage: $0 <C111_device_name> <RPC_timeout_(sec)>"
        exit
    }

    _c111varinit()

    C111_DEV= "$1"
    C111_RPCTIMEOUT= $2

    # --- set RPC timeout
    if (C111_RPCTIMEOUT < 3) 
        C111_RPCTIMEOUT = 3

    esrf_io(C111_DEV,"tcp")
    esrf_io(C111_DEV,"timeout",C111_RPCTIMEOUT)

    # --- read current status
    if (_c111_getstatus()) {
        # -- initialize limits for plotting
        if (whatis("C111_PLOTMIN")&0x8000000)
            C111_PLOTMIN= 0
        if (whatis("C111_PLOTMAX")&0x8000000)
            C111_PLOTMAX= C111_NBCOLS-1
        if (whatis("C111_PLOTUNIT")&0x8000000)
            C111_PLOTUNIT= 2

        # -- initialize saving limits
        if (whatis("C111_SAVEMIN")&0x8000000)
            C111_SAVEMIN= 0
        if (whatis("C111_SAVEMAX")&0x8000000)
            C111_SAVEMAX= C111_NBCOLS-1

        if (_c111_checkconfig()) {
            c111arrays
        }
    }

    cdef("cleanup_always","_c111_cleanup; ","c111set")
    setup_tail("c111")
}'


#-------------------------- c111unsetup -----------------------
#%UU%
#%MDESC%
#  Deletes c111 part in cleanup_always
#
def c111unsetup '{
  c111off
  cdef("","","c111set","delete")

}'
#------------------------------------------------------------
# END of macros related to initialization/setup
#------------------------------------------------------------




#============================================================
#
# State/Status/Configuration/Statistics related macros
#
#============================================================
#

#%UU%
#%MDESC%
#  Display a menu to access all C111 config/options
#
def c111 '{ c111menu }'
def c111menu '{
    local option

    option= 1
    while (option) {
        nl= 0

        tty_cntl("ho"); tty_cntl("cd")
        tty_move(15, nl++, "\[md\]< C111 MENU >\[me\]")
        tty_move(10, nl++, sprintf("Device Name : \[md\]%s\[me\]", C111_DEV))
        nl+= 2

        tty_move(0, nl, "(1) Use C111 in all on ct/scans......:")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_ON?"YES":"NO"))
        tty_move(0, nl, "(2) Use statistics in ct/scans.......:")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_STATISTICS?"YES":"NO"))

        nl++
        tty_move(0, nl++, "(3) Device Configuration.............:")
        tty_move(0, nl, sprintf("(4) Spectrum Range (max=%5d).......:", C111_MAXCOLS))
		tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_NBCOLS))

        nl++
        tty_move(0, nl, "(5) ROIs definition..................:")
		tty_move(40, nl++, sprintf("\[md\]%d\[me\] roi(s)", list_n(C111_ROI)))
        tty_move(0, nl, "(6) Saving options...................:")
		tty_move(40, nl++, sprintf("\[md\]%s\[me\]", \
							(C111_SAVE|C111_SAVESPECTRUM) ? "ON" : "OFF"))
        tty_move(0, nl++, "(7) Plotting options.................:")

        option= getval("\n\n\tOption ---> ", 0)
        printf("\n\n")

        if (option==1) {
            if (C111_ON) c111off
            else c111on
        }
        else if (option==2) {
            if (C111_STATISTICS) c111statoff
            else c111staton
        }
        else if (option==3) {
            c111config
        }
		else if (option==4) {
			c111range
		}
        else if (option==5) {
            c111roimenu
        }
        else if (option==6) {
            c111savemenu
        }
		else if (option==7) {
			c111plotmenu
		}
    }
}'

        


#------------------------- c111state ---------------------------------
#UU%
#%MDESC%
#  Get and show the state of C111 device
#  For brevity did not name this macro c111getstate but c111state
#
def c111state '{

    C111_STATE=esrf_io(C111_DEV,"DevC111GetStateString")
    printf("%s\n",C111_STATE)

}'


#-------------------------- _c111_getconfig ---------------------------
#%IU%
#%MDESC%
#  Get C111 configuration parameters (less than full status)
#
def _c111_getconfig '{
    local C111_CONFIG[]

    if (esrf_io(C111_DEV,"DevC111GetConfig",C111_CONFIG) < 0) {
        printf("c111getconfig: Error reading C111 configuration. Giving up\n")
        exit
    }
    C111_DEBUGFL     = C111_CONFIG[0]
    C111_BOOT_CONFIG = C111_CONFIG[1]
    C111_MODE_TYPE   = C111_CONFIG[2]
    C111_TIMEOUT     = C111_CONFIG[3]
    C111_SKIP        = C111_CONFIG[4]
    C111_EXTINHFC    = C111_CONFIG[5]
    C111_OFFSET_X    = C111_CONFIG[6]
    C111_OFFSET_Y    = C111_CONFIG[7]
    C111_PILEUP_X    = C111_CONFIG[8]
    C111_PILEUP_Y    = C111_CONFIG[9]
    C111_HALF_RES    = C111_CONFIG[10]
    C111_FP_MONITOR  = C111_CONFIG[11]
    C111_MUX_SEL     = C111_CONFIG[12]
    C111_STAT_TIMER  = C111_CONFIG[13]
    C111_DURATION    = C111_CONFIG[14]
    C111_ACQ_BANK    = C111_CONFIG[15]

}'


#-------------------------- c111status -----------------------
#%UU%
#%MDESC%
#  Gives full status information for C111.
#  For brevity did not name this macro c111getstatus but c111status
#
def c111status '{
    if (_c111_getstatus()) {
        for (i = 0; i < 36; i++) {
            printf("%s = %d\n", C111_STA_STR[i],C111_STATUS[i])
        }
    }
}'

#%IU% ()
#%MDESC%
#  Read C111 status and update all global variables %BR%
#  Return 1 on success, 0 otherwise
def _c111_getstatus() '{
    if (esrf_io(C111_DEV,"DevC111GetStatus",C111_STATUS) < 0) {
        printf("Error reading C111 status\n")
        return (0)
    }

    C111_DEBUGFL     = C111_STATUS[0]
    C111_BOOT_CONFIG = C111_STATUS[1]
    C111_MODE_TYPE   = C111_STATUS[2]
    C111_TIMEOUT     = C111_STATUS[3]
    C111_SKIP        = C111_STATUS[4]
    C111_EXTINHFC    = C111_STATUS[5]
    C111_OFFSET_X    = C111_STATUS[6]
    C111_OFFSET_Y    = C111_STATUS[7]
    C111_PILEUP_X    = C111_STATUS[8]
    C111_PILEUP_Y    = C111_STATUS[9]
    C111_HALF_RES    = C111_STATUS[10]
    C111_FP_MONITOR  = C111_STATUS[11]
    C111_MUX_SEL     = C111_STATUS[12]
    C111_STAT_TIMER  = C111_STATUS[13]
    C111_DURATION    = C111_STATUS[14]
    C111_ACQ_BANK    = C111_STATUS[15]
    C111_NBROWS      = C111_STATUS[16]
    C111_MAXCOLS     = C111_STATUS[17]
    if ((C111_NBCOLS<=0)||(C111_NBCOLS>C111_MAXCOLS)) {
		C111_NBCOLS= C111_MAXCOLS
	}

    return (1)
}'


def c111range '{
    if ($#==1) {
		C111_NBCOLS= int($2)
	} else {
		C111_NBCOLS= getval(sprintf("Spectrum range [max=%d]", C111_MAXCOLS), C111_NBCOLS)
	}

	if ((C111_NBCOLS<=0)||(C111_NBCOLS>C111_MAXCOLS)) {
		C111_NBCOLS= C111_MAXCOLS
	}
	_c111_checkrange
}'

def _c111_checkrange '{
	local roinb roimne roimin roimax

    if (C111_PLOTMIN >= C111_NBCOLS-1) C111_PLOTMIN = 0
    if (C111_PLOTMAX > C111_NBCOLS-1) C111_PLOTMAX = C111_NBCOLS - 1 
    if (C111_SAVEMIN >= C111_NBCOLS-1) C111_SAVEMIN = 0
    if (C111_SAVEMAX > C111_NBCOLS-1) C111_SAVEMAX = C111_NBCOLS - 1 

    roinb= list_n(C111_ROI)
    for (roi=1; roi<=roinb; roi++) {
        roimne= list_item(C111_ROI, roi)
        roimin= C111_ROI[roimne]["min"]
        roimax= C111_ROI[roimne]["max"]
		if (roimin >= C111_NBCOLS-1) C111_ROI[roimne]["min"]= 0
		if (roimax > C111_NBCOLS-1) C111_ROI[roimne]["max"]= C111_NBCOLS - 1
	}
}'

#-------------------------- c111arrays ---------------------------
#%IU%
#%MDESC%
#  Creates C111 data arrays (%B%C111_DATA, C111_XDATA%B%)
#
def c111arrays '{

    shared ulong array C111_DATA[C111_NBCOLS][1]
    shared ulong array C111_XDATA[C111_NBCOLS][1]
    array_op("fill", C111_XDATA)

}'


#-------------------------- c111show ---------------------------
#%UU%
#%MDESC%
#  Show main C111 config/status parameters
#
def c111show '{ _c111_show() }'
def _c111_show() '{
    nl= 0

    tty_cntl("ho"); tty_cntl("cd")

    tty_cntl("ho"); tty_cntl("cd")
    tty_move(15, nl++, "\[md\]< C111 CONFIGURATION >\[me\]")
    tty_move(10, nl++, sprintf("Device Name : \[md\]%s\[me\]", C111_DEV))
    nl++

    tty_move(0, nl, "* Boot Configuration .................")
    tty_move(40, nl++, sprintf("\[md\]%s\[me\]", \
            C111_BOOT_CONFIG==0?"GFD":(C111_BOOT_CONFIG==1?"MHIT":"MHIP")))

    tty_move(0, nl, "* Operation mode .....................")
    tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_MODE_TYPE?"Test":"Normal"))

    tty_move(0, nl, "* Timeout (ns) .......................")
    tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_TIMEOUT))

    if (C111_BOOT_CONFIG == 0) {
        # Show offsets, pileups and half resolution only for GFD mode
        tty_move(0, nl, "* External Inhibit / Fast Clear ......")
        tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_EXTINHFC))

        tty_move(0, nl, "* X offset (ns) ......................")
        tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_OFFSET_X))

        tty_move(0, nl, "* Y offset (ns) ......................")
        tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_OFFSET_Y))

        tty_move(0, nl, "* X pileup ...........................")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_PILEUP_X?"YES":"NO"))

        tty_move(0, nl, "* Y pileup ...........................")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_PILEUP_Y?"YES":"NO"))

        tty_move(0, nl, "* Resolution .........................")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_HALF_RES?"Half":"Full"))

    } else if (C111_BOOT_CONFIG == 1) {
        tty_move(0, nl, "* Skip Flag ..........................")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_SKIP?"YES":"NO"))
    }
    # Nothing extra to show for MHIP mode

    tty_move(0, nl, "* Monitoring on front pannel .........")
    tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_FP_MONITOR))

    if (C111_FP_MONITOR==3) {
        tty_move(0, nl, "* ASIC monitoring on front pannel ....")
        tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_MUX_SEL))
    }

    tty_move(0, nl, "* Statistic timer ....................")
    tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_STAT_TIMER?"Enabled":"Disabled"))

    if (C111_STAT_TIMER == 1) {
        tty_move(0, nl, "* Statistic timer duration (sec) .")
        tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_DURATION))
    }

    tty_move(0, nl, "* Bank selected for acquisition ......")
    tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_ACQ_BANK))

    tty_move(0, nl, "* Number of rows for data ............")
    tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_NBROWS))

    tty_move(0, nl, "* Maximum number of columns for data .")
    tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_MAXCOLS))

    tty_move(0, nl, "* Used number of columns for data ....")
    tty_move(40, nl++, sprintf("\[md\]%d\[me\]", C111_NBCOLS))

    return (++nl)
}'



#-------------------------- _c111_checkconfig -----------------------
#%IU% ()
#%MDESC%
#  Checks that the configuration corresponds to GFD 1D case
#  (normal or test mode)
#
def _c111_checkconfig() '{

    #
    # Check that Mode Select(FPGA boot config) is GFD 
    # [this should be OK in device server resources!!]
    #
    if (C111_BOOT_CONFIG != 0) {
        printf("_c111_checkconfig: The mode select is not GFD. Giving up\n")
        printf("_c111_checkconfig: Fix dev. server resources + restart server\n")
        return (0)
    }
    #
    # Check that Mode Type is normal
    # In fact skip this test to be able to run also in
    # test/sum mode (to get DL length)
    #
#    if (C111_MODE_TYPE != 0) {
#        printf("_c111_checkconfig: The mode type is not normal. Giving up\n")
#        printf("_c111_checkconfig: Fix dev. server resources + restart server\n")
#        return (0)
#    }
    #
    # Check that only X pileup is enabled (and not Y) 
    # [this should be OK in device server resources!!]
    #
    if ((C111_PILEUP_X == 0) || (C111_PILEUP_Y == 1)) {
        printf("_c111_checkconfig: The mode is not 1D (along X). Giving up\n")
        printf("_c111_checkconfig: Fix dev. server resources + restart server\n")
        return (0)
    }

    #
    # TODO: could check here that the X offset is not 0
    #       since in this case part of the data are cut/lost.
    #
    return (1)
}'


#---------------------- c111newfile --------------------------
#%UU% [<data-directory> <file-prefix> [<run-number>]]
#%MDESC%
# Choose a new directory, file prefix and run/series number for data files
# when data are saved outside counting and scanning.
# If the run number is not passed as argument or if the file prefix is changed,
# the run number is reset to 0.
# This macro can be used at any moment to change data directory
#
def c111newfile '{
    local datadir prefix runnb
    local filename

    if (!C111_DATA_DIR) C111_DATA_DIR="/tmp"
    if (!C111_FILE_PREFIX) C111_FILE_PREFIX="tst"

    if ($#<2) {
        datadir = getval (" - Directory   ", C111_DATA_DIR)
        prefix  = getval (" - File Prefix ", C111_FILE_PREFIX)
        if (prefix!=C111_FILE_PREFIX) C111_RUN_NUMBER= 0
        runnb   = getval (" - Run Number  ", C111_RUN_NUMBER)
    }
    else {
        datadir= "$1"
        prefix= "$2"
        if ($#==3) runnb= $3
        else {
            if (prefix!=C111_FILE_PREFIX) runnb= 0
            else runnb= C111_RUN_NUMBER
        }
    }
    C111_DATA_DIR= datadir
    C111_FILE_PREFIX= prefix
    C111_RUN_NUMBER= runnb
}'


#-------------- c111config ------------------------
#%UU%
#%MDESC%
#  Display a menu to access all possible config %BR%
#  Allow to reconfigure using: %BR%
#       - values from database %BR%
#       - full interactive reconfig %BR%
#       - partial interactive reconfig %BR%
#
def c111config '{
    local nl option

    if (_c111_getstatus()) {
        option= 1
        while (option) {
            nl= _c111_show()

            tty_move(0, nl++, "(1) Reconfigure with default values from database")
            tty_move(0, nl++, "(2) FULL Manual configuration")
            tty_move(0, nl++, "(3) Configure main parameters only")
            tty_move(0, nl++, "(0) Quit")

            option= getval("\n\n\tOption ---> ", 0)
            printf("\n\n")

            if (option==1) _c111_reconfig
            else if (option==2) _c111_setconfig
            else if (option==3) _c111_tuneconfig
        }
    }
}'



#-------------- _c111_resolchange ------------------------
#%IU% (old_resolution, new_resolution)
#%MDESC%
#  Scale properly the C111_PLOTMIN/MAX and min/max
#  channels of any ROI pseudo-counters that might 
#  be defined since the resolution changed from
#  half to full or vice-versa. Change min/max channels
#  of any ROI pseudo-counters.
#  
#  This can happen in the following 3 macros:
#  _c111_reconfig   ... reconfiguring from database
#  _c111_setconfig  ... reconfiguring interactively
#  _c111_tuneconfig ... reconfiguring interactively, but limited set
#
def _c111_resolchange(oldhr, newhr) '{
    local roinb roi roinum roimne roimin roimax
    local rscale


    if (newhr != oldhr) {
        roinb= list_n(C111_ROI)

        printf("OLD resolution = %s\n", oldhr?"HALF":"FULL")
        printf("OLD plot range = [ %d, %d ]\n", C111_PLOTMIN, C111_PLOTMAX)
        printf("OLD save range = [ %d, %d ]\n", C111_SAVEMIN, C111_SAVEMAX)

        if ((newhr==0)&&(oldhr==1)) rscale= 2
        if ((newhr==1)&&(oldhr==0)) rscale= 0.5

        C111_PLOTMIN = int(rscale*C111_PLOTMIN)
        C111_PLOTMAX = int(rscale*C111_PLOTMAX)
    
        C111_SAVEMIN = int(rscale*C111_SAVEMIN)
        C111_SAVEMAX = int(rscale*C111_SAVEMAX)

        for (roi=1; roi<=roinb; roi++) {
            roimne= list_item(C111_ROI, roi)
            if ((roinum=cnt_num(roimne))!=-1) {
                roimin= C111_ROI[roimne]["min"]
                roimax= C111_ROI[roimne]["max"]
                C111_ROI[roimne]["min"] = int(rscale*roimin)
                C111_ROI[roimne]["max"] = int(rscale*roimax)
            }
        }

        c111arrays

        printf("NEW resolution = %s\n", newhr?"HALF":"FULL")
        printf("NEW plot range = [ %d, %d ]\n", C111_PLOTMIN, C111_PLOTMAX)
        printf("NEW save range = [ %d, %d ]\n", C111_SAVEMIN, C111_SAVEMAX)
    }
	_c111_checkrange
}'


#-------------- c111reconfig ------------------------
#%UU%
#%MDESC%
#  ReConfigure C111 with values FROM the DATABASE.
#
def c111reconfig '{
    if (_c111_getstatus()) {
        _c111_reconfig
    }
}'

#%IU%
def _c111_reconfig '{
    local oldhr

    # get the current value of half resolution flag 
    # so that will suitably modify the C111_PLOTMIN/MAX 
    # and min/max channels of any ROI pseudo-counters
    # that might be defined.
    oldhr = C111_HALF_RES

    if (esrf_io(C111_DEV,"DevC111ReConfigFromDB",C111_STATUS) < 0) {
        printf("c111reconfig: Error reconfig C111. Giving up\n")
        exit
    }
    # check the configuration to be sure it correponds to 
    # GFD 1D mode!!
    if (_c111_checkconfig()) {
        if (_c111_getstatus()) {
            _c111_resolchange(oldhr, C111_HALF_RES)
        }
    }
}'


#-------------- c111setconfig ------------------------
#%UU%
#%MDESC%
#  ReConfigure C111 with values entered interactively 
#
def c111setconfig '{
    if (_c111_getstatus()) {
        _c111_setconfig
    }
}'

#%IU%
def _c111_setconfig '{
    local oldhr
    local C111_CONFIG[]

    # get the current value of half resolution flag 
    # so that will suitably modify the C111_PLOTMIN/MAX 
    # and min/max channels of any ROI pseudo-counters
    # that might be defined.
    oldhr = C111_HALF_RES

    # enter parameters interactively
    C111_DEBUGFL        = getval(" - Device server debug flag          ",C111_DEBUGFL)
    C111_BOOT_CONFIG    = 0          # should be GFD
    C111_MODE_TYPE      = getval(" - Mode type <0=normal/1=testsum>    ",0)
    C111_TIMEOUT        = getval(" - Timeout (in ns)                   ",C111_TIMEOUT)
    C111_SKIP           =0
    C111_EXTINHFCi      = getval(" - ExtInhibit <0> / FastClear <1>    ",C111_EXTINHFC)
    C111_PILEUP_X       = 1       # must be 1 since X axis used
    C111_PILEUP_Y       = 0       # must be 0 since only X axis used
    C111_OFFSET_X       = getval(" - X Offset (in ns)                  ",C111_OFFSET_X)
    C111_OFFSET_Y       = 0       # dont care
    C111_HALF_RES       = getval(" - Half Resolution <0=full,1=half>   ",C111_HALF_RES)

    printf("\n   Possible values for front pannel monitor:\n")
    printf("\t (0) gate\n\t (1) clear error \n\t (2) ALU overflow \n\t (3) AMS111(ASIC)monitor \n")
    C111_FP_MONITOR     = getval(" - Signal for front pannel monitor   ", C111_FP_MONITOR)
    if (fpmon==3) {
            C111_MUX_SEL= getval(" - ASIC monitor(0=MSB cntr/1=MASK4)  ", C111_MUX_SEL)
    }
    else {
        C111_MUX_SEL= 0
    }

    C111_STAT_TIMER     = 0     # by default disable statistics timer
    C111_DURATION       = 0
    C111_ACQ_BANK       = getval(" - Select bank for acquisition       ",C111_ACQ_BANK)

    C111_CONFIG[0]  = C111_DEBUGFL
    C111_CONFIG[1]  = C111_BOOT_CONFIG
    C111_CONFIG[2]  = C111_MODE_TYPE
    C111_CONFIG[3]  = C111_TIMEOUT
    C111_CONFIG[4]  = C111_SKIP
    C111_CONFIG[5]  = C111_EXTINHFC
    C111_CONFIG[6]  = C111_OFFSET_X
    C111_CONFIG[7]  = C111_OFFSET_Y
    C111_CONFIG[8]  = C111_PILEUP_X
    C111_CONFIG[9]  = C111_PILEUP_Y
    C111_CONFIG[10] = C111_HALF_RES
    C111_CONFIG[11] = C111_FP_MONITOR
    C111_CONFIG[12] = C111_MUX_SEL
    C111_CONFIG[13] = C111_STAT_TIMER
    C111_CONFIG[14] = C111_DURATION
    C111_CONFIG[15] = C111_ACQ_BANK

    if (esrf_io(C111_DEV,"DevC111SetConfig",C111_CONFIG, C111_STATUS) < 0) {
        printf("c111setconfig: Error setting C111 config. Giving up\n")
    }

    # to get among other things C111_NBCOLS needed in c111arrays
    if (_c111_getstatus()) {
        _c111_resolchange(oldhr, C111_HALF_RES)
    }
}'


#-------------- c111tuneconfig ------------------------
#%UU%
#%MDESC%
#  Tune + ReConfigure C111 C111 with few new values; i.e. does not
#  cover all parameters but only few which usually need tunning.
#  The following parameters can be changed:
#    - timeout   : Timeout in ns
#    - skip      : Skip flag = ignored for GFD and MHIP
#    - extinhfc  : External inhibit(0) or Fast Clear Flag(1)
#    - offset_x  : X offset in ns
#    - offset_y  : Y offset in ns
#    - half_res  : Half resolution flag
#    - fp_monitor: external signal on front pannel for monitoring
#    - mux_sel   : subselection for ASCI monitor
#
def c111tuneconfig '{
    if (_c111_getstatus()) {
        _c111_tuneconfig
    }
}'

#%IU%
def _c111_tuneconfig '{
    local timo skip extinhfc offx offy halfr fpmon mux
    local oldhr
    local C111_TUNE_ARGIN[]

    oldhr= C111_HALF_RES

    timo        = getval(" - Timeout (in ns)                   ", C111_TIMEOUT)
    skip        = 0
    extinhfc    = getval(" - Ext Inhibit <0> or Fast Clear <1> ", C111_EXTINHFC)
    offx        = getval(" - X Offset (in ns)                  ", C111_OFFSET_X)
    offy        = 0
    halfr       = getval(" - Half Resolution <0=full, 1=half>  ",C111_HALF_RES)

    printf("\n   Possible values for front pannel monitor:\n")
    printf("\t (0) gate\n\t (1) clear error \n\t (2) ALU overflow \n\t (3) AMS111(ASIC)monitor \n")
    fpmon       = getval(" - Signal for front pannel monitor   ", C111_FP_MONITOR)
    if (fpmon==3) {
            mux = getval(" - ASIC monitor(0=MSB cntr/1=MASK4)  ", C111_MUX_SEL)
    }
    else {
        mux= 0
    }
   
    if ((timo!=C111_TIMEOUT) || (extinhfc!=C111_EXTINHFC) || (offx!=C111_OFFSET_X) || \
        (offy!=C111_OFFSET_Y) || (halfr!=C111_HALF_RES) || (fpmon!=C111_FP_MONITOR) || \
        (mux!=C111_MUX_SEL)) {

            C111_TUNE_ARGIN[0] = timo
            C111_TUNE_ARGIN[1] = skip
            C111_TUNE_ARGIN[2] = extinhfc
            C111_TUNE_ARGIN[3] = offx
            C111_TUNE_ARGIN[4] = offy
            C111_TUNE_ARGIN[5] = halfr
            C111_TUNE_ARGIN[6] = fpmon
            C111_TUNE_ARGIN[7] = mux

            if (esrf_io(C111_DEV,"DevC111Tune",C111_TUNE_ARGIN,C111_STATUS) < 0) {
                printf("c111tune: Error tunning C111. Giving up\n")
            }
            else {
                if (_c111_getstatus()) {
                    _c111_resolchange(oldhr, C111_HALF_RES)
                }
        }
    }
}'


#-------------- c111stattimer ------------------------
#%UU%
#%MDESC%
#  Allows to disable or enable statistics timer with certain duration.
#  Statistcs timer disabling/enabling+defining its duration is done
#  among other things in the c111config (= setting config), but this
#  macro can be convenient. It could also use DevC111SetConfig() D.S. command.
#
# Usage: c111stattimer <enable_disable> <duration>
#
def c111stattimer '{
    local stattimon
    local C111_ST_IN[]

    if ($# == 2) {
        C111_STAT_TIMER = $1
        C111_DURATION = $2
    } else {
        stattimon = yesno(" - Want to enable statistics timer ",0)
        if (stattimon) {
            C111_STAT_TIMER = 1
            C111_DURATION=getval(" - Stat.timer duration(sec) ",C111_DURATION)
        } else {
            C111_STAT_TIMER = 0
            C111_DURATION=0
        }
    }

    C111_ST_IN[0] = C111_STAT_TIMER
    C111_ST_IN[1] = C111_DURATION

    if (esrf_io(C111_DEV,"DevC111EnDisStatTimer",C111_ST_IN,C111_STATUS) < 0){
        printf("c111stattimer: Error dis/enable stat.timer. Giving up\n")
        if (_c111_getstatus()) {
            printf("c111stattimer: Cannot read back status\n")
        }
    }
}'


#-------------------------- _c111statistics -----------------------
#%IU%
#%MDESC%
#  Gives statistics information for C111
#
def _c111statistics '{

    local C111_STT[]

    C111_STT[0] = 0
    while (C111_STT[0] < C111_DURATION) {
        if (esrf_io(C111_DEV,"DevC111GetStatistics",C111_STT) < 0) {
            printf("c111statistics: Error reading C111 statistics\n")
            exit
        } else {
            if ($# == 0) {
                printf("Elapsed time (sec)        = %3.1f\n",C111_STT[0])
                printf("Nb of hits on chan. 0(X1) = %d\n", C111_STT[1])
                printf("Nb of hits on chan. 1(X2) = %d\n", C111_STT[2])
                #printf("Nb of hits on chan. 2(Y1) = %d\n", C111_STT[3])
                #printf("Nb of hits on chan. 3(Y2) = %d\n", C111_STT[4])
                #printf("Nb of lost hits (MHIT)    = %d\n", C111_STT[5])
                printf("Nb of common starts       = %d\n", C111_STT[6])
                printf("Nb of rejected events     = %d\n", C111_STT[7])
                printf("Nb of ALU overflows       = %d\n", C111_STT[8])
            }
        }
        sleep(1)
    }
    # get statistics one more time
    if (esrf_io(C111_DEV,"DevC111GetStatistics",C111_STT) < 0) {
        printf("c111statistics: Error reading C111 statistics\n")
        exit
    }
    printf("Elapsed time (sec)        = %3.1f\n", C111_STT[0])
    printf("Nb of hits on chan. 0(X1) = %d\n", C111_STT[1])
    printf("Nb of hits on chan. 1(X2) = %d\n", C111_STT[2])
    #printf("Nb of hits on chan. 2(Y1) = %d\n", C111_STT[3])
    #printf("Nb of hits on chan. 3(Y2) = %d\n", C111_STT[4])
    #printf("Nb of lost hits (MHIT)    = %d\n", C111_STT[5])
    printf("Nb of common starts       = %d\n", C111_STT[6])
    printf("Nb of rejected events     = %d\n", C111_STT[7])
    printf("Nb of ALU overflows       = %d\n", C111_STT[8])

}'


#-------------------------- c111regs -----------------------
#%IU%
#%MDESC%
#  Read value of some C111 registers
#  (usefull for debugging)
#
def c111regs '{

    global C111_REGS

    if (esrf_io(C111_DEV,"DevC111GetSomeRegs",C111_REGS) < 0) {
        printf("c111regs: Error reading some C111 registers\n")
        exit
    }
    printf("CUB Status        reg. = 0x%08x\n", C111_REGS[0])
    printf("CUB SDRAM clear   reg. = 0x%08x\n", C111_REGS[1])
    printf("CUB SDRAM start   reg. = 0x%08x\n", C111_REGS[2])
    printf("CUB SDRAM end     reg. = 0x%08x\n", C111_REGS[3])
    printf("CUB SDRAM pattern reg. = 0x%08x\n", C111_REGS[4])
    printf("Config1           reg. = 0x%08x\n", C111_REGS[5])
    printf("Config2           reg. = 0x%08x\n", C111_REGS[6])
    printf("Config3           reg. = 0x%08x\n", C111_REGS[7])
    printf("Config4           reg. = 0x%08x\n", C111_REGS[8])
    printf("Statistics timer  reg. = 0x%08x\n", C111_REGS[9])

}'


#-------------- c111readreg ------------------------
#%UU%
#%MDESC%
#  Read a register (usefull for debugging)
#  Input:
#    - base adddress reg. index: 0 = AMCC, 1/2 = 1st/2dn group of C111 regs
#    - offs : offset to base
#
def c111readreg '{
    local value
    local C111_RR_ARGIN[]

    if ($# == 2) {
        C111_RR_ARGIN[0] = $1
        C111_RR_ARGIN[1] = $2
    } else {
        C111_RR_ARGIN[0] = getval("Base addr. reg. index",2)
        printf("Possible base address indeces are: \n")
        printf("0 = AMCC operation registers\n")
        printf("1 = C111 1st register group\n")
        printf("2 = C111 2nd register group\n")

        if (C111_RR_ARGIN[0] == 0) {
            printf("Offsets of AMCC registers are:\n")

        } else if (C111_RR_ARGIN[0] == 1) {
            printf("Offsets in 1st C111 reg. group are:\n")

        } else if (C111_RR_ARGIN[0] == 2) {
            printf("Offsets in 2nd C111 reg. group are:\n")
        } else {
            printf("Bad base address reg. index!!!\n")
            exit
        }
        C111_RR_ARGIN[1] = getval("Choose offset",0x08)
    }

    if (value = esrf_io(C111_DEV,"DevC111ReadReg",C111_RR_ARGIN) < 0) {
        printf("c111readreg: Error reading register\n")
    }
    else {
        printf("Register value = 0x%08x\n", value)
    }
}'


#-------------- c111writereg ------------------------
#%UU%
#%MDESC%
#  Write a register (usefull for debugging)
#  Input:
#    - base adddress reg. index: 0 = AMCC, 1/2 = 1st/2dn group of C111 regs
#    - offs : offset to base
#    - value : register value 
#
def c111writereg '{
    local value
    local C111_WR_ARGIN[]

    if ($# == 3) {
        C111_WR_ARGIN[0] = $1
        C111_WR_ARGIN[1] = $2
        C111_WR_ARGIN[2] = $3
    } else {
        C111_WR_ARGIN[0] = getval("Base addr. reg. index",2)
        printf("Possible base address indeces are: \n")
        printf("0 = AMCC operation registers\n")
        printf("1 = C111 1st register group\n")
        printf("2 = C111 2nd register group\n")

        if (C111_WR_ARGIN[0] == 0) {
            printf("Offsets of AMCC registers are:\n")

        } else if (C111_WR_ARGIN[0] == 1) {
            printf("Offsets in 1st C111 reg. group are:\n")

        } else if (C111_WR_ARGIN[0] == 2) {
            printf("Offsets in 2nd C111 reg. group are:\n")
        } else {
            printf("Bad base address reg. index!!!\n")
            exit
        }
        C111_WR_ARGIN[1] = getval("Choose offset",0x08)
        C111_WR_ARGIN[2] = getval("Choose register value",0)
    }

    printf("Base reg. index = %d\n",C111_WR_ARGIN[0])
    printf("Offset          = 0x%08x\n",C111_WR_ARGIN[1])
    printf("Value           = 0x%08x\n",C111_WR_ARGIN[2])

    if (esrf_io(C111_DEV,"DevC111WriteReg",C111_WR_ARGIN) < 0) {
        printf("c111writereg: Error writing register\n")
    } 
}'


#-------------- c111pupon ------------------------
#%UU%
#%MDESC%
#  Enable X pileup
#
def c111pupon '{
    c111writereg 2 0x08 0x11
}'


#-------------- c111pupoff ------------------------
#%UU%
#%MDESC%
#  Disable both X and Y pileups
#
def c111pupoff '{
    c111writereg 2 0x08 0x1
}'

#------------------------------------------------------------
# END of macros related to state/status/configuration/statistics
#------------------------------------------------------------




#============================================================
#
# Memory banks related macros
#
#============================================================
#
#
#-------------------------- c111setacqbank -----------------------
#%UU%
#%MDESC%
#  Select bank to be used for acquisition. Acq. bank is already selected
#  with c111config, but can be modified with this macro.
#
# Usage: c111setacqbank <bank_id>
#
def c111setacqbank '{
    local acqbank

    if ($# != 1 && $# != 0 ) {
        printf("Usage: c111setacqbank <bank_id>\n")
        exit
    }

    if ($# == 1 ) {
        acq_bank= $1
    }
    else {
        acq_bank=getval(" Enter bank to be used for acquisition ",C111_ACQ_BANK)
    }
    if ((acq_bank != 0) && (acq_bank != 1)) {
        printf("Bank index should be 0 or 1\n")
    }
    else {
        if (acq_bank != C111_ACQ_BANK) {
            # change acq bank, otherwise do nothing
            if (esrf_io(C111_DEV,"DevC111SetAcqBank",acq_bank) < 0) {
                printf("c111setacqbank: Error setting bank for acquisition\n")
            }
            else {
                C111_ACQ_BANK = acq_bank
            }
        }
    }
}'


#-------------------------- c111swapbanks -----------------------
#%UU%
#%MDESC%
#  Swap banks
#
def c111swapbanks '{

    if (esrf_io(C111_DEV,"DevC111SwapBanks") < 0) {
        printf("c111swapbanks: Error swapping banks\n")
    }
    else {
        _c111_getstatus()
    }
}'


#-------------------------- c111initbank -----------------------
#%UU%
#%MDESC%
#  Init bank that is currently selected for acquisition (= bank
#  on port M).
#
# Usage: c111initbank <start_value> <increment_flag>
#
def c111initbank '{
    local startval ans increment
    local C111_IBANK_ARGIN[]

    if ($# != 2 && $# !=0 ) {
        printf("Usage: c111initbank <start_value> <increment_flag> \n")
        exit
    }

    if ($# == 0) {
        startval = getval(" Memory start value ",0)
        ans      = yesno(" Want to increment from one loc.to next ",0)
        increment = 0
        if (ans) increment = 1
    }
    if ($# == 2) {
        startval  = $1
        increment = $2
    }

    C111_IBANK_ARGIN[0] = startval
    C111_IBANK_ARGIN[1] = increment

    if (esrf_io(C111_DEV,"DevC111InitBank",C111_IBANK_ARGIN) < 0) {
        printf("c111initbank: Error initialising bank selected for acq.\n")
    }
}'


#-------------------------- c111initbanks_long ------------------
#%UU%
#%MDESC%
#  Init BOTH banks (start with the one which is already on port M
#  = selected for acquisition, then swap them and clear the other)
#
# Usage: c111initbanks_long <start_value> <increment_flag>
#
def c111initbanks_long '{
    local startval ans increment
    local C111_IBANK_ARGIN[]

    if ($# != 2 && $# !=0 ) {
        printf("Usage: c111initbanks <start_value> <increment_flag> \n")
        exit
    }

    if ($# == 0) {
        startval = getval(" Memory start value ",0)
        ans      = yesno(" Want to increment from one loc.to next ",0)
        increment = 0
        if (ans) increment = 1
    }
    if ($# == 2) {
        startval  = $1
        increment = $2
    }

    C111_IBANK_ARGIN[0] = startval
    C111_IBANK_ARGIN[1] = increment

    if (esrf_io(C111_DEV,"DevC111InitBank",C111_IBANK_ARGIN) < 0) {
        printf("c111initbanks: Error initialising bank %d\n", C111_ACQ_BANK)
    }
    else {
        if (esrf_io(C111_DEV,"DevC111SwapBanks") < 0) {
            printf("c111initbanks: Error swapping banks\n")
        }
        else {
            if (_c111_getstatus()) {
                if (esrf_io(C111_DEV,"DevC111InitBank",C111_IBANK_ARGIN) < 0) {
                    printf("c111initbanks: Error initialising bank %d\n", C111_ACQ_BANK)
            }
        }
    }
}'


#-------------------------- c111initbanks -----------------------
#%UU%
#%MDESC%
#  Init BOTH banks. Similar to macro above, but this time more 
#  "compact" command ["DevC111InitBothBanks"] is used to make macro short.
#
# Usage: c111initbanks <start_value> <increment_flag>
#
def c111initbanks '{
    local startval ans increment
    local C111_IBANK_ARGIN[]

    if ($# != 2 && $# !=0 ) {
        printf("Usage: c111initbanks <start_value> <increment_flag> \n")
        exit
    }

    if ($# == 0) {
        startval = getval(" Memory start value ",0)
        ans      = yesno(" Want to increment from one loc.to next ",0)
        increment = 0
        if (ans) increment = 1
    }
    if ($# == 2) {
        startval  = $1
        increment = $2
    }

    C111_IBANK_ARGIN[0] = startval
    C111_IBANK_ARGIN[1] = increment

    if (esrf_io(C111_DEV,"DevC111InitBothBanks",C111_IBANK_ARGIN) < 0) {
        printf("c111initbanks: Error initialising both banks \n")
    }
    # to get C111_ACQ_BANK
    _c111_getstatus()
}'


#-------------------------- c111readbank -----------------------
#%UU%
#%MDESC%
#  Read data from ONE bank. The limits for reading out are 
#  0 and C111_NBCOLS-1
#
def c111readbank '{
    local C111_RB_ARGIN[]


    C111_RB_ARGIN[1] = 0               # start coloumn
    C111_RB_ARGIN[2] = C111_NBCOLS-1    # end coloumn
    C111_RB_ARGIN[3] = 0               # start row
    C111_RB_ARGIN[4] = 0               # end row
    C111_RB_ARGIN[5] = 0               # Binning OFF (since in 1D mode)

    # make a reading into SHM array C111_DATA
    C111_RB_ARGIN[0] = 0     # only 1 channel to read (X)
    esrf_io(C111_DEV,"tcp")
    if (esrf_io(C111_DEV,"DevC111ReadBankData",C111_RB_ARGIN, C111_DATA) < 0) {
        printf("Error reading spectrum %d\n", C111_RB_ARGIN[0])
    }
    else {
        C111_DATA[0][0] = C111_DATA[0][0]
    }
}'


#-------------------------- c111readbanks -----------------------
#%UU%
#%MDESC%
#  Read data from BOTH banks. The limits for reading out are 
#  0 and C111_NBCOLS-1
#
def c111readbanks '{
    local C111_RB_ARGIN[]

    C111_RB_ARGIN[1] = 0               # start coloumn
    C111_RB_ARGIN[2] = C111_NBCOLS-1    # end coloumn
    C111_RB_ARGIN[3] = 0               # start row
    C111_RB_ARGIN[4] = 0               # end row
    C111_RB_ARGIN[5] = 0               # Binning OFF (since in 1D mode)

    # make a reading into SHM array C111_DATA
    C111_RB_ARGIN[0] = 0     # only 1 channel to read (X)
    esrf_io(C111_DEV,"tcp")
    if (esrf_io(C111_DEV,"DevC111ReadBothBanks",C111_RB_ARGIN, C111_DATA) < 0) {
        printf("Error reading spectrum %d\n", C111_RB_ARGIN[0])
    }
    else {
        C111_DATA[0][0] = C111_DATA[0][0]
    }
}'


#-------------------------- c111sum1b -----------------------
#%UU%
#%MDESC%
#  Get sum of hits in a histogram(s) from the bank that is not selected
#  for acquisition. Although this set of macros is for GFD use here
#  general macro (good both for GFD and MHIT).
#
def c111sum1b '{
    local hid sum

    #c111status 1

    # if no arguments will get hist sum for
    # mode GFD 1D/2D: histogram = 0
    # mode MHIT: all 4 histograms

    hid = 0
    if (C111_BOOT_CONFIG == 0) {
        # GFD mode
        esrf_io(C111_DEV,"tcp")
        sumh = esrf_io(C111_DEV,"DevC111GetHistSum1Bank",hid)
        if (sumh < 0) {
            printf("Error getting sum of histogram %d in bank %d\n", hid, 1-C111_ACQ_BANK)
            exit
        }
        printf("Sum of hits in histogram %d in bank %d is %f\n", hid, 1 - C111_ACQ_BANK, sumh)
    } else {
        # MHIT mode
        esrf_io(C111_DEV,"tcp")
        for (hid = 0; hid < 4; hid++) {
            sumh = esrf_io(C111_DEV,"DevC111GetHistSum1Bank",hid)
            if (sumh < 0) {
                printf("Error getting sum of histogram %d in bank %d\n", hid, 1-C111_ACQ_BANK)
                exit
            }
            printf("Sum of hits in histogram %d in bank %d is %f\n", hid, 1 - C111_ACQ_BANK, sumh)
        }
    }
}'


#-------------------------- c111sum2b -----------------------
#%UU%
#%MDESC%
#  Get sum of hits in a histogram(s) from both banks.
#  Although this set of macros is for GFD use here
#  general macro (good both for GFD and MHIT).
#
def c111sum2b '{
    local hid sum

    #c111status 1

    # if no arguments will get hist sum for
    # mode GFD 1D/2D: histogram = 0
    # mode MHIT: all 4 histograms

    hid = 0
    if (C111_BOOT_CONFIG == 0) {
        # GFD mode
        esrf_io(C111_DEV,"tcp")
        sumh = esrf_io(C111_DEV,"DevC111GetHistSum2Banks",hid)
        if (sumh < 0) {
            printf("Error getting sum of histogram %d\n", hid)
            exit
       }
        printf("Sum of hits in histogram %d is %f\n", hid, sumh)
    } else {
        # MHIT mode
        esrf_io(C111_DEV,"tcp")
        for (hid = 0; hid < 4; hid++) {
            sumh = esrf_io(C111_DEV,"DevC111GetHistSum2Banks",hid)
            if (sumh < 0) {
                printf("Error getting sum of histogram %d \n", hid)
                exit
            }
            printf("Sum of hits in histogram %d is %f\n", hid, sumh)
        }
    }
}'


#-------------------------- c111data -----------------------
#%UU%
#%MDESC%
#  Useful macro for X-check with c111sum1b/2b. This macro is summing up
#  contents in C111_DATAn(n=0->3) for MHIT and C111_DATA for GFD.
#  Although this set of macros is for MHIT use here
#  general macro (good both for GFD and MHIT).
#  Since ROI selected for display and readout can be smaller than
#  whole 2D image area (2K*2K pixels for half-resolution
#                       4K*4K pixels for full-resolution)
#  the sum obtained with this macro can be smaller than sum 
#  obtained with c111sum1b/2b.
#
#  Added in this macro = getting max value and 
#                        col/row at max value.
#
def c111data '{ 
    
    #c111status 1
    if (C111_BOOT_CONFIG == 0) {
        if (C111_PILEUP_Y == 0) {
            printf("Sum of hits in spectrum = %d\n", array_op("sum",C111_DATA))
            printf("Maximum value is %d at col = %d\n", array_op("max",C111_DATA), array_op("row_at_max",C111_DATA))
        } else {
            printf("Sum of hits in histogram = %d\n", array_op("sum",C111_DATA))
            printf("Maximum value is %d at col = %d, row = %d\n", array_op("max",C111_DATA), \
                    array_op("row_at_max",C111_DATA), array_op("col_at_max",C111_DATA))
        }
    } else {
        printf("Sum of hits in spectrum 0 = %d\n", array_op("sum",C111_DATA0))
        printf("Maximum value in spect. 0 is %d at col %d\n", array_op("max",C111_DATA0), \
                    array_op("row_at_max",C111_DATA0))
        printf("Sum of hits in spectrum 1 = %d\n", array_op("sum",C111_DATA1))
        printf("Maximum value in spect. 1 is %d at col %d\n", array_op("max",C111_DATA1), \
                    array_op("row_at_max",C111_DATA1))
        printf("Sum of hits in spectrum 2 = %d\n", array_op("sum",C111_DATA2))
        printf("Maximum value in spect. 2 is %d at col %d\n", array_op("max",C111_DATA2), \
                    array_op("row_at_max",C111_DATA2))
        printf("Sum of hits in spectrum 3 = %d\n", array_op("sum",C111_DATA3))
        printf("Maximum value in spect. 0 is %d at col %d\n", array_op("max",C111_DATA3), \
                    array_op("row_at_max",C111_DATA3))
    }
}'
#------------------------------------------------------------
# END of macros related to the memory banks
#------------------------------------------------------------




#============================================================
#
# ASICPower/Starting/Stopping/Polling related macros
#
#============================================================
#
#
#-------------------------- c111power -----------------------
#%UU%
#%MDESC%
#  Powers ASIC C111 up
#
def c111poweron '{
    if (_c111_getstatus()) {
        _c111_power(1)
    }
}'

#%UU%
#%MDESC%
#  Powers ASIC C111 down
#
def c111poweroff '{
    if (_c111_getstatus()) {
        _c111_power(0)
    }
}'

def _c111_power(onoff) '{
    if (C111_STATUS[29]!=onoff) {
        if (esrf_io(C111_DEV, "DevC111PowerUpDn", onoff) < 0) {
            printf("c111power: Error powering %s the C111 ASIC. Giving up\n", onoff?"up":"down")
            return (0)
        }
    }
    return (1)
}'


#-------------------------- c111start -----------------------
#%UU%
#%MDESC%
#  Starts the C111 if it is not running
#
def c111start '{
    local c111time

    if ($#) {
        #
        # convert to miliseconds altohugh the 1/100 of a second is
        # used at the driver level
        #
        c111time = $1 * 1000
    } else {
        c111time = 0
    }
    if (whatis("C111_DATA") & 0x00010000)  C111_DATA = 0

    # check ASIC power; if off put it on 
    #c111status 1
    if (_c111_power(1)) {

        C111_STATE=esrf_io(C111_DEV,"DevC111GetStateString")
        # starts the C111 only if not yet running
        if (index(C111_STATE,"RUNNING") == 0) {
            #printf("Will Start C111\n")
            if (esrf_io(C111_DEV,"DevC111Start",c111time) < 0) {
                print "c111start: Cannot start C111. Help!"
            }
        }
    }
}'


#------------- c111stop -----------------------------------
#%UU%
#%MDESC%
#  Stops the C111 if it is running.
#
def c111stop '{

    C111_STATE=esrf_io(C111_DEV,"DevC111GetStateString")
    # stop the C111 only if not yet in IDLE state
    if (index(C111_STATE,"IDLE") == 0) {
        #printf("Will Stop C111\n")
        if (esrf_io(C111_DEV,"DevC111Stop") < 0) {
            print "c111stop: Cannot stop C111. Help!"
        }
    }
}'


#------------- c111poll ------------------------------
#%UU%
#%MDESC%
#  Poll to see when acq. over (only for time limited acq.)
#
# Usage: c111poll <refresh_period> <read_data_for_display>
#
def c111poll '{
    local waitime readfordisp
    local elapsedtime
    local message

    if (($# != 2) && ($# != 0)) {
        printf("Usage: c111poll <refresh_period> <read_data_for_display>\n")
        exit
    }

    if ($# == 0) {
        waitime     = 1
        readfordisp = 1
    }
    if ($# == 2) {
        waitime = $1
        readfordisp = $2
    }
    #if (waitime < 3) waitime = 3

    while(1) {
        C111_STATE=esrf_io(C111_DEV,"DevC111GetStateString")
        if (index(C111_STATE,"RUNNING") == 0) {
            message = sprintf("C111 has stopped after %f seconds",time()-C111_ACQSTART_TIME)
            printf("%s\r", message)
            break;
        } else {
            message = sprintf("C111 is running for %f seconds",time()-C111_ACQSTART_TIME)
            printf("%s\r", message)
            if (readfordisp) {
                c111readbanks
		c111plot
            }
        }
        sleep(waitime)
    }

}'


#------------- c111acq ------------------------------
#%UU%
#%MDESC%
#  Make a finite-time acquisition. If pass only 1 parameter (= acq. time)
#  then the C111 memory is always cleared before the acquisition, while
#  if in addition the second parameter is passed the C111 memory is not
#  cleared.
#  Always (= independent of acq. time) both banks are used.
#  If automatic file-saving was selected in c111config (C111_SAVE)
#  the spectrum is saved in MCA-like file with the name:
#  C111_FILE_PREFIX_C111_RUN_NUMBER. 
#  If saving in both MCA-like and file for PADI/JADI was selected
#  in c111config(C111_SAVE_PADI), then in addition to MCA-like file
#  the file for PADI/JADI is written. Its name is:
#  C111_FILE_PREFIX_padi_C111_RUN_NUMBER.
#  If data-saving selected what is pout in MCA-like file are ROI
#  counter values (and not statistics = anode,x1,x2,rej.ev,ALU ovf)
#  and other counters defined in config have no meaning, since they 
#  do not count during c111acq!!!.
#
# Usage: c111acq <acquisition_time> [<donotclearflag>]
#
def c111acq '{

    c111roiclear
    c111statclear

    # must give finite acq. time
    if (($# < 1) || ($# > 2)) {
        printf("Usage: c111acq <acquisition_time> [<donotclear_flag>]\n")
        exit
    }

    if ($1 == 0) COUNT_TIME = 10
    else         COUNT_TIME = $1

    if ($# < 2) {
        p "Will clear banks"
        # clear both banks
        c111initbanks 0 0
    }
    C111_ACQSTART_TIME = time()
    c111start COUNT_TIME 
    # poll with period of 1 second, and each time read the data
    # for the display (plotting invoked inside c111poll macro)
    c111poll 1 1
    # at the end of polling nevertheless invoke c111stop to be sure
    # that the C111 is stopped.
    c111stop
    # read banks one more time
    c111readbanks

    # read rois
    _c111_updaterois

    # display data
    c111plot
    if (C111_SAVE) {
        # save in MCA-like file
        C111_ACQSAVE = 1
        c111save
        C111_ACQSAVE = 0
        if (C111_SAVE_PADI) {
            # decrement run number to have the same in MCA-like file
            # and for PADI file
            C111_RUN_NUMBER--
            # save in file for PADI
            c111save_padi
        }
    }

}'


#------------- c111statacq ------------------------------
#%UU%
#%MDESC%
#  Make a finite-time acquisition to look at statistics
#  Set statistics timer duration shorter than counting time.
#  This time should be nonzero. If second argument is passed,
#  then the both X+Y pileups are disabled (Y Pup is anyway 
#  all the time disabled in GFD 1D mode).
#
# Usage: c111statacq <statistics_timer_duration> <disablePileUps>
#
def c111statacq '{
    local duration tostop

    # must pass at least one arg = statistics timer duration
    if (($# == 0) || ($# > 2)) {
        printf("Usage: c111statacq <statistics_timer_duration> <disablePileUP\n")
        exit
    }

    # if stat.timer duration on input is 0 set it to 1 second
    if ($1 == 0) {
        duration = 1
    } else {
        duration = $1
    }

    C111_STATE=esrf_io(C111_DEV,"DevC111GetStateString")
    if (index(C111_STATE,"RUNNING") != 0) {
        printf("The C111 is running\n")
        tostop = yesno("Do you want to stop it",0)
        if (tostop) {
            c111stop
        } else {
            printf("Sorry wont do statistics measurements\n")
            exit
        }
    }

    # Enable statistics timer with given duration
    c111stattimer 1 duration 
   
    # disable both pileups only if second argument exist (whatever its value)
    if ($# == 2) {
        c111pupoff
    }
 
    # even not necessary, but usefull to read banks and plot in the end
    c111initbanks 0 0

    # invoke c111status to get C111_DURATION
    if (_c111_getstatus()) {

        # acquire for "infinite" time (all data go in one bank)
        c111start 0 

        # polling is done inside _c111statistics until statistics timer expires

        # show statistics only in the end
        _c111statistics 1

        # show statistics during life-time of statistics timer + after its
        # expiration
        #_c111statistics

        # stop the acquisition now and disable statistics timer 
        c111stop

        # even not necessary, but usefull to compare with total counts in plot 
        # of course in the plot will have a bit more hits since acq. is not
        # stopped exactly at statistics timer expiration.
        c111readbanks
        c111plot

        # disable statistics timer
        c111stattimer 0 duration 

        # reenable X pileup only if second argument exist (whatever its value)
        if ($# == 2) {
            c111pupon
        }
    }

}'

#-------------------------- c111savemenu -----------------------
#%UU%
#%MDESC%
#  Display a short menu with all saving options
#
def c111savemenu '{
    local option

    option= 1
    while (option) {
        nl= 0

        tty_cntl("ho"); tty_cntl("cd")
        tty_move(15, nl++, "\[md\]< C111 SAVING OPTIONS >\[me\]")
        tty_move(10, nl++, sprintf("Device Name : \[md\]%s\[me\]", C111_DEV))
        nl+= 2

        tty_move(0, nl, "(1) Save spectrums in scans .........:")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_SAVESPECTRUM?"YES":"NO"))

        tty_move(0, nl, "(2) Save after ct/c111acq............:")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_SAVE?"YES":"NO"))

        nl++
        tty_move(0, nl, "(3) Saving file......................:")
        tty_move(40, nl++, sprintf("\[md\]%s\[me\]", C111_SAVEINPRIVATE?"Private":"Standard"))

        if (C111_SAVEINPRIVATE) {
            tty_move(5, nl, "- Directory   : ")
            tty_move(22, nl++, sprintf("\[md\]%s\[me\]", C111_DATA_DIR))
            tty_move(5, nl, "- File Prefix :")
            tty_move(22, nl++, sprintf("\[md\]%s\[me\]", C111_FILE_PREFIX))
            tty_move(5, nl, "- Run number  :")
            tty_move(22, nl++, sprintf("\[md\]%d\[me\]", C111_RUN_NUMBER))
        }
        else {
            tty_move(5, nl, "- Spec Datafile : ")
            tty_move(24, nl++, sprintf("\[md\]%s\[me\]", DATAFILE))
        }

        nl++
        tty_move(0, nl, "(4) Saved channel range [min, max]...:")
        tty_move(40, nl++, sprintf("\[md\][%d, %d]\[me\]", C111_SAVEMIN, C111_SAVEMAX))


        option= getval("\n\n\tOption ---> ", 0)
        printf("\n\n")

        if (option==1) {
            C111_SAVESPECTRUM= !C111_SAVESPECTRUM
        }       
        else if (option==2) {
            C111_SAVE= !C111_SAVE
        }
        else if (option==3) {
            C111_SAVEINPRIVATE= yesno(" - Save in private file", C111_SAVEINPRIVATE)
            if (C111_SAVEINPRIVATE) {
                c111newfile
            }
        }
        else if (option==4) {
            c111saverange
        }
    }
}'


#%UU% <save_in_scan> <save_in_ct> <save_in_private> [<save_in_padi>]
#%MDESC%
#  Set saving options (for filename/directory use c111newfile)
#  All options can be set to 0 (=no) or 1 (=yes)
#
def c111savesetup '{
    if ($#<3) {
        print "$0 <save_in_scan> <save_in_ct> <save_in_private> [<save_in_padi>]"
    }
    else {
        C111_SAVESPECTRUM= $1
        C111_SAVE= $2
        C111_SAVEINPRIVATE= $3
        C111_SAVE_PADI= $#==4?$4:0
    }
}'

#%UU% < [chmin] [chmax] >
#%MDESC%
#  Set spectrum range which will be saved
#
def c111saverange '{
    local chmin chmax chtmp

    if ($#!=2) {
        chmin= getval(" - Start saving at channel [min=0]", C111_SAVEMIN) 
        chmax= getval(sprintf(" - Stop saving at channel [max=%d]", C111_NBCOLS-1), C111_SAVEMAX)
    }
    else {
        chmin= $1
        chmax= $2
    }
    if (chmax<chmin) {
        chtmp= chmax
        chmax= chmin
        chmin= chtmp
    }
    C111_SAVEMIN= (chmin<0)?0:chmin
    C111_SAVEMAX= (chmax>(C111_NBCOLS-1))?(C111_NBCOLS-1):chmax
}'

#------------- c111save ------------------------------
#%UU%
#%MDESC%
#  To save data when acquire outside counting and scanning(= when
#  do c111acq dT) or when want to save data after counting (= after
#  ct dT).
#
#  Writes a header and data in a format that looks like in scan
#  to be able to read file with standard tools.
#
#  If the full filename is given as input parameter, then it
#  is used, otherwise the filename is composed from C111_DATA_DIR,
#  C111_FILE_PREFIX and C111_RUN_NUMBER.
#
#  Since this macro is only called at the end of c111acq or after
#  counting outside scan (in _c111_handlecounts) the test if (NPTS == _n1)
#  was removed around the block defining HEADING.
#
# Usage: c111save <filename>
#
def c111save '{
    local filename
    local npts cmin cmax meltime
    local ret

    if ($# > 1) {
        printf("Usage: c111save <filename>\n")
        exit
    }
    c111_user_presave
    if ($# == 1) {
        filename = "$1"
        scanno   = 0
    } else {
        if (C111_SAVEINPRIVATE) {
	    filename = sprintf("%s/%s_%.3d",C111_DATA_DIR,C111_FILE_PREFIX, C111_RUN_NUMBER++)
            scanno   = 0
        }
        else {
            filename = DATAFILE
            scanno   = SCAN_N
        }
    }
    if (filename != DATAFILE) {
        if (open(filename)) {
            printf("c111save: Error opening file %s\n", filename)
            exit
        }
 
        if (savefileheader(filename)<0) {
            printf("c111save: Error saving file header in file %s\n", filename)
            exit
        }
    }


    # if omit next section then would have HEADING and DATE from the
    # last scan (of course #S has still the number of the last scan done) 
    if (C111_ACQSAVE) {
            HEADING=sprintf("c111acq %s", COUNT_TIME)
    } else {
            HEADING=sprintf("ct %s", COUNT_TIME)
    }
    DATE = date()


    if (savestdheader1(filename, 3, scanno)<0) {
        printf("c111save: Error saving std header in file %s\n", filename)
        exit
    }
    npts = C111_SAVEMAX - C111_SAVEMIN + 1
    cmin = C111_SAVEMIN
    cmax = C111_SAVEMAX
    meltime = COUNT_TIME 
    if (savemcaheader(filename,"%16C",npts,cmin,cmax,0,0,meltime,meltime)<0) {
        printf("c111save: Error saving mca header in file %s\n", filename)
        exit
    }

# out of next 3: savemcaroi, savecntheader, savecounters
#         only savemcaroi has sense after c111acq, but all 
#         3 are usefull after ct.
    # save the ROI header
    _c111_savemcaroi(filename)

    # Next line added on 15.09.2005 
    FPRNT=""
    # PB wants this also outside scan
    for (i=0;i<_nm;i++) {
     	 FPRNT=sprintf("%s%s  ",FPRNT,motor_name(_m[i]))
    }
    FPRNT=sprintf("%s%s  ",FPRNT,_hkl_sym1)
    savecntheader1(filename)
    # PB wants this also outside scan
    FPRNT=""
    for (i=0;i<_nm;i++) {
        FPRNT=sprintf("%s%.8g ",FPRNT,A[_m[i]])
    }
    FPRNT=sprintf("%s%s ",FPRNT,_hkl_val)
    savecounters1(filename)

    if (savemcadata(filename,C111_DATA[C111_SAVEMIN:C111_SAVEMAX],npts,"%16C")<0) {
        printf("c111save: Error saving c111 data in file %s\n", filename)
        exit
    }

    if (filename != DATAFILE) {
        close(filename)
    }
    else {
        SCAN_N++
    }
    c111_user_postsave
    printf("Data saved in file = %s \n", filename)
}'


#------------- c111save_padi (for JADI/PADI) ----------------------------
#%UU%
#%MDESC%
#  Save data in a simple ASCII file (when acquire outside scan)
#  Format in the file is such that the data can be then plotted
#  with padi or jadi.
#  If the full filename is given as input parameter, then it
#  is used, otherwise the filename is composed from C111_DATA_DIR,
#  C111_FILE_PREFIX and C111_RUN_NUMBER.
#
# Usage: c111save_padi <filename>
#
def c111save_padi '{
    local filename ii

    if ($# > 1) {
        printf("Usage: c111save <filename>\n")
        exit
    }
    if ($# == 1) {
        filename = "$1"
    } else {
        filename = sprintf("%s/%s_padi_%.3d",C111_DATA_DIR,C111_FILE_PREFIX,C111_RUN_NUMBER++)
    }
    if (open(filename)) {
        printf("c111save: Error opening file %s\n", filename)
        exit
    }
    on(filename)
    offt
    for (ii = C111_SAVEMIN; ii <= C111_SAVEMAX; ii++) {
        fprintf(filename,"%u\n", C111_DATA[ii][0])
    }
    off(filename)
    ont
    close(filename) 
    printf("Data saved in file = %s \n", filename)
}'


def c111save_jadi 'c111save_padi'


#------------------------------------------------------------
# END of macros related to power/start/stop/poll/acquire
#------------------------------------------------------------




#============================================================
#
# Counting/Scanning related macros
#
#============================================================
#


#-------------------------- c111on -----------------------
#%UU%
#%MDESC%
#  Switch on C111 acq. during ct + scan
#  By modifying user_prepcount + user_getcount rather than
#  measure0 and measure1 the code below is good both for
#  counting AND scanning. If would modify measure0/1 than
#  c111on would swich on C111 acq. only during scan and not
#  during normal counting.
#
def c111on '{
    if (!C111_STATISTICS) {
        c111statoff
    }
    cdef("user_prepcount","_c111_prepcount; ","c111")
    ##cdef("user_pollcounts","_c111_pollcounts; ","c111")
    cdef("user_getcounts","_c111_getcounts; ","c111")
    cdef("user_handlecounts", "_c111_handlecounts; ", "c111")
    cdef("user_scan_loop","_c111_scan_loop;","c111")
    cdef("user_Fheader","_c111_savehead;","c111")
    C111_ON = 1
}'

 
#-------------------------- c111off -----------------------
#%UU%
#%MDESC%
#  Switch off C111 acq. during ct + scan
#
def c111off '{
    cdef("","","c111","delete")
    C111_ON = 0
    c111roiclear
    c111statclear
}'


#-------------------------- c111statclear -----------------------
#%IU%
#%MDESC%
#  Clear all statistics counters (reset to 0)
#
def c111statclear '{
    if(cnt_num("anode") != -1) S[cnt_num("anode")] = 0
    if(cnt_num("x1") != -1) S[cnt_num("x1")] = 0
    if(cnt_num("x2") != -1) S[cnt_num("x2")] = 0
    if(cnt_num("rejev") != -1) S[cnt_num("rejev")] = 0
    if(cnt_num("aluov") != -1) S[cnt_num("aluov")] = 0
}'

#%UU%
#%MDESC%
#  Enable statistics counters
#
def c111staton '{
    C111_STATISTICS= 1
}'

#%UU%
#%MDESC%
#  Disable statistics counters
#
def c111statoff '{
    c111statclear
    C111_STATISTICS= 0
    c111stattimer 0 10
}'

#-------------------------- _c111_prepcount -----------------------
#%IU%
#%MDESC%
#  Done at each scan point before counting
#
def _c111_prepcount '{

    ## beamcheck
    ## while (!BCHK_BEAM) {
    ##     beampoll
    ##     beamcheck
    ## }

    c111roiclear

# inserted stop here since sometimes in scan got complaints from 
# c111initbanks that this cannot be done in running state (but here
# c111 is supposed to be stopped!!!).
    # new 15 06 2004
    #c111stop
    #sleep(0.01)



    c111initbanks 0 0
    ##c111initbank 0 0
    if (C111_STATISTICS) {
        c111statclear
        c111stattimer 1 COUNT_TIME+3
    }
    # printf("**** In _c111_prepcount before c111 start \n")
    c111start 0
}'


#------------- _c111_pollcounts -----------------------------------
#
#%IU%
#%MDESC%
#  Done during counting when polling for end of counting
#  with polling interval COUNTERSPOLLTIME (0.01sec)
#  We DO NOT USE it
#
def _c111_pollcounts '{
    c111readbanks
}'


#------------- _c111_getcounts -----------------------------------
#%IU%
#%MDESC%
#  Done at each scan point, after counting (i.e. chk_count = 0) and
#  in scan also during counting if selected by setscans. C111 is stopped
#  only when the counting is over (i.e. when chk_count = 0).
#
def _c111_getcounts '{
    if ((chk_count==0) && (C111_STATISTICS == 0)) {
        c111stop
        c111readbanks
    }
    if (C111_STATISTICS) {
        local C111_STT[]
        if (esrf_io(C111_DEV,"DevC111GetStatistics",C111_STT) < 0) {
            printf("Error reading C111 statistics\n")
        } else {
            if(cnt_num("anode") != -1) S[cnt_num("anode")] = C111_STT[6] 
            if(cnt_num("x1") != -1) S[cnt_num("x1")] = C111_STT[1] 
            if(cnt_num("x2") != -1) S[cnt_num("x2")] = C111_STT[2]
            if(cnt_num("rejev") != -1) S[cnt_num("rejev")] = C111_STT[7] 
            if(cnt_num("aluov") != -1) S[cnt_num("aluov")] = C111_STT[8] 
        }
        if (chk_count==0) {
            c111stop 
            c111readbanks
            c111stattimer 0 10
        }
    }

    # --- update rois
    _c111_updaterois

    # --- update plot
    c111plot
}'

#------------- _c111_handlecounts -----------------------------------
#%IU%
#%MDESC%
#  Save data after counting.
#  Since called only after counting and NOT after counting in scan
#  test if (NPTS == _n1) was removed since makes no sense.
#
def _c111_handlecounts '{
    if (chk_count == 0 && C111_SAVE) {
	c111save
    }
}'



#------------- _c111_scan_loop ------------------------------------
#%IU%
#%MDESC%
#  Adds C111 data to scan file
#
def _c111_scan_loop '{
    local npts cmin cmax meltime
    c111_user_prescan_loop
    npts = C111_SAVEMAX - C111_SAVEMIN + 1
    #if (savemcadata(DATAFILE,C111_DATA,C111_NBCOLS,"%16C")<0) {
    if (C111_SAVESPECTRUM) {
        if (C111_SAVEINPRIVATE == 0) { 
            if(savemcadata(DATAFILE,C111_DATA[C111_SAVEMIN:C111_SAVEMAX],npts,"%16C")<0) {
                printf("Failed to wrote c111 data in %s\n", DATAFILE)
                #exit
            }
        } else {
            filename = sprintf("%s/%s_%.3d_%.3d",C111_DATA_DIR,C111_FILE_PREFIX, SCAN_N, NPTS) 
            FPRNT=""

            # newly added part (23.Aug.2005)
            for (i=0;i<_nm;i++) {
        	 FPRNT=sprintf("%s%s  ",FPRNT,motor_name(_m[i]))
            }
            FPRNT=sprintf("%s%s  ",FPRNT,_hkl_sym1)

            open(filename)
            savefileheader(filename)
            #savestdheader1(filename, 3, 0)
            savestdheader1(filename, 3, SCAN_N-1)
            cmin = C111_SAVEMIN
            cmax = C111_SAVEMAX
            meltime = COUNT_TIME
            if (savemcaheader(filename,"%16C",npts,cmin,cmax,0,0,meltime,meltime)<0) {
               printf("Error saving mca header in file %s\n", filename)
            }
            # save the ROI header
	    _c111_savemcaroi(filename)
            
            savecntheader1(filename)
	    FPRNT=""
	    for (i=0;i<_nm;i++) {
                 FPRNT=sprintf("%s%.8g ",FPRNT,A[_m[i]])
            }
            FPRNT=sprintf("%s%s ",FPRNT,_hkl_val)
            savecounters1(filename)
	    if(savemcadata(filename,C111_DATA[C111_SAVEMIN:C111_SAVEMAX],npts,"%16C")<0) {
                printf("Failed to wrote c111 data in %s\n", filename)
            }
            close(filename) 
        }
    }
    c111_user_postscan_loop
}'

#%IU% (filename)
#%MDESC% Save C111 ROI header in specfile
#
def _c111_savemcaroi(filename) '{
    local roinb roi roinum roimne roimin roimax roiname
    roinb= list_n(C111_ROI)
    for (roi=1; roi<=roinb; roi++) {
	roimne= list_item(C111_ROI, roi)
	if ((roinum=cnt_num(roimne))!=-1) {
	    roimin= C111_ROI[roimne]["min"]
	    roimax= C111_ROI[roimne]["max"]
	    roiname=cnt_name(roinum)
	    if (savemcaroi(filename,roimin,roimax,roiname)<0) {
		printf("C111_ERROR: Failed to wrote roi header in %s\n", filename)
            }
	}
    }
}'




#------------- _c111_savehead -----------------------------------
#%IU%
#%MDESC%
#  Adds info on nb of channels read and elapsed time in scan header
#  Since in C111 server(driver) do not measure the acq. time take
#  the scan time per scan point.
#  TODO: See if instead of COUNT_TIME could also use _ctime
# 
def _c111_savehead '{
    local npts cmin cmax meltime
    local ret

    npts = C111_SAVEMAX - C111_SAVEMIN + 1
    cmin = C111_SAVEMIN
    cmax = C111_SAVEMAX
    meltime = COUNT_TIME 
    if (savemcaheader(DATAFILE,"%16C",npts,cmin,cmax,0,0,meltime,meltime)<0) {
        printf("Failed to wrote mca header in %s\n", DATAFILE)
    }

    # save then the ROI header
    _c111_savemcaroi(DATAFILE)
}'

#------------------------------------------------------------
# END of macros related to counting/scanning
#------------------------------------------------------------




#============================================================
#
# ROI related macros
#
# ==============================================================
#
#
#%IU%
#%MDESC%
#  Update counters with roi values
#
def _c111_updaterois '{
    local roinb roi roinum roimne roimin roimax
    roinb= list_n(C111_ROI)
    for (roi=1; roi<=roinb; roi++) {
        roimne= list_item(C111_ROI, roi)
        if ((roinum=cnt_num(roimne))!=-1) {
            roimin= C111_ROI[roimne]["min"]
            roimax= C111_ROI[roimne]["max"]
            S[roinum]= array_op("sum", C111_DATA[roimin:roimax])
        }
    }
}'

#-------------------------- _c111roiset -----------------------
#%IU% 
#%MDESC% 
#  Internal macro function to Setup(= Add or Modify) an ROI.
#
def _c111roiset(cmne,cmin,cmax) '{
    local roimin roimax
    roimin= cmin>=0?cmin:0
    roimax= (cmax<=C111_NBCOLS-1)?cmax:C111_NBCOLS-1
    if (list_check(C111_ROI, cmne)<=0) {
	list_add(C111_ROI, cmne)
    }
    C111_ROI[cmne]["min"]= roimin
    C111_ROI[cmne]["max"]= roimax
}'


#-------------------------- _c111roishow -----------------------
#%IU% ()
#%MDESC%
#  Internal macro function to show ROI(s) definitions.
#
def _c111roishow() '{
    local nroi nb roimne inconfig

    if ((nroi=list_n(C111_ROI))<0) list_init C111_ROI

    tty_cntl("ho"); tty_cntl("cd")
    tty_move(0,1,"\[md\]<C111 ROI Definition>\[me\]")
    tty_move(0,3,"Counter From   To     Configured")
    tty_move(0,4,"------- ------ ------ ----------")
    nb= 5
    for (roi=1; roi<=nroi; roi++) {
        tty_move(0,nb++, \
        sprintf("\[md\]%7s\[me\] %6d %6d        %s", \
                list_item(C111_ROI, roi), list_getpar(C111_ROI, roi, "min"), \
                list_getpar(C111_ROI, roi, "max"), \
                (cnt_num(C111_ROI[roi])==-1)?" No":"Yes"))
    }
    nb++
    return (nb)
}'


#-------------------------- c111roishow -----------------------
#%UU%
#%MDESC% 
#  Macro to Show the ROI definitions.
#
def c111roishow '_c111roishow()'


#-------------------------- c111roi -----------------------
#%UU%
#%MDESC%
#  Macro to Add/Remove/Modify ROIs used to get integral count
#  for each of them. ROI index goes from 1 to 8.
#
def c111roi '{
    if (list_n(C111_ROI)<0) list_init C111_ROI

    if ($#==0)	{
	c111roimenu
    }
    else if ($#==3) {
	_c111roiset("$1",$2,$3)
    }
    else {
	print "USAGE: c111roi <mnemonic> <chan_min> <chan_max>"
	print "    or c111roi without arguments for interactive menu"
    }
}'


#-------------------------- c111roimenu -----------------------
#%UU%
#%MDESC%
#  Macro to Interactively Add/Remove/Modify ROI(s) to get integral 
#  of counts for channels within ROI.
#
def c111roimenu '{
    local key cmne cmin cmax nb

    while (1) {
        nb= _c111roishow()
	tty_move(0,nb++, \
		"\[md\]A\[se\]dd/\[md\]R\[se\]emove/\[md\]M\[se\]odify or \[md\]Q\[se\]uit ? ")
	while ((key=input(-1))=="") {}
	key=substr(key,1,1)
	printf("\n\n")
	if (key=="q"||key=="Q") break
	else if (key=="r"||key=="R") {
	    cmne= getval("Counter mnemonic",0)
	    if (cmne!="0") {
		list_remove(C111_ROI, cmne)
	    }
	}
	else if (key=="a"||key=="A") {
	    cmne= getval("Counter mnemonic",0)
	    if (cmne!="0") {
		cmin= getval("First channel ", 0)
		cmax= getval("Last channel  ", C111_NBCOLS-1)
	    }
	    _c111roiset(cmne, cmin, cmax)
	}
	else if (key=="m"||key=="M") {
	    cmne= getval("Counter mnemonic",0)
	    if (list_check(C111_ROI, cmne)>0) {
		cmin= getval("First channel ", C111_ROI[cmne]["min"])
		cmax= getval("Last channel  ", C111_ROI[cmne]["max"])
		_c111roiset(cmne, cmin, cmax)
	    }
	}
    }
}'


#-------------------------- c111roiclear -----------------------
#%UU%
#%MDESC% 
#  Macro to Clear the ROI counters.
#
def c111roiclear '{
    local nb roi roinum

    nb= list_n(C111_ROI)
    for (roi=1; roi<=nb; roi++) {
        roinum= cnt_num(list_item(C111_ROI, roi))
        if (roinum!=-1) {
            S[roinum]= 0
        }
    }
}'

#------------------------------------------------------------
# END of ROI related macros 
#------------------------------------------------------------




# ==============================================================
#
# Plotting related macros
#
# ==============================================================
#
def c111plotunit '{
    if (!$#) {
        print "Usage: $0 <plot_filter_number>"
    }
    else {
        C111_PLOTUNIT= int($1)<2?2:int($1)
    }
}'
#
#-------------------------- _c111splot -----------------------
#%IU%
#%MDESC%
#  Internal macro to create plot and display 1D C111 spectrum using
#  standard SPEC plotting with linear/log Y scale.
#  - abscissa array = coloumns array = C111_XDATA
#  - ordinate array = 1D C111 data = C111_DATA
#  The range of C111 channels to be plotted is between minimum and 
#  maximum which are passed as parameters along with macro name:
#  _c111splot <xmin> <xmax>
#
def _c111splot '{
    local pmin pmax
    local res1 res2

    pmin= $1
    pmax= $2 - 1

    plot_cntl(sprintf("filter%d", C111_PLOTUNIT))

    if (PLOT_MODE&128) {
        plot_cntl(sprintf("colors=%s",splot_col))
        plot_cntl("open")
        plot_cntl("-ylog +lines -dots -ebars")
    }

    plot_cntl("erase")
    plot_move(0,0,"C111 ACQ SPECTRUM")
    plot_move(0,1, sprintf("Scan %d", SCAN_N))
    plot_move(0,2,"Counts")
    plot_move(0,-1,"Channels")

    plot_range(pmin,pmax,array_op("min", C111_DATA[pmin:pmax]),array_op("max",C111_DATA[pmin:pmax]))

    plot_cntl("mca")
    if (C111_PLOTLOG) plot_cntl("+ylog")
    array_plot(C111_XDATA[pmin:pmax], C111_DATA[pmin:pmax])

#
# next 2 (res1, res2) are optional
#
    res1 = sprintf("Peak at %.5g is %.5g.  COM at %.5g.   ", \
        array_op("row_at_max", C111_DATA[pmin:pmax]), \
        array_op("max", C111_DATA[pmin:pmax]), \
        array_op("com", C111_XDATA[pmin:pmax], C111_DATA[pmin:pmax]))
    res2= sprintf("FWHM is %.5g at %.5g.  Total counts are %g", \
        array_op("fwhm", C111_XDATA[pmin:pmax], C111_DATA[pmin:pmax]), \
        array_op("cfwhm", C111_XDATA[pmin:pmax], C111_DATA[pmin:pmax]), \
        array_op("sum", C111_DATA[pmin:pmax]))
    plot_move(-50,0,res1)
    plot_move(-50,1,res2)

    plot_cntl("filter1")
}'

#-------------------------- c111plot -----------------------
#%UU%
#%MDESC%
#  Macro that wraps _c111splotlin and which is to be used without parameters
#  i.e. it creates a plot covering channels between C111_PLOTMIN and 
#  C111_PLOTMAX. So by default the plot is done with linear Y scale.
#
def c111plot '{
	if ($#==2) {
		_c111splot $1 $2
	} else {
		_c111splot C111_PLOTMIN C111_PLOTMAX
	}
}'


#-------------------------- c111tolin -----------------------
#%UU%
#%MDESC%
# Macro to set plot in linear Y-scale.
#
def c111tolin '{
   C111_PLOTLOG= 0
}'


#-------------------------- c111tolog -----------------------
#%UU%
#%MDESC%
#  Macro to set plot in logarithmic Y-scale.
#
def c111tolog '{
   C111_PLOTLOG= 1
}'


#-------------------------- c111splotrange -----------------------
#%UU%
#%MDESC%
#  Macro that allows to change limit channels for plotting if new 
#  limits are passed as input parameters. 
#  c111splotrange <xmin> <xmax>
#  If no parameters passed then C111_PLOTMIN = 0           and 
#                               C111_PLOTMAX = C111_NBCOLS-1
#
def c111plotrange 'c111splotrange'
def c111splotrange '{
    if ($#==2) {
        C111_PLOTMIN= int($1)
        C111_PLOTMAX= int($2)
        if (C111_PLOTMIN<0||C111_PLOTMIN>=C111_NBCOLS-1) C111_PLOTMIN= 0
        if (C111_PLOTMAX<0||C111_PLOTMAX>=C111_NBCOLS-1) C111_PLOTMAX= C111_NBCOLS-1
    } else {
        print "Usage: $0 <min> <max>"
        C111_PLOTMIN= 0
        C111_PLOTMAX= C111_NBCOLS-1
    }
    printf("C111 Plot Range is now: %d - %d\n", C111_PLOTMIN, C111_PLOTMAX)
}'

def c111plotmenu '{
	printf("\n\nC111 Plotting options:\n")
    C111_PLOTLOG= yesno ("Plot in log Y-scale ", C111_PLOTLOG)
	C111_PLOTMIN= getval("Plot minimum channel", C111_PLOTMIN)
	C111_PLOTMAX= getval("Plot maximum channel", C111_PLOTMAX)
}'

#------------------------------------------------------------
# END of Plotting related macros 
#------------------------------------------------------------
#

#
# Some auxiliary macros
#
def c111forever '{
    for (;;) {
        ct 1
    }
}'


def c111getbank '{
    if (_c111_getstatus()) {
        printf(" %d\n",C111_ACQ_BANK)   
    }
}'


# to investigate problem with bank contents
def c111invest '{
    local acqtime pollper 
    if ($# == 1) acqtime = $1
    else         acqtime = 1 
    pollper = acqtime/5

    for (;;) {
        c111getbank
        c111initbanks 0 0
        c111getbank
        c111start acqtime 
        c111poll pollper 0
        c111readbanks
        c111data
        c111swapbanks
    }
}'




# savecntheader1() function which is to be used in _c111_scan_loop
# and c111save instead of savecntheader() from ID01mca.mac, since the latter
# makes a test: if cnt_name(i) != "unused", which has not wanted effect since
# cnt_name(i) is retured for used and unused counters and so by this criteria
# cannot distinguish used and unused counters.
# Therefore here below we rather use function is_using_counter(i)
# and so in the file (one per scan point, written by _c111_scan_loop) 
# or the one after ct dT or c111acq dT (written by c111save) we save only
# counters that are used.

def savecntheader1(file) '{

local i j g

if (file!="") {
  if (open(file)) return -1
  on (file); offt
  Fheader

  g = _ctime < 0? sec:MON

  # filter info is saved ONLY for ID01 and only in private file
  # (one per scan point) or the one written after ct dT or c111acq dT
  # and not into std spec scan file (DATAFILE)
  if (SPECBL == "ID01") {
    fprintf(file,"#UFILTER_ATTN %g (%s)\n", FILTER_ATTN,FILTER_LOG)
  }

  for (i=j=0;i<COUNTERS;i++) if (i!=g && i!=DET && is_using_counter(i)) j++

  # found that in SPEC scan files in the macro _head (which comes from 
  # standard.mac), the #N was 1 more and correct in DATAFILE (= SPEC std
  # scan file) and not in file into which this macro writes. Therefore 
  # here below _cols is set to 1 before fprintf and then reset to 0
  # (it is reset to 0 also in macro _head)
  #_cols = 0
  _cols = 1
  fprintf(file,"#N %d\n", _cols + (MON<0? 2:3) + j)
  _cols = 0


  # in order that the first thing in line starting with #L is Epoch 
  # when this macro is used in c111save [i.e. = OUTSIDE scan (= when do
  # c111acq dT or ct dT)] FPRNT must be set to empty string, but I 
  # commented next modifications since PB wants the same text (i.e. motor
  # name of the motor used for the last scan + H K L) as in scan-files
  # So the same lines for FPRNT appear in c111save as Armando put them
  # in _c111_scan_loop before call to savecntheader1.
  ##if (_n1 == NPTS) {
  ##  FPRNT=""
  ##}

  fprintf(file,"#L %s%sEpoch",FPRNT,Flabel)

  for (i=0;i<COUNTERS;i++) if (i!=g && i!=DET && is_using_counter(i)==1) \
    fprintf(file,"  %s",cnt_name(i))

  if (g >= 0) fprintf(file,"  %s",cnt_name(g))
  fprintf(file,"  %s\n",cnt_name(DET))
  off (file); ont
}
return 0
}'


# savecounters1() function which is to be used in _c111_scan_loop
# and c111save instead of savecounters() from saveload.mac, since the latter 
# makes a test: if cnt_name(i) .ne. unused, which has not wanted effect since
# cnt_name(i) is retured for used and unused counters and so by this criteria
# cannot distinguish used and unused counters.
# Therefore here below we rather use function is_using_counter(i)
# and so in the file (one per scan point, written by _c111_scan_loop) 
# or the one after ct dT or c111acq dT (written by c111save) we save only
# counters that are used.

def savecounters1(file) '{
if (file!="") {

  local z

  if (open(file)) return -1

  # in order that the first thing in the line displaying counter
  # values when this macro is used in c111save [i.e. = OUTSIDE scan (= when do
  # c111acq dT or ct dT)] is value of Epoch counter, FPRNT must be set to 
  # empty string, but I commented next modifications since PB wants the same
  # text (i.e. motor position of the motor used for the last scan + H K L 
  # values) as in scan-files.
  # So the same lines for FPRNT appear in c111save as Armando put them
  # in _c111_scan_loop before call to savecounters1.
  ##if (_n1 == NPTS) {
  ##  FPRNT=""
  ##}
  fprintf(file,"%s%s%d",FPRNT,Fout,time()-EPOCH)

  z = _ctime < 0? sec:MON

  for (i=0;i<COUNTERS;i++)
    if (i != z && i != DET && is_using_counter(i) == 1)
      fprintf(file," %g",S[i])
  if (z >= 0) fprintf(file," %g",S[z])
  fprintf(file," %g\n",S[DET]);
}
return 0
}'


def _mo_loop1 '{
        local s
        for (j = i, s = ""; j < i + 8 && j < k; j++) {
                s = s sprintf("%$1", $2)
                if (j < i + 7) s = s " "
        }
        print s
}'


def savestdheader1(file,flag,lastindex) '{
if (open(file)) return (-(lastindex+1))
if (file!="") {

  fprintf(file,"\n#S %d  %s\n#D %s\n",++lastindex,HEADING,DATE)

  if (flag&1) {
    if (COUNT_TIME<0) fprintf(file,"#M %g  (%s)\n", -COUNT_TIME,cnt_name(MON))
    else fprintf(file,"#T %g  (%s)\n", COUNT_TIME,cnt_name(sec))
  }

  if (!(flag&4)) {
    on(file); offt; _head_par G 0; _head_par U 1; _head_par M 2; ont; off(file)
  }

  if (flag&2) {
    local i j k
    fprintf(file,"#Q %s\n", _hkl_val)
    for (i = 0, k = MOTORS; i < k; i += 8) {
      fprintf(file,"#P%d ", i/8)
      on(file) ; offt; _mo_loop1 .8g "A[mA[j]]" ; ont; off(file)
    }
  }
} else lastindex++

return(lastindex)
}'




#%MACROS%
#%DEPENDENCIES%
#%PRE%
#
#  - The file %B%disable.mac%B% from STD ESRF spec macro set must be loaded, 
#    if want to mark counters to be enabled/disabled with function:
#    disable_counter(ctn_mne(i), s), where if s = 0 counter is enabled and
#                                          if s = 1 counter is disabled.
#
#    Alternative to using the macros from file disable.mac is the following:
#    Counter can be disabled also by:
#        counter_par(ctn_mne(i),"disable",1) 
#    and can be enabled by:
#        counter_par(ctn_mne(i),"disable",0)
#
#    The enable/disable state can be examined with:
#        p counter_par(ctn_mne(i), "disabled")
#    or with:
#        p is_using_counter(ctn_mne(i))
#
#    Macros from this macro set (= this file) do not use anywhere calls to
#    macro functions from disable.mac.
#
#
#  - The file %B%saveload.mac%B% from STD ESRF spec macro set must be loaded
#    BEFORE this macro file, because certain nb of macro functions are used 
#    from it like savefileheader() etc.
#
#    Instead of macro functions savecntheader() and savecounters() from
#    saveload.mac we use macro functions savecntheader1() and savecounters1()
#    from this macro file.
#    The reason for doing it is that in macros from saveload.mac test:
#         cnt_name(i)!="unused"   
#    is used instead of: 
#         is_using_counter(cnt_mne(i)) == 1
#    The test cnt_name()!="unused" is unfortunately not distinguishing 
#    between enabled/disabled counters!!!  
#
#
#  - The file ID01mca.mac does not need any more to be loaded, since 
#    its savecntheader is now replaced by savecntheader1() from this 
#    macro file and which uses is_using_counter() == 1 in tests and which
#    for ID01 (SPECBL == "ID01") writes Filter info in file.
#
#%PRE%