esrf

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

#%TITLE% BV.MAC
#%NAME% BV.MAC - Macros for accessing the Standard Pneumatic BeamViewer (BV) control electronics through WAGO I/O station.

#%DESCRIPTION%
#%PRE%
# PAY PARTICULAR ATTENTION TO THE WAGO MODULES ORDERING: OUT IN LEDON LEDOFF GAIN ...
# more details forward. 
#
# These macros, on one hand, interfaces White Beam Viewers control boxes based on Wago,
# and on the other hand allow to set up macro motor for controlling screen pneumatic insertion/extraction,
# and macros counters to read in diode current or range settings.
#
# These macros relies on some particular naming convention in the wago taco resources.
# Each wago channel name is composed of 2 concatened strings <BV name><function key>. 
# 
# e.g. below are resources for 2 BV so called wb1 and wb2.
# ID20/wcid20c/wc/module0:   750-436,wb1status,wb1status,wb1status,wb1status, wb2status,wb2status,wb2status,wb2status
# ID20/wcid20c/wc/module1:   750-530,wb1out,wb1in,wb1ledon,wb1ledoff,wb1gain,wb1gain,wb1gain,wb1gain
# ID20/wcid20c/wc/module2:   750-530,wb2out,wb2in,wb2ledon,wb2ledoff,wb2gain,wb2gain,wb2gain,wb2gain
# ID20/wcid20c/wc/module3:   750-479,wb1curr,wb2curr
#
# A standard BV wago control box holds
# 4 channels of a module 750-436, "8 Channel Digital Input", to report on BV status. 
#   respectively: Screen OUT, Screen IN, Led ON, Remote Gain Setting Enabled (not used).
#   default function key is "status"
# 8 channels of a module 750-530, "8 Channel Digital Output", to control 
#	pneumatic screen insertion (function keys "out" and "in")
#	illuminator on/off (function keys "ledon" and "ledoff")
#	gain setting (4 channels) (function key "gain")
# 1 channel of a module  750-479,  "2 Channel +-10V Input", for diode current. (function key "curr")
#
# the default function keys listed above can eventually be changed by the way of these globals:
#
#  BVKEYS ["status"]="status"	
#  BVKEYS ["in"]="in"	
#  BVKEYS ["out"]="out"	
#  BVKEYS ["on"]="ledon"	
#  BVKEYS ["off"]="ledoff"	
#  BVKEYS ["range"]="gain"	
#  BVKEYS ["current"]="curr"	
#
#%PRE%
#%BR%
#%EXAMPLE%
#%DL%
#%DT% bvsetup wb1 wb2
#%DD% initialises software for 2 beamviewers so named wb1 wb2 in wago taco resources.
#%DD% it is COMPULSORY to run it also to have the macro motors and counters operationnal.
#%DT% bvstatus or bvshow
#%DD% displays the status of setup beam viewers.
#%PRE%
#
#== wb1 =================
#   Screen is      OUT
#   Illuminator is OFF
#   Range is       1uA
#   Current is     0.000976562 uA
#== wb2 =================
#   Screen is      OUT
#   Illuminator is OFF
#   Range is       10nA
#   Current is     0.00152588 nA
#%PRE%
#%DT% bvledon wb1 
#%DD% Switches on illuminator on wb1.
#%DT% bvledoff wb1 
#%DD% Switches off illuminator on wb1.
#%DT% bvrange wb1 100nA
#%DD% Sets up gain (actualy range 100nA) on wb1.
#%DD% available ranges are 1mA 100uA 10uA 1uA 100nA 10nA
#%DT% bvautorange wb1 
#%DD% Automatically Set up more accurate gain on wb1.
#%DT% bvin wb1
#%DD% inserts screen.
#%DT% bvout wb1
#%DD% removes screen.
#%XDL%
#
"""
   this macro file also allows to define MACRO MOTORS to control SCREEN INSERTION.
   you must define in SPEC config:

   - a bvscr MOTOR controller with as many channels as screens (eg 2):

   MOTORS       DEVICE    ADDR   <>MODE      NUM               <>TYPE
      YES       bvscr                          2          Macro Motors

   - Motors referring to that controller, with a MOTPAR:wbv parameter that
     is the Wago BV name. 

   MOT025 = MAC_MOT:9/0/0   2000  1  2000  200   50  125    0 0x003     wbv1  wbv1
   MOTPAR:wbv = wbv1
   MOT034 = MAC_MOT:9/0/1   2000  1  2000  200   50  125    0 0x003     wbv2  wbv2 
   MOTPAR:wbv = wbv2

   - Optional MOTPAR:cntlst parameter that keeps related counter mnemonics list. Those 
     counters are automatically disabled when screen is moved to 0. 

   MOT034 = MAC_MOT:9/0/1   2000  1  2000  200   50  125    0 0x003     wbv2  wbv2 
   MOTPAR:cntlst = bv2in bv2x bv2y bv2fwy bv2fwx

   this macro file also allows to define MACRO COUNTERS to read in diode CURRENT or
   RANGE.

   you must define in SPEC config:

   - as many bvcurrent SCALER controller as many diode you read:
     ADDR holds the corresponding Wago BV name. 	

   SCALERS        DEVICE   ADDR  <>MODE  NUM                                 <>TYPE
        YES     bvcurrent   wbv1            3                          Macro Counter
        YES     bvcurrent   wbv2            3                          Macro Counter

   - Counters in config, the channel defines what to read from the controller.
     chan == 0 will read in direct ADC value
     chan == 1 will read value converted in nA
     chan == 2 will read the setup range in nA

   14   <unter 14       dio1   MAC_CNT     0     0    counter             1
   15   <unter 15       rge1   MAC_CNT     0     2    counter             1
   16   <unter 16       cur2   MAC_CNT     1     1    counter             1


"""


