esrf

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

#%TITLE% I0_cub.mac
#%NAME% I0 board control
#%DESCRIPTION% Control of I0 boards for acquisition.
#%BR%In the spec setup, the user should define:
#%UL%
#%LI%- I0_setup <device0> <virtex0> <spartanlist0> <device1> <virtex1> ...
#%BR% which defines the devices, virtex files and spartan list file.
#%LI%- The definition of harmonics that the user wants by
#board/mezzanin/channel.
#%BR%- I0harminit <board[0..]> <mezz [1,2]> <ch[1,2,3,4]> <harm1> <harm2> ..
#%BR%- I0harmadd <board[0..]> <mezz [1,2]> <ch[1,2,3,4]> <harm1> <harm2> ..
#%BR%- ...
#%BR% note that I0harminit cleans all the already defined
#harmonics before starting a new definition, while I0harmadd add a new one.
#%XUL%
#%BR%*****************************************
#%BR%The I0 boards may have 1 or 2 mezzanines. 
#%BR%board numbers: [0..n]
#%BR%mezzanin: [1,2]
#%BR%channels: [1,2,3,4]
#%BR%*****************************************
#%BR%#We apply the following conventions for all the boards:
#%BR%
#%BR%- if 2 mezzanins, always mezzanin 1 will be the master
#and mezzanin 2 will be the slave
#%BR%- timer bit is disabled (stop acquisition done by a software stop
#and the data are normalized with the real acquisition time).
#%BR%- modes for acquisition: there are 3 modes:
#%BR%-- softare mode: each board is started independently
#%BR%-- hardware mode: a board is defined by the user as master trig board
#and is supposed to be daisy chained to all the other to transmit the start
#of acquisition. master trig board is started by soft.
#%BR%-- hardware external mode: same as previous but the master trig board is 
#started by a hardware external signal.
#%BR%*** Modifications:
#%BR%- division of tablu by tim if not timer mode
#%BR%- now use I0tablutoch to work with I0_ch[] instead of tablu[][]
#%BR%- checking of board, mezzanin, channel parameters implemented
#%BR%- I0_dac, I0_savedac, I0_getdac
#%BR%- I0Rout and I0tablutoc(), do not recalculate I0_xch .... arrays
#%BR%- I0_gethwinfo
#%BR%- I0_sethwchan
#%BR%- remove debug print
#%BR%- clean I0_ch[][] before tablutoch
#%END%

long array I0_acqen[2]
long array I0_timer[2]
long array I0_trig_hs[2]
long array I0_trig_master[2]
long array I0_tim_reg[2]
long array I0_acq_tim_reg[2]
long array I0_chan_en[2][4]
long array I0_dac_en[2][4]
global I0ON
global ESRF_ERR

#===============================================================
# I0_setup
#===============================================================
#%UU% <device> <virtex> <spartanlist>
#%MDESC%list of I0 devices. The .bit files are supposed to be under
#/users/blissadm/local/spec/userconf/CUB/I0/BIT 
def I0_setup'{
   global I0_ARR I0_NBDEV
   global I0_HARM I0_DAC
   
   local ii myarr nn jj 

   if($#){
      nn = split("$*",myarr)
      I0_NBDEV = int(nn/3)
      if ( (I0_NBDEV*3) != nn) {
         p "usage: I0_setup <device0> <virtex0> <spartanlist0> <device1> ..."
         exit
      }
      jj = 0
      for (ii=0; ii<I0_NBDEV; ii++) {
          I0_ARR[ii]["dev"] = myarr[jj]
          jj++
          I0_ARR[ii]["virtex"] = sprintf("/users/blissadm/local/spec/userconf/CUB/I0/BIT/%s",myarr[jj])
          jj++
          I0_ARR[ii]["spartan"] = sprintf("/users/blissadm/local/spec/userconf/CUB/I0/BIT/%s",myarr[jj])
          jj++
      }
   }
   else {
      p "usage: I0_setup <device0> <virtex0> <spartanlist0> <device1> ..."
      exit
   } 
   
}'

#===============================================================
# I0_load_virtex_spartan
#===============================================================
#%UU% 
#%MDESC%- loads virtex and spartan on the list of I0_setup
#%BR%the path to these files is:
#%BR%/users/blissadm/local/spec/userconf/CUB/XDS/BIT.
#%BR%- retrieves some hardware info
def  I0_load_virtex_spartan'{
   local ii
   
   for (ii=0; ii<I0_NBDEV; ii++) {
      _I0_LoadVirtex  ii I0_ARR[ii]["virtex"]
   }
   for (ii=0; ii<I0_NBDEV; ii++) {
      _I0_LoadSpartanList  ii I0_ARR[ii]["spartan"]
   }

   _I0_preparearray  
   
   I0setdim  

#  retrieves some info from hardware   
   I0_gethwinfo    

#  ask user for potential channels
   I0_sethwchan
}'


#===============================================================
# _I0_LoadVirtex
#===============================================================
#%IU% <board> <bit file>
#%MDESC% loads virtex. A timeout of 40 sec is set for the load
#on the device

def _I0_LoadVirtex '{
   local bitFile myboard
   
   if ($# != 2) { 
   
      p "usage: _I0_LoadVirtex <board> <bit file>"
          exit
   }
   bitFile = $2
   myboard = I0_ARR[$1]["dev"]

   printf("--- _I0_LoadVirtex: [%s]\n", bitFile);
   esrf_io(myboard,"timeout",40)
   ESRF_ERR = -1
   ESRF_ERR = esrf_io(myboard,"DevLoadVirtex",bitFile)
   if (ESRF_ERR) {
      p "_I0_LoadVirtex Failed for board " $1 
      p "exit"
      exit
   } 
   esrf_io(myboard,"timeout",0)

}'



#===============================================================
# _I0_LoadSpartanList
#===============================================================
#%IU% <board> <bit file>
#%MDESC% loads list of spartan. A timeout of 40 sec is set for the load
#on the device 
def _I0_LoadSpartanList '{
   local bitFileList myboard
   
   if ($# != 2) { 
   
      p "usage: _I0_LoadSpartanList <board> <bit file>"
          exit
   }
   bitFileList = $2
   myboard = I0_ARR[$1]["dev"]

   printf("--- _I0_LoadSpartanList: [%s]\n", bitFileList);
   esrf_io(myboard,"timeout",40)
   ESRF_ERR = -1
   ESRF_ERR = esrf_io(myboard,"DevLoadSpartanList",bitFileList)
   if (ESRF_ERR) {
      p "_I0_LoadSpartanList Failed for board " $1 
      p "exit"
      exit
   } 
   esrf_io(myboard,"timeout",0)

}'

#===============================================================
# I0harminit
#===============================================================
#%UU%<board[0..]> <mezz[1,2]> <ch[1,2,3,4]> <harm1> <harm2> ...
#%MDESC%cleans all the already defined harmonics and defines 
#the harmonics for a board/mezz/channel.
def I0harminit'{
   unglobal I0_HARM
   
   I0harmadd $*
        
}'

#===============================================================
# I0harmadd
#===============================================================
#%UU%<board[0..]> <mezz[1,2]> <ch[1,2,3,4]> <harm1> <harm2> ...
#%MDESC%defines the harmonics for a board/mezz/channel.
def I0harmadd'{
   local mynb hararr jj myb mymez mych ind harmind
   global I0_HARM
   
   mynb = split("$*",hararr)
   
   if (mynb <4) {
      p "usage: I0harminit <board[0..]> <mezz[1,2]> <ch[1,2,3,4]> <harm1> <harm2> ..."
      exit
   }
   myb = $1
   mymez = $2
   mych = $3
   if ( !_i0_check_board(myb) || !_i0_check_mezz(mymez) || !_i0_check_ch(mych) ){
      exit
   }
   
   harmind = myb*100 + mymez*10 + mych
   ind = 0
   I0_HARM[harmind]["nb"] = mynb-3
   for (jj = 3; jj<mynb; jj++) {
      I0_HARM[harmind][ind] = hararr[jj]
      ind++
   }
        
}'


#===============================================================
# _I0_checkifset
#===============================================================
#%IU%
#%MDESC% checks if I0_ARR global associative array has
#been already set
def _I0_checkifset'{
  if((whatis("I0_ARR") & 0x08000000)) {
     p "ERROR: I0_setup must be called first"
     exit
  }
}'


#===============================================================
# _I0_preparearray
#===============================================================
#%IU%
#%MDESC%prepare the I0_ARR array with some information.
#%BR%Should be called inside I0_setup. 
#%BR%- reads if mezzanine 2 is present
#%BR%If following not already set decide that:
#%BR%- all boards are in use (can be changed with I0_enable, I0_disable)
#%BR%- work in software mode (can be changed with I0_setmodehard, setmodehardext,
#setmodesoft)
#%BR%- enable only channel4 on each mezzanine
#%BR%for all, mezzanine 1 is master and mezzanine 2 is slave (cannot be changed)
def _I0_preparearray'{
   local ii mystr mm mystr

#  set information on mezzanine 2    
   for (ii=0; ii<I0_NBDEV; ii++) {
      if (_I0h_ismez2(ii)) {
         I0_ARR[ii]["mezz2"] = 1
      }
      else {
         I0_ARR[ii]["mezz2"] = 0
      }
   }

#  to start with some default values if not already set
#  both mezzanines are set, even if mezzanine 2 not present
#  I0_ARR[ii]["mezz2"] will say if we use info of mezzanine 2. 

#  decide master trig board is the first
   if ( whatis("I0_ARR[\"master_trig\"]") == 0) {   
      I0_ARR["master_trig"] = 0
   }
#  decide mode software
   myname = I0_ARR["mode"]
   if (whatis("I0_ARR[\"mode\"]") == 0) {   
      I0_ARR["mode"] = 0
   }
   for (ii=0; ii<I0_NBDEV; ii++) {
#     decide that everybody is valid
      mystr = sprintf("I0_ARR[%d][\"used\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["used"] = 1 
      }
#     decide that work in software mode
      mystr = sprintf("I0_ARR[%dd][\"hwbit_mezz1\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["hwbit_mezz1"] = 0 
      }
      mystr = sprintf("I0_ARR[%d][\"hwbit_mezz2\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["hwbit_mezz2"] = 0 
      }
#     decide that timer is disable
      mystr = sprintf("I0_ARR[%d][\"timerbit_mezz1\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["timerbit_mezz1"] = 0 
      }
      mystr = sprintf("I0_ARR[%d][\"timerbit_mezz2\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["timerbit_mezz2"] = 0 
      }
#     decide that mezzanine 1 is master and 2 is slave  
      mystr = sprintf("I0_ARR[%d][\"masterbit_mezz1\"]",ii)   
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["masterbit_mezz1"] = 1 
      }
      mystr = sprintf("I0_ARR[%d][\"masterbit_mezz2\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["masterbit_mezz2"] = 0 
      }
#     decide use only channel 4 on mezzanin 1
#     work on mezzanin 1
      mystr = sprintf("I0_ARR[%d][\"ch11\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["ch11"] = 0 
      }
      mystr = sprintf("I0_ARR[%d][\"ch12\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["ch12"] = 0 
      }
      mystr = sprintf("I0_ARR[%d][\"ch13\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["ch13"] = 0 
      }
      mystr = sprintf("I0_ARR[%d][\"ch14\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["ch14"] = 1 
      }
#     work on mezzanin 2
      mystr = sprintf("I0_ARR[%d][\"ch21\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["ch21"] = 0 
      }
      mystr = sprintf("I0_ARR[%d][\"ch22\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["ch22"] = 0 
      }
      mystr = sprintf("I0_ARR[%d][\"ch23\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["ch23"] = 0 
      }
      mystr = sprintf("I0_ARR[%d][\"ch24\"]",ii)
      if (whatis(mystr) == 0) {
        I0_ARR[ii]["ch24"] = 0 
      }
            
   }
   
}'

