Index: /trunk/FACT++/gui/FactGui.h
===================================================================
--- /trunk/FACT++/gui/FactGui.h	(revision 11730)
+++ /trunk/FACT++/gui/FactGui.h	(revision 11731)
@@ -382,5 +382,5 @@
 
     DimStampedInfo fDimFtmPassport;
-    DimStampedInfo fDimFtmTriggerCounter;
+    DimStampedInfo fDimFtmTriggerRates;
     DimStampedInfo fDimFtmError;
     DimStampedInfo fDimFtmFtuList;
@@ -542,5 +542,5 @@
     }
 
-    void RemoveService(const std::string &server, const std::string &service, bool iscmd)
+    void RemoveService(std::string server, std::string service, bool iscmd)
     {
         UnsubscribeService(server+'/'+service, true);
@@ -1669,12 +1669,127 @@
     // ===================== FTM ============================================
 
-    double fTimeStamp1;
-
-    void handleFtmTriggerCounter(const DimData &d)
-    {
-        if (!CheckSize(d, sizeof(FTM::DimTriggerCounter)))
-            return;
-
-        const FTM::DimTriggerCounter &sdata = d.ref<FTM::DimTriggerCounter>();
+    void UpdateTriggerRate(const FTM::DimTriggerRates &sdata)
+    {
+#ifdef HAVE_ROOT
+        TCanvas *c = fFtmRateCanv->GetCanvas();
+
+        TH1 *h = (TH1*)c->FindObject("TimeFrame");
+
+        if (sdata.fTriggerRate<0)
+        {
+            fGraphFtmRate.Set(0);
+
+            const double tm = Time().RootTime();
+
+            h->SetBins(1, tm, tm+60);
+            h->GetXaxis()->SetTimeFormat("%M'%S\"");
+            h->GetXaxis()->SetTitle("Time");
+
+            c->Modified();
+            c->Update();
+            return;
+        }
+
+        const double t1 = h->GetXaxis()->GetXmax();
+        const double t0 = h->GetXaxis()->GetXmin();
+
+        const double now = t0+sdata.fTimeStamp/1000000.;
+
+        h->SetBins(h->GetNbinsX()+1, t0, now+1);
+        fGraphFtmRate.SetPoint(fGraphFtmRate.GetN(), now, sdata.fTriggerRate);
+
+        if (t1-t0>60)
+        {
+            h->GetXaxis()->SetTimeFormat("%Hh%M'");
+            h->GetXaxis()->SetTitle("Time");
+        }
+
+        h->SetMinimum(0);
+
+        c->Modified();
+        c->Update();
+#endif
+    }
+
+    void UpdateRatesCam(const FTM::DimTriggerRates &sdata)
+    {
+#ifdef HAVE_ROOT
+        if (fThresholdIdx->value()>=0)
+        {
+            const int isw = fThresholdIdx->value();
+            const int ihw = fPatchMapHW[isw];
+            fPatchRate->setValue(sdata.fPatchRate[ihw]);
+        }
+
+        valarray<double> dat(0., 1440);
+
+        // fPatch converts from software id to software patch id
+        for (int i=0; i<1440; i++)
+        {
+            const int ihw = fPatchHW[i];
+//            const int isw = fPatch[i];
+//            const int ihw = fPatchMapHW[isw];
+            dat[i] = sdata.fPatchRate[ihw];
+        }
+
+        TCanvas *c = fRatesCanv->GetCanvas();
+        Camera *cam = (Camera*)c->FindObject("Camera");
+
+        cam->SetData(dat);
+
+        c->Modified();
+        c->Update();
+#endif
+    }
+
+    int64_t fTimeStamp0;
+
+    void UpdateRatesGraphs(const FTM::DimTriggerRates &sdata)
+    {
+#ifdef HAVE_ROOT
+        if (fTimeStamp0<0)
+        {
+            fTimeStamp0 = sdata.fTimeStamp;
+            return;
+        }
+
+        TCanvas *c = fFtmRateCanv->GetCanvas();
+
+        TH1 *h = (TH1*)c->FindObject("TimeFrame");
+
+        const double tdiff = sdata.fTimeStamp-fTimeStamp0;
+        fTimeStamp0 = sdata.fTimeStamp;
+
+        if (tdiff<0)
+        {
+            for (int i=0; i<160; i++)
+                fGraphPatchRate[i].Set(0);
+            for (int i=0; i<40; i++)
+                fGraphBoardRate[i].Set(0);
+
+            return;
+        }
+
+        //const double t1 = h->GetXaxis()->GetXmax();
+        const double t0 = h->GetXaxis()->GetXmin();
+
+        for (int i=0; i<160; i++)
+            fGraphPatchRate[i].SetPoint(fGraphPatchRate[i].GetN(),
+                                        t0+sdata.fTimeStamp/1000000., sdata.fPatchRate[i]);
+        for (int i=0; i<40; i++)
+            fGraphBoardRate[i].SetPoint(fGraphBoardRate[i].GetN(),
+                                        t0+sdata.fTimeStamp/1000000., sdata.fBoardRate[i]);
+
+        c->Modified();
+        c->Update();
+#endif
+    }
+
+    void handleFtmTriggerRates(const DimData &d)
+    {
+        if (!CheckSize(d, sizeof(FTM::DimTriggerRates)))
+            return;
+
+        const FTM::DimTriggerRates &sdata = d.ref<FTM::DimTriggerRates>();
 
         fFtmTime->setText(QString::number(sdata.fTimeStamp/1000000., 'f', 6)+ " s");
@@ -1686,65 +1801,18 @@
             fTriggerCounterRate->setValue(0);
 
-
         // ----------------------------------------------
-#ifdef HAVE_ROOT
-
-        if (fTriggerCounter0<0)
-        {
-            fTriggerCounter0 = sdata.fTriggerCounter;
-            fTimeStamp1      = sdata.fTimeStamp;
-            return;
-        }
-
-        TCanvas *c = fFtmRateCanv->GetCanvas();
-
-        TH1 *h = (TH1*)c->FindObject("TimeFrame");
-
-        const double rate  = sdata.fTriggerCounter-fTriggerCounter0;
-        const double tdiff = sdata.fTimeStamp     -fTimeStamp1;
-
-        fTriggerCounter0   = sdata.fTriggerCounter;
-        fTimeStamp1        = sdata.fTimeStamp;
-
-        if (rate<0 && tdiff<=0)
-        {
-            fGraphFtmRate.Set(0);
-
-            const double tm = Time().RootTime();
-
-            h->SetBins(1, tm, tm+60);
-            h->GetXaxis()->SetTimeFormat("%M'%S\"");
-            h->GetXaxis()->SetTitle("Time");
-
-            c->Modified();
-            c->Update();
-            return;
-        }
-
-        if (rate<0)
-            return;
-
-//        const double avgrate = sdata.fTimeStamp>0 ? double(sdata.fTriggerCounter)/sdata.fTimeStamp*1000000 : 1;
-
-        const double t1 = h->GetXaxis()->GetXmax();
-        const double t0 = h->GetXaxis()->GetXmin();
-
-        h->SetBins(h->GetNbinsX()+1, t0, t0+sdata.fTimeStamp/1000000.+1);
-        fGraphFtmRate.SetPoint(fGraphFtmRate.GetN(),
-                               t0+sdata.fTimeStamp/1000000., 1000000*rate/tdiff);
-
-        if (t1-t0>60)
-        {
-            h->GetXaxis()->SetTimeFormat("%Hh%M'");
-            h->GetXaxis()->SetTitle("Time");
-        }
-
-        h->SetMinimum(0);
-//        h->SetMaximum(2*avgrate);
-
-        c->Modified();
-        c->Update();
-#endif
+
+        fOnTime->setText(QString::number(sdata.fOnTimeCounter/1000000., 'f', 6)+" s");
+
+        if (sdata.fTimeStamp>0)
+            fOnTimeRel->setValue(100.*sdata.fOnTimeCounter/sdata.fTimeStamp);
+        else
+            fOnTimeRel->setValue(0);
+
         // ----------------------------------------------
+
+        UpdateTriggerRate(sdata);
+        UpdateRatesGraphs(sdata);
+        UpdateRatesCam(sdata);
     }
 
@@ -1764,7 +1832,4 @@
     }
 
-    int64_t fTriggerCounter0;
-    int64_t fTimeStamp0;
-
     void handleFtmDynamicData(const DimData &d)
     {
@@ -1773,11 +1838,4 @@
 
         const FTM::DimDynamicData &sdata = d.ref<FTM::DimDynamicData>();
-
-        fOnTime->setText(QString::number(sdata.fOnTimeCounter/1000000., 'f', 6)+" s");
-
-        if (sdata.fTimeStamp>0)
-            fOnTimeRel->setValue(100.*sdata.fOnTimeCounter/sdata.fTimeStamp);
-        else
-            fOnTimeRel->setValue(0);
 
         fFtmTemp0->setValue(sdata.fTempSensor[0]*0.1);
@@ -1787,77 +1845,4 @@
 
         SetLedColor(fClockCondLed, sdata.fState&FTM::kFtmLocked ? kLedGreen : kLedRed, d.time);
-
-#ifdef HAVE_ROOT
-
-        // ----------------------------------------------
-
-        if (fTimeStamp0<0)
-        {
-            fTimeStamp0 = sdata.fTimeStamp;
-            return;
-        }
-
-        TCanvas *c = fFtmRateCanv->GetCanvas();
-
-        TH1 *h = (TH1*)c->FindObject("TimeFrame");
-
-        const double tdiff = sdata.fTimeStamp-fTimeStamp0;
-        fTimeStamp0 = sdata.fTimeStamp;
-
-        if (tdiff<0)
-        {
-            for (int i=0; i<160; i++)
-                fGraphPatchRate[i].Set(0);
-            for (int i=0; i<40; i++)
-                fGraphBoardRate[i].Set(0);
-
-            return;
-        }
-
-        //const double t1 = h->GetXaxis()->GetXmax();
-        const double t0 = h->GetXaxis()->GetXmin();
-
-        for (int i=0; i<160; i++)
-            fGraphPatchRate[i].SetPoint(fGraphPatchRate[i].GetN(),
-                                       t0+sdata.fTimeStamp/1000000., float(sdata.fRatePatch[i])*2/fFtmStaticData.fPrescaling[i]);
-        for (int i=0; i<40; i++)
-            fGraphBoardRate[i].SetPoint(fGraphBoardRate[i].GetN(),
-                                       t0+sdata.fTimeStamp/1000000., float(sdata.fRateBoard[i])*2/fFtmStaticData.fPrescaling[i]);
-
-        c->Modified();
-        c->Update();
-
-        //fGraphFtmRate.ComputeRange(x[0], x[1], x[2], x[3]);
-
-        // ----------------------------------------------
-
-        if (fThresholdIdx->value()>=0)
-        {
-            const int isw = fThresholdIdx->value();
-            const int ihw = fPatchMapHW[isw];
-            fPatchRate->setValue(sdata.fRatePatch[ihw]);
-        }
-
-        valarray<double> dat(0., 1440);
-
-        // fPatch converts from software id to software patch id
-        for (int i=0; i<1440; i++)
-        {
-            const int ihw = fPatchHW[i];
-//            const int isw = fPatch[i];
-//            const int ihw = fPatchMapHW[isw];
-            dat[i] = sdata.fRatePatch[ihw];
-        }
-
-        c = fRatesCanv->GetCanvas();
-        Camera *cam = (Camera*)c->FindObject("Camera");
-
-        cam->SetData(dat);
-
-        c->Modified();
-        c->Update();
-
-        // ----------------------------------------------
-#endif
     }
 
@@ -2543,6 +2528,6 @@
             return PostInfoHandler(&FactGui::handleLoggerFilenameRun);
 
-        if (getInfo()==&fDimFtmTriggerCounter)
-            return PostInfoHandler(&FactGui::handleFtmTriggerCounter);
+        if (getInfo()==&fDimFtmTriggerRates)
+            return PostInfoHandler(&FactGui::handleFtmTriggerRates);
 
         if (getInfo()==&fDimFtmCounter)
@@ -2966,5 +2951,5 @@
         //-
         fDimFtmPassport        ("FTM_CONTROL/PASSPORT",         (void*)NULL, 0, this),
-        fDimFtmTriggerCounter  ("FTM_CONTROL/TRIGGER_COUNTER",  (void*)NULL, 0, this),
+        fDimFtmTriggerRates    ("FTM_CONTROL/TRIGGER_RATES",    (void*)NULL, 0, this),
         fDimFtmError           ("FTM_CONTROL/ERROR",            (void*)NULL, 0, this),
         fDimFtmFtuList         ("FTM_CONTROL/FTU_LIST",         (void*)NULL, 0, this),
@@ -2992,6 +2977,4 @@
         //-
 	fEventData(0), fDrsCalibration(1440*1024*6),
-	fTimeStamp1(0),
-	fTriggerCounter0(0),
 	fTimeStamp0(0)
 
@@ -3199,6 +3182,4 @@
         hf->GetYaxis()->SetRangeUser(0, 1010);
 
-        fTriggerCounter0 = -1;
-
         fGraphFtmRate.SetMarkerStyle(kFullDotSmall);
         fGraphFtmRate.Draw("LP");
Index: /trunk/FACT++/src/HeadersFTM.h
===================================================================
--- /trunk/FACT++/src/HeadersFTM.h	(revision 11730)
+++ /trunk/FACT++/src/HeadersFTM.h	(revision 11731)
@@ -147,4 +147,5 @@
     } __attribute__((__packed__));
 
