Index: trunk/FACT++/src/biasctrl.cc
===================================================================
--- trunk/FACT++/src/biasctrl.cc	(revision 13235)
+++ trunk/FACT++/src/biasctrl.cc	(revision 13236)
@@ -41,6 +41,5 @@
 
     bool fIsVerbose;
-
-    vector<uint16_t> fDacCmd;     // Current command voltage in DAC units (12bit = 90V)
+    bool fIsDummyMode;
 
     vector<bool>     fPresent;
@@ -50,5 +49,4 @@
 
     int16_t fGlobalDacCmd;      // Command value to be reached
-//    uint16_t fExpertVoltRef;      // Command value to be reached
 
     int16_t fRampStep;
@@ -65,13 +63,7 @@
 
 protected:
-    vector<uint16_t> fDac;        // Current voltage in DAC units (12bit = 90V)
-    vector<uint16_t> fDacRef;     // Current reference voltage in DAC units (12bit = 90V)
-    vector<uint16_t> fDacGapd;    // Nominal G-APD voltages at 25deg C
 
     vector<int16_t>  fCurrent;     // Current in ADC units (12bit = 5mA)
 
-    uint16_t fDacMaxAbs;
-    uint16_t fDacMaxRel;
-
     virtual void UpdateA()
     {
@@ -86,39 +78,21 @@
     }
 
+    // ====================================================
+
+    vector<float> fBreakdownVoltage;      // Breakdown voltage of GAPDs
+    vector<float> fOvervoltage;           // Requested overvoltage of GAPDs
+    vector<float> fChannelCalibration;    // Bias crate channel offset
+    vector<float> fChannelOffset;         // User defined channel offset
+
+    float fVoltageMaxAbs;  // Maximum voltage
+    float fVoltageMaxRel;  // Maximum voltgage above (what?)
+
+    vector<uint16_t> fDacTarget;    // Target values
+    vector<uint16_t> fDacCommand;   // Last sent command value
+    vector<uint16_t> fDacActual;    // Actual value
+
+    // ====================================================
+
 private:
-    bool CheckChDac(const string &cmd, uint16_t dac, uint16_t ch=0)
-    {
-        ostringstream str;
-        str << cmd << " - ";
-
-        if (ch>=kNumChannels)
-        {
-            str << "Channel " << ch << " out of range [0,416].";
-            Error(str);
-            return false;
-        }
-
-        if (dac>kMaxDac)
-        {
-            str << "DAC value " << dac << " out of range [0,4095].";
-            Error(str);
-            return false;
-        }
-        if (dac>fDacMaxAbs)
-        {
-            str << "DAC value " << dac << " exceeds allowed absolute maximum of " << fDacMaxAbs;
-            Error(str);
-            return false;
-        }
-        if (dac>fDacGapd[ch]+fDacMaxRel)
-        {
-            str << "DAC value " << dac << " exceeds allowed channel maximum of " << fDacGapd[ch] << " + " << fDacMaxRel;
-            Error(str);
-            return false;
-        }
-
-        return true;
-    }
-
     vector<char> GetCmd(uint16_t board, uint16_t channel, Command_t cmd, uint16_t dac=0)
     {
@@ -230,5 +204,5 @@
         {
             Message("Reset button on crate pressed!");
-            SetZero();
+            RampAllDacs(0);
             return true;
         }
@@ -251,5 +225,5 @@
             {
                 for (int i=0; i<kNumChannels; i++)
-                    fDac[i] = fGlobalDacCmd;
+                    fDacActual[i] = fGlobalDacCmd;
 
                 fGlobalDacCmd = -1;
@@ -293,5 +267,5 @@
 
         if (cmd==kCmdChannelSet)
-            fDac[id] = fDacCmd[id];
+            fDacActual[id] = fDacCommand[id];
 
         return true;
@@ -583,7 +557,7 @@
         if (fWrapCounter<0)
         {
-            fDac.assign(   kNumChannels, 0);
-            fDacRef.assign(kNumChannels, 0);
-            fDacCmd.assign(kNumChannels, 0);
+            fDacTarget.assign(kNumChannels, 0);
+            fDacCommand.assign(kNumChannels, 0);
+            fDacActual.assign(kNumChannels, 0);
         }
 
@@ -648,6 +622,46 @@
     // --------------------------------------------------------------------
 
+    void PrintLineCmdDac(int b, int ch, const vector<uint16_t> &dac)
+    {
+        Out() << setw(2) << b << "|";
+
+        for (int c=ch; c<ch+4; c++)
+        {
+            const int id = c+kNumChannelsPerBoard*b;
+            Out() << " " << setw(4) << int32_t(dac[id])<<"/"<<fDacActual[id] << ":" << setw(5) << fDacTarget[id]*90./4096;
+        }
+        Out() << endl;
+    }
+
+    void PrintCommandDac(const vector<uint16_t> &dac)
+    {
+        Out() << dec << setprecision(2) << fixed << setfill(' ');
+        for (int b=0; b<kNumBoards; b++)
+        {
+            if (!fPresent[b])
+            {
+                Out() << setw(2) << b << "-" << endl;
+                continue;
+            }
+
+            PrintLineCmdDac(b,  0, dac);
+            PrintLineCmdDac(b,  4, dac);
+            PrintLineCmdDac(b,  8, dac);
+            PrintLineCmdDac(b, 12, dac);
+            PrintLineCmdDac(b, 16, dac);
+            PrintLineCmdDac(b, 20, dac);
+            PrintLineCmdDac(b, 24, dac);
+            PrintLineCmdDac(b, 28, dac);
+        }
+    }
+
     void SetAllChannels(const vector<uint16_t> &dac, bool special=false)
     {
+        if (fIsDummyMode)
+        {
+            PrintCommandDac(dac);
+            return;
+        }
+
         vector<char> data;
         data.reserve(kNumChannels*3);
@@ -659,5 +673,5 @@
             data.insert(data.end(), cmd.begin(), cmd.end());
 
-            fDacCmd[ch] = dac[ch];
+            fDacCommand[ch] = dac[ch];
         }
 
@@ -674,11 +688,11 @@
     uint16_t RampOneStep(uint16_t ch)
     {
-        if (fDacRef[ch]>fDac[ch])
-            return fDac[ch]+fRampStep>fDacRef[ch] ? fDacRef[ch] : fDac[ch]+fRampStep;
-
-        if (fDacRef[ch]<fDac[ch])
-            return fDac[ch]-fRampStep<fDacRef[ch] ? fDacRef[ch] : fDac[ch]-fRampStep;
-
-        return fDac[ch];
+        if (fDacTarget[ch]>fDacActual[ch])
+            return fDacActual[ch]+fRampStep>fDacTarget[ch] ? fDacTarget[ch] : fDacActual[ch]+fRampStep;
+
+        if (fDacTarget[ch]<fDacActual[ch])
+            return fDacActual[ch]-fRampStep<fDacTarget[ch] ? fDacTarget[ch] : fDacActual[ch]-fRampStep;
+
+        return fDacActual[ch];
     }
 
@@ -702,5 +716,5 @@
         {
             dac[ch] = RampOneStep(ch);
-            if (dac[ch]!=fDac[ch] && fPresent[ch/kNumChannelsPerBoard])
+            if (dac[ch]!=fDacActual[ch] && fPresent[ch/kNumChannelsPerBoard])
                 identical = false;
         }
@@ -785,5 +799,5 @@
         fBufferUpdate(3*kNumChannels),
         fIsVerbose(false),
-        fDacCmd(kNumChannels),
+        fIsDummyMode(false),
         fPresent(kNumBoards),
         fWrapCounter(-1),
@@ -795,11 +809,217 @@
         fWaitingForAnswer(-1),
         fCounter(8),
-        fDac(kNumChannels),
-        fDacRef(kNumChannels),
-        fDacGapd(kNumChannels),
-        fCurrent(kNumChannels)
+        fCurrent(kNumChannels),
+        fBreakdownVoltage(kNumChannels, 0),
+        fOvervoltage(kNumChannels),
+        fChannelCalibration(kNumChannels),
+        fChannelOffset(kNumChannels),
+        fVoltageMaxAbs(75),
+        fVoltageMaxRel(2),
+        fDacTarget(kNumChannels),
+        fDacCommand(kNumChannels),
+        fDacActual(kNumChannels)
     {
         SetLogStream(&imp);
     }
+
+    // --------------------------------------------------------------------
+
+    bool CheckDac(uint16_t dac)
+    {
+        if (dac<4096)
+            return true;
+
+        ostringstream msg;
+        msg << "CheckDac - Dac value of " << dac << " exceeds maximum of 4095.";
+        Error(msg);
+        return false;
+    }
+
+    bool CheckChannel(uint16_t ch)
+    {
+        if (ch<kNumChannels)
+            return true;
+
+        ostringstream msg;
+        msg << "CheckChannel - Channel " << ch << " out of range [0;" << kNumChannels-1 << "].";
+        Error(msg);
+        return false;
+    }
+
+    bool CheckChannelVoltage(uint16_t ch, float volt)
+    {
+        if (volt>fVoltageMaxAbs)
+        {
+            ostringstream msg;
+            msg << "CheckChannelVoltage - Set voltage " << volt << "V of channel " << ch << " exeeds absolute limit of " << fVoltageMaxAbs << "V.";
+            Error(msg);
+            return false;
+        }
+
+        if (fBreakdownVoltage[ch]<=0)
+            return true;
+
+        if (volt>fBreakdownVoltage[ch]+fVoltageMaxRel)
+        {
+            ostringstream msg;
+            msg << "CheckChannelVoltage - Set voltage " << volt << "V of channel " << ch << " exeeds limit of " << fVoltageMaxRel << "V above breakdown voltage " << fBreakdownVoltage[ch] << "V + limit " << fVoltageMaxRel << "V.";
+            Error(msg);
+            return false;
+        }
+
+        return true;
+    }
+
+    // --------------------------------------------------------------------
+
+    bool RampSingleChannelDac(uint16_t ch, uint16_t dac)
+    {
+        if (!CheckChannel(ch))
+            return false;
+
+        if (!CheckDac(dac))
+            return false;
+
+        fDacTarget[ch] = dac;
+        UpdateV();
+
+        if (!fIsRamping)
+            fIsRamping = RampOneStep();
+
+        return true;
+    }
+
+    bool RampAllChannelsDac(const vector<uint16_t> &dac)
+    {
+        for (int ch=0; ch<kNumChannels; ch++)
+            if (!CheckDac(dac[ch]))
+                return false;
+
+        fDacTarget = dac;
+        UpdateV();
+
+        if (!fIsRamping)
+            fIsRamping = RampOneStep();
+
+        return true;
+    }
+
+    bool RampAllDacs(uint16_t dac)
+    {
+        return RampAllChannelsDac(vector<uint16_t>(kNumChannels, dac));
+    }
+
+    // --------------------------------------------------------------------
+
+    uint16_t ConvertVoltToDac(uint16_t ch, double volt)
+    {
+        volt += fChannelCalibration[ch];
+        if (volt<0)
+            volt = 0;
+
+        return volt*4096/90;
+    }
+
+    // --------------------------------------------------------------------
+
+    bool RampSingleChannelVoltage(uint16_t ch, float volt)
+    {
+        if (!CheckChannel(ch))
+            return false;
+
+        if (!CheckChannelVoltage(ch, volt))
+            return false;
+
+        const uint16_t dac = ConvertVoltToDac(ch, volt);
+        return RampSingleChannelDac(ch, dac);
+    }
+
+    bool RampAllChannelsVoltage(const vector<float> &volt)
+    {
+        vector<uint16_t> dac(kNumChannels);
+        for (size_t ch=0; ch<kNumChannels; ch++)
+        {
+            if (!CheckChannelVoltage(ch, volt[ch]))
+                return false;
+
+            dac[ch] = ConvertVoltToDac(ch, volt[ch]);
+        }
+
+        return RampAllChannelsDac(dac);
+    }
+
+    bool RampAllVoltages(float volt)
+    {
+        return RampAllChannelsVoltage(vector<float>(kNumChannels, volt));
+    }
+
+    // --------------------------------------------------------------------
+
+    bool RampSingleChannelOffset(uint16_t ch, float offset, bool relative)
+    {
+        if (!CheckChannel(ch))
+            return false;
+
+        if (relative)
+            offset += fDacActual[ch]*90./4096 - fBreakdownVoltage[ch] - fOvervoltage[ch];
+
+        const float volt = fBreakdownVoltage[ch]>0 ? fBreakdownVoltage[ch] + fOvervoltage[ch] + offset : 0;
+
+        if (!RampSingleChannelVoltage(ch, volt))
+            return false;
+
+        fChannelOffset[ch] = offset;
+
+        return true;
+    }
+
+    bool RampAllChannelsOffset(vector<float> offset, bool relative)
+    {
+        vector<float> volt(kNumChannels);
+
+        if (relative)
+            for (size_t ch=0; ch<kNumChannels; ch++)
+                offset[ch] += fDacActual[ch]*90./4096 - fBreakdownVoltage[ch] - fOvervoltage[ch];
+
+        for (size_t ch=0; ch<kNumChannels; ch++)
+            volt[ch] = fBreakdownVoltage[ch]>0 ? fBreakdownVoltage[ch] + fOvervoltage[ch] + offset[ch] : 0;
+
+        if (!RampAllChannelsVoltage(volt))
+            return false;
+
+        fChannelOffset = offset;
+
+        return true;
+    }
+
+    bool RampAllOffsets(float offset, bool relative)
+    {
+        return RampAllChannelsOffset(vector<float>(kNumChannels, offset), relative);
+    }
+
+    /*
+    bool RampSingleChannelOvervoltage(float offset)
+    {
+        return RampAllChannelsOvervoltage(vector<float>(kNumChannels, offset));
+    }
+    bool RampAllOvervoltages(const vector<float> &overvoltage)
+    {
+        vector<float> volt(kNumChannels);
+
+        for (size_t ch=0; ch<kNumChannels; ch++)
+            volt[ch] = fBreakdownVoltage[ch] + fOvervoltage[ch] + fChannelOffset[ch];
+
+#warning What about empty channels?
+
+        if (!RampAllChannelsVoltage(volt))
+            return false;
+
+        for (size_t ch=0; ch<kNumChannels; ch++)
+            fOvervoltage[ch] = overvoltage[ch];
+
+        return true;
+    }*/
+
+    // --------------------------------------------------------------------
 
     void OverCurrentReset()
@@ -819,8 +1039,9 @@
         }
 
-        vector<uint16_t> dac(kNumChannels);
+        vector<uint16_t> dac(fDacActual);
 
         for (int ch=0; ch<kNumChannels; ch++)
-            dac[ch] = fCurrent[ch]<0 ? 0 : fDac[ch];
+            if (fCurrent[ch]<0)
+                dac[ch] = 0;
 
         SetAllChannels(dac, true);
@@ -856,268 +1077,24 @@
     }
 