#===============================================================
# I0_showconf
#===============================================================
#%UU%
#%MDESC% Shows the I0_ARR definitions
def I0_showconf'{
   local ii inf jj 

   p "---------------------------------------- "   
   p "Your I0 present configuration is:"
   p " "
   p "   * I0 boards (not use: 0, in use: 1) are:"
   for (ii=0; ii<I0_NBDEV; ii++) {
      inf = I0_ARR[ii]["used"] 
      if (inf == 1) {
         inf = I0_ARR[ii]["mezz2"] 
         p " "
         p "     board " ii ": used with " inf+1 " mezzanines" 
         for (jj=0; jj<4; jj++) {
            inf = I0_ARR[ii][sprintf("ch%d",jj+11)] 
            p "       mezz1: channel" jj+1 ": " inf
         }
         if (I0_ARR[ii]["mezz2"] ==1 ) {
            for (jj=0; jj<4; jj++) {
               inf = I0_ARR[ii][sprintf("ch%d",jj+21)] 
               p "       mezz2: channel" jj+1 ": " inf
            }
         }
      }
      else {
         p " "
         p "     board " ii ": not used"
      }
   }

   p " "
   p "   * Working in: "
   inf = I0_ARR["mode"]
   if (inf == 0) {
      p "       software mode"  
   } 
   else if (inf == 1) {
      p "       hardware mode"  
   } 
   else if (inf == 2) {
      p "       external hardware mode"  
   } 
   else {
      p "       UNKNOWN MODE !!!!"  
   }

   inf = I0_ARR["master_trig"]
   p " "
   p "   * Master trig board is : " inf
   
   p "---------------------------------------- "  
   
    
}'

#===============================================================
# I0_askforconf
#===============================================================
#%UU% 
#%MDESC%Proposes to change some parameters of the global I0 boards
#configuration.
def I0_askforconf'{
   local ii inf rep jj

#  Change boards in use?
   rep = 0
   rep = getval("Do you want to change the boards or channels in use(0:no, 1:yes)?",rep)
   if (rep == 1){
      for (ii=0; ii<I0_NBDEV; ii++) {
         rep = I0_ARR[ii]["used"]  
         p " "
         rep = getval(sprintf("use board %d (0:no 1:yes)?",ii),rep)
         if (rep == 1) {
            I0_enable ii
#           for mezzanin 1            
            for (jj =0; jj<4; jj++) {
               rep = I0_ARR[ii][sprintf("ch%d",jj+11)]
               rep = getval(sprintf("   mezz1: use channel %d (0:no, 1: yes)?",jj+1),rep)
               if (rep == 1){
                  I0_enable_ch ii 1 jj+1
               }
               else {
                  I0_disable_ch ii 1 jj+1
               }
            }
            if (I0_ARR[ii]["mezz2"] == 1) {
#           for mezzanin 2 
               for (jj =0; jj<4; jj++) {
                  rep = I0_ARR[ii][sprintf("ch%d",jj+21)]
                  rep = getval(sprintf("   mezz2: use channel %d (0:no, 1: yes)?",jj+1),rep)
                  if (rep == 1){
                     I0_enable_ch ii 2 jj+1
                  }
                  else {
                     I0_disable_ch ii 2 jj+1
                  }
               }
            }
         }
         else {
            I0_disable ii
         }
      }
   }

#  Changing the mode ?   
   rep = 0
   p " "
   rep = getval("do you want to change the mode (0:no, 1:yes)",rep)
   if (rep == 1) {
      rep = I0_ARR["mode"]
      rep = getval("which mode (0:soft, 1:hard, 2:external hard)?",rep)
      if (rep == 0) {
         I0_setmodesoft   
      } 
      else  if (rep == 1) {
         I0_setmodehard   
      }
      else if (rep == 2) {
         I0_setmodehardext 
      } 
   }

#  Changing the master trig board ? 
#  master trig board is meaningful only if hardware or external hardware mode
   if (I0_ARR["mode"] != 0) {  
      rep = 0
      p " "
      rep = getval("do you want to change the master trig board (0:no, 1:yes)",rep)
      if (rep == 1) {
         rep = I0_ARR["master_trig"]
         rep = getval(sprintf("which board among the used ones [0..%d]?",I0_NBDEV-1),rep)
         I0_setmastertrig rep
      }
   }

#  check in any case that master trig board is correct
   if ( ( (I0_ARR["mode"] == 1) || (I0_ARR["mode"] == 2)) && \
        (I0_ARR[I0_ARR["master_trig"]]["used"] == 0) ){
      p "YOUR MASTER TRIG BOARD IS NOT IN USE. YOU SHOULD DEFINE IT !!!"
      exit 
   }
         
}'
   
#===============================================================
# I0h_applyarray
#===============================================================
#%UU%
#%MDESC%applies the I0_ARR information on the boards in used
#%BR%- hw bit -
#%BR%- timer bit -
#%BR%- master/slave bit -
#%BR%- channels in use -
def I0h_applyarray'{
   local ii mystr mm

#  if mode hardware, need to check that master trig is is use !!!
   if ((I0_ARR["mode"] == 1) || (I0_ARR["mode"] == 2) ){
      if (I0_ARR[I0_ARR["master_trig"]]["used"] == 0) {
         mm = I0_ARR["master_trig"]
         p "master trig board " mm " not used !!!! exit"
         exit
      }
   }

#  now we can program the board
   for (ii=0; ii< I0_NBDEV; ii++) {
      if (I0_ARR[ii]["used"] == 1) {
#        harware bit
         I0h_selectmez(ii,1)
         _I0h_sethwbit ii 1 I0_ARR[ii]["hwbit_mezz1"]
         if (I0_ARR[ii]["mezz2"]) {
            I0h_selectmez(ii,2)
            _I0h_sethwbit ii 2 I0_ARR[ii]["hwbit_mezz2"]
         }
         
#        timer
         I0h_selectmez(ii,1)
         _I0h_settimerbit ii 1 I0_ARR[ii]["timerbit_mezz1"]
         if (I0_ARR[ii]["mezz2"]) {
            I0h_selectmez(ii,2)
            _I0h_settimerbit ii 2 I0_ARR[ii]["timerbit_mezz2"]
         }
         
#        master/slave
         I0h_selectmez(ii,1)
         _I0h_sethmasterbit ii 1 I0_ARR[ii]["masterbit_mezz1"]
         if (I0_ARR[ii]["mezz2"]) {
            I0h_selectmez(ii,2)
            _I0h_sethmasterbit ii 2 I0_ARR[ii]["masterbit_mezz2"]
         }
         
#        channels in use
         I0h_selectmez(ii,1)
         _I0h_setchannel ii I0_ARR[ii]["ch11"] I0_ARR[ii]["ch12"] I0_ARR[ii]["ch13"] I0_ARR[ii]["ch14"]
         if (I0_ARR[ii]["mezz2"]) {
            I0h_selectmez(ii,2)
            _I0h_setchannel ii I0_ARR[ii]["ch21"] I0_ARR[ii]["ch22"] I0_ARR[ii]["ch23"] I0_ARR[ii]["ch24"]
         }
      }
   }
}'

#===============================================================
# _I0_isused
#===============================================================
#%IU% (I0_index)
#%MDESC%returns 1 if used, 0 if not in use
def _I0_isused(n)'{
  
  _I0_checkifset
  
  return(I0_ARR[n]["used"])
}'

#===============================================================
# I0_enable
#===============================================================
#%UU% <I0_index>
#%MDESC%define a board as in use
def I0_enable'{

   if ( !_i0_check_board($1) ){
      exit
   }

   if ($# == 1){
      I0_ARR[$1]["used"] = 1
   }
}'

#===============================================================
# I0_disable
#===============================================================
#%UU% <I0_index>
#%MDESC%define a board as unused
def I0_disable'{

   if ( !_i0_check_board($1) ){
      exit
   }

   if ($# == 1){
      I0_ARR[$1]["used"] = 0
   }
   
}'

#===============================================================
# I0_enable_ch
#===============================================================
#%UU% <I0_index> <mezz 1:2> <ch1:4>
#%MDESC%enables channel for a board,mezzanin
#%BR%- I0_index: 0..
#%BR%- mezz: 1,2
#%BR%- ch: 1,2,3,4
def I0_enable_ch'{
   local mych mymez

   if ( !_i0_check_board($1) || !_i0_check_mezz($2) || !_i0_check_ch($3) ){
      exit
   }
   
   if ($# == 3){
      mych = $2*10+$3
      I0_ARR[$1][sprintf("ch%d",mych)] = 1
   }
}'

#===============================================================
# I0_disable_ch
#===============================================================
#%UU% <I0_index> <mezz 1:2> <ch1:4> 
#%MDESC%disable a channel for a board,mezza
#%BR%- I0_index: 0..
#%BR%- mezz: 1,2
#%BR%- ch: 1,2,3,4
def I0_disable_ch'{
   local mych

   if ( !_i0_check_board($1) || !_i0_check_mezz($2) || !_i0_check_ch($3) ){
      exit
   }
   
   if ($# == 3){
      mych = $2*10+$3
      I0_ARR[$1][sprintf("ch%d",mych)] = 0
   }
}'


#===============================================================
# I0h_selectmez
#===============================================================
#%UU%(<I0_index>, <mezz>)
#%MDESC%select mezzanine (val:1 or 2)
def I0h_selectmez(i0_i,mezz)'{
  local myp val dig myw 
	
   myp[0] = 2
   myp[1] = 4
        
  _I0_checkifset

   if ( !_i0_check_board(i0_i)  || !_i0_check_mezz(mezz)){
      exit
   }

  val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
  #p i0_i
  #p I0_ARR[i0_i]["dev"]
  if (I0DEB >0){ printf("csr=%08x \n", val)}
  dig = (val>>21) & 0x3
  dig = (mezz - 1) << 21
  myw[0] = 2
  myw[1] = 4
  myw[2] = (val & 0xFF9FFFFF) | (dig & 0x7FFFFF)
  if (I0DEB >0){printf("write%08x\n", myw[2])}
  
  esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",myw)
  val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
  dig = (val>>21) & 0x3
  if (I0DEB >0){ printf("PUDS#%d now addressed\n", dig + 1)}
}'


#===============================================================
# _I0h_ismez2
#===============================================================
#%IU% (<I0_index>)
#%MDESC%returns 1 if mezzanine 2 is present, 0 if not
def _I0h_ismez2(i0_i)'{
  local val myboard myp

   if ( !_i0_check_board(i0_i) ){
      exit
   }
  
  I0h_selectmez(i0_i,1)
  myp[0] = 2
  myp[1] = 4
  val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
  if ( (val>>15 & 0x01) == 0) {
     return(1)
  }
  else{
     return(0)
  }
}'

#===============================================================
# I0_setmodehard
#===============================================================
#%UU%
#%MDESC%Set mode hardware on all the I0 boards. They are supposed to 
#be hardware trigged (daisy chain) by the mezzanine 1 of the master trig I0 board.
#%BR%the mezzanine 1 of master trig board is supposed to be software started
#-hw bit- is set to 1 to everybody but the mezzanine 1 of the master trig board.
def I0_setmodehard'{
   local ii first

   first = 0   
   for (ii=0; ii<I0_NBDEV; ii++) {
      if ( ii == I0_ARR["master_trig"]){
         I0_ARR[ii]["hwbit_mezz1"] = 0 
         I0_ARR[ii]["hwbit_mezz2"] = 1 
      }
      else {
         I0_ARR[ii]["hwbit_mezz1"] = 1 
         I0_ARR[ii]["hwbit_mezz2"] = 1 
      }
  }
  I0_ARR["mode"] = 1
}'

#===============================================================
# I0_setmodehardext
#===============================================================
#%UU%
#%MDESC%Set mode hardware on all the I0 boards. They are supposed to 
#be hardware trigged (daisy chain) by the mezzanine 1 of the master trig board.
#-hw bit- will be set to 1 to every used board.
def I0_setmodehardext'{
   local ii 
   
   for (ii=0; ii<I0_NBDEV; ii++) {
        I0_ARR[ii]["hwbit_mezz1"] = 1 
        I0_ARR[ii]["hwbit_mezz2"] = 1 
   }
   I0_ARR["mode"] = 2
}'

