Index: trunk/FACT++/src/feedback.cc
===================================================================
--- trunk/FACT++/src/feedback.cc	(revision 15018)
+++ trunk/FACT++/src/feedback.cc	(revision 15019)
@@ -51,4 +51,5 @@
     DimDescribedService fDimDeviation;
     DimDescribedService fDimCalibration;
+    DimDescribedService fDimCurrents;
 
     vector<int64_t>  fCurrentsAvg;
@@ -57,4 +58,5 @@
     vector<float>    fCalibration;
     vector<float>    fVoltGapd;
+    vector<float>    fBiasVolt;
 
     vector<vector<float>> fData;
@@ -66,4 +68,5 @@
     Time fBiasLast;
     Time fStartTime;
+    Time fCalibTime;
 
     valarray<double> fPV[3];  // Process variable (intgerated/averaged amplitudes)
@@ -367,5 +370,8 @@
         }
 
-        fDimCalibration.Update(fCalibration);
+        fCalibTime = Time();
+
+        fDimCalibration.setData(fCalibration);
+        fDimCalibration.Update(fCalibTime);
 
         fOutputEnabled = false;
@@ -719,4 +725,80 @@
     }
 
+    void HandleCalibrateCurrents(const EventImp &evt)
+    {
+        if (fBiasVolt.size()==0 || fCalibration.size()==0)
+            return;
+
+        struct dim_data {
+            float I[416];
+            float Iavg;
+            float Irms;
+            float Imed;
+            float Idev;
+            uint16_t N;
+            float Tdiff;
+
+            dim_data() : Iavg(0), Irms(0), Imed(0), Idev(0), N(0), Tdiff(0) { memset(I, 0, sizeof(float)*416); }
+        } __attribute__((__packed__));;
+
+        const int16_t *I = evt.Ptr<int16_t>();
+        const float   *R = fCalibration.data()+BIAS::kNumChannels*2;
+        const float   *U = fBiasVolt.data();
+
+        vector<float> med(416);
+        uint16_t cnt = 0;
+
+        double avg = 0;
+        double rms = 0;
+
+        dim_data data;
+        for (int i=0; i<416; i++)
+        {
+            const PixelMapEntry &hv = fMap.hv(i);
+            if (!hv)
+                continue;
+
+            if (R[i]<=0)
+                continue;
+
+            data.I[i]  = I[i]*5000./4096 - U[i]/R[i]*1e6;
+            data.I[i] /= hv.group() ? 5 : 4;
+
+            avg += data.I[i];
+            rms += data.I[i]*data.I[i];
+
+            if (i>=320)
+                continue;
+
+            med[cnt++] = data.I[i];
+        }
+
+        if (cnt==0)
+            return;
+
+        avg /= cnt;
+        rms /= cnt;
+
+        data.N = cnt;
+        data.Iavg = avg;
+        data.Irms = sqrt(rms-avg*avg);
+
+        sort(med.data(), med.data()+cnt);
+
+        data.Imed = cnt%2 ? (med[cnt/2-1]+med[cnt/2])/2 : med[cnt/2];
+
+        for (int i=0; i<cnt; i++)
+            med[i] = fabs(med[i]-data.Imed);
+
+        sort(med.data(), med.data()+cnt);
+
+        data.Idev = med[uint32_t(0.682689477208650697*cnt)];
+
+        data.Tdiff = evt.GetTime().UnixTime()-fCalibTime.UnixTime();
+
+        fDimCurrents.setData(&data, sizeof(dim_data));
+        fDimCurrents.Update(evt.GetTime());
+    }
+
     int HandleBiasCurrent(const EventImp &evt)
     {
@@ -736,4 +818,6 @@
         }*/
 
+        HandleCalibrateCurrents(evt);
+
         return GetCurrentState();
     }
@@ -756,4 +840,10 @@
         Info("Nominal bias voltages received.");
 
+        return GetCurrentState();
+    }
+
+    int HandleBiasVoltage(const EventImp &evt)
+    {
+        fBiasVolt.assign(evt.Ptr<float>(), evt.Ptr<float>()+416);
         return GetCurrentState();
     }
@@ -1199,4 +1289,13 @@
                         "|Rms[uA]:Rms of offset"
                         "|R[Ohm]:Measured calibration resistor"),
+        fDimCurrents("FEEDBACK/CALIBRATED_CURRENTS", "F:416;F:1;F:1;F:1;F:1;I:1;F:1",
+                     "Calibrated currents"
+                     "|I[uA]:Calibrated currents"
+                     "|I_avg[uA]:Average calibrated current (320 channels)"
+                     "|I_rms[uA]:Rms of calibrated current (320 channels)"
+                     "|I_med[uA]:Median calibrated current (320 channels)"
+                     "|I_dev[uA]:Deviation of calibrated current (320 channels)"
+                     "|N:Number of valid values"
+                     "|T_diff[s]:Time difference to calibration"),
         fSP(BIAS::kNumChannels),
         fKp(0), fKi(0), fKd(0), fT(-1),
@@ -1221,4 +1320,6 @@
         Subscribe("BIAS_CONTROL/CURRENT")
             (bind(&StateMachineFeedback::HandleBiasCurrent, this, placeholders::_1));
+        Subscribe("BIAS_CONTROL/VOLTAGE")
+            (bind(&StateMachineFeedback::HandleBiasVoltage, this, placeholders::_1));
         Subscribe("BIAS_CONTROL/FEEDBACK_DATA")
             (bind(&StateMachineFeedback::HandleBiasData,    this, placeholders::_1));
