Index: /trunk/FACT++/src/biasctrl.cc
===================================================================
--- /trunk/FACT++/src/biasctrl.cc	(revision 17023)
+++ /trunk/FACT++/src/biasctrl.cc	(revision 17024)
@@ -69,5 +69,5 @@
     vector<int16_t>  fCurrent;     // Current in ADC units (12bit = 5mA)
 
-    virtual void UpdateAV()
+    virtual void UpdateVA()
     {
     }
@@ -84,6 +84,5 @@
 
     vector<float> fBreakdownVoltage;      // Breakdown voltage of GAPDs
-    vector<float> fOvervoltage;           // Requested overvoltage of GAPDs
-    vector<float> fChannelOffset;         // User defined channel offset
+    //vector<float> fChannelOffset;         // User defined channel offset
 
     vector<float> fCalibrationOffset;     // Bias crate channel offset
@@ -375,5 +374,5 @@
         // Check if new values have been received
         if (cmd==kCmdRead || cmd==kCmdChannelSet || cmd==kExpertChannelSet)
-            UpdateAV();
+            UpdateVA();
 
         // ----- Take action depending on what is going on -----
@@ -658,5 +657,5 @@
         {
             const int id = c+kNumChannelsPerBoard*b;
-            Out() << " " << setw(4) << int32_t(dac[id])<<"/"<<fDacActual[id] << ":" << setw(5) << fDacTarget[id]*90./4096;
+            Out() << " " << setw(4) << int32_t(dac[id])<<"/"<<fDacActual[id] << ":" << setw(5) << ConvertDacToVolt(id, fDacTarget[id]);
         }
         Out() << endl;
@@ -841,8 +840,7 @@
         fCurrent(kNumChannels),
         fBreakdownVoltage(kNumChannels, 0),
-        fOvervoltage(kNumChannels),
-        fChannelOffset(kNumChannels),
+        //fChannelOffset(kNumChannels),
         fCalibrationOffset(kNumChannels),
-        fCalibrationSlope(kNumChannels, 90./4096),
+        fCalibrationSlope(kNumChannels, 90000),
         fVoltageMaxAbs(75),
         fVoltageMaxRel(2),
@@ -945,15 +943,18 @@
     uint16_t ConvertVoltToDac(uint16_t ch, double volt)
     {
-        volt -= fCalibrationOffset[ch];
-        volt /= fCalibrationSlope[ch];
-        if (volt<0)
-            volt = 0;
-
-        return nearbyint(volt);
+        if (fCalibrationSlope[ch]<=0)
+            return 0;
+
+        const double current = (volt-fCalibrationOffset[ch])/fCalibrationSlope[ch];
+        return current<0 ? 0 : nearbyint(current*4096000); // Current [A] to dac [ /= 1mA/4096]
     }
 
     double ConvertDacToVolt(uint16_t ch, uint16_t dac)
     {
-        return dac*fCalibrationSlope[ch] + fCalibrationOffset[ch];
+        if (fCalibrationSlope[ch]<=0)
+            return 0;
+
+        const double current = dac/4096000.;  // Convert dac to current [A] [ *= 1mA/4096]
+        return current*fCalibrationSlope[ch] + fCalibrationOffset[ch];
     }
 
@@ -993,4 +994,5 @@
     // --------------------------------------------------------------------
 