#===============================================================
# I0_setmodesoft
#===============================================================
#%UU%
#%MDESC%Set mode sofware on the all the I0 boards:
#%BR%-hw bit- will be set to 0 for every used board.
def I0_setmodesoft'{
   local ii 
   
   for (ii=0; ii<I0_NBDEV; ii++) {
        I0_ARR[ii]["hwbit_mezz1"] = 0 
        I0_ARR[ii]["hwbit_mezz2"] = 0 
   }
   I0_ARR["mode"] = 0
}'

#===============================================================
# I0_setmastertrig
#===============================================================
#%UU% <I0_index>
#%MDESC%Redefines the master trig board.
def I0_setmastertrig'{
   local ii oldmaster myboard
   
   myboard = $1
   if (_I0_isused(myboard) == 0){
      p "this board is not in use. exit"
      exit
   }
      
   I0_ARR["master_trig"] = $1
   
#  need to redefine the mezzanines if mode hard with software trig 
#  of the master trig card
   if (I0_ARR["mode"] == 1) {
      I0_setmodehard   
   }
   
}'

#===============================================================
# I0_settimerbit
#===============================================================
#%UU% 0/1
#%MDESC%Redefines the timer bit for all the hardware
#%BR% 0: default value. acquired data will be divided by the time
#%BR% 1: no division in the data
def I0_settimerbit'{
   local ii val
   
   val = $1
   if ( (val != 0) && (val != 1) ){
      p "timerbit value must be 0 or 1"
      exit
   }
   
   for (ii=0; ii<I0_NBDEV; ii++) {
   {
#     timer
      I0_ARR[ii]["timerbit_mezz1"] = val
      I0h_selectmez(ii,1)
      _I0h_settimerbit ii I0_ARR[ii]["timerbit_mezz1"]
      if (I0_ARR[ii]["mezz2"]) {
         I0_ARR[ii]["timerbit_mezz2"] = val
         I0h_selectmez(ii,2)
         _I0h_settimerbit ii I0_ARR[ii]["timerbit_mezz2"]
      }
   }
   
}'

#===============================================================
# _I0h_sethwbit
#===============================================================
#%IU% <I0_index> <val:0,1>
#%MDESC%set hardware bit to <val> on the selected mezzanine
#%BR%do nothing if board not in used
def _I0h_sethwbit'{
   local myboard myval val myp

   if (I0DEB >0){ p "---> in _I0h_sethwbit"}
   myboard = $1
   myval = $3
   myp[0] = 2
   myp[1] = 4
   
   if ( !_i0_check_board($1) || !_i0_check_mezz($2) ){
      exit
   }
   
   if (_I0_isused(myboard)) {
      val = esrf_io(I0_ARR[myboard]["dev"],"DevReadReg32",myp)
      val = val & 0xFFFFFFFD
      myp[2] = val | myval

      esrf_io(I0_ARR[myboard]["dev"],"DevWriteReg32",myp)
   }      
}'


#===============================================================
# _I0h_settimerbit
#===============================================================
#%IU% <I0_index> <val:0,1>
#%MDESC%set timer bit to <val> on the selected mezzanine
#%BR%do nothing if board not in used
def _I0h_settimerbit'{
   local myboard myval val myp

   if (I0DEB >0){ p "---> in _I0h_settimerbit"}
   myboard = $1
   myval = $3
   myp[0] = 2
   myp[1] = 4

   if ( !_i0_check_board($1) || !_i0_check_mezz($2) ){
      exit
   }

   if (_I0_isused(myboard)) {
      val = esrf_io(I0_ARR[myboard]["dev"],"DevReadReg32",myp)
      val = val & 0xFFFFFFFB
      myp[2] = val | myval

      esrf_io(I0_ARR[myboard]["dev"],"DevWriteReg32",myp)
   }      
}'

#===============================================================
# _I0h_sethmasterbit
#===============================================================
#%IU% <I0_index> <val:0,1>
#%MDESC%set timer bit to <val> on the selected mezzanine
#%BR%do nothing if board not in used
def _I0h_sethmasterbit'{
   local myboard myval val myp myw

   if (I0DEB >0){ p "---> in _I0h_sethmasterbit"}
   myboard = $1
   myval = $3
   myp[0] = 2
   myp[1] = 4

   if ( !_i0_check_board($1) || !_i0_check_mezz($2) ){
      exit
   }

   if (_I0_isused(myboard)) {
      val = esrf_io(I0_ARR[myboard]["dev"],"DevReadReg32",myp)
      val = val & 0xFFFFFFF7
      myw[0] = 2
      myw[1] = 4
      myw[2] = val | myval

      esrf_io(I0_ARR[myboard]["dev"],"DevWriteReg32",myw)
   }      
}'

#===============================================================
# _I0h_setchannel
#===============================================================
#%IU% <I0_index> <ch1> <ch2> <ch3> <ch4>
#%MDESC%set channel on or off on an already selected mezzanine
#%BR%do nothing if board not in used
def _I0h_setchannel'{
   local myboard myval val myctrl myp myw

   if (I0DEB >0){ p "---> in _I0h_setchannel"}
   myboard = $1
   mych1 = $2
   mych2 = $3
   mych3 = $4
   mych4 = $5

   if ( !_i0_check_board($1) ){
      exit
   }

   if (_I0_isused(myboard)) {
#     myctrl = (mych1 << 3) | (mych2 << 2) | (mych3 << 1) | (mych4)
     myctrl = (mych3 << 3) | (mych2 << 2) | (mych1 << 1) | (mych4)
     myp[0] = 2
     myp[1] = 24
     val = esrf_io(I0_ARR[myboard]["dev"],"DevReadReg32",myp)
     val = val & 0xFFFFFFF0
     myw[0] = 2
     myw[1] = 24
     myw[2] = val | (~myctrl & 0xF)
     if (I0DEB >0){ printf("my=%02x,chan=%08x\n", ~myctrl & 0xF, myw[2])}
     esrf_io(I0_ARR[myboard]["dev"],"DevWriteReg32",myw)
   }  
   
       
}'



#===============================================================
# I0_setparam
#===============================================================
#%UU% <silent>
#%MDESC%Proposes to change some parameters of the global I0 boards
#configuration before applying it to the hardware
#%BR%if give one parameter to the macro, applies the I0_ARR conf
#without asking for confirmation
def I0_setparam'{

   if ($# == 0) {
      I0_showconf
      p " "

      I0_askforconf
   }
   
   p " "
   p "Applying I0_ARR parameters to the boards"
   I0h_applyarray
   
   p " "
   p "Getting some hardware information"
   #I0_getchinfo
   
   p " "
   p "Checking channel request with hardware version"
   I0_checkchinfo

}'


#===============================================================
# I0setdim
#===============================================================
def I0setdim '{
   
   global I0_ARR_DIM


   I0_ARR_DIM = 256

   shared float array I0_ch[5][I0_ARR_DIM]
   shared float array I0_fft[4][2*I0_ARR_DIM]
   shared float array essfft[2*I0_ARR_DIM]

   float array tablu[I0_NBDEV*2+1][I0_ARR_DIM]
   long array tablu_pudid[I0_NBDEV*2+1]
   long array tablu_xch[I0_NBDEV*2+1]
   long array tablu_bloc[I0_NBDEV*2+1]
   long array tablu_tim[I0_NBDEV*2+1]
#mcd: added to handle the dimension by channel
   long array tablu_chdim[I0_NBDEV*2+1]
   long array tablu_chen[I0_NBDEV*2+1][5]
   long array _myret[I0_NBDEV*2+1]
   	
}'

#===============================================================
# I0CsrR
#===============================================================
#%UU% <I0_index>
#%MDESC%read csr
def I0CsrR'{
   local myp val dig i0_i

   myp[0] = 2
   myp[1] = 4

   _I0_checkifset
   i0_i = $1
   if ( !_i0_check_board(i0_i) ){
      exit
   }
        
   val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
   printf("--- I0 CSR_reg is: [0x%08x]\n", val)
   dig = (val>>21) & 0x3
   printf("PUDS#%d currently addressed\n", dig + 1)
   dig = (val>>15) & 0x1
   printf(dig ? "\tNo other PUDS plugged\n" : "\tThere is another PUDS plugged\n")
   dig = (val>>13) & 0x1
   printf(dig ? "\tMain DLL LOCKED OK\n" : "\t!!!! Main DLL UNLOCKED!!!\n")
   dig = (val>>14) & 0x1
   printf(dig ? "\tInput DLL LOCKED OK\n" : "\t!!!! Input DLL UNLOCKED!!!\n")
}'

#===============================================================
# I0ChEn
#===============================================================
#%UU% <I0_index> <val>
#%MDESC%
# seg=2, add=18h
#MACRO: Enable channels for datacq
# val = 4 bits : channel 4 3 2 1, 1 for En, 0 for DIS
#%END%

def I0ChEn'{
   local myp i0_i

   _I0_checkifset
   i0_i = $1
   if ( !_i0_check_board(i0_i) ){
      exit
   }
   
   myp[0] = 2
   myp[1] = 0x18
   myp[2] = (0x$2 & 0xF) << 4

   if (I0DEB >0){ printf("--- writing: [0x%08x]\n", myp[2])}
   esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",myp)
}'

#===============================================================
# I0RegR
#===============================================================
#%UU% (board,mezz,regad)
#%MDESC%provide address and read any I0 register of an already selected mezzanine
#%END%
def I0RegR(bb, mez, adreg)'{
  local myp, val

   if ( !_i0_check_board(bb) ){
      exit
   }

   myp[0] = 2
   myp[1] = adreg

   I0h_selectmez(bb,mez)

   val = esrf_io(I0_ARR[bb]["dev"],"DevReadReg32",myp)
   printf("--- I0 reg%08x is: [0x%08x]\n", adreg, val)
}'

#===============================================================
# I0RegW
#===============================================================
#%UU% (board,mezz,regad,val)
#%MDESC%write the value <val32> in Register <adreg>  on board <bb> mezzanine <mez>
def I0RegW(bb, mez, adreg, val32)'{
     local mytw

   if ( !_i0_check_board(bb) ){
      exit
   }
   
     mytw[0] = 2
     mytw[1] = adreg
     mytw[2] = val32 


     I0h_selectmez(bb,mez)

     esrf_io(I0_ARR[bb]["dev"],"DevWriteReg32",mytw)
}'

#===============================================================
# I0LedR
#===============================================================
#%UU% <I0_index> 
#%MDESC%
# seg=2, add=20h=32d
#MACRO: read LED Register
#%END%

def I0LedR(brdindex)'{
  local myp val

   _I0_checkifset
   if ( !_i0_check_board(brdindex) ){
      exit
   }

   myp[0] = 2
   myp[1] = 32

   val = esrf_io(I0_ARR[brdindex]["dev"],"DevReadReg32",myp)
   printf("--- I0 LED_reg is: [0x%08x]\n", val)
   return(val)
}'

#===============================================================
# I0ChR
#===============================================================
#%UU% (<I0_index>) 
#%MDESC%
# seg=2, add=18h
#MACRO: read LED Register
#%END%

def I0ChR(i0_i)'{
  local myp val

   _I0_checkifset
   if ( !_i0_check_board(i0_i) ){
      exit
   }

   myp[0] = 2
   myp[1] = 0x18

   val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
   printf("--- I0 Ch_reg is: [0x%08x]\n", val)
}'

#===============================================================
# I0LedW
#===============================================================
#%UU% <I0_index> <val>
#%MDESC%
# seg=2, add=20h=32d
#MACRO: write the value  <val> in LED register
#and <addr> position
#%END%