-    // --------------------------------------------------------------------
-
-    bool ChannelSetDac(uint16_t ch, uint16_t dac)
-    {
-        if (!CheckChDac("ChannelSetDac", dac, ch))
-            return false;
-
-        fDacRef[ch] = dac;
-
-        if (!fIsRamping)
-            fIsRamping = RampOneStep();
-
-        return true;
-    }
-
-    bool ChannelSetVolt(uint16_t ch, double volt)
-    {
-        if (volt<0 || volt>90)
-        {
-            ostringstream msg;
-            msg << "ChannelSetVolt - Given voltage " << volt << "V out of range [0V,90V].";
-            Error(msg);
-            return false;
-        }
-
-        return ChannelSetDac(ch, volt*4096/90.);
-    }
-/*
-    bool GlobalSetDac(uint16_t dac)
-    {
-        if (!CheckChDac("GlobalSetDac", dac))
-            return false;
-
-        for (size_t ch=0; ch<kNumChannels; ch++)
-            fVoltRef[ch] = dac;
-
-        if (!fIsRamping)
-            fIsRamping = RampOneStep();
-
-        return true;
-    }
-
-    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 AddDac(const vector<int16_t> &dac)
-    {
-        if (dac.size()!=kNumChannels)
-        {
-            Error("AddDac - Wrong size of array.");
-            return false;
-        }
-
-        for (size_t ch=0; ch<kNumChannels; ch++)
-        {
-            if (fDacRef[ch]+dac[ch]>kMaxDac)
-            {
-                ostringstream msg;
-                msg << "AddDac - New voltage reference " << fDacRef[ch] << "+" << dac[ch] << " out of range [0," << kMaxDac << " for channel " << ch << ".";
-                Error(msg);
-                return false;
-            }
-
-            if (fDacRef[ch]+dac[ch]<0)
-                fDacRef[ch] = 0;
-            else
-                fDacRef[ch] += dac[ch];
-        }
-
-        if (!fIsRamping)
-            fIsRamping = RampOneStep();
-
-        return true;
-    }
-
-    bool AddVolt(const vector<float> &offset)
-    {
-        vector<int16_t> dac(offset.size());
-
-        for (size_t ch=0; ch<offset.size(); ch++)
-        {
-            if (offset[ch]<-90 || offset[ch]>90)
-            {
-                ostringstream msg;
-                msg << "AddVolt - Offset voltage " << offset[ch] << "V for channel " << ch << " out of range [-90V,90V].";
-                Error(msg);
-                return false;
-            }
-            dac[ch] = offset[ch]*4096/90;
-        }
-
-        return AddDac(dac);
-    }
-
-    bool GlobalAddDac(int16_t offset)
-    {
-        return AddDac(vector<int16_t>(kNumChannels, offset));
-    }
-
-    bool GlobalAddVolt(float offset)
-    {
-        return AddVolt(vector<float>(kNumChannels, offset));
-    }
-
-    bool SetDac(const vector<int16_t> &dac)
-    {
-        if (dac.size()!=kNumChannels)
-        {
-            Error("SetDac - Wrong size of array.");
-            return false;
-        }
-
-        for (size_t ch=0; ch<kNumChannels; ch++)
-        {
-            if (!CheckChDac("SetDac", dac[ch]))
-                return false;
-
-            fDacRef[ch] = dac[ch];
-        }
-
-        if (!fIsRamping)
-            fIsRamping = RampOneStep();
-
-        return true;
-    }
-
-    bool SetVolt(const vector<float> &volt)
-    {
-        vector<int16_t> dac(volt.size());
-
-        for (size_t ch=0; ch<volt.size(); ch++)
-        {
-            if (volt[ch]<0 || volt[ch]>90)
-            {
-                ostringstream msg;
-                msg << "SetVolt - Voltage " << volt[ch] << "V out of range [0V,90V] for channel " << ch << ".";
-                Error(msg);
-                return false;
-            }
-            dac[ch] = volt[ch]*4096/90;
-        }
-
-        return SetDac(dac);
-    }
-
-    bool GlobalSetDac(int16_t dac)
-    {
-        return SetDac(vector<int16_t>(kNumChannels, dac));
-    }
-
-    bool GlobalSetVolt(float volt)
-    {
-        return SetVolt(vector<float>(kNumChannels, volt));
-    }
-
-
-    // --------------------------------------------------------------------
-
-    bool SetGapdVoltage(float offset)
-    {
-        if (offset<-90 || offset>90)
-        {
-            ostringstream msg;
-            msg << "SetGapdVoltage - Offset voltage " << offset << "V out of range [-90V,90V].";
-            Error(msg);
-            return false;
-        }
-
-        const int16_t dac = offset*4096/90;
-
-        for (size_t ch=0; ch<kNumChannels; ch++)
-            if (fDacGapd[ch]+dac>kMaxDac)
-            {
-                ostringstream msg;
-                msg << "SetGapdVoltage - New voltage reference " << fDacGapd[ch] << "+" << dac << " out of range [0," << kMaxDac << " for channel " << ch << ".";
-                Error(msg);
-                return false;
-            }
-
-        for (size_t ch=0; ch<kNumChannels; ch++)
-            fDacRef[ch] = fDacGapd[ch]+dac<0 ? 0 : fDacGapd[ch]+dac;
-
-        if (!fIsRamping)
-            fIsRamping = RampOneStep();
-
-        return true;
-    }
-
-    bool SetGapdVoltages(const vector<float> &offset)
-    {
-        vector<int16_t> dac(kNumChannels);
-        for (size_t ch=0; ch<kNumChannels; ch++)
-        {
-            if (offset[ch]<-90 || offset[ch]>90)
-            {
-                ostringstream msg;
-                msg << "SetGapdVoltage - Offset voltage " << offset[ch] << "V of channel " << ch << " out of range [-90V,90V].";
-                Error(msg);
-                return false;
-            }
-
-            dac[ch] = offset[ch]*4096/90;
-
-            if (fDacGapd[ch]+dac[ch]>kMaxDac)
-            {
-                ostringstream msg;
-                msg << "SetGapdVoltage - New voltage reference " << fDacGapd[ch] << "+" << dac[ch] << " out of range [0," << kMaxDac << " for channel " << ch << ".";
-                Error(msg);
-                return false;
-            }
-        }
-
-        for (size_t ch=0; ch<kNumChannels; ch++)
-            fDacRef[ch] = fDacGapd[ch]+dac[ch]<0 ? 0 : fDacGapd[ch]+dac[ch];
-
-        if (!fIsRamping)
-            fIsRamping = RampOneStep();
-
-        return true;
-    }
-
-    bool SetGapdReferenceCh(uint16_t ch)
-    {
-        if (!CheckChDac("SetGapdReferenceCh", fDacGapd[ch], ch))
-            return false;
-
-        fDacRef[ch] = fDacGapd[ch];
-
-        if (!fIsRamping)
-            fIsRamping = RampOneStep();
-
-        return true;
-    }
-
-
-    void SetZero()
-    {
-        for (size_t ch=0; ch<kNumChannels; ch++)
-            fDacRef[ch] = 0;
-
-        if (!fIsRamping)
-            fIsRamping = RampOneStep();
-    }
-
-    bool SetNewGapdVoltage(const vector<float> &volt)
+    bool SetReferences(const vector<float> &volt, const vector<float> &offset)
     {
         if (volt.size()!=kNumChannels)
         {
             ostringstream out;
-            out << "SetNewGapdVoltage - Given vector has " << volt.size() << " elements - expected " << kNumChannels << endl;
+            out << "SetReferences - Given vector has " << volt.size() << " elements - expected " << kNumChannels << endl;
             Error(out);
             return false;
         }
-
-        for (size_t i=0; i<kNumChannels; i++)
-            fDacGapd[i] = volt[i]*4096/90;
+        if (offset.size()!=kNumChannels)
+        {
+            ostringstream out;
+            out << "SetReferences - Given vector has " << volt.size() << " elements - expected " << kNumChannels << endl;
+            Error(out);
+            return false;
+        }
+
+        fBreakdownVoltage   = volt;
+        fChannelCalibration = offset;
+        fOvervoltage.assign(kNumChannels, 0);
 
         UpdateVgapd();
@@ -1195,8 +1172,8 @@
         }
 
-        if (!CheckChDac("ExpertChannelSetDac", dac, ch))
-            return false;
-
-        fDacCmd[ch] = dac;
+        if (!CheckDac(dac))
+            return false;
+
+        fDacCommand[ch] = dac;
 
         ostringstream msg;
@@ -1227,5 +1204,5 @@
         }
 
-        if (!CheckChDac("ExpertGlobalSetDac", dac))
+        if (!CheckDac(dac))
             return false;
 
@@ -1259,4 +1236,9 @@
     {
         fIsVerbose = b;
+    }
+
+    void SetDummyMode(bool b)
+    {
+        fIsDummyMode = b;
     }
 
@@ -1319,7 +1301,7 @@
             const int id = c+kNumChannelsPerBoard*b;
             Out() << " ";
-            Out() << (fDac[id]==fDacRef[id]?kGreen:kRed);
-            Out() << setw(5) << fDac[id]*90/4096. << '/';
-            Out() << setw(5) << fDacRef[id]*90/4096.;
+            Out() << (fDacActual[id]==fDacTarget[id]?kGreen:kRed);
+            Out() << setw(5) << fDacActual[id]*90/4096. << '/';
+            Out() << setw(5) << fDacTarget[id]*90/4096.;
         }
         Out() << endl;
@@ -1355,10 +1337,10 @@
         {
             const int id = c+kNumChannelsPerBoard*b;
-            Out() << " " << setw(5) << fDacGapd[id]*90/4096.;
+            Out() << " " << setw(5) << fBreakdownVoltage[id]+fOvervoltage[id];
         }
         Out() << endl;
     }
 
-    void PrintGapd()
+    void PrintReferenceVoltage()
     {
         Out() << dec << setprecision(2) << fixed << setfill(' ');
@@ -1400,58 +1382,31 @@
     void SetVoltMaxAbs(float max)
     {
-        fDacMaxAbs = max*4096/90;
-        if (fDacMaxAbs>4095)
-            fDacMaxAbs = 4095;
+        if (max>90)
+            max = 90;
         if (max<0)
-            fDacMaxAbs = 0;
+            max = 0;
+
+        fVoltageMaxAbs = max;
     }
 
     void SetVoltMaxRel(float max)
     {
-        fDacMaxRel = max*4096/90;
-        if (fDacMaxRel>4095)
-            fDacMaxRel = 4095;
+        if (max>90)
+            max = 90;
         if (max<0)
-            fDacMaxRel = 0;
+            max = 0;
+
+        fVoltageMaxRel = max;
     }
 
     uint16_t GetVoltMaxAbs() const
     {
-        return fDacMaxAbs * 90./4096;
+        return fVoltageMaxAbs;
     }
 
     uint16_t GetVoltMaxRel() const
     {
-        return fDacMaxRel * 90./4096;
-    }
-
-/*
-    void AdaptVoltages()
-    {
-        // Correct voltages according to current
-        for (int i=0; i<kNumChannels; i++)
-        {
-            if (fVoltRef[i]==0 || fCurrent[i]<0 || fRefCurrent[i]<0)
-                continue;
-
-            // Calculate difference and convert ADC units to Amp
-            // const double diffcur = (fRefCurrent[i]-fCurrent[i])*5000/4096
-            //const int32_t diffcur = int32_t(fRefCurrent[i]-fCurrent[i])*5000;
-
-            // Calculate voltage difference
-            // #define RESISTOR 1000 // Ohm
-            //const double diffvolt = diffcur*RESISTOR/1e6;
-
-            // Calculate new vlaue by onverting voltage difference to DAC units
-            //const int32_t dac = fRefVolt[i] + diffvolt*4096/90.0;
-            SetVoltage(i, fRefVolt[i] + (fRefCurrent[i]-fCurrent[i])/18);
-        }
-    }
-
-    void SetReferenceCurrent()
-    {
-        fRefCurrent = fCurrent;
-    }
-    */
+        return fVoltageMaxRel;
+    }
 
     States_t GetStatus()