+    /*
     bool RampSingleChannelOffset(uint16_t ch, float offset, bool relative)
     {
@@ -998,8 +1000,8 @@
             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 (relative)
+//            offset += fDacActual[ch]*90./4096 - fBreakdownVoltage[ch];
+
+        const float volt = fBreakdownVoltage[ch]>0 ? fBreakdownVoltage[ch] + offset : 0;
 
         if (!RampSingleChannelVoltage(ch, volt))
@@ -1015,10 +1017,10 @@
         vector<float> volt(kNumChannels);
 
-        if (relative)
-            for (size_t ch=0; ch<kNumChannels; ch++)
-                offset[ch] += fDacActual[ch]*90./4096 - fBreakdownVoltage[ch] - fOvervoltage[ch];
+//        if (relative)
+//            for (size_t ch=0; ch<kNumChannels; ch++)
+//                offset[ch] += fDacActual[ch]*90./4096 - fBreakdownVoltage[ch];
 
         for (size_t ch=0; ch<kNumChannels; ch++)
-            volt[ch] = fBreakdownVoltage[ch]>0 ? fBreakdownVoltage[ch] + fOvervoltage[ch] + offset[ch] : 0;
+            volt[ch] = fBreakdownVoltage[ch]>0 ? fBreakdownVoltage[ch] + offset[ch] : 0;
 
         if (!RampAllChannelsVoltage(volt))
@@ -1034,4 +1036,5 @@
         return RampAllChannelsOffset(vector<float>(kNumChannels, offset), relative);
     }
+    */
 
     /*
@@ -1141,5 +1144,4 @@
         fCalibrationOffset = offset;
         fCalibrationSlope  = slope;
-        fOvervoltage.assign(kNumChannels, 0);
 
         UpdateVgapd();
@@ -1347,6 +1349,9 @@
             Out() << " ";
             Out() << (fDacActual[id]==fDacTarget[id]?kGreen:kRed);
-            Out() << setw(5) << fDacActual[id]*90/4096. << '/';
-            Out() << setw(5) << fDacTarget[id]*90/4096.;
+            //Out() << setw(5) << fDacActual[id]*90/4096. << '/';
+            //Out() << setw(5) << fDacTarget[id]*90/4096.;
+
+            Out() << setw(5) << ConvertDacToVolt(id, fDacActual[id]) << '/';
+            Out() << setw(5) << ConvertDacToVolt(id, fDacTarget[id]);
         }
         Out() << endl;
@@ -1382,5 +1387,5 @@
         {
             const int id = c+kNumChannelsPerBoard*b;
-            Out() << " " << setw(5) << fBreakdownVoltage[id]+fOvervoltage[id];
+            Out() << " " << setw(5) << fBreakdownVoltage[id];
         }
         Out() << endl;
@@ -1506,11 +1511,12 @@
     DimDescribedService fDimGapd;
 
-    void UpdateAV()
+    void UpdateVA()
     {
         const Time now;
+
+        UpdateV(now);
+
         fDimCurrent.setTime(now);
         fDimCurrent.Update(fCurrent);
-
-        UpdateV(now);
     }
 
@@ -1539,5 +1545,4 @@
         volt.reserve(3*kNumChannels);
         volt.insert(volt.end(), fBreakdownVoltage.begin(),   fBreakdownVoltage.end());
-        volt.insert(volt.end(), fOvervoltage.begin(),        fOvervoltage.end());
         volt.insert(volt.end(), fCalibrationOffset.begin(),  fCalibrationOffset.end());
         volt.insert(volt.end(), fCalibrationSlope.begin(),   fCalibrationSlope.end());
@@ -1557,7 +1562,6 @@
         fDimGapd("BIAS_CONTROL/NOMINAL", "F:416;F:416;F:416;F:416",
                  "|Ubr[V]:Nominal breakdown voltage at 25deg C"
-                 "|Uov[V]:Nominal overvoltage"
                  "|Uoff[V]:Bias crate channel calibration offsets"
-                 "|Uslope[V/dac]:Bias crate channel calibration slope")
+                 "|Rcal[Ohm]:Bias crate channel calibration slope")
     {
     }
@@ -1660,41 +1664,5 @@
     // --------------------------------------------------------------------
 
-    // SET_GLOBAL_OFFSET
-    int SetGlobalOffset(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetGlobalOffset", 4))
-            return false;
-
-        fBias.RampAllOffsets(evt.GetFloat(), false);
-
-        return T::GetCurrentState();
-    }
-
-    // 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
+/*    // INCREASE_GLOBAL_VOLTAGE
     int IncGlobalVolt(const EventImp &evt)
     {
@@ -1729,56 +1697,78 @@
         return T::GetCurrentState();
     }
-
+*/
     // --------------------------------------------------------------------
 
-    // SET_CHANNEL_OFFSET_TO_ZERO
-    int SetChannelOffsetToZero(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "SetChannelOffsetToZero", 2))
-            return false;
-
-        fBias.RampSingleChannelOffset(evt.GetUShort(), 0, false);
+    int ExpertSetGlobalVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "ExpertSetGlobalVolt", 4))
+            return false;
+
+        fBias.ExpertGlobalSetVolt(evt.GetFloat());
 
         return T::GetCurrentState();
     }
 