def I0LedW(brdindex,valled)'{
   local myp
   
   _I0_checkifset
   if ( !_i0_check_board(brdindex) ){
      exit
   }

   myp[0] = 2
   myp[1] = 32
   myp[2] = valled 

   esrf_io(I0_ARR[brdindex]["dev"],"DevWriteReg32",myp)
}'

#===============================================================
# I0DacOutEn
#===============================================================
#%UU% <I0_index> <DacOut_channel> <val>
#%MDESC%
# seg=2, add=20h=32d
#MACRO: Enable Dac Out channels in LED register
#%END%

def I0DacOutEn(brdi, dac_ch, binval)'{
   local myw ledacr myvall
   
   _I0_checkifset
   
   if (!_i0_check_board(brdi) ){
      exit
   }

   ledacr = I0LedR(brdi)
   if ((dac_ch != 0) && (dac_ch != 1)) {
     p "Usage : Args = brd, dac_channel, enable : dac_channel = 0,1"
     exit
   }
   if ((binval != 0) && (binval != 1)) {
     p "Usage : Args = brd, dac_channel, enable : Enable = 0,1"
     exit
   }
   myw[0] = 2
   myw[1] = 32   
#     bit16 : clear and set
   if (dac_ch == 0) {
     ledacr = ledacr & 0xFFFEFFFF
     myvall = (binval << 16) & 0x10000
     myw[2] = ledacr | myvall
   }
#    bit17 : clear and set
   if (dac_ch == 1) {
     ledacr = ledacr & 0xFFFDFFFF
     myvall = (binval << 17) & 0x20000
     myw[2] = ledacr | myvall
   }
   esrf_io(I0_ARR[brdi]["dev"],"DevWriteReg32",myw)
}'

#===============================================================
# I0DacOutClkEn
#===============================================================
#%UU% <I0_index> <DacOut_channel> <val>
#%MDESC%
# seg=2, add=20h=32d
#MACRO: Enable free running clock on Dac Out channels in LED register
#%END%

def I0DacOutClkEn(brdi, dac_ch, binval)'{
   local myw ledacr myvall
   
   _I0_checkifset
   
   if (!_i0_check_board(brdi) ){
      exit
   }
   p "Enable free running clock on DAC_out channel : periodic pattern output"
   p "If disabled, programmable constant output with dacout_pul function"
   ledacr = I0LedR(brdi)
   if ((dac_ch != 0) && (dac_ch != 1)) {
     p "Usage : Args = brd, dac_channel, enable : dac_channel = 0,1"
     exit
   }
   if ((binval != 0) && (binval != 1)) {
     p "Usage : Args = brd, dac_channel, enable : Enable = 0,1"
     exit
   }
   myw[0] = 2
   myw[1] = 32   
#    bit18 : clear and set
   if (dac_ch == 0) {
     ledacr = ledacr & 0xFFFBFFFF
     myvall = (binval << 18) & 0x40000
     myw[2] = ledacr | myvall
   }
#    bit19 : clear and set
   if (dac_ch == 1) {
     ledacr = ledacr & 0xFFF7FFFF
     myvall = (binval << 19) & 0x80000
     myw[2] = ledacr | myvall
   }
   esrf_io(I0_ARR[brdi]["dev"],"DevWriteReg32",myw)
}'

#===============================================================
# I0DacOutPul
#===============================================================
#%UU% <I0_index> <DacOut_channel>
#%MDESC%
# seg=2, add=20h=32d
#MACRO: Programming pulse on DAC_out channels in LED register
#%END%

def I0DacOutPul(brdi, dac_ch)'{
   local myw ledacr myvall
   
   _I0_checkifset
   
   if (!_i0_check_board(brdi) ){
      exit
   }
   p "Pulse to program registered value on DAC_out"
   ledacr = I0LedR(brdi)
   if ((dac_ch != 0) && (dac_ch != 1)) {
     p "Usage : Args = brd, dac_channel, enable : dac_channel = 0,1"
     exit
   }
   myw[0] = 2
   myw[1] = 32   
#     case bit20
   if (dac_ch == 0) {
     ledacr = ledacr & 0xFFEFFFFF
     myvall = (1 << 20) & 0x100000
     myw[2] = ledacr | myvall
     esrf_io(I0_ARR[brdi]["dev"],"DevWriteReg32",myw)
     sleep(1)
     myw[2] = ledacr & 0xFFEFFFFF
     esrf_io(I0_ARR[brdi]["dev"],"DevWriteReg32",myw)
   }
#     case bit21
   if (dac_ch == 1) {
     ledacr = ledacr & 0xFFDFFFFF
     myvall = (1 << 21) & 0x200000
     myw[2] = ledacr | myvall
     esrf_io(I0_ARR[brdi]["dev"],"DevWriteReg32",myw)
     sleep(1)
     myw[2] = ledacr & 0xFFEFFFFF
     esrf_io(I0_ARR[brdi]["dev"],"DevWriteReg32",myw)
   }
}'

#===============================================================
# I0DacOutReg (added september 2011)
#===============================================================
#%UU% <I0_index> <DacOut_register>
#%MDESC%
# seg=2, add=50h, 54h, 58h, 5Ch (=80d, 84d, 88d, 92d)
#MACRO: Programming DAC_out registers
#%END%

def I0DacOutReg(brdi, regi, valreg)'{
   local myw
   
   _I0_checkifset
   
   if (!_i0_check_board(brdi) ){
      exit
   }
   
   if ((regi <= 0) && (regi > 5)) {
     p "Usage : DAC_out register = 1,2,3,4"
     exit
   }
   
   myw[0] = 2
   myw[1] = 0x50 + 4*(regi-1)
   myw[2] = valreg & 0xFFFFFFFF
   esrf_io(I0_ARR[brdi]["dev"],"DevWriteReg32",myw)
}'

#===============================================================
# I0ChW
#===============================================================
#%UU% <I0_index> <val>
#%MDESC%
# seg=2, add=18h
#MACRO: write the value  <val> in LED register
#and <addr> position
#%END%

def I0ChW(i0_i, valeur)'{
   local myp
   
   _I0_checkifset
   if ( !_i0_check_board(i0_i) ){
      exit
   }

   myp[0] = 2
   myp[1] = 0x18
   myp[2] = valeur 

   esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",myp)
}'

#===============================================================
# I0TstR
#===============================================================
#%UU%<I0_index>
#%MDESC%
# seg=2, add=24h=36d
#MACRO: read TST Register
#%END%
def I0TstR'{
   local myp val i0_i

   _I0_checkifset
   i0_i = $1
   if ( !_i0_check_board(i0_i) ){
      exit
   }

   myp[0] = 2
   myp[1] = 36

   val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
   printf("--- I0 TST_reg is: [0x%08x]\n", val)
}'

#===============================================================
# I0TstW
#===============================================================
#%UU% <I0_index> <val>
#%MDESC%
# seg=2, add=24h=36d
#MACRO: write the value  <val> in TST Register
#and <addr> position
#%END%

def I0TstW'{
   local myp i0_i
   
   _I0_checkifset
   i0_i = $1
   if ( !_i0_check_board(i0_i) ){
      exit
   }
   
   myp[0] = 2
   myp[1] = 36
   myp[2] = $2 

   esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",myp)
}'

#===============================================================
# I0IdR
#===============================================================
#%UU% <I0_index>
#%MDESC%
# seg=2, add=2Ch=44d
#MACRO: read SDAC_ld Register
#%END%

def I0IdR'{
   local myp val dig i0_i

   _I0_checkifset
    i0_i = $1
   if ( !_i0_check_board(i0_i)  ){
      exit
   }

   myp[0] = 2
   myp[1] = 44

   val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
   printf("--- PUDS ID is: [0x%04x]\n", val)
   dig = (val>>12) & 0xF
   printf((dig==0x1) ? "\tI0" : "\t!!!!!!!!!!!!PUDS IS NOT I0 !!!!\n")
   dig = val & 0xF
   if(dig==0x1) {
      printf(" - 1 channel")
   }
   if(dig==0x2) {
      printf(" - 2 channels")
   }
   if(dig==0x4) {
      printf(" - 4 channels")
   }
   dig = (val>>4) & 0x1
   printf(dig ? "\t - Double period\n" : "\t - Single period\n")
   
}'

#===============================================================
# I0SDacW
#===============================================================
#%UU% (<I0_index>,<mezz 1,2>,<channel 1,2,3,4>,<dac_type G,O>,<12bit_val>)
#%MDESC%
# seg=2, add=30h to 3Ch = 48d to 60d for SDAC_reg
# then seg=2, add=2Ch = 44d for SDAC_ld
#MACRO: write the value <val> in channel <cha> SDAC_reg
# at G(ain), O(ffset), H(igh_in_dscri), L(ow_in_discri)
# then load with SDAC_ld
#%END%

def I0SDacW(i0_i,mezz,cha,dac,valb)'{
   local myp val tru
   
   if (I0DEB >0){ p "i0_i " i0_i}
   if (I0DEB >0){ p "mezz " mezz}
   if (I0DEB >0){ p "cha " cha}
   if (I0DEB >0){ p "dac " dac}
   if (I0DEB >0){ p "valb " valb}

   _I0_checkifset
   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezz) || !_i0_check_ch(cha) ){
      exit
   }
   if (mezz == 1) {
      I0h_selectmez(i0_i,1)
   }
   if (mezz == 2) {
      if (I0_ARR[i0_i]["mezz2"] != 1) {
         p "no mezza2 in board " i0_i " . command not executed"
	 exit
      }
      else {
         I0h_selectmez(i0_i,2)
      }
   }
   
   myp[0] = 2
   val = valb & 0xFFF
	 
   myp[1] = 48 + 4*((cha-1) % 4)
	 
   if(dac == "G") {
      if (I0DEB > 0){ p "found G"}
      tru = (0x9 << 28) | (val << 16)
   } else
   if(dac == "O") {
      if (I0DEB > 0){ p "found O"}
      tru = (0xA << 28) | (val << 16)
   } else {
      p "usage:<dac_type G, O>"
   }
   
   if (I0DEB > 0){ printf ("sdac_add = %d ; sdac_val = %08x\n", myp[1], tru)}
   myp[2] = tru

   esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32", myp)

   myp[0] = 2
   myp[1] = 44
   myp[2] = 0 

   esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",myp)
}'

#===============================================================
# I0TimeR
#===============================================================
#%UU% (I0_index)
#%MDESC%
# seg=2, add=28h=40d
#MACRO: read Acquisition_Time register Register
#%END%

def I0TimeR(i0_i)'{
   local myp val 
   myp[0] = 2
   myp[1] = 40

   if ( !_i0_check_board(i0_i) ){
      exit
   }

   val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
   tim = (val*31*32)/352.202E+06
   if (I0DEB >0){ printf("--- I0 AcqTime is: [%e] s\n", tim)}
   return(val)
}'


#===============================================================
# I0Rout
#===============================================================
#%UU% (<I0_index>,<mezza>)
#%MDESC%
# seg=2, add_ch4=4Ch, add_ch3=48h, add_ch2=44h, add_ch1=40h
#MACRO: Readout common to i04, i02, i01
#Read Channel 4,3,2,1 (front panel order top to bottom)
#%END%
def I0Rout(i0_iib,mymezza)'{
  local myp valu vald val xch x12 pudid chen j myindiceb
  float array tabla[2*I0_ARR_DIM]

  _I0_checkifset

   if ( !_i0_check_board(i0_iib) || !_i0_check_mezz(mymezza) ){
      exit
   }
  if (I0DEB >0){ p "I0Rout: " i0_iib " " mymezza}  
  
  myindiceb = (2*i0_iib) +mymezza

  #tablu_bloc[myindiceb] = 0
  myp[0] = 2
  #myp[1] = 0x2C

  I0h_selectmez(i0_iib,mymezza)