@@ -1475,5 +1430,5 @@
         bool isoff = true;
         for (int ch=0; ch<kNumChannels; ch++)
-            if (fPresent[ch/kNumChannelsPerBoard] && fDac[ch]!=0)
+            if (fPresent[ch/kNumChannelsPerBoard] && fDacActual[ch]!=0)
                 isoff = false;
         if (isoff)
@@ -1481,5 +1436,5 @@
 
         for (int ch=0; ch<kNumChannels; ch++)
-            if (fPresent[ch/kNumChannelsPerBoard] && fDac[ch]!=fDacRef[ch])
+            if (fPresent[ch/kNumChannelsPerBoard] && fDacActual[ch]!=fDacTarget[ch])
                 return BIAS::kNotReferenced;
 
@@ -1497,5 +1452,6 @@
 
     DimDescribedService fDimCurrent;
-    DimDescribedService fDimVoltage;
+    DimDescribedService fDimDac;
+    DimDescribedService fDimVolt;
     DimDescribedService fDimGapd;
 
@@ -1507,13 +1463,23 @@
     void UpdateV()
     {
-        vector<uint16_t> vec;
-        vec.insert(vec.end(), fDac.begin(),    fDac.end());
-        vec.insert(vec.end(), fDacRef.begin(), fDacRef.end());
-        fDimVoltage.Update(vec);
+        vector<uint16_t> val(2*kNumChannels);
+        memcpy(val.data(),              fDacActual.data(), kNumChannels*2);
+        memcpy(val.data()+kNumChannels, fDacTarget.data(), kNumChannels*2);
+        fDimDac.Update(val);
+
+        vector<float> volt(kNumChannels);
+        for (float ch=0; ch<kNumChannels; ch++)
+            volt[ch] = fDacActual[ch]*90./4096 - fChannelCalibration[ch];
+        fDimVolt.Update(volt);
     }
 
     void UpdateVgapd()
     {
-        fDimGapd.Update(fDacGapd);
+        vector<float> volt;
+        volt.reserve(3*kNumChannels);
+        volt.insert(volt.end(), fBreakdownVoltage.begin(),   fBreakdownVoltage.end());
+        volt.insert(volt.end(), fOvervoltage.begin(),        fOvervoltage.end());
+        volt.insert(volt.end(), fChannelCalibration.begin(), fChannelCalibration.end());
+        fDimGapd.Update(volt);
     }
 