#%END%

##############################################################################
#
#            I N S E R T I O N   M A C R O S   M O T O R S    
#
##############################################################################

def bvscr_config (mne, type, unit, module, chan) '{

#  print "BVSCR CONFIG mne:"mne,"/ type:"type,"/ unit:" unit,"/ module:"module,"/ chan:" chan 


  if (mne == "..") {
    print "Using BVSCR BeamViewer Macro Motor with",module,"channels configured. (MAC/CNT_MOT unit",unit")"

  } else {
  
    if (type == "mot") {

      local dev cntlst p1

      print "MOTOR",motor_name(mne),": ctrl BVSCR Unit",unit,"Module",module,"Channel",chan
      dev = motor_par(mne,"wbv")
      cntlst = motor_par(mne,"cntlst")
      if (__bv_read (dev, "status")==4) {
       p1 = (BV_WAGO [0] && !BV_WAGO[1])?0:(!BV_WAGO [0] && BV_WAGO[1])?1:0
       print "      Screen is     ",(BV_WAGO [0] && !BV_WAGO[1])?"IN":(!BV_WAGO [0] && BV_WAGO[1])?"OUT":"FAULT"
       cntlst = motor_par(mne,"cntlst")
       _bvscr_disable (cntlst,p1)

      } else {
#        return ".error."
      }
    }
  }
}'

def bvscr_cmd (mne, cmd, p1, p2) '{
  
#  print "BVSCR CMD mne:"mne,"/ cmd:"cmd,"/ p1:" p1,"/ p2:"p2

  if (mne=="..") {

    if (cmd=="preread_all") {
    } else if (cmd=="prestart_all") {
    } else if (cmd=="start_all") {
    } else if (cmd=="flush_all") {
    } else if (cmd=="abort_all") {
    }

  } else {

    local dev cntlst

    if (cmd=="get_status") {
      local reval
      retval = 0
      if (MOVING) {retval|=0x02}
      if (LOWLIMIT) {retval|=0x04}
      if (HIGLIMIT) {retval|=0x08}
      return retval            
    }
    else if (cmd=="preread_one") {
    }
    else if (cmd=="prestart_one") {
    }
    else if (cmd=="start_one") {
       # p1 : target position in dial units for absolute motion.
       # p2 : magnitude in dial units for relative motion.

       dev = motor_par(mne,"wbv")
       cntlst = motor_par(mne,"cntlst")
       if (p1==1) {
             __bv_pulse (dev,"in"); sleep(3)
             _bvscr_disable (cntlst,0)
       } else if (p1==0) {
             __bv_pulse (dev,"out"); sleep(3)
             _bvscr_disable (cntlst,1)
       } 
    }
    else if (cmd=="magnitude") {
       # p1 : position in dial units and includes sign of the move.
    }
    else if (cmd=="position") {
       local pos
       # pos = current motor pos in dial units.

      dev = motor_par(mne,"wbv")
      if (__bv_read (dev, "status")==4) {
        pos = (BV_WAGO [0] && !BV_WAGO[1])?1:(!BV_WAGO [0] && BV_WAGO[1])?0:-1
      } else {
        pos = -1
      }
      return pos
    }
  }
}'