#following removed because done in I0_setparam
#=== get version
  #val = esrf_io(I0_ARR[i0_iib]["dev"],"DevReadReg32",myp)
  #tablu_pudid[myindiceb] = (val>>12) & 0xF

  if(tablu_pudid[myindiceb] ==0x1) {
     #tablu_xch[myindiceb] = val & 0xF
     #x12 = (val>>4) & 0x1
     #if(x12==0) {
     #   tablu_bloc[myindiceb] = 128
     #} else {
     #   tablu_bloc[myindiceb] = 256
     #}

     myp[1] = 0x40
#    === readout
     #p "........ down values"
     for (j=0; j<tablu_bloc[myindiceb]; j++) {
        vald[j] = esrf_io(I0_ARR[i0_iib]["dev"],"DevReadReg32",myp)
	#p ".. "vald[j]
     }
     #p "........ up values"
     for (j=0; j<tablu_bloc[myindiceb]; j++) {
        valu[j] = esrf_io(I0_ARR[i0_iib]["dev"],"DevReadReg32",myp)
	#p ".. "valu[j]
        valu[j] = valu[j] & 0x3FFFF
        tabla[j] = (valu[j] * 4294967296) + vald[j]
        tablu[myindiceb][j] = tabla[j]
     }
     
  }
  else {
        printf("\t!!!!!!!!!!!!PUDS IS NOT I0 !!!!\n")
  }
}'  


#===============================================================
# I0tablutoch_orig
#===============================================================
#%UU% (<I0_index>, <mezza>)
#%MDESC%creates I0_ch[1], I0_ch[2], I0_ch[3], I0_ch[4] from tablu[]
def I0tablutoch_orig(i0_ia,mymezza)'{
   local myindicea myp chen j bloc

   myindicea = 2*i0_ia+mymezza
   if (I0DEB >0){ p "myindicea: " myindicea}

   if ( !_i0_check_board(i0_ia) || !_i0_check_mezz(mymezza) ){
      exit
   }
   myp[0] = 2

   bloc = tablu_bloc[myindicea]
   if (I0DEB >0){ p "bloc: " bloc}
#    === channel allocation
     print "toch " tablu_xch[myindicea]

     if(tablu_xch[myindicea]==0x1) {
#       === check channel enable
        myp[1] = 0x18
        chen = ((esrf_io(I0_ARR[i0_ia]["dev"],"DevReadReg32",myp)) >> 5) & 0x1
	p "chen: " chen
#       === then allocate data
        if(chen==0) {
	
           I0_ch[4][] = tablu[myindicea][]
        } else {
           I0_ch[2][] = tablu[myindicea][]
        }
	if (bloc == 256) {
	   tablu_chdim[myindicea]= 256
	}
	else {
	   tablu_chdim[myindicea]= 128
	}
	print "myindicea " myindicea
	print "set tablu_ch " tablu_chdim[myindicea]
     }


     if(tablu_xch[myindicea]==0x2) {
#       === check channel enable
        myp[1] = 0x18
        chen = ((esrf_io(I0_ARR[i0_ia]["dev"],"DevReadReg32",myp)) >> 4) & 0x3
	p "chen: " chen
#       === then allocate data
#       === even = ch#0/4 or ch#2
        for (j=0; j<bloc; j=j+2) {
           if((chen==0) || (chen==2)) {
              I0_ch[4][j/2] = tablu[myindicea][j]
           } else {
              I0_ch[2][j/2] = tablu[myindicea][j]
           }
        }
#       === odd = ch#1 or ch#3
        for (j=1; j<bloc; j=j+2) {
           if((chen==0) || (chen==1)) {
              I0_ch[1][(j-1)/2] = tablu[myindicea][j]
           } else {
              I0_ch[3][(j-1)/2] = tablu[myindicea][j]
           }
        }
	if (bloc == 256) {
	   tablu_chdim[myindicea]= 128
	}
	else {
	   tablu_chdim[myindicea]= 64
	}
     }
     
     if(tablu_xch[myindicea]==0x4) {
#       === check channel enable
        myp[1] = 0x18
        chen = ((esrf_io(I0_ARR[i0_ia]["dev"],"DevReadReg32",myp)) >> 4) & 0xF
	p "chen: " chen
#       === then allocate data
#       === even = ch#0/4 or ch#2
        for (j=0; j<bloc; j=j+4) {
           if((chen & 0x1) == 1) {
              I0_ch[4][j/4] = tablu[myindicea][j]
           }
        }
        for (j=1; j<bloc; j=j+4) {
           if((chen & 0x2) == 2) {
              I0_ch[1][(j-1)/4] = tablu[myindicea][j]
           }
        }
        for (j=2; j<bloc; j=j+4) {
           if((chen & 0x4) == 4) {
              I0_ch[2][(j-2)/4] = tablu[myindicea][j]
           }
        }
        for (j=3; j<bloc; j=j+4) {
           if((chen & 0x8) == 8) {
              I0_ch[3][(j-3)/4] = tablu[myindicea][j]
           }
        }
	if (bloc == 256) {
	   tablu_chdim[myindicea]= 64
	}
	else {
	   tablu_chdim[myindicea]= 32
	}
     }	  
}'

#===============================================================
# I0tablutoch
#===============================================================
#%UU% (<I0_index>, <mezza>)
#%MDESC%creates I0_ch[1], I0_ch[2], I0_ch[3], I0_ch[4] from tablu[]
def I0tablutoch(i0_ia,mymezza)'{
   local myindicea myp chen j

   myindicea = 2*i0_ia+mymezza
   if (I0DEB >0){ p "myindicea: " myindicea}

   if ( !_i0_check_board(i0_ia) || !_i0_check_mezz(mymezza) ){
      exit
   }

#    clean all arrays
     I0_ch = 0
     
     if(tablu_xch[myindicea]==0x1) {
        if(tablu_chen[myindicea][4] == 1) {
            I0_ch[4][] = tablu[myindicea][]
        } else if(tablu_chen[myindicea][2] == 1){
           I0_ch[2][] = tablu[myindicea][]
        }
     }


     if(tablu_xch[myindicea]==0x2) {
        for (j=0; j<tablu_bloc[myindicea]; j=j+2) {
           if(tablu_chen[myindicea][4] == 1) {
              I0_ch[4][j/2] = tablu[myindicea][j]
	   } else if(tablu_chen[myindicea][2] == 1) {
              I0_ch[2][j/2] = tablu[myindicea][j]
           }
        }
#       === odd = ch#1 or ch#3
        for (j=1; j<tablu_bloc[myindicea]; j=j+2) {
           if(tablu_chen[myindicea][1] == 1) {
              I0_ch[1][(j-1)/2] = tablu[myindicea][j]
           } else if(tablu_chen[myindicea][3] == 1){
              I0_ch[3][(j-1)/2] = tablu[myindicea][j]
           }
        }
     }
     
     if(tablu_xch[myindicea]==0x4) {
        for (j=0; j<tablu_bloc[myindicea]; j=j+4) {
           if(tablu_chen[myindicea][4] == 1) {
              I0_ch[4][j/4] = tablu[myindicea][j]
           }
        }
        for (j=1; j<tablu_bloc[myindicea]; j=j+4) {
           if(tablu_chen[myindicea][1] == 1) {
              I0_ch[1][(j-1)/4] = tablu[myindicea][j]
           }
        }
        for (j=2; j<tablu_bloc[myindicea]; j=j+4) {
           if(tablu_chen[myindicea][2] == 1) {
              I0_ch[2][(j-2)/4] = tablu[myindicea][j]
           }
        }
        for (j=3; j<tablu_bloc[myindicea]; j=j+4) {
           if(tablu_chen[myindicea][3] == 1) {
              I0_ch[3][(j-3)/4] = tablu[myindicea][j]
           }
        }
     }	  
}'

#===============================================================
# I0Calc(i0fft)
#===============================================================
#%IU% (i0fft)
#%MDESC%
def I0Calc(i0fft) '{
 
   local ampdc amphar cols i
	
   cols = array_op("cols", i0fft) / 2
   ampdc = sqrt(i0fft[0]*i0fft[0] + i0fft[cols]* i0fft[cols])
   amphar = 0
	 	
   for(i=1; i<cols/2; i++) 
      amphar = amphar + sqrt(i0fft[i]*i0fft[i] + i0fft[cols+i]* i0fft[cols+i])
				  
   if (I0DEB >0){ printf("--- DC = %e, Harmonics = %e \n", ampdc, amphar)}
 }'


#===============================================================
# I0cton
#===============================================================
#%UU%
#%MDESC%enables pseudo count.
def I0cton'{
   local ii 

   cdef("user_getcounts","I0ctcalc_getcounts;","cubi0",0)
   cdef("user_precount","I0count_precount;","cubi0",0)
   I0ON = 1

}'

#===============================================================
# I0ctoff
#===============================================================
#%UU% 
#%MDESC%disables pseudo count.
def I0ctoff'{
   local ii 

   cdef("user_getcounts","","cubi0","delete")
   cdef("user_precount","","cubi0","delete")
   I0ON = 0

}'

#===============================================================
# I0body
#===============================================================
#%IU% 
#%MDESC% For blmenu (use blmenu.mac).
def I0body(mode) '{

   if (mode == 1) {
      if (I0ON) {
         I0ctoff
      }
      else {
         I0cton
      }
      
   }
   return(sprintf("%s",I0ON?"ON":"OFF"))
}'




#===============================================================
# I0count_precount
#===============================================================
#%IU%
#%MDESC%precount pseudo mechanism.Enables acqui on all boards mezzanines
#and finishing with the mezzanin 1 of master trig board
def I0count_precount'{
   local ii
   
#  first tablu is set to 0
   tablu = 0

#  first loop of all the boards but the master trig
   for (ii=0; ii<I0_NBDEV; ii++) {
      if ( (ii != I0_ARR["master_trig"]) && (I0_ARR[ii]["used"] == 1) ) {
         I0h_selectmez(ii,1)
         I0Acq_precount ii
         if (I0_ARR[ii]["mezz2"] == 1) {
            I0h_selectmez(ii,2)
            I0Acq_precount ii
         }
      }   
   }

#  now the master trig one
#  mezzanin 2 if any
#  we test that master trig board is in use because it could be not used (allowed
#  only in software mode)
   if ( (I0_ARR[I0_ARR["master_trig"]]["mezz2"] == 1) && \
        (I0_ARR[I0_ARR["master_trig"]]["used"] == 1) ) {
      I0h_selectmez(I0_ARR["master_trig"],2)
      I0Acq_precount I0_ARR["master_trig"]
   }

#  mezzanin 1
   if (I0_ARR[I0_ARR["master_trig"]]["used"] == 1){
      I0h_selectmez(I0_ARR["master_trig"],1)
      I0Acq_precount I0_ARR["master_trig"]
   }
   

}'

#===============================================================
# I0Acq_precount
#===============================================================
#%IU% <I0_index>
#%MDESC%enables acquisitions on a board, on the already selected 
#mezzanin.
#%BR%- Stop acqui
#%BR%- Read CSR
#%BR%- set acq_en bit in CSR
#%END%
def I0Acq_precount'{
   local myp val dig ryp i0_i mez

   _I0_checkifset
   if (I0DEB >0){ p "I0Acq_precount : " $1}
   i0_i = $1
   if ( !_i0_check_board(i0_i) ){
      exit
   }
   
   I0AcqStop(i0_i)

   myp[0] = 2
   myp[1] = 4

   val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
   val = val & 0xFFFFFFFE
   myp[2] = val | 0x1

   esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",myp)
	

}'

#===============================================================
# I0AcqStop
#===============================================================
#%UU% (I0_index)
#%MDESC%stop acquisition on the specified board, on the 
#already selected mezzanin
def I0AcqStop(i0_i)'{
   local ryp dig

   _I0_checkifset
   if ( !_i0_check_board(i0_i) ){
      exit
   }

   ryp[0] = 2
   ryp[1] = 4
   dig = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",ryp)
   ryp[2] = dig & 0xFFFFFFFE

   esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",ryp)

}'

#===============================================================
# I0ctcalc_getcounts
#===============================================================
#%IU%
#%MDESC%pseudo reading data mechanism.
#gets the data for mezzanin 1, and mezzanin 2 (if exists)
def I0ctcalc_getcounts'{
   local ii
   