@@ -1521,7 +1487,15 @@
     ConnectionDimBias(ba::io_service& ioservice, MessageImp &imp) :
         ConnectionBias(ioservice, imp),
-        fDimCurrent("BIAS_CONTROL/CURRENT", "S:416",       "|I[uA]:Bias current"),
-        fDimVoltage("BIAS_CONTROL/VOLTAGE", "S:416;S:416", "|U[V]:Applied bias voltage|Uref[V]:Reference bias voltage"),
-        fDimGapd(   "BIAS_CONTROL/NOMINAL", "S:416",       "|U[V]:Nominal G-APD voltage at 25deg C")
+        fDimCurrent("BIAS_CONTROL/CURRENT", "S:416",
+                    "|I[uA]:Bias current"),
+        fDimDac("BIAS_CONTROL/DAC", "S:416;S:416",
+                "|U[dac]:Current dac setting"
+                "|Uref[dac]:Reference dac setting"),
+        fDimVolt("BIAS_CONTROL/VOLTAGE", "F:416",
+                 "|Uout[V]:Output voltage"),
+        fDimGapd("BIAS_CONTROL/NOMINAL", "F:416;F:416;F:416",
+                 "|Ubr[V]:Nominal breakdown voltage at 25deg C"
+                 "|Uov[V]:Nominal overvoltage"
+                 "|Uoff[V]:Bias crate channel offsets")
     {
     }