+    /*
     struct DimTriggerCounter
     {
@@ -158,5 +159,5 @@
         }
     } __attribute__((__packed__));
-
+    */
 
     struct StaticDataBoard
@@ -535,9 +536,11 @@
         uint16_t fRateOverflow[40];
 
+        uint16_t fPrescaling[40];
+
         uint16_t fCrcError[40];
 
         uint16_t fState;
 
-        DimDynamicData(const Header &h, const DynamicData &d) :
+        DimDynamicData(const Header &h, const DynamicData &d, const StaticData &s) :
             fTimeStamp(h.fTimeStamp),
             fOnTimeCounter(d.fOnTimeCounter),
@@ -554,4 +557,38 @@
                 for (int j=0; j<4; j++)
                     fRatePatch[i*4+j] = d[i].fRatePatch[j];
+
+                fPrescaling[i] = s[i].fPrescaling;
+            }
+        }
+
+    } __attribute__((__packed__));
+
+    struct DimTriggerRates
+    {
+        uint64_t fTimeStamp;
+        uint64_t fOnTimeCounter;
+        uint32_t fTriggerCounter;
+        float    fTriggerRate;
+        float    fBoardRate[40];
+        float    fPatchRate[160];
+
+        DimTriggerRates(const Header &h, const DynamicData &d, const StaticData &s, float rate) :
+            fTimeStamp(h.fTimeStamp), fOnTimeCounter(d.fOnTimeCounter),
+            fTriggerCounter(h.fTriggerCounter), fTriggerRate(rate)
+        {
+            for (int i=0; i<40; i++)
+            {
+                if ((d[i].fOverflow>>4)&1)
+                    fBoardRate[i] = float(UINT32_MAX+1)*2/s[i].fPrescaling;
+                else
+                    fBoardRate[i] = float(d[i].fRateTotal)*2/s[i].fPrescaling;
+
+                // FIXME: Include fCrcError in calculation
+                //fRateOverflow[i] = d[i].fOverflow;
+                for (int j=0; j<4; j++)
+                    if ((d[i].fOverflow>>j)&1)
+                        fPatchRate[i*4+j] = float(UINT32_MAX+1)*2/s[i].fPrescaling;
+                    else
+                        fPatchRate[i*4+j] = float(d[i].fRatePatch[j])*2/s[i].fPrescaling;
             }
         }
Index: /trunk/FACT++/src/ftmctrl.cc
===================================================================
--- /trunk/FACT++/src/ftmctrl.cc	(revision 11730)
+++ /trunk/FACT++/src/ftmctrl.cc	(revision 11731)
@@ -1135,5 +1135,5 @@
 
     DimDescribedService fDimPassport;
-    DimDescribedService fDimTriggerCounter;
+    DimDescribedService fDimTriggerRates;
     DimDescribedService fDimError;
     DimDescribedService fDimFtuList;
@@ -1142,4 +1142,7 @@
     DimDescribedService fDimCounter;
 
+    uint64_t fTimeStamp;
+    uint32_t fTriggerCounter;
+
     void UpdateFirstHeader()
     {
@@ -1150,4 +1153,5 @@
     }
 
+    /*
     void UpdateHeader()
     {
@@ -1159,5 +1163,5 @@
         const FTM::DimTriggerCounter data(fHeader);
         fDimTriggerCounter.Update(data);
-    }
+    }*/
 
     void UpdateFtuList()
@@ -1181,6 +1185,21 @@
         ConnectionFTM::UpdateDynamicData();
 
-        const FTM::DimDynamicData data(fHeader, fDynamicData);
+        const FTM::DimDynamicData data(fHeader, fDynamicData, fStaticData);
         fDimDynamicData.Update(data);
+
+        float rate = -1;
+        if (fHeader.fTimeStamp>=fTimeStamp && fHeader.fTriggerCounter>=fTriggerCounter)
+        {
+            const uint64_t tdiff = fHeader.fTimeStamp     -fTimeStamp;
+            const uint32_t cdiff = fHeader.fTriggerCounter-fTriggerCounter;
+
+            rate = tdiff==0 ? 0 : 1000000*float(cdiff)/tdiff;
+        }
+
+        fTimeStamp      = fHeader.fTimeStamp;
+        fTriggerCounter = fHeader.fTriggerCounter;
+
+        const FTM::DimTriggerRates rates(fHeader, fDynamicData, fStaticData, rate);
+        fDimTriggerRates.Update(rates);
     }
 