#  first stops the master trig board
#  mezzanin 1
   if (I0_ARR[I0_ARR["master_trig"]]["used"] == 1) {
      I0h_selectmez(I0_ARR["master_trig"],1)
      I0AcqStop(I0_ARR["master_trig"])

#     mezzanin 2 if any
      if (I0_ARR[I0_ARR["master_trig"]]["mezz2"] == 1) {
         I0h_selectmez(I0_ARR["master_trig"],2)
         I0AcqStop(I0_ARR["master_trig"])
      }
   }

#  then stop the others   
   for (ii=0; ii<I0_NBDEV; ii++) {
      if ((ii != I0_ARR["master_trig"]) && I0_ARR[ii]["used"] == 1){
         I0h_selectmez(ii,1)
         I0AcqStop(ii)

#        mezzanin 2 if any
         if (I0_ARR[ii]["mezz2"] == 1) {
            I0h_selectmez(ii,2)
            I0AcqStop(ii)
         }
      }
   }

#  now get the result and calculate per board and mezzanin
   for (ii=0; ii<I0_NBDEV; ii++) {
      if (I0_ARR[ii]["used"] == 1) {
         I0h_selectmez(ii,1)
         _I0ctcalc_getcounts(ii,1)
         I0_calc(ii,1)
         if (I0_ARR[ii]["mezz2"] == 1){
            I0h_selectmez(ii,2)
            _I0ctcalc_getcounts(ii,2)
            I0_calc(ii,2)
         }
      }   
   }
}'

#===============================================================
# _I0ctcalc_getcounts
#===============================================================
#%IU%(I0_index,mezza)
#%MDESC%get data for a particular mezzanin (1 or 2)
#%BR%this macro provides also 4 blocks of data corresponding to each channel
#of the mezzanin.
#%BR%- I0_index : 0..
#%BR%- mezza: 1,2
def _I0ctcalc_getcounts(i0_i,mezzaa)'{
   local tim ii myindicee

   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezzaa) ){
      exit
   }

   if (I0DEB >0){ p "in _I0ctcalc_getcounts: " i0_i " " mezzaa}
   tim = I0TimeR(i0_i)
   if (I0DEB >0){ p "in _I0ctcalc_getcounts: " i0_i " " mezzaa}
   if (I0DEB >0){ p tim}
   myindicee = i0_i*2+mezzaa
   tablu_tim[myindicee] = tim

#  read
   if (I0DEB >0){ p "in _I0ctcalc_getcounts: " i0_i " " mezzaa}
   I0Rout(i0_i,mezzaa)

#  divide by tim in not timer mode !!!!!!!!!!!
   if ( (mezzaa == 1) && (I0_ARR[i0_i]["timerbit_mezz1"] == 0) && (tim != 0) ) {
      tablu[myindicee][0:tablu_bloc[myindicee]] = tablu[myindicee][0:tablu_bloc[myindicee]]/ tim
   }
   else if ( (mezzaa == 2) && (I0_ARR[i0_i]["timerbit_mezz2"] == 0) && (tim != 0) ) {
      tablu[myindicee][0:tablu_bloc[myindicee]] = tablu[myindicee][0:tablu_bloc[myindicee]]/ tim
   }   

}'

#===============================================================
# I0_calc
#===============================================================
#%IU%(I0_index,mezza)
#%MDESC%calculate data for a particular board/mezzanin 
#%BR%- I0_index : 0..
#%BR%- mezza: 1,2
def I0_calc(i0_i,mezza)'{
   if (I0DEB >0){ p "in I0_calc"}

   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezza) ){
      exit
   }

   if (mezza == 1) {
      for (jj=0; jj<4; jj++) {
         if (I0_ARR[i0_i][sprintf("ch%d",jj+11)] == 1) {
#           data for this channel is requested         
            I0_calcdef(i0_i,mezza,jj+1)
         }
      }
   }
   else if (mezza == 2) {
      for (jj=0; jj<4; jj++) {
         if (I0_ARR[i0_i][sprintf("ch%d",jj+21)] == 1) {
#           data for this channel is requested         
            I0_calcdef(i0_i,mezza,jj+1)
         }
      }   
   }
}'


#===============================================================
# I0_calcdef
#===============================================================
#%IU%(I0_index,mezza,ch)
#%MDESC%calculate the serie of harmonics  for a particular board/mezzanin/channel 
#%BR%I0_ch[1:4][] contains the raw data for the 4 channels
#%BR%- I0_index : 0..
#%BR%- mezza: 1,2
#%BR%- ch: 1,2,3,4 
def I0_calcdef(i0_i,mezza,ch)'{
   local indharm mynbharm found myloc myindice
   local ii jj mystr
   local mydim
   
   if (I0DEB >0){ p "I0_calcdef " i0_i " " mezza " " ch}

   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezza) || !_i0_check_ch(ch) ){
      exit
   }

   myindice = 2*i0_i + mezza

#  tablu to I0_ch
   I0tablutoch(i0_i,mezza)
   
#  valid data is in I0_ch[][0..tablu_chdim[]-1]
#  p tablu_chdim[myindice]
   float array inter_ch[tablu_chdim[myindice]]
   float array essfft[2*tablu_chdim[myindice]]
   float array essfft2[tablu_chdim[myindice]]
#  may be because we need float
   inter_ch[] = I0_ch[ch][0:tablu_chdim[myindice]-1]

   fft_do(inter_ch, essfft)
   I0Calc(essfft)
   fftshow_rms_noplot(essfft,essfft2)

   indharm = i0_i*100 + mezza*10 + ch
   if (I0DEB >0){ p "indharm = " indharm}
   if ( I0_HARM[indharm]["nb"] != 0) {
#     found the channel     
      mynbharm = I0_HARM[indharm]["nb"]
      if (I0DEB >0){ p "-> " mynbharm "  harmonics for board " i0_i ", mezzanin " mezza ", channel " ch}
      for (ii=0; ii<mynbharm; ii++) {
#        example: for board0, mezzanin 1, channel 3 
#        we will have ha013_1  for first harmonic requested
#                     ha013_2  for second harmonic requested
         mystr = sprintf("ha%d%d%d_%d",i0_i,mezza,ch,ii+1)
         if (@mystr != 0) {
#           pseudo exists. NEED TO CHECK IT IS A PSEUDO CNT !!!!
            S[@mystr] = essfft2[I0_HARM[indharm][ii]]
            if (I0DEB >0){ p S[@mystr]}
         }
      }
      
      myloc = cnt_num(sprintf("ha%d%d%d",i0_i,mezza,ch))
      if (I0DEB >0){print "in I0_calcdef " myloc}
      if (myloc != -1) {
         S[myloc] = 0
         for (ii=0; ii<mynbharm; ii++) {
             S[myloc] += essfft2[I0_HARM[indharm][ii]]
#	     print "in I0_calcdef " S[myloc]
         }
      }
   }
}'

#%IU% <I0_index> <mezza> <ch>
#%MDESC%Shows raw data on board/mezzanin/channel
def I0_showin'{
   local i0_i mezza ch myindice ii
   
   i0_i = $1
   mezza = $2
   ch = $3
   
   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezza) || !_i0_check_ch(ch) ){
      exit
   }
   
   myindice = i0_i*2+mezza
#  tablu to I0_ch
   I0tablutoch(i0_i,mezza)

   float array inter_ch[tablu_chdim[myindice]]
   float array essfft[2*tablu_chdim[myindice]]
   float array essfft2[tablu_chdim[myindice]]
   inter_ch[] = I0_ch[ch][0:tablu_chdim[myindice]-1]
   if (I0DEB >0){ p tablu}

   fftshow_in(inter_ch)

}'


#%IU% <I0_index> <mezza> <ch>
#%MDESC%Shows fft spectrum on board/mezzanin/channel
def I0_showrms'{
   local i0_i mezza ch myindice ii
   
   i0_i = $1
   mezza = $2
   ch = $3

   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezza) || !_i0_check_ch(ch) ){
      exit
   }

   myindice = i0_i*2+mezza
#  tablu to I0_ch
   I0tablutoch(i0_i,mezza)

   float array inter_ch[tablu_chdim[myindice]]
   float array essfft[2*tablu_chdim[myindice]]
   float array essfft2[tablu_chdim[myindice]]
   inter_ch[] = I0_ch[ch][0:tablu_chdim[myindice]-1]

   fft_do(inter_ch, essfft)
   I0Calc(essfft)

   fftshow_rms(essfft,essfft2)

}'

#%UU%<filename>
#%MDESC%stores the present I0 configuration on <filename>
#(under ~blissadm/local/spec/userconf)
def I0_putconf'{
   local ii mystr myofile mycompletefile ret jj
   
   if ($# == 0) {
      p "usage: I0_putconf <filename>"
      exit
   }
   myofile = "$1"
   if (I0DEB >0){ p myofile}
   mycompletefile = "~blissadm/local/spec/userconf/" myofile
   if (unix(sprintf("test -s %s",mycompletefile))){
      p "Writing configuration to file " mycompletefile
   }
   else{
      p "file already exists. exit"
      exit
   }    
   ret = open(mycompletefile)
   if (ret == -1) {
      p "cannot open file" mycompletefile
      p "exit"
      exit
   }
   on(mycompletefile);offt
   
   printf("#I0");printf("\n")
   printf("#dev ")
   for (ii=0; ii<I0_NBDEV; ii++){
      if (I0_ARR[ii]["used"] == 1) {
        printf("%s ",I0_ARR[ii]["dev"])
      }
   }
   printf("\n")

   printf("#mezz2 ")
   for (ii=0; ii<I0_NBDEV; ii++){
      if (I0_ARR[ii]["used"] == 1) {
        printf("%d ",I0_ARR[ii]["mezz2"])
      }
   }
   printf("\n")

   for (jj=1; jj<5; jj++) {
      printf("#m1ch%d ",jj)
      for (ii=0; ii<I0_NBDEV; ii++){
         if (I0_ARR[ii]["used"] == 1) {
           printf("%d ",I0_ARR[ii][sprintf("ch%d",jj+10)])
         }
      }
      printf("\n")
   }

   for (jj=1; jj<5; jj++) {
      printf("#m2ch%d ",jj)
      for (ii=0; ii<I0_NBDEV; ii++){
         if (I0_ARR[ii]["used"] == 1) {
           printf("%d ",I0_ARR[ii][sprintf("ch%d",jj+20)])
         }
      }
      printf("\n")
   }
   
   printf("#mode %d\n",I0_ARR["mode"])   
   printf("#master_trig %d\n",I0_ARR["master_trig"])   
      
   ont;close(mycompletefile)
}'


#===============================================================
# _I0_compat_nbdev
#===============================================================
#%IU%(nb_devref,nb_dev)
#%MDESC% verifies if the number of elements are compatible
#to the reference number.
#%BR% return: 0 if not ok, 1 if ok
def _I0_compat_nbdev(nb_devref,nb_dev)'{
    if ( (nb_devref == 0) || (nb_dev == nb_devref) ){
       return(1)
    }
    else {
       return(0)
    }
}'


#===============================================================
#  I0_getconf
#===============================================================
#%UU%<filename>
#%MDESC%reads a configuration file (under ~blissadm/local/spec/userconf)
#and applies it to the hardware
def I0_getconf'{
   local myf
   
   if ($# != 1) {
      p "usage: I0_getconf <filename>"
      exit
   }
   p "-> Reading file " "$1"
   _I0_getconf $*
   
   p "->Verify compatibility with present hardware"
   if (_I0_compatarchi() == 0) {
      p "hardware not compatible. exit"
      exit
   }
   else {
      p "hardware is compatible"
   }
   
   p "->Copy to spec structure"
   _I0_cpconf
   
   I0_showconf
   
   p "->Applying to hardware "
   I0h_applyarray
}'