def _bvscr_disable (cntlst,flag) '{

  local _cnta _no _i

  if (cntlst==0) return;
  if (cntlst=="") return;

  _no = split (cntlst,_cnta)

  for (_i=0;_i<_no;_i++) {
    print _cnta[_i],flag?"Disabled":"Enabled"
    counter_par(_cnta[_i],"disable",flag)
  }
}'

##############################################################################
#
#            C U R R E N T   M A C R O S   C O U N T E R S
#
##############################################################################

def bvcurrent_config(mne,type,unit,mod,chan) '{
    if (mne != "..") {
       print "Using " cnt_mne(mne) " as a BeamViewer BVCURRENT "chan" Macro Counter on " bvcurrent_ADDR
    }
}'

def bvcurrent_cmd(mne, cmd, p1, p2) '{

    local dev
    dev = bvcurrent_ADDR

    if (mne == ".." && cmd == "prestart_all") {
         # Clear all
    }

    if (mne == ".." && cmd == "halt_all") {
        # read hardware only once per card
       global _BV []

       _BV [dev] = __bv_read (dev,"current")
    }

    if (cmd == "counts") {
         local chan value rge

         chan = counter_par(mne,"channel")
         value = -1
 
         if (chan != 0) {

           if (__bv_read (dev, "range")==4) {

             rge=pow(10,BV_WAGO[0]*1+BV_WAGO[1]*2+BV_WAGO[2]*4)

             if (chan ==1 ) {
               value = _BV [dev]*rge
             } else if (chan ==2)  {
               value = rge*10
             } 
           }
         } else {
           value = _BV [dev]
         }
         return value
    }
}'

##############################################################################
#
#                       U S E R   C O N T R O L   M A C R O S 
#
##############################################################################

#%UU% <bv1name> [<bv2name> ...] 
#%MDESC% COMPULSORY command to use this set of macros to initialise software, even for using macros motors or counters.
def bvsetup '{

  global BVKEYS []
  global BVRANGE []

  global BV_DEVICE []

  BVKEYS ["status"]	=   BVKEYS["status"]?BVKEYS["status"]:"status"  
  BVKEYS ["in"]		=   BVKEYS["in"]?BVKEYS["in"]:"in"  
  BVKEYS ["out"]	=   BVKEYS["out"]?BVKEYS["out"]:"out"  
  BVKEYS ["on"]		=   BVKEYS["on"]?BVKEYS["on"]:"ledon"  
  BVKEYS ["off"]	=   BVKEYS["off"]? BVKEYS["off"]:"ledoff"  
  BVKEYS ["range"]	=   BVKEYS["range"]?BVKEYS["range"]:"gain"  
  BVKEYS ["current"]	=   BVKEYS["current"]?BVKEYS["current"]:"curr"  

  BVRANGE ["1mA"]   = "1010"
  BVRANGE ["100uA"] = "0010"
  BVRANGE ["10uA"]  = "1100" 
  BVRANGE ["1uA"]   = "0100"
  BVRANGE ["100nA"] = "1000"
  BVRANGE ["10nA"]  = "0000"
  BVRANGE [5]   = "1mA"
  BVRANGE [4] = "100uA"
  BVRANGE [3]  = "10uA"
  BVRANGE [2]   = "1uA"
  BVRANGE [1] = "100nA"
  BVRANGE [0]  = "10nA"
  
  local argv

  if ( ! split ("$*",argv)) {
    print "Usage: $0 [bv1key] [bv2key]"
  } else {
    for (i=0;i<$#;i++) {
      BV_DEVICE[argv[i]]=1
    }
  }
}'