@@ -1564,21 +1538,58 @@
     // --------------------------------------------------------------------
 
-    int SetGapdVoltage(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetGapdVoltage", 4))
-            return false;
-
-        fBias.SetGapdVoltage(evt.GetFloat());
+    // SET_GLOBAL_DAC_VALUE
+    int SetGlobalDac(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetGlobalDac", 2))
+            return false;
+
+        fBias.RampAllDacs(evt.GetUShort());
 
         return T::GetCurrentState();
     }
 
-    int SetGapdVoltages(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetGapdVoltages", 4*416))
+    // SET_CHANNEL_DAC_VALUE
+    int SetChannelDac(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetChannelDac", 4))
+            return false;
+
+        fBias.RampSingleChannelDac(evt.Get<uint16_t>(), evt.Get<uint16_t>(2));
+
+        return T::GetCurrentState();
+    }
+
+    // --------------------------------------------------------------------
+
+    // SET_CHANNEL_VOLTAGE
+    int SetChannelVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetChannelVolt", 6))
+            return false;
+
+        fBias.RampSingleChannelVoltage(evt.GetUShort(), evt.Get<float>(2));
+
+        return T::GetCurrentState();
+    }
+
+    // SET_GLOBAL_VOLTAGE
+    int SetGlobalVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetGlobalVolt", 4))
+            return false;
+
+        fBias.RampAllVoltages(evt.GetFloat());
+
+        return T::GetCurrentState();
+    }
+
+    // SET_ALL_CHANNELS_VOLTAGES
+    int SetAllChannelsVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetAllChannelsVolt", 4*kNumChannels))
             return false;
 
         const float *ptr = evt.Ptr<float>();
-        fBias.SetGapdVoltages(vector<float>(ptr, ptr+416));
+        fBias.RampAllChannelsVoltage(vector<float>(ptr, ptr+kNumChannels));
 
         return T::GetCurrentState();
@@ -1587,24 +1598,41 @@
     // --------------------------------------------------------------------
 
-    int SetGlobalVolt(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetGlobalVolt", 4))
-            return false;
-
-        fBias.GlobalSetVolt(evt.GetFloat());
+    // SET_GLOBAL_OFFSET
+    int SetGlobalOffset(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetGlobalOffset", 4))
+            return false;
+
+        fBias.RampAllOffsets(evt.GetFloat(), false);
 
         return T::GetCurrentState();
     }
 
-    int SetGlobalDac(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetGlobalDac", 2))
-            return false;
-
-        fBias.GlobalSetDac(evt.GetUShort());
+    // SET_SINGLE_CHANNEL_OFFSET
+    int SetChannelOffset(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetSingleChannelOffset", 6))
+            return false;
+
+        fBias.RampSingleChannelOffset(evt.Get<uint16_t>(), evt.Get<float>(2), false);
 
         return T::GetCurrentState();
     }
 
+    // SET_ALL_CHANNELS_OFFSET
+    int SetAllChannelsOffset(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetAllChannelsOffset", 4*kNumChannels))
+            return false;
+
+        const float *ptr = evt.Ptr<float>();
+        fBias.RampAllChannelsOffset(vector<float>(ptr, ptr+kNumChannels), false);
+
+        return T::GetCurrentState();
+    }
+
+    // --------------------------------------------------------------------
+
+    // INCREASE_GLOBAL_VOLTAGE
     int IncGlobalVolt(const EventImp &evt)
     {
@@ -1612,112 +1640,41 @@
             return false;
 
-        fBias.GlobalAddVolt(evt.GetFloat());
+        fBias.RampAllOffsets(evt.GetFloat(), true);
 
         return T::GetCurrentState();
     }
 
-    int IncGlobalDac(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "IncGlobalDac", 2))
-            return false;
-
-        fBias.GlobalAddDac(evt.GetShort());
+    // INCREASE_CHANNEL_VOLTAGE
+    int IncChannelVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "IncChannelVolt", 6))
+            return false;
+
+        fBias.RampSingleChannelOffset(evt.Get<uint16_t>(), evt.Get<float>(2), true);
 
         return T::GetCurrentState();
     }
 
-    int DecGlobalVolt(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "DecGlobalVolt", 4))
-            return false;
-
-        fBias.GlobalAddVolt(-evt.GetFloat());
+    // INCREASE_ALL_CHANNELS_VOLTAGES
+    int IncAllChannelsVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "IncAllChannelsVolt", 4*kNumChannels))
+            return false;
+
+        const float *ptr = evt.Ptr<float>();
+        fBias.RampAllChannelsOffset(vector<float>(ptr, ptr+416), true);
 
         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)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetChannelVolt", 6))
-            return false;
-
-        fBias.ChannelSetVolt(evt.GetUShort(), evt.Get<float>(2));
-
-        return T::GetCurrentState();
-    }
-
-    int SetChannelDac(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetChannelDac", 4))
-            return false;
-
-        fBias.ChannelSetDac(evt.Get<uint16_t>(), evt.Get<uint16_t>(2));
-
-        return T::GetCurrentState();
-    }
-
-    int SetGapdReferenceCh(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetGapdReferenceCh", 2))
-            return false;
-
-        fBias.SetGapdReferenceCh(evt.GetUShort());
-
-        return T::GetCurrentState();
-    }
-
-
     // --------------------------------------------------------------------
 