#===============================================================
# _I0_getconf
#===============================================================
#%IU% <filename>
#%MDESC%reads the file in ~blissadm/local/spec/userconf 
def _I0_getconf'{
   local myfile ii cont ret myf myarr mybn ret0
   global I0_m_dev I0_m_mezz2 
   global I0_m1_ch1 I0_m1_ch2 I0_m1_ch3 I0_m1_ch4 
   global I0_m2_ch1 I0_m2_ch2 I0_m2_ch3 I0_m2_ch4 
   global I0_m_mode I0_m_master_trig I0_nb_dev I0_m_corres
   
   myf = "$1"
   myfile = "~blissadm/local/spec/userconf/" myf
   p "reading file " myfile
   cont = 1
   ret0 = getline(myfile,"open")
   I0_nb_dev = 0
   if (ret0 != -1)
   {
      ret0 = getline(myfile)
#     to remove the trailing newline, to be able to correctly compare strings.
      ret = substr(ret0,1,length(ret0)-1)
      if (I0DEB >0){ p ret}
      mynb = split(ret, myarr)
      if (myarr[0] != "#I0") {
         p "this is not a I0 file. exit"
         exit
      }
      while(cont == 1) {
         ret0 = getline(myfile)
         if (ret0 == -1) {
            cont = 0
            getline(myfile,"close")  
         }
         else {
            ret = substr(ret0,1,length(ret0)-1)
            if (I0DEB >0){ p ret}
            mynb = split(ret,myarr)
            myflag = myarr[0] 
            if (myflag == "#dev") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #dev elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m_dev[jj-1] = myarr[jj]
               }
            }       
            else if (myflag == "#mezz2") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #mezz2 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m_mezz2[jj-1] = myarr[jj]
               }
            
            }       
            else if (myflag == "#m1ch1") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #m1ch1 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m1_ch1[jj-1] = myarr[jj]
               }
            
            }       
            else if (myflag == "#m1ch2") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #m1ch2 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m1_ch2[jj-1] = myarr[jj]
               }
            
            }       
            else if (myflag == "#m1ch3") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #m1ch3 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m1_ch3[jj-1] = myarr[jj]
               }
            
            }       
            else if (myflag == "#m1ch4") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #m1ch4 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m1_ch4[jj-1] = myarr[jj]
               }
            
            }   
            else if (myflag == "#m2ch1") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #m2ch1 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m2_ch1[jj-1] = myarr[jj]
               }
            
            }       
            else if (myflag == "#m2ch2") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #m2ch2 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m2_ch2[jj-1] = myarr[jj]
               }
            
            }       
            else if (myflag == "#m2ch3") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #m2ch3 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m2_ch3[jj-1] = myarr[jj]
               }
            
            }       
            else if (myflag == "#m2ch4") {
               if ( _I0_compat_nbdev(I0_nb_dev,mynb-1) == 0) {
                  p "bad number of #m2ch4 elements. exit"
                  exit
               } 
               I0_nb_dev = mynb-1
               for (jj=1; jj<mynb; jj++) {
                  I0_m2_ch4[jj-1] = myarr[jj]
               }
            
            }       
            else if (myflag == "#mode") {
               if (mynb != 2) {
                  p "bad number of #mode elements. exit"
                  exit
               }
               I0_m_mode = myarr[1] 
            }       
            else if (myflag == "#master_trig") {
               if (mynb !=2) {
                  p "bad number of #master_trig elements(" mynb "). exit"
                  exit
               } 
               I0_m_master_trig = myarr[1]
               if (I0_m_master_trig >= I0_nb_dev) {
                  p "bad value of master trig element"
                  exit
               }
            }
            else {
               p "unknown line: " ret " ignored."
            }       
        }
      }         
   }
}'

#===============================================================
# _I0_compatarchi()
#===============================================================
#%IU%
#%MDESC% checks if the architecture loaded in I0_m_xx is compatible
#with the present devices. it checks:
#%BR% - presence of requested devices
#%BR% - number of mezzanin on the devices.
#%BR% creates an array I0_m_corres for corrspondance I0_m_xx  -> I0_ARR
def _I0_compatarchi()'{
   local ii jj found

#  first check that all the devices are here   
   for (ii=0; ii<I0_nb_dev; ii++) {
       found = 0
       for (jj=0; jj<I0_NBDEV; jj++) {
          if (I0_ARR[jj]["dev"] == I0_m_dev[ii]) {
             I0_m_corres[ii] = jj
             found = 1
             break
          }
       }
       if (found == 0) {
          p "device " I0_m_dev[ii] " missing!!"
          return(0)
       }
   }
   
#  and that the mezzanin are here
   for (ii=0; ii<I0_nb_dev; ii++) {
      if (I0_m_mezz2[ii] != I0_ARR[I0_m_corres[ii]]["mezz2"]) {
         p "device " I0_m_dev[ii] " should have " I0_m_mezz2[ii]+1 " mezzanin !!"
         return(0)
      }
   }   

   return(1)
   
}'


#===============================================================
# _I0_cpconf
#===============================================================
#%IU%
#%MDESC%copies the configuration loaded in the I0_ARR array
def _I0_cpconf'{
   local ii

#  first set as unused all the elements   
   for (ii=0; ii<I0_NBDEV; ii++){
      I0_ARR[ii]["used"] = 0
   }
   
#  the work on the really used ones
   for (ii=0; ii<I0_nb_dev; ii++) {
#     in use
      I0_ARR[I0_m_corres[ii]]["used"] = 1
#     the channels
      I0_ARR[I0_m_corres[ii]]["ch11"] = I0_m1_ch1[ii]
      I0_ARR[I0_m_corres[ii]]["ch12"] = I0_m1_ch2[ii]
      I0_ARR[I0_m_corres[ii]]["ch13"] = I0_m1_ch3[ii]
      I0_ARR[I0_m_corres[ii]]["ch14"] = I0_m1_ch4[ii]
      I0_ARR[I0_m_corres[ii]]["ch21"] = I0_m2_ch1[ii]
      I0_ARR[I0_m_corres[ii]]["ch22"] = I0_m2_ch2[ii]
      I0_ARR[I0_m_corres[ii]]["ch23"] = I0_m2_ch3[ii]
      I0_ARR[I0_m_corres[ii]]["ch24"] = I0_m2_ch4[ii]
      
   }

#  master trig      
   I0_setmastertrig I0_m_corres[I0_m_master_trig]
   
#  mode
   I0_ARR["mode"] = I0_m_mode
   if (I0_ARR["mode"] == 0){
      I0_setmodesoft
   }
   else if (I0_ARR["mode"] == 1) {
      I0_setmodehard
   }
   else if (I0_ARR["mode"] == 2){
      I0_setmodehardext
   }
   
}'


#%UU%
#%MDESC%Shows the harmonics defined by board/mezzanin/channel
def I0_showharm'{
   local ii myb mym myc jj kk myind myw ll harmo
   
   for (ii=0; ii<I0_NBDEV; ii++) {
      for (jj=1; jj<3; jj++) {
         for (kk=1; kk<5; kk++) {
            myind = ii*100+jj*10+kk
            myw = sprintf("I0_HARM[%d][\"nb\"]",myind)
            if (whatis(myw) != 0) {
               p "Harmonics for board: " ii " mezzanin: " jj " channel: " kk 
               for (ll=0; ll<I0_HARM[myind]["nb"]; ll++) {
                  harmo[ll] = I0_HARM[myind][ll]
                  printf("%d ",harmo[ll])
               }
               printf("\n")
            }
         }
      }
   }
}'


#%IU%(board)
#%MDESC%check validity of a board number: returns 1 if board number is 
#a valid number
def _i0_check_board(bo)'{
   if ( (bo< 0) || (bo >= I0_NBDEV)){
      p "board number should be  [0.." I0_NBDEV-1 "]. it is " bo
      return(0)
   }
   else {
      return(1)
   }
}'

#%IU%(mezz)
#%MDESC%check validity of a mezzanin number :returns 1 if mezzanin is [1,2],
# 0 else
def _i0_check_mezz(mezz)'{
   if ( (mezz != 1) && (mezz != 2) ){
      p "mezzanin number should be [1,2]. it is " mezz
      return(0)
   }
   else{
      return(1)
   }
}'

#%IU%(ch)
#%MDESC%check validity of a channel number: returns 1 if ch is [1,2,3,4],
# 0 else
def _i0_check_ch(ch)'{
   if ( (ch < 1)|| (ch > 4) ){
      p "channel number should be [1..4]. it is " ch
      return(0)
   }
   else{
      return(1)
   }
}'

#%UU%
#%MDESC% DAC definitions. interactive command.
#then applies to hardware
def I0_dac'{
   local bo1 ch1 valind
   
   for (bo1=0; bo1< I0_NBDEV; bo1++) {
      if (I0_ARR[bo1]["used"] == 1) {
#        1st mezzanine
         for (ch1=1; ch1<5;ch1++){
            valind = bo1*100 + 10 + ch1
	    if (I0_ARR[bo1][sprintf("ch1%d",ch1)] == 1) {
               I0_DAC[valind]["gain"] = getval(sprintf("gain value (12bits) for board:%d mezza1 ch:%d ?",bo1,ch1),I0_DAC[valind]["gain"])
               I0_DAC[valind]["offset"] = getval(sprintf("offset value (12bits) for board:%d mezza1 ch:%d ?",bo1,ch1),I0_DAC[valind]["offset"])
	    } 
         }

#        2d mezzanine if there
         if (I0_ARR[bo1]["mezz2"]) {
            for (ch1=1; ch1<5; ch1++){
               valind = bo1*100 + 20 + ch1
	       if (I0_ARR[bo1][sprintf("ch2%d",ch1)] == 1) {
                  I0_DAC[valind]["gain"] = getval(sprintf("gain value (12bits) for board:%d mezza2 ch:%d ?",bo1,ch1),I0_DAC[valind]["gain"]) 
                  I0_DAC[valind]["offset"] = getval(sprintf("offset value (12bits) for board:%d mezza2 ch:%d ?",bo1,ch1),I0_DAC[valind]["offset"]) 
	       }  
	    }
         }
      }
   }
   if (I0DEB >0){ p I0_DAC}
   
   _I0_applydac()
}'

#%IU%
#%MDESC%applies gain and offset values to hardware
def _I0_applydac()'{
   local bo1 ch1 valind
   
   for (bo1=0; bo1< I0_NBDEV; bo1++) {
      if (I0_ARR[bo1]["used"] == 1) {
#        1st mezzanine
         for (ch1=1; ch1<5;ch1++){
            valind = bo1*100 + 10 + ch1
	    if (I0_ARR[bo1][sprintf("ch1%d",ch1)] == 1) {
               I0SDacW(bo1,1,ch1,"G",I0_DAC[valind]["gain"])
               I0SDacW(bo1,1,ch1,"O",I0_DAC[valind]["offset"])
	    } 
         }

#        2d mezzanine if there
         if (I0_ARR[bo1]["mezz2"]) {
            for (ch1=1; ch1<5; ch1++){
               valind = bo1*100 + 20 + ch1
	       if (I0_ARR[bo1][sprintf("ch2%d",ch1)] == 1) {
                  I0SDacW(bo1,2,ch1,"G",I0_DAC[valind]["gain"])
                  I0SDacW(bo1,2,ch1,"O",I0_DAC[valind]["offset"])
	       }  
	    }
         }
      }
   }
}'

#%UU%<filename>
#%MDESC% write dac values to file
def I0_savedac'{
   local myfileroot ret

   if ($# !=1 ) {
	    p "usage: I0_savedac <filename>"
	 } 
   myfileroot = "$1"

   if (unix(sprintf("test -s %s",myfileroot)) == 0){
      p "file already exists. exit"
      exit
   }	 
   ret = open(myfileroot)
   if (ret == -1) {
      p "cannot open file" myfileroot
      p "exit"
      exit
   }
   p "on file " myfileroot
   on(myfileroot);offt
   p I0_DAC
   ont;close(myfileroot)

}'