#%UU% [<bv1name> <bv2name> ...]
#%MDESC% 
def bvunsetup '{

  local argv

  if ( ! split ("$*",argv)) {
    for (i in BV_DEVICE) {
        print "deleting " i
        delete BV_DEVICE[i]
      }
  } else {
    for (i=0;i<$#;i++) {
      if (argv[i] in BV_DEVICE) {
        print "deleting " argv[i]
        delete BV_DEVICE[argv[i]]
      }
    }
  }
}'

#%UU% 
#%MDESC% 
def bvstatus 'bvshow'

#%UU% 
#%MDESC% same as bvstatus.
def bvshow '{

  global BV_DEVICE []
  local dev 
  

  for (dev in BV_DEVICE) {
   if (BV_DEVICE[dev]==1) {
     print "==",dev,"=================" 
     _bvstatus (dev) 
     _bvrange  (dev)
     _bvcurrent(dev)
   }
  }
}'

#%UU% <bv1name> [<bv2name> ...]
#%MDESC% insert screen in beam.
def bvin '{
  local argv []

  if (split("$*",argv)<=0) {
     print "USAGE: $0 <bv1> [<bv2> ...]"
     exit
  }
  
  for (dev in argv) {
    if (!(argv[dev] in BV_DEVICE)) {
      printf ("ERROR: %s is unknown beam viewer.\n", argv[dev])
      printf ("\tHas \"bvsetup\" been done?\n")
      printf ("\tHint: \"bvstatus\" might help.\n")
    } else {
      printf ("== %s =================\n",argv[dev])	
      if (__bv_read (argv [dev], "status") == 4) {
        if (BV_WAGO [0] && !BV_WAGO[1]) {
          print "Screen is already IN."
        } else {
          print "Screen was",(!BV_WAGO [0] && BV_WAGO[1])?"OUT":"FAULT"
          __bv_pulse (argv [dev],"in"); sleep(3)
	  _bvstatus (argv [dev])
          _bvrange  (argv [dev])
          _bvcurrent(argv [dev])
        }
      } else {
        eprintf ("ERROR occured.\n")
      }
    }
    printf("\n")
  }
}'

#%UU% <bv1name> [<bv2name> ...]
#%MDESC% get screen out of beam.
def bvout '{

  local argv []

  if (split("$*",argv)<=0) {
     print "USAGE: $0 <bv1> [<bv2> ...]"
     exit
  }
  
  for (dev in argv) {
    if (!(argv[dev] in BV_DEVICE)) {
      printf ("ERROR: %s is unknown beam viewer.\n", argv[dev])
      printf ("\tHas \"bvsetup\" been done?\n")
      printf ("\tHint: \"bvstatus\" might help.\n")
    } else {
      printf ("== %s =================\n",argv[dev])
	
      if (__bv_read (argv [dev], "status")==4) {
        if (!BV_WAGO [0] && BV_WAGO[1]) {
          print "Screen is already OUT."
        } else {
          print "Screen was",(BV_WAGO [0] && !BV_WAGO[1])?"IN":"FAULT"
          __bv_pulse (argv [dev],"out");sleep(3)
  	  _bvstatus (argv [dev])
          _bvrange  (argv [dev])
          _bvcurrent(argv [dev])
        }
      } else {
        eprintf ("ERROR occured.\n")
      }
    }
    printf("\n")
  }

}'

#%UU% <bv1name> [<bv2name> ...]
#%MDESC% set internal light on.
def bvledon '{
  local argv []

  if (split("$*",argv)<=0) {
     print "USAGE: $0 <bv1> [<bv2> ...]"
     exit
  }
  
  for (dev in argv) {
    if (!(argv[dev] in BV_DEVICE)) {
      printf ("ERROR: %s is unknown beam viewer.\n", argv[dev])
      printf ("\tHas \"bvsetup\" been done?\n")
      printf ("\tHint: \"bvstatus\" might help.\n")
    } else {
      printf ("== %s =================\n",argv[dev])
	
      if (__bv_read (argv [dev], "status")==4) {
        if (BV_WAGO [2]) {
          print "Light is already ON."
        } else {
          print "Light was OFF."
          __bv_pulse (argv [dev],"on");sleep(0.1)
  	  _bvstatus (argv [dev])
          _bvrange  (argv [dev])
          _bvcurrent(argv [dev])
        }
      } else {
        eprintf ("ERROR occured.\n")
      }
    }
    printf("\n")
  }
}'