-    int AddReferenceDac(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "AddReferenceDac", 2*kNumChannels))
-            return false;
-
-        const int16_t *ptr = evt.Ptr<int16_t>();
-        fBias.AddDac(vector<int16_t>(ptr, ptr+416));
-
-        return T::GetCurrentState();
-    }
-
-    int AddReferenceVolt(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "AddReferenceVolt", 4*kNumChannels))
-            return false;
-
-        const float_t *ptr = evt.Ptr<float>();
-        fBias.AddVolt(vector<float>(ptr, ptr+416));
-
-        return T::GetCurrentState();
-    }
-
-    int SetReferenceDac(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetReferenceDac", 2*kNumChannels))
-            return false;
-
-        const int16_t *ptr = evt.Ptr<int16_t>();
-        fBias.SetDac(vector<int16_t>(ptr, ptr+416));
-
-        return T::GetCurrentState();
-    }
-
-    int SetReferenceVolt(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetReferenceVolt", 4*kNumChannels))
-            return false;
-
-        const float_t *ptr = evt.Ptr<float>();
-        fBias.SetVolt(vector<float>(ptr, ptr+416));
+    // SET_CHANNEL_OFFSET_TO_ZERO
+    int SetChannelOffsetToZero(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetChannelOffsetToZero", 2))
+            return false;
+
+        fBias.RampSingleChannelOffset(evt.GetUShort(), 0, false);
 
         return T::GetCurrentState();
@@ -1816,4 +1773,14 @@
 
         fBias.SetVerbose(evt.GetBool());
+
+        return T::GetCurrentState();
+    }
+
+    int SetDummyMode(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "SetDummyMode", 1))
+            return T::kSM_FatalError;
+
+        fBias.SetDummyMode(evt.GetBool());
 
         return T::GetCurrentState();
@@ -1890,8 +1857,13 @@
 
         // Verbosity commands