-    // --------------------------------------------------------------------
-
-    int ExpertSetGlobalVolt(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "ExpertSetGlobalVolt", 4))
-            return false;
-
-        fBias.ExpertGlobalSetVolt(evt.GetFloat());
+    int ExpertSetGlobalDac(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "ExpertSetGlobalDac", 2))
+            return false;
+
+        fBias.ExpertGlobalSetDac(evt.GetUShort());
 
         return T::GetCurrentState();
     }
 
-    int ExpertSetGlobalDac(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "ExpertSetGlobalDac", 2))
-            return false;
-
-        fBias.ExpertGlobalSetDac(evt.GetUShort());
+    int ExpertSetChannelVolt(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "ExpertSetChannelVolt", 6))
+            return false;
+
+        fBias.ExpertChannelSetVolt(evt.GetUShort(), evt.Get<float>(2));
 
         return T::GetCurrentState();
     }
 
-    int ExpertSetChannelVolt(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "ExpertSetChannelVolt", 6))
-            return false;
-
-        fBias.ExpertChannelSetVolt(evt.GetUShort(), evt.Get<float>(2));
+    int ExpertSetChannelDac(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "ExpertSetChannelDac", 4))
+            return false;
+
+        fBias.ExpertChannelSetDac(evt.Get<uint16_t>(), evt.Get<uint16_t>(2));
 
         return T::GetCurrentState();
     }
 
-    int ExpertSetChannelDac(const EventImp &evt)
-    {
-        if (!CheckEventSize(evt.GetSize(), "ExpertSetChannelDac", 4))
-            return false;
-
-        fBias.ExpertChannelSetDac(evt.Get<uint16_t>(), evt.Get<uint16_t>(2));
+    int ExpertLoadMapFile(const EventImp &evt)
+    {
+        if (evt.GetSize()==0)
+        {
+            T::Warn("ExpertLoadMapFile - No file name given.");
+            return T::GetCurrentState();
+        }
+
+        if (fBias.GetStatus()!=State::kVoltageOff)
+        {
+            T::Warn("ExpertLoadMapFile - Voltage must have been turned off.");
+            return T::GetCurrentState();
+        }
+
+        BiasMap map;
+
+        try
+        {
+            map.Read(evt.GetText());
+        }
+        catch (const runtime_error &e)
+        {
+            T::Warn("Getting reference voltages failed: "+string(e.what()));
+            return T::GetCurrentState();
+        }
+
+        if (!fBias.SetReferences(map.Vgapd(), map.Voffset(), map.Vslope()))
+        {
+            T::Warn("Setting reference voltages failed.");
+            return T::GetCurrentState();
+        }
 
         return T::GetCurrentState();
@@ -1964,7 +1954,7 @@
             (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");
-
-
+             "|voltage[V]:New reference voltage for all channels");
+
+/*
         T::AddEvent("INCREASE_CHANNEL_VOLTAGE", "S:1;F:1", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::kOverCurrent)
             (bind(&StateMachineBias::IncChannelVolt, this, placeholders::_1))
@@ -1980,30 +1970,5 @@
             ("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", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::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", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::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", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::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 the G-APD reference voltage globally");
-
-
-        T::AddEvent("SET_GLOBAL_OFFSET_TO_ZERO", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::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_OFFSET_TO_ZERO", "S:1", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::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]");
+*/
 
 
@@ -2064,4 +2029,8 @@
             (bind(&StateMachineBias::ExpertSetChannelDac, this, placeholders::_1))
             ("Send a single channel set command.");
+
+        T::AddEvent("EXPERT_LOAD_MAP_FILE", "C", State::kExpertMode)
+            (bind(&StateMachineBias::ExpertLoadMapFile, this, placeholders::_1))
+            ("Load a new mapping file.");
     }
 
@@ -2192,5 +2161,5 @@
         ("sync-delay",      var<uint16_t>(500),  "Delay between sending the inital 0's after a newly established connection to synchronize the output stream in milliseconds")
         ("volt-max-abs",    var<float>(75),      "Absolte upper limit for the voltage (in Volts)")
-        ("volt-max-rel",    var<float>(2.5),     "Relative upper limit for the voltage w.r.t. the G-APD reference voltage (in Volts)")
+        ("volt-max-rel",    var<float>(3.5),     "Relative upper limit for the voltage w.r.t. the G-APD reference voltage (in Volts)")
         ("bias-map-file",   var<string>(),       "File with nominal and offset voltages for each channel.")
         ("bias-database",   var<string>(),       "")