#%UU% <bv1name> [<bv2name> ...]
#%MDESC% set internal light off.
def bvledoff '{
  local argv []

  if (split("$*",argv)<=0) {
     print "USAGE: $0 <bv1> [<bv2> ...]"
     exit
  }

  for (dev in argv) {
    if (!(argv[dev] in BV_DEVICE)) {
      printf ("ERROR: %s is unknown beam viewer.\n", argv[dev])
      printf ("\tHas \"bvsetup\" been done?\n")
      printf ("\tHint: \"bvstatus\" might help.\n")
    } else {
      printf ("== %s =================\n",argv[dev])
	
      if (__bv_read (argv [dev], "status")==4) {
        if (!BV_WAGO [2]) {
          print "Light is already OFF."
        } else {
          print "Light was ON."
          __bv_pulse (argv [dev],"off");sleep(0.1)
  	  _bvstatus (argv [dev])
          _bvrange  (argv [dev])
          _bvcurrent(argv [dev])
        }
      } else {
        eprintf ("ERROR occured.\n")
      }
    }
    printf("\n")
  }
}'

#%UU% <bv1name> <range> [<bv2name> <range>...]
#%MDESC% set up diode current ADC range. available ranges: 1mA 100uA 10uA 1uA 100nA 10nA
def bvrange '{ 
  local argv []
  local n args range rr nn

  for (nn in BVRANGE) {
    if(length(nn) > 1)
      range = sprintf ("%s %s", range, nn)
  }

  if ((n = split("$*",argv))<=0 || (int(n/2)!=n/2)) {
     print "USAGE: $0 <bv1> <range> [<bv2> <range> ...]"
     printf ("available range values:%s\n", range)
     exit
  }
  
  for (i=0;i<n;i+=2) {
    if (!(argv[dev] in BV_DEVICE)) {
      printf ("ERROR: %s is unknown beam viewer.\n", argv[dev])
      printf ("\tHas \"bvsetup\" been done?\n")
      printf ("\tHint: \"bvstatus\" might help.\n")
      print "USAGE: $0 <bv1> <range> [<bv2> <range> ...]"
      printf ("available range values:%s\n", range)
      exit
    }
    rr = -1
    for (nn in BVRANGE) {
      if (length(nn) == 1) {
        if (argv [i+1] == BVRANGE[nn]) {
          rr = 0
          break
        }
      }
    }
    if (rr == -1) {
      printf ("available range values:%s\n", range)
      exit
    }
    printf ("== %s =================\n",argv[dev])
    __bv_setrange (argv[i], argv [i+1])
    _bvstatus  (argv[i])
    _bvrange   (argv[i])
    _bvcurrent (argv[i])
  }
}'

#%UU% <bv1name> [<bv2name> ...]
#%MDESC% automatic set up of diode current ADC.
def bvautorange '{
local argv []

  if (split("$*",argv)<=0) {
    print "USAGE: $0 <bv1> [<bv2> ...]"
    exit
  }

  for (dev in argv) {
    if (!(argv[dev] in BV_DEVICE)) {
      printf ("ERROR: %s is unknown beam viewer.\n", argv[dev])
      printf ("       Has \"bvsetup\" been done?\n")
      printf (" HINT: \"bvstatus\" might help.\n")
    } else {
      printf ("== %s =================\n",argv[dev])
      if (_bvautorange(argv[dev]) == 0) {
        _bvstatus   (argv [dev])
        _bvrange    (argv [dev])
        _bvcurrent  (argv [dev])
      }
    }
    printf("\n")
  }
}' 

#%UU% <bv1name> [<bv2name> ...]
#%MDESC% adjust the range for the bv1name> [<bv2name> ...] beam viewer(s)
#diode. the procedure starts with the most sensitive range possible.
def bvadjustrange '{
local argv[]

  if (split("$*",argv)<=0) {
     print "USAGE: $0 <bv1> [<bv2> ...]"
     exit
  }
  
  for (dev in argv) {
    if (!(argv[dev] in BV_DEVICE)) {
      printf ("ERROR: %s is unknown beam viewer.\n", argv[dev])
      printf ("       Has \"bvsetup\" been done?\n")
      printf (" HINT: \"bvstatus\" might help.\n")
    } else {
      printf ("== %s =================\n",argv[dev])

      if (_bvadjustrange(argv[dev]) == 0) {
        _bvstatus   (argv [dev])
        _bvrange    (argv [dev])
        _bvcurrent  (argv [dev])
      }
    }
  }
}'