#%UU%<filename>
#%MDESC%gets dac values from file
def I0_getdac'{
   local myfileroot 

   if ($# !=1) {
      p "usage: I0_getdac <filename>"
   } 
   myfileroot = "$1"

   p "reading " myfileroot	 
   qdofile(myfileroot)

}'


#%IU% (<I0_index>, <mezza>)
#%MDESC%
def _I0h_getchinfo_old(i0_i,mezz)'{
   local myindice myp chen val x12

   myindice = 2*i0_i+mezz

   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezz) ){
      exit
   }

  tablu_bloc[myindice] = 0
  myp[0] = 2
  myp[1] = 0x2C

  I0h_selectmez(i0_i,mezz)
# get version
  val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
  tablu_pudid[myindice] = (val>>12) & 0xF

  if(tablu_pudid[myindice] ==0x1) {
     tablu_xch[myindice] = val & 0xF
     x12 = (val>>4) & 0x1
     if(x12==0) {
        tablu_bloc[myindice] = 128
     } else {
        tablu_bloc[myindice] = 256
     }
   }
   else {
     printf("\t!!!!!!!!!!!!PUDS IS NOT I0 !!!!\n")
   }
   
   tablu_chen[myindice][1] = 0
   tablu_chen[myindice][2] = 0
   tablu_chen[myindice][3] = 0
   tablu_chen[myindice][4] = 0

#  get hardware channel enable info

   if(tablu_xch[myindice]==0x1) {
#  chen == 0: channel 4
#  else:      channel 2
      myp[1] = 0x18
      chen = ((esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)) >> 5) & 0x1
      if (I0DEB >0){ p "chen: " chen}
      if (chen == 0){
         tablu_chen[myindice][4] = 1
      }
      else {
         tablu_chen[myindice][2] = 1
      }

      if (tablu_bloc[myindice] == 256) {
	 tablu_chdim[myindice]= 256
      }
      else {
	 tablu_chdim[myindice]= 128
      }
   }


   if(tablu_xch[myindice]==0x2) {
#  channel enable
#  chen == 0: channel 4 and channel 1
#  chen == 1: channel 1 and channel 2
#  chen == 2: channel 3 and channel 4
#  chen == 3: channel 2 and channel 3
      myp[1] = 0x18
      chen = ((esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)) >> 4) & 0x3
      if (I0DEB >0){ p "chen: " chen}
      if (chen == 0) {
         tablu_chen[myindice][4] = 1
         tablu_chen[myindice][1] = 1
      }
      else if (chen == 1) {
         tablu_chen[myindice][2] = 1
         tablu_chen[myindice][1] = 1
      }
      else if (chen == 2) {
         tablu_chen[myindice][3] = 1
         tablu_chen[myindice][4] = 1
      }
      else{
         tablu_chen[myindice][2] = 1
         tablu_chen[myindice][3] = 1
      }

      if (tablu_bloc == 256) {
	 tablu_chdim[myindice]= 128
      }
      else {
	 tablu_chdim[myindice]= 64
      }
   }
     
   if(tablu_xch[myindice]==0x4) {
      myp[1] = 0x18
      chen = ((esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)) >> 4) & 0xF
      if (I0DEB >0){ p "chen: " chen}
#  channels 1, 2, 3, 4
      if((chen & 0x1) == 1) {
         tablu_chen[myindice][4] = 1
      }
      if((chen & 0x2) == 2) {
         tablu_chen[myindice][1] = 1
      }
      if((chen & 0x4) == 4) {
         tablu_chen[myindice][2] = 1
      }
      if((chen & 0x8) == 8) {
         tablu_chen[myindice][3] = 1
      }

      if (tablu_bloc == 256) {
	 tablu_chdim[myindice]= 64
      }
      else {
	 tablu_chdim[myindice]= 32
      }

   }
     
}'

#%IU% (<I0_index>, <mezza>)
#%MDESC%
def _I0h_gethwinfo(i0_i,mezz)'{
   local myindice myp chen val x12

   myindice = 2*i0_i+mezz

   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezz) ){
      exit
   }

  tablu_bloc[myindice] = 0
  myp[0] = 2
  myp[1] = 0x2C

  I0h_selectmez(i0_i,mezz)
# get version
  val = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
  tablu_pudid[myindice] = (val>>12) & 0xF

  if(tablu_pudid[myindice] ==0x1) {
     tablu_xch[myindice] = val & 0xF
     x12 = (val>>4) & 0x1
     if(x12==0) {
        tablu_bloc[myindice] = 128
     } else {
        tablu_bloc[myindice] = 256
     }
     
     if(tablu_xch[myindice]==0x1) {
        if (tablu_bloc[myindice] == 256) {
	   tablu_chdim[myindice]= 256
        }
        else {
	   tablu_chdim[myindice]= 128
        }
     }
     if(tablu_xch[myindice]==0x2) {
        if (tablu_bloc[myindice] == 256) {
	   tablu_chdim[myindice]= 128
        }
        else {
	   tablu_chdim[myindice]= 64
        }
     }
     if(tablu_xch[myindice]==0x4) {
        if (tablu_bloc[myindice] == 256) {
	   tablu_chdim[myindice]= 64
        }
        else {
	   tablu_chdim[myindice]= 32
        }
     }
   }
   else {
     printf("\t!!!!!!!!!!!!PUDS IS NOT I0 !!!!\n")
   }
   
   tablu_chen[myindice][1] = 0
   tablu_chen[myindice][2] = 0
   tablu_chen[myindice][3] = 0
   tablu_chen[myindice][4] = 0     
}'


#%UU%
#%MDESC%gets some info from hardware.
def I0_gethwinfo'{
   local bo1 

#  it will fill tablu_pudid[], tablu_xch[] , tablu_bloc  
   for (bo1=0; bo1< I0_NBDEV; bo1++) {
#     1st mezzanine
      _I0h_gethwinfo(bo1,1)

#     2d mezzanine if there
      if (I0_ARR[bo1]["mezz2"]) {
         _I0h_gethwinfo(bo1,2)
      }
   }
}'

#%IU% (<I0_index>, <mezza>)
#%MDESC% sets hardware bit4 and bit5 to enable channels, according to version.
def _I0h_sethwchan(i0_i,mezz)'{
   local myindice myp chen x12 ret valc rett myval
   
   myindice = 2*i0_i+mezz

   if ( !_i0_check_board(i0_i) || !_i0_check_mezz(mezz) ){
      exit
   }
   
   myp[0] = 2
   tablu_chen[myindice][1] = 0
   tablu_chen[myindice][2] = 0
   tablu_chen[myindice][3] = 0
   tablu_chen[myindice][4] = 0

#  get hardware channel enable info

   myp[1] = 0x18
   valc = esrf_io(I0_ARR[i0_i]["dev"],"DevReadReg32",myp)
   if (I0DEB >0){ printf("reading %x\n",valc)}
   
   if(tablu_xch[myindice]==0x1) {
#  channel 4 or channel 2
      p "board: " i0_i " mezza: " mezz "   1-channel"
      _myret[myindice] = getval("enable ch4(0) or ch2(1)?",_myret[myindice])
      ret = _myret[myindice]
      if ( (ret !=0) && (ret !=1) ){
         p "you must answer 0 or 1. exit"
	 exit
      }  
#     clear bit4 and bit5
      valc = valc & 0xFFFFFFCF
      myval = ( ret << 5) & 0xF0
      myp[2] = valc | myval
      if (I0DEB >0){ printf("writing %x\n",myp[2])}
      rett = esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",myp)
      if (ret == 0){
         tablu_chen[myindice][4] = 1
      }
      else {
         tablu_chen[myindice][2] = 1
      }
   }

   if(tablu_xch[myindice]==0x2) {
#  0: channel 4 and channel 1
#  1: channel 1 and channel 2
#  2: channel 3 and channel 4
#  3: channel 2 and channel 3
      p "board: " i0_i " mezza: " mezz "   2-channel"
      _myret[myindice] = getval("enable ch4/ch1(0) or ch2/ch1(1) or ch3/ch4(2) or ch2/ch3(3)?",_myret[myindice])
      ret = _myret[myindice]
      if ( (ret !=0) && (ret !=1) && (ret !=2) && (ret !=3)){
         p "you must answer [0,1,2,3]. exit"
	 exit
      }  
#     clear bit4 and bit5
      valc = valc & 0xFFFFFFCF
      myval = (ret << 4) & 0xF0
      myp[2] = valc | myval
      if (I0DEB >0){ printf("writing %x\n",myp[2])}
      rett = esrf_io(I0_ARR[i0_i]["dev"],"DevWriteReg32",myp)
      if (ret == 0) {
         tablu_chen[myindice][4] = 1
         tablu_chen[myindice][1] = 1
      }
      else if (ret == 1) {
         tablu_chen[myindice][2] = 1
         tablu_chen[myindice][1] = 1
      }
      else if (ret == 2) {
         tablu_chen[myindice][3] = 1
         tablu_chen[myindice][4] = 1
      }
      else{
         tablu_chen[myindice][2] = 1
         tablu_chen[myindice][3] = 1
      }

   }
     
   if(tablu_xch[myindice]==0x4) {
#     nothing to do
      p "board: " i0_i " mezza: " mezz "   4-channel"
      tablu_chen[myindice][1] = 1
      tablu_chen[myindice][2] = 1
      tablu_chen[myindice][3] = 1
      tablu_chen[myindice][4] = 1
   }
     
}'

#%UU%
#%MDESC%sets hardware channel enable according to board version.
def I0_sethwchan'{
   local bo1 

#  it will fill tablu_chen[], tablu_xch[] , tablu_chdim  
   for (bo1=0; bo1< I0_NBDEV; bo1++) {
#     1st mezzanine
      _I0h_sethwchan(bo1,1)

#     2d mezzanine if there
      if (I0_ARR[bo1]["mezz2"]) {
         _I0h_sethwchan(bo1,2)
      }
   }
}'

#%UU%
#%MDESC%check user requirement with hardware
def I0_checkchinfo'{
   local bo1 ch myindicea
   
   for (bo1=0; bo1< I0_NBDEV; bo1++) {
      if (I0DEB >0){ p "board: " bo1}
      if (I0_ARR[bo1]["used"] == 1) {
#        1st mezzanine
         myindicea = 2*bo1 + 1
         for (ch=1; ch<5; ch++){
	    if ((I0_ARR[bo1][sprintf("ch1%d",ch)] == 1) && \
	        (tablu_chen[myindicea][ch] == 0)){
#              software enabled but not hardware enabled
	       p "ch " ch ": software: " I0_ARR[bo1][sprintf("ch1%d",ch)] " hardw: " tablu_chen[myindicea][ch] " INCONSISTANT!"
	    }else {
	       p "ch " ch ": software: " I0_ARR[bo1][sprintf("ch1%d",ch)] " hardw: " tablu_chen[myindicea][ch]
	    }	
	 }

#        2d mezzanine if there
         if (I0_ARR[bo1]["mezz2"]) {
         myindicea = 2*bo1 + 2
            for (ch=1; ch<5; ch++){
	       if ((I0_ARR[bo1][sprintf("ch2%d",ch)] == 1) && \
	           (tablu_chen[myindicea][ch] == 0)){
#                 software enabled but not hardware enabled
	          p "ch " ch ": software: " I0_ARR[bo1][sprintf("ch2%d",ch)] " hardw: " tablu_chen[myindicea][ch] " INCONSISTANT!"
	       }
	       else {
	          p "ch " ch ": software: " I0_ARR[bo1][sprintf("ch2%d",ch)] " hardw: " tablu_chen[myindicea][ch]
	       
	       }	
	    }
         }
      }
   }
}'

#%UU% <0/1>
#%MDESC%set debug mode
def I0_debug'{
   global I0DEB
   
   I0DEB = $1
}'



#%MACROS%
#%IMACROS%
#%AUTHOR% G.Goujon, MCD
#%TOC%