Index: /trunk/FACT++/src/biasctrl.cc
===================================================================
--- /trunk/FACT++/src/biasctrl.cc	(revision 11947)
+++ /trunk/FACT++/src/biasctrl.cc	(revision 11948)
@@ -756,4 +756,10 @@
     bool ChannelSetVolt(uint16_t ch, double volt)
     {
+        if (volt<0 || volt>90)
+        {
+            Error("ChannelSetVolt - Voltage out of range [0V,90V].");
+            return false;
+        }
+
         return ChannelSetDac(ch, volt*4096/90.);
     }
@@ -775,20 +781,67 @@
     bool GlobalSetVolt(float volt)
     {
+        if (volt<0 || volt>90)
+        {
+            Error("GlobalSetVolt - Voltage out of range [0V,90V].");
+            return false;
+        }
+
         return GlobalSetDac(volt*4096/90);
     }
 
-    // --------------------------------------------------------------------
-
-    bool SetGapdVoltage()
+    bool GlobalAddDac(int16_t dac)
     {
         for (size_t ch=0; ch<kNumChannels; ch++)
-            if (fVoltGapd[ch]>kMaxDac)
+        {
+            if (fVoltRef[ch]+dac>kMaxDac)
             {
-                Error("SetGapdVoltage - Voltage reference for G-APD channel out of range.");
+                Error("GlobalAddDac - New voltage reference out of range.");
                 return false;
             }
 
+            if (fVoltRef[ch]+dac<0)
+                fVoltRef[ch] = 0;
+            else
+                fVoltRef[ch]+= dac;
+        }
+
+        if (!fIsRamping)
+            fIsRamping = RampOneStep();
+
+        return true;
+    }
+
+    bool GlobalAddVolt(float offset)
+    {
+        if (offset<-90 || offset>90)
+        {
+            Error("GlobalAddVolt - Offset out of range [-90V,90V].");
+            return false;
+        }
+
+        return GlobalAddDac(offset*4096/90);
+    }
+
+    // --------------------------------------------------------------------
+
+    bool SetGapdVoltage(float offset)
+    {
+        if (offset<-90 || offset>90)
+        {
+            Error("SetGapdVoltage - Offset out of range [-90V,90V].");
+            return false;
+        }
+
+        const int16_t dac = offset*4096/90;
+
         for (size_t ch=0; ch<kNumChannels; ch++)
-            fVoltRef[ch] = fVoltGapd[ch];
+            if (fVoltGapd[ch]+dac>kMaxDac)
+            {
+                Error("SetGapdVoltage - New voltage reference out of range.");
+                return false;
+            }
+
+        for (size_t ch=0; ch<kNumChannels; ch++)
+            fVoltRef[ch] = fVoltGapd[ch]+dac<0 ? 0 : fVoltGapd[ch]+dac;
 
         if (!fIsRamping)
@@ -1192,4 +1245,16 @@
     // --------------------------------------------------------------------
 
+    int SetGapdVoltage(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetGapdVoltage", 4))
+            return false;
+
+        fBias.SetGapdVoltage(evt.GetFloat());
+
+        return T::GetCurrentState();
+    }
+
+    // --------------------------------------------------------------------
+
     int SetGlobalVolt(const EventImp &evt)
     {
@@ -1197,6 +1262,5 @@
             return false;
 
-        if (!fBias.GlobalSetVolt(evt.GetFloat()))
-            T::Error("Supplied voltage out of range (0-90)");
+        fBias.GlobalSetVolt(evt.GetFloat());
 
         return T::GetCurrentState();
@@ -1208,10 +1272,49 @@
             return false;
 
-        if (!fBias.GlobalSetDac(evt.GetUShort()))
-            T::Error("Supplied voltage out of range (0-90)");
+        fBias.GlobalSetDac(evt.GetUShort());
 
         return T::GetCurrentState();
     }
 
+    int IncGlobalVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "IncGlobalVolt", 4))
+            return false;
+
+        fBias.GlobalAddVolt(evt.GetFloat());
+
+        return T::GetCurrentState();
+    }
+
+    int IncGlobalDac(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "IncGlobalDac", 2))
+            return false;
+
+        fBias.GlobalAddDac(evt.GetShort());
+
+        return T::GetCurrentState();
+    }
+
+    int DecGlobalVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "DecGlobalVolt", 4))
+            return false;
+
+        fBias.GlobalAddVolt(-evt.GetFloat());
+
+        return T::GetCurrentState();
+    }
+
+    int DecGlobalDac(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "DecGlobalDac", 2))
+            return false;
+
+        fBias.GlobalAddDac(-evt.GetShort());
+
+        return T::GetCurrentState();
+    }
+
     int SetChannelVolt(const EventImp &evt)
     {
@@ -1219,6 +1322,5 @@
             return false;
 
-        if (!fBias.ChannelSetVolt(evt.GetUShort(), evt.Get<float>(2)))
-            T::Error("Value out of range");
+        fBias.ChannelSetVolt(evt.GetUShort(), evt.Get<float>(2));
 
         return T::GetCurrentState();
@@ -1230,6 +1332,5 @@
             return false;
 
-        if (!fBias.ChannelSetDac(evt.Get<uint16_t>(), evt.Get<uint16_t>(2)))
-            T::Error("Value out of range");
+        fBias.ChannelSetDac(evt.Get<uint16_t>(), evt.Get<uint16_t>(2));
 
         return T::GetCurrentState();
@@ -1243,6 +1344,5 @@
             return false;
 
-        if (!fBias.ExpertGlobalSetVolt(evt.GetFloat()))
-            T::Error("Supplied voltage out of range (0-90)");
+        fBias.ExpertGlobalSetVolt(evt.GetFloat());
 
         return T::GetCurrentState();
@@ -1254,6 +1354,5 @@
             return false;
 
-        if (!fBias.ExpertGlobalSetDac(evt.GetUShort()))
-            T::Error("Supplied voltage out of range (0-90)");
+        fBias.ExpertGlobalSetDac(evt.GetUShort());
 
         return T::GetCurrentState();
@@ -1265,6 +1364,5 @@
             return false;
 
-        if (!fBias.ExpertChannelSetVolt(evt.GetUShort(), evt.Get<float>(2)))
-            T::Error("Value out of range");
+        fBias.ExpertChannelSetVolt(evt.GetUShort(), evt.Get<float>(2));
 
         return T::GetCurrentState();
@@ -1276,6 +1374,5 @@
             return false;
 
-        if (!fBias.ExpertChannelSetDac(evt.Get<uint16_t>(), evt.Get<uint16_t>(2)))
-            T::Error("Value out of range");
+        fBias.ExpertChannelSetDac(evt.Get<uint16_t>(), evt.Get<uint16_t>(2));
 
         return T::GetCurrentState();
@@ -1425,4 +1522,20 @@
             ("Set all channels to a new DAC reference. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)");
 
+        T::AddEvent("INCREASE_GLOBAL_VOLTAGE", "F:1", kConnected, kAtReference, kOverCurrent)
+            (bind(&StateMachineBias::IncGlobalVolt, this, placeholders::_1))
+            ("Set all channels to a new reference voltage. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)");
+
+        T::AddEvent("INCREASE_GLOBAL_DAC", "S:1", kConnected, kAtReference, kOverCurrent)
+            (bind(&StateMachineBias::IncGlobalDac, this, placeholders::_1))
+            ("Set all channels to a new DAC reference. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)");
+
+        T::AddEvent("DECREASE_GLOBAL_VOLTAGE", "F:1", kConnected, kAtReference, kOverCurrent)
+            (bind(&StateMachineBias::DecGlobalVolt, this, placeholders::_1))
+            ("Set all channels to a new reference voltage. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)");
+
+        T::AddEvent("DECREASE_GLOBAL_DAC", "S:1", kConnected, kAtReference, kOverCurrent)
+            (bind(&StateMachineBias::DecGlobalDac, this, placeholders::_1))
+            ("Set all channels to a new DAC reference. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)");
+
         T::AddEvent("SET_CHANNEL_VOLTAGE", "S:1;F:1", kConnected, kAtReference, kOverCurrent)
             (bind(&StateMachineBias::SetChannelVolt, this, placeholders::_1))
@@ -1434,6 +1547,10 @@
 
         T::AddEvent("SET_GAPD_REFERENCE_VOLTAGE", kConnected, kAtReference, kOverCurrent)
-            (Wrapper(bind(&ConnectionBias::SetGapdVoltage, &fBias)))
+            (Wrapper(bind(&ConnectionBias::SetGapdVoltage, &fBias, 0.)))
             ("Set all channels to their G-APD reference voltage. Starts ramping if necessary.");
+
+        T::AddEvent("SET_GAPD_REFERENCE_OFFSET", "F:1", kConnected, kAtReference, kOverCurrent)
+            (bind(&StateMachineBias::SetGapdVoltage, this, placeholders::_1))
+            ("Set all channels to their G-APD reference voltage plus the given offset. Starts ramping if necessary.");
 
         T::AddEvent("SET_ZERO_VOLTAGE", kConnected, kAtReference, kOverCurrent)
@@ -1606,5 +1723,5 @@
         ("dev",             var<string>("FTE00FOH"),  "Device address of USB port to bias-power supply")
         ("quiet,q",         po_bool(),           "Disable printing contents of all received messages (except dynamic data) in clear text.")
-        ("ramp-time",       var<uint16_t>(15),   "Delay between the answer of one ramping steps and sending the next ramp command to all channels in milliseconds.")
+        ("ramp-time",       var<uint16_t>(15),   "Delay between the answer of one ramping step and sending the next ramp command to all channels in milliseconds.")
         ("ramp-step",       var<uint16_t>(46),   "Maximum step in DAC counts during ramping (Volt = DAC*90/4096)")
         ("update-interval", var<uint16_t>(3000), "Interval between two current requests in milliseconds")
@@ -1630,10 +1747,13 @@
 {
     cout <<
-        "The biasctrl controls the bias-power supply boards.\n"
+        "The biasctrl program controls the bias-power supply boards.\n"
         "\n"
-        "The default is that the program is started without user intercation. "
-        "All actions are supposed to arrive as DimCommands. Using the -c "
-        "option, a local shell can be initialized. With h or help a short "
-        "help message about the usuage can be brought to the screen.\n"
+        "Note: At default the program is started without a command line (user) "
+        "interface. In this case Actions/Commands are available via Dim "
+        "exclusively.\n"
+        "Use the -c option to start the program with a command line interface.\n"
+        "\n"
+        "In the running application:\n"
+        "Use h or help to print a short help message about its usage.\n"
         "\n"
         "Usage: biasctrl [-c type] [OPTIONS]\n"