######################################################################################################
#
#                                 D E V   F U N CT I O N S
#
######################################################################################################

##################
#%IU%
#%MDESC%
def _bvstatus(dev) '{
     if (__bv_read (dev, "status")==4) {
       print "   Screen is     ",(BV_WAGO [0] && !BV_WAGO[1])?"IN":(!BV_WAGO [0] && BV_WAGO[1])?"OUT":"FAULT"
       print "   Illuminator is",BV_WAGO [2]?"ON":"OFF"
#       print "   Remote gain is",BV_WAGO [3]?"Enabled":"Disabled"
     } else {
       print "   ERROR"
     }
}'


#%IU%
#%MDESC%
def _bvrange (dev) '{
     if (__bv_read (dev, "range")==4) {
       print "   Range is      ", BVRANGE[BV_WAGO[0]*1+BV_WAGO[1]*2+BV_WAGO[2]*4]	

     } else {
       print "   ERROR occured."
     }
}'

#%IU% (dev)
#%MDESC% read the current of the %B%dev%B% beam viewer diode.
def _bvcurrent (dev) '{

       local value range
       value = __bv_read (dev,"current")
       if (__bv_read (dev, "range")==4) {
         range = BVRANGE[BV_WAGO[0]*1+BV_WAGO[1]*2+BV_WAGO[2]*4]	
         rg0=substr(range,1,length(range)-2)
         rg1=substr(range,length(range)-1)

         print "   Current is    ",value/10*rg0,rg1

     } else {
       print "   ERROR occured."
       return -1
     }
}'

#%IU% (dev)
#%MDESC% adjust automatically the range for the %B%dev%B% beam viewer diode.
#Procedure starting with the current range.
def _bvautorange (dev) '{
local idx value

  if (__bv_read (dev, "status") == 4) {
    if (!(BV_WAGO [0] && !BV_WAGO[1])) {
      eprintf("ERROR: the screen is not in, will not continue\n")
      return(-1)
    }
  }

  msg = "diode saturated at its less sensitive range"

  while ((value = __bv_read (dev,"current")) > 9.9) {
    if (__bv_read (dev, "range") == 4) {
      idx = BV_WAGO[0]*1+BV_WAGO[1]*2+BV_WAGO[2]*4
      printf("  AUTORANGING - value measured: %f for range of %s\n", \
	value, BVRANGE[idx])

      if (idx<5) {
        __bv_setrange (dev, BVRANGE[++idx])
      } else {
        eprintf("  WARNING: %s, will not procede", msg)
        return(-1)
      }
    } else {
      eprintf ("  ERROR occured.\n")
      return(-1)
    }
  }

  msg = "cannot set more accurate range"
  while (value < 0.98) {
    if (__bv_read (dev, "range") == 4) {
      idx = BV_WAGO[0]*1+BV_WAGO[1]*2+BV_WAGO[2]*4
      printf("  AUTORANGING - value measured: %f for range of %s\n", \
	value, BVRANGE[idx])  

      if (idx>0) {
        __bv_setrange (dev, BVRANGE[--idx])
      } else {
        eprintf("  WARNING: %s, will not procede", msg)
        return(-1)
      }		 
    } else {
      eprintf ("  ERROR occured.\n")
      return(-1)
    }
    value = __bv_read (dev,"current") 
  }

  if (__bv_read (dev, "range") == 4) {
    idx = BV_WAGO[0]*1+BV_WAGO[1]*2+BV_WAGO[2]*4
    printf("  AUTORANGING - value measured: %f for range of %s\n", \
	value, BVRANGE[idx]) 
    return idx 	
  } else {
    eprintf ("  ERROR occured.\n")
    return(-1)
  }
}'