-        T::AddEvent("SET_VERBOSE", "B")
+        T::AddEvent("SET_VERBOSE", "B:1")
             (bind(&StateMachineBias::SetVerbosity, this, placeholders::_1))
             ("set verbosity state"
              "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
+
+        T::AddEvent("ENABLE_DUMMY_MODE", "B:1")
+            (bind(&StateMachineBias::SetDummyMode, this, placeholders::_1))
+            ("Enable dummy mode. In this mode SetAllChannels prints informations instead of sending anything to the bias crate."
+             "|enable[bool]:disable or enable dummy mode");
 
         // Conenction commands
@@ -1899,5 +1871,4 @@
             (bind(&StateMachineBias::Disconnect, this))
             ("disconnect from USB");
-
         T::AddEvent("RECONNECT", "O", kDisconnected, kConnected, kVoltageOff)
             (bind(&StateMachineBias::Reconnect, this, placeholders::_1))
@@ -1922,89 +1893,76 @@
 
 
-
+        T::AddEvent("SET_CHANNEL_DAC", "S:1;S:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::SetChannelDac, this, placeholders::_1))
+            ("Set a new target value in DAC counts for a single channel. Starts ramping if necessary."
+             "|channel[short]:Channel for which to set the target voltage [0-415]"
+             "|voltage[dac]:Target voltage in DAC units for the given channel");
+        T::AddEvent("SET_GLOBAL_DAC", "S:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::SetGlobalDac, this, placeholders::_1))
+            ("Set a new target value for all channels in DAC counts. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)"
+             "|voltage[dac]:Global target voltage in DAC counts.");
+
+
+        T::AddEvent("SET_CHANNEL_VOLTAGE", "S:1;F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::SetChannelVolt, this, placeholders::_1))
+            ("Set a new target voltage for a single channel. Starts ramping if necessary."
+             "|channel[short]:Channel for which to set the target voltage [0-415]"
+             "|voltage[V]:Target voltage in volts for the given channel (will be converted to DAC units)");
         T::AddEvent("SET_GLOBAL_VOLTAGE", "F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
             (bind(&StateMachineBias::SetGlobalVolt, 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.)"
+            ("Set a new target voltage for all channels. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)"
              "|voltage[V]:Global target voltage in volts (will be converted to DAC units)");
-
-        T::AddEvent("SET_GLOBAL_DAC", "S:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::SetGlobalDac, 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.)"
-             "|voltage[dac]:Global target voltage as DAC counts.");
-
+        T::AddEvent("SET_ALL_CHANNELS_VOLTAGE", "F:416", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::SetAllChannelsVolt, this, placeholders::_1))
+            ("Set all channels to the given new reference voltage. Starts ramping if necessary."
+             "voltage[V]:New reference voltage for all channels");
+
+
+        T::AddEvent("INCREASE_CHANNEL_VOLTAGE", "S:1;F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::IncChannelVolt, this, placeholders::_1))
+            ("Increases the voltage of all channels by the given offset. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)"
+             "|channel[short]:Channel for which to adapt the voltage [0-415]"
+             "|offset[V]:Offset to be added to all channels (will be converted to DAC counts)");
         T::AddEvent("INCREASE_GLOBAL_VOLTAGE", "F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, 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.)"
+            ("Increases the voltage of all channels by the given offset. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)"
              "|offset[V]:Offset to be added to all channels (will be converted to DAC counts)");
-
-        T::AddEvent("INCREASE_GLOBAL_DAC", "S:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, 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.)"
-             "|offset[dac]:Offset to be added to all channels as DAC counts");
-
-        T::AddEvent("DECREASE_GLOBAL_VOLTAGE", "F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, 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.)"
-             "|offset[V]:Offset to be subtracted from all channels (will be converted to DAC counts)");
-
-        T::AddEvent("DECREASE_GLOBAL_DAC", "S:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, 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.)"
-             "|offset[dac]:Offset to be subtracted from all channels as DAC counts");
-
-        T::AddEvent("SET_CHANNEL_VOLTAGE", "S:1;F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::SetChannelVolt, this, placeholders::_1))
-            ("Set a single channel to a new reference voltage. Starts ramping if necessary."
-             "|channel[short]:Channel for which to set the target voltage [0-416]"
-             "|voltage[V]:Target voltage in volts for the given channel (will be converted to DAC units)");
-
-        T::AddEvent("SET_CHANNEL_DAC", "S:1;S:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::SetChannelDac, this, placeholders::_1))
-            ("Set a single channel to a new DAC reference value. Starts ramping if necessary."
-             "|channel[short]:Channel for which to set the target voltage [0-416]"
-             "|voltage[dac]:Target voltage in DAC units for the given channel");
-
-        T::AddEvent("SET_GLOBAL_GAPD_REFERENCE_VOLTAGE", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (Wrapper(bind(&ConnectionBias::SetGapdVoltage, &fBias, 0.)))
+        T::AddEvent("INCREASE_ALL_CHANNELS_VOLTAGE", "F:416", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::IncAllChannelsVolt, this, placeholders::_1))
+            ("Add the given voltages to the current reference voltages. Starts ramping if necessary."
+             "offset[V]:Offsets to be added to the reference voltage of all channels in volts");
+
+
+        // SET_SINGLE_CHANNEL_OFFSET
+        T::AddEvent("SET_CHANNEL_OFFSET", "S:1;F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::SetChannelOffset, this, placeholders::_1))
+            ("Set single channels to its G-APD breakdown voltage plus overvoltage plus the given offset. Starts ramping if necessary."
+             "|channel[short]:Channel for which to set the target voltage [0-415]"
+             "|offset[V]:Offset to be added to the G-APD reference voltage of the given channel");
+        T::AddEvent("SET_GLOBAL_OFFSET", "F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::SetGlobalOffset, this, placeholders::_1))
+            ("Set all channels to their G-APD breakdown voltage plus overvoltage plus the given offset. Starts ramping if necessary."
+             "|offset[V]:Offset to be added to the G-APD reference voltage globally");
+        T::AddEvent("SET_ALL_CHANNELS_OFFSET", "F:416", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::SetAllChannelsOffset, this, placeholders::_1))
+            ("Set all channels to their G-APD reference voltage plus the given offset. Starts ramping if necessary."
+             "|offset[V]:Offset to be added to teh G-APD reference voltage globally");
+
+
+        T::AddEvent("SET_GLOBAL_OFFSET_TO_ZERO", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (Wrapper(bind(&ConnectionBias::RampAllOffsets, &fBias, 0., false)))
             ("Set all channels to their G-APD reference voltage. Starts ramping if necessary.");
 
-        T::AddEvent("SET_CHANNEL_GAPD_REFERENCE_VOLTAGE", "S:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::SetGapdReferenceCh, this, placeholders::_1))
+        T::AddEvent("SET_CHANNEL_OFFSET_TO_ZERO", "S:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
+            (bind(&StateMachineBias::SetChannelOffsetToZero, this, placeholders::_1))
             ("Set a single channel channels to its G-APD reference voltage. Starts ramping if necessary."
              "|channel[short]:Channel for which to set the target voltage [0-416]");
 
-        T::AddEvent("SET_GAPD_REFERENCE_OFFSET", "F:1", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::SetGapdVoltage, this, placeholders::_1))
-            ("Set all channels to their G-APD reference voltage plus the given offset. Starts ramping if necessary."
-             "|offset[V]:Offset to be added to teh G-APD reference voltage globally");
-
-        T::AddEvent("SET_ALL_CHANNELS_OFFSET", "F:416", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::SetGapdVoltages, this, placeholders::_1))
-            ("Set all channels to their G-APD reference voltage plus the given offset. Starts ramping if necessary."
-             "|offset[V]:Offset to be added to teh G-APD reference voltage");
+
 
         T::AddEvent("SET_ZERO_VOLTAGE", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (Wrapper(bind(&ConnectionBias::SetZero, &fBias)))
+            (Wrapper(bind(&ConnectionBias::RampAllDacs, &fBias, 0)))
             ("Set all channels to a zero reference voltage. Starts ramping if necessary.");
 
-        T::AddEvent("SET_REFERENCE_VOLTAGES", "F:416", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::SetReferenceVolt, this, placeholders::_1))
-            ("Set all channels to the given new reference voltage. Starts ramping if necessary."
-             "voltage[V]:New reference voltage for all channels");
-
-        T::AddEvent("SET_REFERENCE_DACS", "S:416", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::SetReferenceDac, this, placeholders::_1))
-            ("Set all channels to the given new reference voltage. Starts ramping if necessary."
-             "voltage[dac]:New reference voltage for all channels in DAC units");
-
-        T::AddEvent("ADD_REFERENCE_VOLTAGES", "F:416", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::AddReferenceVolt, this, placeholders::_1))
-            ("Add the given voltages to the current reference voltages. Starts ramping if necessary."
-             "offset[V]:Offsets to be added to the reference voltage of all channels in volts");
-
-        T::AddEvent("ADD_REFERENCE_DACS", "S:416", kConnected, kVoltageOff, kVoltageOn, kNotReferenced, kOverCurrent)
-            (bind(&StateMachineBias::AddReferenceDac, this, placeholders::_1))
-            ("Add the given voltages to the current reference voltages. Starts ramping if necessary."
-             "offset[dac]:Offsets to be added to the reference voltage of all channels in DAC units");
 
 
@@ -2031,6 +1989,6 @@
             ("Print a table with all voltages (current and reference voltages as currently in memory)");
         T::AddEvent("PRINT_GAPD_REFERENCE_VOLTAGES")
-            (Wrapper(bind(&ConnectionBias::PrintGapd, &fBias)))
-            ("Print the G-APD reference values obtained from file");
+            (Wrapper(bind(&ConnectionBias::PrintReferenceVoltage, &fBias)))
+            ("Print the G-APD reference values (breakdown voltage + overvoltage) obtained from file");
 
 
@@ -2068,4 +2026,5 @@
 
         fBias.SetVerbose(!conf.Get<bool>("quiet"));
+        fBias.SetDummyMode(conf.Get<bool>("dummy-mode"));
 
         if (conf.Has("dev"))
@@ -2147,5 +2106,5 @@
         }
 
-        if (!fBias.SetNewGapdVoltage(map.Vgapd()))
+        if (!fBias.SetReferences(map.Vgapd(), map.Voffset()))
         {
             T::Error("Setting reference voltages failed.");
@@ -2179,4 +2138,5 @@
         ("dev",             var<string>(),       "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.")
+        ("dummy-mode",      po_bool(),           "Dummy mode - SetAllChannels prints info instead of sending new values.")
         ("ramp-delay",      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)")