@@ -1214,10 +1233,12 @@
         ConnectionFTM(ioservice, imp),
         fDimPassport      ("FTM_CONTROL/PASSPORT",        "X:1;S:1", ""),
-        fDimTriggerCounter("FTM_CONTROL/TRIGGER_COUNTER", "X:1;I:1", ""),
+        fDimTriggerRates  ("FTM_CONTROL/TRIGGER_RATES",   "X:2;I:1;F:1;F:40;F:160", ""),
         fDimError         ("FTM_CONTROL/ERROR",           "X:1;S:1;S:28", ""),
         fDimFtuList       ("FTM_CONTROL/FTU_LIST",        "X:1;X:1;S:1;C:4;X:40;C:40;C:40",  ""),
         fDimStaticData    ("FTM_CONTROL/STATIC_DATA",     "X:1;S:1;S:1;X:1;S:1;S:3;S:1;S:1;S:1;S:1;S:1;S:1;I:1;I:8;S:90;S:160;S:40;S:40", ""),
-        fDimDynamicData   ("FTM_CONTROL/DYNAMIC_DATA",    "X:1;X:1;F:4;I:160;I:40;S:40;S:40;S:1", ""),
-        fDimCounter       ("FTM_CONTROL/COUNTER",         "I:6", "")
+        fDimDynamicData   ("FTM_CONTROL/DYNAMIC_DATA",    "X:1;X:1;F:4;I:160;I:40;S:40;S:40;S:40;S:1", ""),
+        fDimCounter       ("FTM_CONTROL/COUNTER",         "I:6", ""),
+        fTimeStamp(UINT64_MAX),
+        fTriggerCounter(UINT32_MAX)
     {
     }