#%IU% (dev)
#%MDESC% adjust automatically the range for the %B%dev%B% beam viewer diode.
#Procedure starting with the most sensitive range.
def _bvadjustrange(dev) '{
local value range r0 msg

  if (__bv_read (dev, "status") == 4) {
    if (!(BV_WAGO [0] && !BV_WAGO[1])) {
      eprintf("The %s screen is not in, will not continue\n", dev)
      return(-1)
    }
  }

  msg = "Diode saturated at its less sensituve range"
  value = __bv_read (dev,"current")
  if (__bv_read (dev, "range")==4)
    range = BV_WAGO[0]*1+BV_WAGO[1]*2+BV_WAGO[2]*4
  if ((range == 5) && (value > 9.9)) {
    eprintf("%s, will not adjust", msg)
    return(-1)
  }

  r0 = range
  #set the most sensitive range
  if (range > 0)
    range = 0
  __bv_setrange(dev, BVRANGE[0])

  while (__bv_read (dev,"current") > 9.9) {
    range += 1
    if (range > 5) {
      eprintf("%s, check your beam", msg)
      return(-1)
    }
    __bv_setrange(dev, BVRANGE[range])
  }

  if (r0 == range)
    printf ("Range not changed:\n")
  else
    printf("After the adjustment:\n")
  return(0)
}'

#######################################################################################
#
#                                W A G O   A C C E S S 
#
#######################################################################################


float array BV_WAGO [128]


#%IU% (dev, bvkey)
#%MDESC% read the %B%bvkey%B% channel for %B%dev%B%.
def __bv_read (dev, bvkey) '{
  
  local key module nch ds

  key = sprintf ("%s%s",dev,  BVKEYS[bvkey])

  if (key in WAGOKEYS) {
    module= WAGOKEYS[key]
    ds    = WAGOKEYS[key]["ds"]
    nch   = WAGOKEYS[key]["nch"]

    return wago_readch(key, BV_WAGO)
        
  } else {
    print "   ERROR:",key,"key not found."  
    print "          has \"wagosetup\" been done ?"
    print "         \"wagoshow\" might help."
    return -1
  }
}'

#%IU% (dev, inout)
#%MDESC% set the %B%inout%B% channel for %B%dev%B%.
def __bv_pulse (dev,inout)'{

  local key module nch ds

  key = sprintf ("%s%s",dev,  BVKEYS[inout])

  if (key in WAGOKEYS) {
    module= WAGOKEYS[key]
    ds    = WAGOKEYS[key]["ds"]
    nch   = WAGOKEYS[key]["nch"]

    if (wago_writech(key, 0)>0) {
	sleep(0.01)
        wago_writech(key, 1)
	sleep(0.01)
        wago_writech(key, 0)
    }

  } else {
    print "ERROR:",key,"key not found."  
    print "       has \"wagosetup\" been done ?"
    print "       \"wagoshow\" might help."
    return -1
  }
}'

#%IU% (dev, range)
#%MDESC% set the %B%range%B% for %B%dev%B%.
def __bv_setrange (dev , range)'{
       
  local key item nch ds

  key = sprintf ("%s%s",dev,  BVKEYS["range"])

  if (key in WAGOKEYS) {
     item  = WAGOKEYS[key]
     ds    = WAGOKEYS[key]["ds"]
     nch   = WAGOKEYS[key]["nch"]

     if ((range in BVRANGE) && (length(range>2))) {

       local short array rangevalue [4]

       rangevalue[0]=substr (BVRANGE[range],1,1)+0
       rangevalue[1]=substr (BVRANGE[range],2,1)+0
       rangevalue[2]=substr (BVRANGE[range],3,1)+0
       rangevalue[3]=0

       return wago_writech(key, rangevalue)

     } else {
       str=""
       for (bli in BVRANGE) { if (length(bli)>2) { str=sprintf("%s %s",str,bli) }} ;
       print "ERROR:",range,"is unknown range."  
       print "       has \"bvsetup\" been done ?"
       print "       allowed range are ",str
       return -1
     }

  } else {
    print "ERROR:",key,"key not found."  
    print "       has \"wagosetup\" been done ?"
    print "       \"wagoshow\" might help."
    return -1
  }
              
}'

#%MACROS%
#%IMACROS%
#%AUTHOR% BCU - MCL - 2012/10/12 - based on E.Paiser-Ph.Chappelet macros.
#%TOC%