Index: /trunk/FACT++/aclocal.m4
===================================================================
--- /trunk/FACT++/aclocal.m4	(revision 15489)
+++ /trunk/FACT++/aclocal.m4	(revision 15490)
@@ -1725,5 +1725,5 @@
 #   exception to the GPL to apply to your modified version as well.
 
-#serial 16
+#serial 17
 
 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
@@ -1899,5 +1899,12 @@
         case "${host_cpu}-${host_os}" in
             *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
-            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+            *-osf* | *-hpux*) flag="-D_REENTRANT";;
+            *solaris*)
+            if test "$GCC" = "yes"; then
+                flag="-D_REENTRANT"
+            else
+                flag="-mt -D_REENTRANT"
+            fi
+            ;;
         esac
         AC_MSG_RESULT(${flag})
Index: /trunk/FACT++/configure
===================================================================
--- /trunk/FACT++/configure	(revision 15489)
+++ /trunk/FACT++/configure	(revision 15490)
@@ -18490,5 +18490,12 @@
         case "${host_cpu}-${host_os}" in
             *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
-            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+            *-osf* | *-hpux*) flag="-D_REENTRANT";;
+            *solaris*)
+            if test "$GCC" = "yes"; then
+                flag="-D_REENTRANT"
+            else
+                flag="-mt -D_REENTRANT"
+            fi
+            ;;
         esac
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5
@@ -23980,5 +23987,5 @@
 
 		cat > conftest.$ac_ext <<EOF
-#line 23982 "configure"
+#line 23989 "configure"
 #include "confdefs.h"
 #include <qglobal.h>
Index: /trunk/FACT++/src/EventBuilder.c
===================================================================
--- /trunk/FACT++/src/EventBuilder.c	(revision 15489)
+++ /trunk/FACT++/src/EventBuilder.c	(revision 15490)
@@ -73,34 +73,17 @@
 
 int g_maxProc;
-int g_maxSize;
-int gi_maxSize;
 int gi_maxProc;
 
 uint g_actTime;
-uint g_actUsec;
 int g_runStat;
 int g_reset;
-int g_useFTM;
-
-int gi_reset, gi_resetR, gi_resetS, gi_resetW, gi_resetX;
+
 size_t g_maxMem;                //maximum memory allowed for buffer
 
-//no longer needed ...
-int g_maxBoards;                //maximum number of boards to be initialized
-int g_actBoards;
-//
-
 FACT_SOCK g_port[NBOARDS];      // .addr=string of IP-addr in dotted-decimal "ddd.ddd.ddd.ddd"
 
-
-int gi_runStat;
-int gp_runStat;
-int gw_runStat;
-
-uint32_t actrun = 0;
-
 uint gi_NumConnect[NBOARDS];    //4 crates * 10 boards
 
-EVT_STAT gi;
+//EVT_STAT gi;
 GUI_STAT gj;
 
@@ -166,4 +149,6 @@
     // Add the last free slot to the stack
     TGB_entry *entry = (TGB_entry*)malloc(sizeof(TGB_entry));
+
+    // FIXME: Really free memory if memory usuage exceeds g_maxMem
 
     entry->prev = tgb_last;
@@ -220,18 +205,4 @@
 /*-----------------------------------------------------------------*/
 
-
-
-int
-runFinish1 (uint32_t runnr)
-{
-   factPrintf(kInfo, 173, "Should finish(1) run %d (but not yet possible)", runnr);
-   return 0;
-}
-int
-runFinish (uint32_t runnr)
-{
-    factPrintf(kInfo, 173, "Should finish run %d (but not yet possible)", runnr);
-    return 0;
-}
 
 int
@@ -438,51 +409,68 @@
     }
 
-    // FIXME: This should be the time of the first receiped board
+    // If we have already queued at least one event,
+    // check the roi if the previous event
+    // already belongs to the same run.
+
+    // Get the runCtrl entry of the previous event.
+    // If none is in the queue (we are anyhow super fast)
+    // just get the correct entry from the runCtrl array.
+    int idx = evtCtrl[beg].runCtrl_idx;
+
+    // If there is an event in the queue and it has the same runID, we can use
+    // that event to check for the roi consistency throughout the run
+    if (evtCtrl_frstPtr!=evtCtrl_lastPtr && runCtrl[idx].runId==runID)
+    {
+        // Check if run already registered (old entries should have runId==-1)
+        if (runCtrl[idx].roi0 != nRoi[0] || runCtrl[idx].roi8 != nRoi[8])
+        {
+            factPrintf(kError, 931, "Mismatch of roi within run. Expected roi=%d and roi_tm=%d, got %d and %d (runID=%d, evID=%d)",
+                       runCtrl[idx].roi0, runCtrl[idx].roi8, nRoi[0], nRoi[8], runID, evID);
+            return -9301;
+        }
+    }
+
+    // If there is none in the queue, we have to search for the correct entry
+    if (evtCtrl_frstPtr==evtCtrl_lastPtr)
+    {
+        idx = -1;
+
+        for (int k=0; k<MAX_RUN; k++)
+        {
+            if (runCtrl[k].runId==runID)
+            {
+                idx = k;
+                break;
+            }
+        }
+    }
+
     struct timeval tv;
-    gettimeofday (&tv, NULL);
+    gettimeofday(&tv, NULL);
 
     const uint32_t tsec = tv.tv_sec;
     const uint32_t tusec = tv.tv_usec;
 
-    //check if runId already registered in runCtrl
-
-    uint oldest = g_actTime + 1000;
-    int jold = -1;
-
-    int found = 0;
-
-    // fileId==-2: not yet used or run assigned but not open
-    // fileId== 0: file open
-    // fileId>0:   run closed
-
-    for (int k=0; k<MAX_RUN; k++)
+    // Run not yet registered, register run
+    // If we haven't found a corresponding entry in the queue, or the runId has changed
+    // we find the oldest empty entry in the runCtrl array and create a new runCtrl entry
+    if (idx<0 || runCtrl[idx].runId!=runID)
     {
-        // Check if run already registered (old entries should have runId==-1)
-        if (runCtrl[k].runId == runID)
+        // If there is none in the queue or
+        idx = -1;
+
+        uint oldest = g_actTime + 1000;
+        for (int k=0; k<MAX_RUN; k++)
         {
-            // FIXME: Compare to previous event
-            if (runCtrl[k].roi0 != nRoi[0] || runCtrl[k].roi8 != nRoi[8])
+            // This is just for sanity. We use the oldest free entry (until
+            // we have understood the concept and can use "just" a free entry
+            if (runCtrl[k].runId==0 && runCtrl[k].closeTime < oldest)
             {
-                factPrintf(kError, 931, "Mismatch of roi within run. Expected roi=%d and roi_tm=%d, got %d and %d (runID=%d, evID=%d)",
-                           runCtrl[k].roi0, runCtrl[k].roi8, nRoi[0], nRoi[8], runID, evID);
-                return -9301;
+                oldest = runCtrl[k].closeTime;
+                idx = k;
             }
-
-            found = 1;
-            break;
         }
 
-        // This is just for sanity. We use the oldest free entry (until
-        // we have understood the concept and can use "just" a free entry
-        if (runCtrl[k].runId==0 && runCtrl[k].closeTime < oldest)
-        {
-            oldest = runCtrl[k].closeTime;
-            jold = k;
-        }
-    }
-
-    if (!found) // Run not yet registered, register run
-    {
-        if (jold < 0)
+        if (idx<0)
         {
             factPrintf(kFatal, 883, "Not able to register the new run %d", runID);
@@ -490,20 +478,17 @@
         }
 
-        const int evFree = jold;
-
-        factPrintf(kInfo, 503, "New run %d (evID=%d, evFree=%d) registered with roi=%d and roi_tm=%d",
-                   runID, evID, evFree, nRoi[0], nRoi[8]);
-
-        runCtrl[evFree].runId      = runID;
-        runCtrl[evFree].roi0       = nRoi[0];  // FIXME: Make obsolete!
-        runCtrl[evFree].roi8       = nRoi[8];  // FIXME: Make obsolete!
-        runCtrl[evFree].fileId     = -2;
-        runCtrl[evFree].procId     = -2;
-        runCtrl[evFree].lastEvt    = 1;         // Number of events partially started to read
-        runCtrl[evFree].actEvt     = 0;         // Number of written events (write)
-        runCtrl[evFree].procEvt    = 0;         // Number of successfully checked events (checkEvent)
-        runCtrl[evFree].maxEvt     = 999999999; // max number events allowed
-        runCtrl[evFree].lastTime   = tsec;      // Time when the last event was written
-        runCtrl[evFree].closeTime  = tsec + 3600 * 24;     //max time allowed
+        factPrintf(kInfo, 503, "New run %d (evt=%d, idx=%d) registered with roi=%d and roi_tm=%d",
+                   runID, evID, idx, nRoi[0], nRoi[8]);
+
+        runCtrl[idx].runId      = runID;
+        runCtrl[idx].roi0       = nRoi[0];  // FIXME: Make obsolete!
+        runCtrl[idx].roi8       = nRoi[8];  // FIXME: Make obsolete!
+        runCtrl[idx].fileId     = -2;
+        runCtrl[idx].lastEvt    = 1;         // Number of events partially started to read
+        runCtrl[idx].actEvt     = 0;         // Number of written events (write)
+        runCtrl[idx].procEvt    = 0;         // Number of successfully checked events (checkEvent)
+        runCtrl[idx].maxEvt     = 999999999; // max number events allowed
+        runCtrl[idx].lastTime   = tsec;      // Time when the last event was written
+        runCtrl[idx].closeTime  = tsec + 3600 * 24;     //max time allowed
     }
 
@@ -516,4 +501,5 @@
         evtCtrl[k].board[b] = -1;
 
+    evtCtrl[k].runCtrl_idx = idx;
     evtCtrl[k].pcTime[0] = tsec;
     evtCtrl[k].pcTime[1] = tusec;
@@ -582,7 +568,4 @@
 mBufFree (int i)
 {
-//delete entry [i] from mBuffer:
-//(and make sure multiple calls do no harm ....)
-
    TGB_free(evtCtrl[i].FADhead);
 
@@ -597,48 +580,7 @@
    gj.bufTot--;
 
-   /*if (gi_memStat < 0) {
-      if (gj.usdMem <= 0.75 * gj.maxMem)
-         gi_memStat = +1;
-   }*/
-
    return 0;
 
 } /*-----------------------------------------------------------------*/
-
-/*
-void
-resetEvtStat ()
-{
-   for (int i = 0; i < MAX_SOCK; i++)
-      gi.numRead[i] = 0;
-
-   for (int i = 0; i < NBOARDS; i++) {
-      gi.gotByte[i] = 0;
-      gi.gotErr[i] = 0;
-
-   }
-
-   gi.evtGet = 0;               //#new Start of Events read
-   gi.evtTot = 0;               //#complete Events read
-   gi.evtErr = 0;               //#Events with Errors
-   gi.evtSkp = 0;               //#Events incomplete (timeout)
-
-   gi.procTot = 0;              //#Events processed
-   gi.procErr = 0;              //#Events showed problem in processing
-   gi.procTrg = 0;              //#Events accepted by SW trigger
-   gi.procSkp = 0;              //#Events rejected by SW trigger
-
-   gi.feedTot = 0;              //#Events used for feedBack system
-   gi.feedErr = 0;              //#Events rejected by feedBack
-
-   gi.wrtTot = 0;               //#Events written to disk
-   gi.wrtErr = 0;               //#Events with write-error
-
-   gi.runOpen = 0;              //#Runs opened
-   gi.runClose = 0;             //#Runs closed
-   gi.runErr = 0;               //#Runs with open/close errors
-
-   return;
-}*/ /*-----------------------------------------------------------------*/
 
 uint64_t reportIncomplete(int id, const char *txt)
@@ -762,8 +704,8 @@
     READ_STRUCT rd[NBOARDS];       //buffer to read IP and afterwards store in mBuffer
 
+    uint32_t actrun = 0;
+
    const int minLen = sizeof(PEVNT_HEADER);  //min #bytes needed to check header: full header for debug
 
-   //start.S = 0xFB01;
-   //stop.S = 0x04FE;
 
 /* initialize run control logics */
@@ -771,6 +713,7 @@
       runCtrl[i].runId  =  0;
       runCtrl[i].fileId = -2;
-      runCtrl[i].procId = -2;
-   }
+   }
+
+   int gi_reset, gi_resetR, gi_resetS, gi_resetW, gi_resetX;
    gi_resetS = gi_resetR = 9;
 
@@ -784,4 +727,5 @@
    //time in seconds
    uint gi_SecTime = time(NULL);;
+   g_actTime = gi_SecTime;
 
    const int cntsock = 8 - NUMSOCK ;
@@ -833,12 +777,5 @@
    while (g_runStat >= 0 && g_reset == 0)
    {
-      gi_runStat = g_runStat;
       gj.readStat = g_runStat;
-
-      struct timeval tv;
-      gettimeofday (&tv, NULL);
-      g_actTime = tv.tv_sec;
-      g_actUsec = tv.tv_usec;
-
 
       for (int b = 0; b < NBOARDS; b++)
@@ -849,5 +786,4 @@
 
           gi_NumConnect[b] = 0;       //must close all connections
-          //gi.numConn[b] = 0;
           gj.numConn[b] = 0;
 
@@ -920,6 +856,4 @@
               continue;
 
-          //numok++;
-
           if (rd[i].bufLen>0)
           {
@@ -933,11 +867,7 @@
                   // There was just nothing waiting
                   if (errno==EWOULDBLOCK || errno==EAGAIN)
-                  {
-                      //numok--;
                       continue;
-                  }
 
                   factPrintf(kError, 442, "Reading from socket %d failed: %m (recv,rc=%d)", i, errno);
-                  //gi.gotErr[b]++;
                   continue;
               }
@@ -951,13 +881,9 @@
                   GenSock(s0, i, 0, NULL, &rd[i]);
 
-                  //gi.gotErr[b]++;
-
                   gi_NumConnect[i]-= cntsock ;
-                  //gi.numConn[b]--;
                   gj.numConn[i]--;
 
                   continue;
               }
-              // Success (jrd > 0)
 
               gj.rateBytes[i] += jrd;
@@ -1073,5 +999,4 @@
               rd[i].rBuf->B[rd[i].fadLen - 2] != 0x04)
           {
-              //gi.evtErr++;
               factPrintf(kError, 301, "End-of-event flag wrong on socket %3d for event %4d (len=%5d), got %3d %3d",
                          i, rd[i].evtID, rd[i].fadLen,
@@ -1171,5 +1096,5 @@
           if (evtCtrl[idx].nBoard==1 && evtCtrl[idx].runNum != actrun)
           {
-              // Signal the fadctrl that a new run has been started
+             // Signal the fadctrl that a new run has been started
               gotNewRun(evtCtrl[idx].runNum, NULL);
 
@@ -1200,5 +1125,6 @@
           // This is a non-ideal hack to lower the probability that
           // in mBufEvt the search for correct entry in runCtrl
-          // will not return a super-old entry
+          // will not return a super-old entry. I don't want
+          // to manipulate that in another thread.
           for (int ir=0; ir<MAX_RUN; ir++)
           {
@@ -1254,4 +1180,6 @@
       const int count = (evtCtrl_lastPtr-evtCtrl_frstPtr+MAX_EVT)%MAX_EVT;
 
+      // This could be improved having the pointer which separates the queue with
+      // the incomplete events from the queue with the complete events
       for (int k0=evtCtrl_frstPtr; k0!=evtCtrl_lastPtr; k0++, k0 %= MAX_EVT)
       {
@@ -1262,5 +1190,5 @@
 
               // Event has not yet timed out or was reported already
-              if (evtCtrl[k0].evtStat==90 || evtCtrl[k0].pcTime[0]/*evtCtrl[k0].lastRecv*/>=g_actTime - 30)
+              if (evtCtrl[k0].evtStat==90 || evtCtrl[k0].pcTime[0]>=g_actTime - 30)
                   continue;
 
@@ -1296,11 +1224,4 @@
               continue;
           }
-
-          // The first events in the queue are either incomplete or
-          // can be deleted (processing finished). As soon as we reach the
-          // first complete events which processing is pending, we can stop.
-          // All other events (if everything works well) must have the same state.
-          // FIXME: This only works if we start from lastPtr and go down to frstPtr
-          //break;
       }
 
@@ -1352,5 +1273,4 @@
 
        //inform others we have to quit ....
-       gi_runStat  = -11;        //inform all that no update to happen any more
        gj.readStat = -11;        //inform all that no update to happen any more
    }
@@ -1393,5 +1313,5 @@
                evtCtrl_frstPtr = (evtCtrl_frstPtr+1) % MAX_EVT;
                evtCtrl[k0].evtStat = -1;
-          }
+           }
 
            usleep(1);
@@ -1421,9 +1341,8 @@
    factPrintf(kInfo, -1, "%ld Bytes flagged as in-use.", tgb_inuse);
 
-   gi_runStat = -99;
    gj.readStat = -99;
 
    factStat (gj);
-   factStatNew (gi);
+   //factStatNew (gi);
 
    return 0;
@@ -1444,23 +1363,24 @@
         for (int k0=evtCtrl_frstPtr; k0!=evtCtrl_lastPtr; k0++, k0 %= MAX_EVT)
         {
-            if (evtCtrl[k0].evtStat != 1000 + threadID)
-            {
-                if (evtCtrl[k0].evtStat < 1000 + threadID)
-                    numWait++;
-
-                continue;
-            }
-
-            /*
-            // gi_resetR>1 : flush buffers asap
-            if (gi_resetR>1)
-            {
-                evtCtrl[k].evtStat = 9000;              // flag as 'to be deleted'
-                continue;
-
-            }*/
-
-            const int jret = subProcEvt(threadID, evtCtrl[k0].FADhead,
-                                        evtCtrl[k0].fEvent, NULL/*mBuffer[id].buffer*/);
+           // This is a threading issue... the evtStat might have been invalid
+           // but the frstPtr is not yet updated
+           if (evtCtrl[k0].evtStat==-1)
+               continue;
+
+           // If we find the first event still waiting for processing
+           // there will be only unprocessed events after this one in the queue
+           if (evtCtrl[k0].evtStat<1000+threadID)
+           {
+               numWait = 1;
+               break;
+           }
+
+           // If the event was processed already, skip it
+           // We could replace that to a moving pointer pointing to the first
+           // non-processed event
+           if (evtCtrl[k0].evtStat!=1000+threadID)
+               continue;
+
+            const int jret = subProcEvt(threadID, evtCtrl[k0].FADhead, evtCtrl[k0].fEvent, 0);
 
             if (jret>0 && jret<=threadID)
@@ -1504,28 +1424,5 @@
    int status;
 
-   int lastRun = 0;             //usually run from last event still valid
-
-//   cpu_set_t mask;
-//   int cpu = 1;                 //process thread  (will be several in final version)
-
    factPrintf(kInfo, -1, "Starting process-thread with %d subprocesses", gi_maxProc);
-
-/* CPU_ZERO initializes all the bits in the mask to zero. */
-//   CPU_ZERO (&mask);
-/* CPU_SET sets only the bit corresponding to cpu. */
-// CPU_SET(  0 , &mask );  leave for system
-// CPU_SET(  1 , &mask );  used by write process
-//   CPU_SET (2, &mask);
-//   CPU_SET (3, &mask);
-//   CPU_SET (4, &mask);
-//   CPU_SET (5, &mask);
-//   CPU_SET (6, &mask);
-// CPU_SET(  7 , &mask );  used by read process
-/* sched_setaffinity returns 0 in success */
-//   if (sched_setaffinity (0, sizeof (mask), &mask) == -1) {
-//      snprintf (str, MXSTR, "P ---> can not create affinity to %d", cpu);
-//      factOut (kWarn, -1, str);
-//   }
-
 
    pthread_t thread[100];
@@ -1540,23 +1437,25 @@
    {
        int numWait = 0;
-       int numProc = 0;
 
        for (int k0=evtCtrl_frstPtr; k0!=evtCtrl_lastPtr; k0++, k0 %= MAX_EVT)
        {
-           if (evtCtrl[k0].evtStat<90 || evtCtrl[k0].evtStat>=1000)
+           // This is a threading issue... the evtStat might have been invalid
+           // but the frstPtr is not yet updated
+           if (evtCtrl[k0].evtStat==-1)
+               continue;
+
+           // If we find the first incomplete event which is not supposed to
+           // be processed, there are only more incomplete events in the queue
+           if (evtCtrl[k0].evtStat<90)
            {
-               if (/*evtCtrl[k0].evtStat>=0 &&*/ evtCtrl[k0].evtStat<90)
-                   numWait++;
-
+               numWait = 1;
+               break;
+           }
+
+           // If the event was processed already, skip it.
+           // We could replace that to a moving pointer pointing to the first
+           // non-processed event
+           if (evtCtrl[k0].evtStat>=1000)
                continue;
-           }
-
-           /*
-           //we are asked to flush buffers asap
-           if (gi_resetR > 1)
-           {
-               evtCtrl[k0].evtStat = 9000;
-               continue;
-           }*/
 
            //-------- it is better to open the run already here, so call can be used to initialize
@@ -1565,42 +1464,15 @@
            const int32_t  ievt = evtCtrl[k0].evNum;
 
-           // Find entry in runCtrl which belongs to the event mBuffer[id]
-           // (only check if there is a need to check)
-           if (runCtrl[lastRun].runId != irun)
+           const int idx = evtCtrl[k0].runCtrl_idx;
+           if (runCtrl[idx].runId!=irun)
            {
-               //check which fileID to use (or open if needed)
-               int j;
-               for (j=0;j<MAX_RUN; j++)
-                   if (runCtrl[j].runId == irun)
-                       break;
-
-               if (j>=MAX_RUN)
-               {
-                   factPrintf(kFatal, 901, "writeEvt: Can not find run %d for event %d in %d", irun, ievt, k0);
-                   // FIXME: What is the right action? (Flag event for deletion?)
-                   continue;
-               }
-
-               lastRun = j;
+               //factPrintf(kFatal, 901, "procEvt: runCtrl entry for run %d vanished (evt=%d)", irun, ievt);
+               // FIXME: What is the right action? (Flag event for deletion?)
+               continue;
            }
 
            // File not yet open
-           if (runCtrl[lastRun].fileId < 0)
+           if (runCtrl[idx].fileId < 0)
            {
-               //----            we need to open a new run ==> make sure all older runs are
-               //----            finished and marked to be closed ....
-               // This loop is unique to procEvt
-               for (int j=0; j<MAX_RUN; j++)
-               {
-                   if (runCtrl[j].fileId == 0)
-                   {
-                       runCtrl[j].procId = 2; //--> do no longer accept events for processing
-
-                       //----                  problem: processing still going on ==> must wait for closing ....
-                       factPrintf(kInfo, -1, "procEvt: Finished run since new one opened %d", runCtrl[j].runId);
-                       runFinish1(runCtrl[j].runId);
-                   }
-               }
-
                RUN_HEAD actRun;
                actRun.Version =  1;
@@ -1616,37 +1488,15 @@
                memcpy(actRun.FADhead, evtCtrl[k0].FADhead, NBOARDS*sizeof(PEVNT_HEADER));
 
-               runCtrl[lastRun].fileHd = runOpen (irun, &actRun, sizeof (actRun));
-               if (runCtrl[lastRun].fileHd == NULL)
+               runCtrl[idx].fileHd = runOpen(irun, &actRun, sizeof (actRun));
+               if (runCtrl[idx].fileHd == NULL)
                {
-                   factPrintf(kError, 502, "procEvt: Could not open a file for run %d (runOpen failed)", irun);
-                   runCtrl[lastRun].fileId = 91;
-                   runCtrl[lastRun].procId = 91;  // Is not set in writeEvt
+                   factPrintf(kError, 502, "procEvt: Could not open new file for run %d (idx=%d, evt=%d, runOpen failed)", irun, idx, ievt);
+                   runCtrl[idx].fileId = 91;
                    continue;
                }
 
-               runCtrl[lastRun].fileId = 0;
-               runCtrl[lastRun].procId = 0;  // Is not set in writeEvt
-
-               factPrintf(kInfo, -1, "procEvt: Opened new file for run %d (evt=%d)", irun, ievt);
-           }
-
-           //-------- also check if run shall be closed (==> skip event, but do not close the file !!! )
-           if (runCtrl[lastRun].procId == 0)
-           {
-               if (runCtrl[lastRun].closeTime < g_actTime ||
-                   runCtrl[lastRun].lastTime < g_actTime - 300 ||
-                   runCtrl[lastRun].maxEvt <= runCtrl[lastRun].procEvt)
-               {
-                   factPrintf(kInfo, 502, "procEvt: Reached end of run condition for run %d", irun);
-                   runFinish1 (runCtrl[lastRun].runId);
-                   runCtrl[lastRun].procId = 1;
-               }
-           }
-
-           // Skip event because of no active run
-           if (runCtrl[lastRun].procId != 0)
-           {
-               evtCtrl[k0].evtStat = 10000; // flag 'to be deleted'
-               continue;
+               runCtrl[idx].fileId = 0;
+
+               factPrintf(kInfo, -1, "procEvt: Opened new file for run %d (idx=%d, evt=%d)", irun, idx, ievt);
            }
 
@@ -1674,18 +1524,13 @@
            }
 
-           const int rc = eventCheck(evtCtrl[k0].runNum, evtCtrl[k0].FADhead,
-                                     evtCtrl[k0].fEvent);
-           //gi.procTot++;
-           numProc++;
-
+           const int rc = eventCheck(evtCtrl[k0].runNum, evtCtrl[k0].FADhead, evtCtrl[k0].fEvent);
            if (rc < 0)
            {
                evtCtrl[k0].evtStat = 10000;        // flag event to be deleted
-               //gi.procErr++;
            }
            else
            {
                evtCtrl[k0].evtStat = 1000;       // flag 'start processing'
-               runCtrl[lastRun].procEvt++;
+               runCtrl[idx].procEvt++;
            }
        }
@@ -1693,16 +1538,11 @@
        if (gj.readStat < -10 && numWait == 0) {  //nothing left to do
            factPrintf(kInfo, -1, "Exit Processing Process ...");
-           gp_runStat = -22;      //==> we should exit
            gj.procStat = -22;     //==> we should exit
            return 0;
        }
 
-       //seems we have nothing to do, so sleep a little
-       if (numProc == 0)
-           usleep(1);
-
-       gp_runStat = gi_runStat;
+       usleep(1);
+
        gj.procStat = gj.readStat;
-
    }
 
@@ -1716,12 +1556,4 @@
    }
 
-   /*
-   for (int k0=evtCtrl_frstPtr; k0!=evtCtrl_lastPtr; k0++, k0 %= MAX_EVT)
-   {
-       if (evtCtrl[k0].evtStat >= 0 && evtCtrl[k0].evtStat < 1000)
-           evtCtrl[k0].evtStat = 9000;    //flag event as 'processed'
-   }*/
-
-   gp_runStat = -99;
    gj.procStat = -99;
 
@@ -1786,10 +1618,4 @@
         ii |= 8; // = 4;
 
-    if (runCtrl[j].procId == 0)
-    {
-        runFinish1(runCtrl[j].runId);
-        runCtrl[j].procId = 92;
-    }
-
     runCtrl[j].closeTime = g_actTime - 1;
 
@@ -1816,23 +1642,9 @@
 /* *** main loop writing event (including opening and closing run-files */
 
-//   cpu_set_t mask;
-//   int cpu = 1;                 //write thread
-
    factPrintf(kInfo, -1, "Starting write-thread");
-
-/* CPU_ZERO initializes all the bits in the mask to zero. */
-//   CPU_ZERO (&mask);
-/* CPU_SET sets only the bit corresponding to cpu. */
-//   CPU_SET (cpu, &mask);
-/* sched_setaffinity returns 0 in success */
-//   if (sched_setaffinity (0, sizeof (mask), &mask) == -1) {
-//      snprintf (str, MXSTR, "W ---> can not create affinity to %d", cpu);
-//   }
-
-   int lastRun = 0;             //usually run from last event still valid
 
    while (g_runStat > -2)
    {
-       int numWrite = 0;
+       //int numWrite = 0;
        int numWait  = 0;
 
@@ -1841,145 +1653,53 @@
        for (int k0=evtCtrl_frstPtr; k0!=evtCtrl_lastPtr; k0++, k0 %= MAX_EVT)
        {
-           if (evtCtrl[k0].evtStat<5000 || evtCtrl[k0].evtStat >= 10000)
+           // This is a threading issue... the evtStat might have been invalid
+           // but the frstPtr is not yet updated
+           if (evtCtrl[k0].evtStat==-1)
+               continue;
+
+           // If we find the first non-written event which is not supposed to
+           // be written, there are only more incomplete events in the queue
+           if (evtCtrl[k0].evtStat<5000)
            {
-               if (/*evtCtrl[k0].evtStat > 0 &&*/ evtCtrl[k0].evtStat < 5000)
-                   numWait++;
-
+               numWait = 1;
+               break;
+           }
+
+           // If the event was written already already, skip it
+           // We could replace that to a moving pointer pointing to the first
+           // non-processed event
+           if (evtCtrl[k0].evtStat!=5000)
+               continue;
+
+           const uint32_t irun = evtCtrl[k0].runNum;
+           const int32_t  ievt = evtCtrl[k0].evNum;
+
+           const int idx = evtCtrl[k0].runCtrl_idx;
+
+           if (runCtrl[idx].runId!=irun)
+           {
+               //factPrintf(kFatal, 901, "writeEvt: runCtrl entry for run %d vanished (evt=%d)", irun, ievt);
+               // FIXME: What is the right action? (Flag event for deletion?)
                continue;
            }
 
-           //we must drain the buffer asap
-           /*
-           if (gi_resetR > 1)
+           // File is open
+           if (runCtrl[idx].fileId==0)
            {
-               evtCtrl[k0].evtStat = 9000;
-               continue;
-           }*/
-
-           const uint32_t irun = evtCtrl[k0].runNum;
-           const int32_t  ievt = evtCtrl[k0].evNum;
-
-           // Find entry in runCtrl which belongs to the event mBuffer[id]
-           // (only check if there is a need to check)
-           if (runCtrl[lastRun].runId != irun)
-           {
-               //check which fileID to use (or open if needed)
-               int j;
-               for (j=0;j<MAX_RUN; j++)
-                   if (runCtrl[j].runId == irun)
-                       break;
-
-               if (j>=MAX_RUN)
-               {
-                   factPrintf(kFatal, 901, "writeEvt: Can not find run %d for event %d in %d", irun, ievt, k0);
-                   // FIXME: What is the right action?
-                   continue;
-               }
-
-               lastRun = j;
-           }
-
-           // File not yet open
-           if (runCtrl[lastRun].fileId < 0)
-           {
-               RUN_HEAD actRun;
-               actRun.Version =  1;
-               actRun.RunType = -1;  //to be adapted
-               actRun.Nroi    = evtCtrl[k0].nRoi;     //runCtrl[lastRun].roi0;
-               actRun.NroiTM  = evtCtrl[k0].nRoiTM;   //runCtrl[lastRun].roi8;
-               actRun.RunTime = evtCtrl[k0].pcTime[0];//runCtrl[lastRun].firstTime;
-               actRun.RunUsec = evtCtrl[k0].pcTime[1];//runCtrl[lastRun].firstUsec;
-               actRun.NBoard  = NBOARDS;
-               actRun.NPix    = NPIX;
-               actRun.NTm     = NTMARK;
-
-               memcpy(actRun.FADhead, evtCtrl[k0].FADhead, NBOARDS * sizeof (PEVNT_HEADER));
-
-               runCtrl[lastRun].fileHd = runOpen (irun, &actRun, sizeof (actRun));
-               if (runCtrl[lastRun].fileHd == NULL)
-               {
-                   factPrintf(kError, 502, "writeEvt: Could not open a file for run %d (runOpen failed)", irun);
-                   runCtrl[lastRun].fileId = 91;
-                   continue;
-               }
-
-               runCtrl[lastRun].fileId = 0;
-               factPrintf(kInfo, -1, "writeEvt: Opened new file for run %d (evt %d)", irun, ievt);
-           }
-
-           /*
-           if (runCtrl[lastRun].fileId > 0)
-           {
-               // There is an event but file is already closed
-               //if (runCtrl[j].fileId < 100)
-               //{
-               //    factPrintf(kWarn, 123, "writeEvt: File for run %d is closed", irun);
-               //    runCtrl[j].fileId += 100;
-               //}
-
-               evtCtrl[k0].evtStat = 9000;
-           }*/
-
-           // File is open
-           if (runCtrl[lastRun].fileId==0)
-           {
-               const int rc = runWrite(runCtrl[lastRun].fileHd, evtCtrl[k0].fEvent,
-                                       0/*sizeof (evtCtrl[k0])*/);
+               const int rc = runWrite(runCtrl[idx].fileHd, evtCtrl[k0].fEvent, 0);
                if (rc >= 0)
                {
                    // Sucessfully wrote event
-                   runCtrl[lastRun].lastTime = g_actTime;
-                   runCtrl[lastRun].actEvt++;
+                   runCtrl[idx].lastTime = g_actTime;
+                   runCtrl[idx].actEvt++;
                }
                else
                    factPrintf(kError, 503, "writeEvt: Writing event for run %d failed (runWrite)", irun);
 
-               checkAndCloseRun(lastRun, irun, rc<0, 1);
+               checkAndCloseRun(idx, irun, rc<0, 1);
            }
 
            evtCtrl[k0].evtStat = 10000;  // event written (or has to be discarded) -> delete
        }
-/*
-       //check if we should close a run (mainly when no event pending)
-       //ETIENNE but first figure out which one is the latest run with a complete event.
-       //i.e. max run Id and lastEvt >= 0
-       //this condition is sufficient because all pending events were written already in the loop just above
-       //actrun
-       uint32_t lastStartedTime = 0;
-       uint32_t runIdFound = 1;
-
-       //If we have an active run, look for its start time
-       if (actrun != 0)
-       {
-           runIdfound = 0;
-           for (int j=0;j<MAX_RUN;j++)
-           {
-               if (runCtrl[j].runId == actrun)
-               {
-                   lastStartedTime = runCtrl[j].lastTime;
-                   runIdFound = 1;
-               }
-           }
-       }
-
-      if (runIdFound == 0)
-      {
-          factPrintf(kInfo, 0, "An Active run (number %u) has been registered, but it could not be found in the runs list", actrun);
-      }
-
-       //Also check if some files will never be opened
-       //EDIT: this is completely useless, because as run Numbers are taken from FADs board,
-       //I will never get run numbers for which no file is to be opened
-       for (int j=0;j<MAX_RUN;j++)
-       {
-           if ((runCtrl[j].fileId < 0) &&
-               (runCtrl[j].lastTime < lastStartedTime) &&
-               (runCtrl[j].runId != 0))
-           {
-               factPrintf(kInfo, 0, "writeEvt: No file will be opened for run %u. Last run: %u (started)", runCtrl[j].runId, actrun);
-               ;//TODO notify that this run will never be opened
-           }
-       }
-       */
 
        // Although the are no pending events, we have to check if a run should be closed (timeout)
@@ -1994,7 +1714,5 @@
        }
 
-      //seems we have nothing to do, so sleep a little
-      if (numWrite == 0)
-          usleep(1);
+       usleep(1);
 
        //nothing left to do
@@ -2002,10 +1720,8 @@
        {
            factPrintf(kInfo, -1, "Finish Write Process ...");
-           gw_runStat = -22;      //==> we should exit
            gj.writStat = -22;     //==> we should exit
            break;
        }
 
-       gw_runStat = gi_runStat;
        gj.writStat = gj.readStat;
    }
@@ -2018,5 +1734,4 @@
    }
 
-   gw_runStat = -99;
    gj.writStat = -99;
 
@@ -2037,5 +1752,4 @@
    struct timespec xwait;
 
-   gi_runStat = gp_runStat = gw_runStat = 0;
    gj.readStat = gj.procStat = gj.writStat = 0;
 
@@ -2047,9 +1761,4 @@
       runCtrl[i].fileId = -2;
    }
-
-//prepare for subProcesses
-   gi_maxSize = g_maxSize;
-   if (gi_maxSize <= 0)
-      gi_maxSize = 1;
 
    gi_maxProc = g_maxProc;
@@ -2260,9 +1969,7 @@
 
    g_maxMem = 1024 * 1024;      //MBytes
-//g_maxMem = g_maxMem * 1024 *10 ; //10GBytes
    g_maxMem = g_maxMem * 200;   //100MBytes
 
    g_maxProc = 20;
-   g_maxSize = 30000;
 
    g_runStat = 40;
Index: /trunk/FACT++/src/FAD.h
===================================================================
--- /trunk/FACT++/src/FAD.h	(revision 15489)
+++ /trunk/FACT++/src/FAD.h	(revision 15490)
@@ -255,4 +255,5 @@
   // ====================================================
 
+
   int32_t  evNum;
   int32_t  fadNum;
@@ -268,5 +269,6 @@
   uint8_t  Errors[4] ;
 
-  uint32_t evtCtrl_idx;
+  //uint32_t evtCtrl_idx;
+  uint32_t runCtrl_idx;
 
   EVENT   *fEvent ;
Index: /trunk/FACT++/src/feedback.cc
===================================================================
--- /trunk/FACT++/src/feedback.cc	(revision 15489)
+++ /trunk/FACT++/src/feedback.cc	(revision 15490)
@@ -37,4 +37,5 @@
         kFeedbackGlobal,
         kCurrents,
+        kCurrentsNew,
     };
 
@@ -94,5 +95,5 @@
     int HandleCameraTemp(const EventImp &evt)
     {
-        if (fControlType!=kTemp && fControlType!=kCurrents)
+        if (fControlType!=kTemp && fControlType!=kCurrents && fControlType!=kCurrentsNew)
             return GetCurrentState();
 
@@ -123,5 +124,242 @@
         fCursorTemp++;
 
-        return HandleCurrentControl();
+        return fControlType==kCurrentsNew ? HandleCurrentControlNew() : HandleCurrentControl();
+    }
+
+    int HandleCurrentControlNew()
+    {
+        if (GetCurrentState()==Feedback::State::kCalibrating && fBiasOffset>fTempOffset-1.2)
+        {
+            fCursorTemp = 0;
+
+            ostringstream msg;
+            msg << " (applied calibration offset " << fBiasOffset << "V exceeds temperature correction " << fTempOffset << "V - 1.2V.";
+            Warn("Trying to calibrate above G-APD breakdown volatge!");
+            Warn(msg);
+            return GetCurrentState();
+        }
+
+        double avg[2] = {   0,   0 };
+        double min[2] = {  90,  90 };
+        double max[2] = { -90, -90 };
+        int    num[2] = {   0,   0 };
+
+        vector<double> med[2];
+        med[0].resize(416);
+        med[1].resize(416);
+
+        const float *Ravg = fCalibration.data()+BIAS::kNumChannels*2; // Measured resistance
+
+        vector<float> vec(2*BIAS::kNumChannels+2);
+
+        vec[BIAS::kNumChannels*2]   = fTempOffset;
+        vec[BIAS::kNumChannels*2+1] = fBiasOffset;
+
+        float *Uoff = vec.data()+BIAS::kNumChannels;
+
+        if (GetCurrentState()==Feedback::State::kCalibrating)
+            for (int i=0; i<BIAS::kNumChannels; i++)
+                Uoff[i] = fBiasOffset;
+        else
+            for (int i=0; i<BIAS::kNumChannels; i++)
+                Uoff[i] = fTempOffset+fBiasOffset;
+
+        if (fControlType==kCurrentsNew)
+        {
+            // Would be a devision by zero. We need informations first.
+            if (fCursorCur==0)
+                return GetCurrentState();
+
+            for (int i=0; i<BIAS::kNumChannels; i++)
+            {
+                const PixelMapEntry &hv = fMap.hv(i);
+                if (!hv)
+                    continue;
+
+                // Nominal breakdown voltage (includes overvoltage already)
+                double Ubd = fVoltGapd[i];
+
+                // Nominal breakdown voltage excluding overvoltage of 1.1V
+                Ubd -= 1.1;
+
+                // Correct breakdown voltage for temperature dependence
+                Ubd += fTempOffset;
+
+                // Number of G-APDs in this patch
+                const int N = hv.group() ? 5 : 4;
+
+                // 100 Ohm measurement resistor for current measurement
+                const double R2 = 100;
+
+                // Serial resistors (one 1kOhm at the output of the bias crate, one 1kOhm in the camera)
+                const double R4 = 2000;
+
+                // Serial resistor of the individual G-APDs
+                double R5 = 3900/N;
+
+                // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor
+                if (i==66)                 // Pixel 830(66)
+                    R5 = 300;              // 2400 = 1/(3/3900 + 1/390)
+                if (i==191 || i==193)      // Pixel 583(191) / Pixel 1401(193)
+                    R5 = 390/1.4;          // 379 = 1/(4/3900 + 1/390)
+
+                // Total resistance of branch with diode
+                const double R3 = R4+R5;
+
+                // Measured calibration resistor
+                const double R1 = Ravg[i] - R2;
+
+                // Voltage output of bias crate
+                const double Uout = fBiasVolt[i];
+
+                // Average current measured for this channel
+                const double Imes = double(fCurrentsAvg[i])/fCursorCur * (5000/4096.); // [uA]
+
+                // Voltage drop at measurement resistor R2 is define
+                // bythe measured current and the resistor
+                const double U2 = R2*Imes;
+
+                // The voltage seen by the calibration resistor R1 is defined by the
+                // bias crate output voltage minus the drop at the measurement resistor R2
+                const double U1 = Uout - U2;
+
+                // The current through the resistor R1 is defined
+                // by the applied voltage and the resistor
+                const double I1 = U1/R1;
+
+                // The current through the diode branch is the measured current
+                // minus the current through the calibration resistor R1
+                const double I3 = Imes - I1;
+
+                // The voltage drop in the diode branch (without the diode) is defined by the
+                // resistor and the current. It is 0 below the breakdown voltage of the G-APD
+                // is reached at the G-APD. This is the case when the output voltage minus
+                // the voltage drop at the calibration resistor reaches the breakdown voltage.
+                const double U3 = Uout-U2<Ubd ? 0 : R3*I3;
+
+                // Voltage drop at measurement resistor R2 and
+                // the total serial resistor R3 in the diode branch
+                const double Udrp = U2 + U3;
+
+                // Voltage finally at each G-APD (bias crate output voltage minus voltage drop)
+                const double Uapd = Uout - Udrp;
+
+                // The over-voltage seen by the G-APD (the voltage above the breakdown voltage) is
+                const double Uov = Uapd<Ubd ? 0 : Uapd - Ubd;
+
+                // The current through one G-APD is the sum divided by the number of G-APDs
+                // (assuming identical serial resistors)
+                double Iapd = I3/N;
+
+                // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor
+                // In this and the previosu case we neglect the resistance of the G-APDs, but we can make an
+                // assumption: The differential resistance depends more on the NSB than on the PDE,
+                // thus it is at least comparable for all G-APDs in the patch. In addition, although the
+                // G-APD with the 390Ohm serial resistor has the wrong voltage applied, this does not
+                // significantly influences the ohmic resistor or the G-APD because the differential
+                // resistor is large enough that the increase of the overvoltage does not dramatically
+                // increase the current flow as compared to the total current flow.
+                if (i==66)
+                    Iapd *= 1.3;
+                if (i==191 || i==193)
+                    Iapd *= 1.4;
+
+                // If the G-APD voltage is above the breakdown voltage we have the current through the
+                // G-APD and the over-voltage applied to the G-APD to calculate its differential resistor.
+                if (Uapd>Ubd)
+                {
+                    // The differential resistance of the G-APD, i.e. the dependence of the
+                    // current above the breakdown voltage, is given by
+                    const double Rapd = Uov/Iapd;
+
+                    // This allows us to estimate the current Iov at the overvoltage we want to apply
+                    const double Iov = (1.1+fBiasOffset)/Rapd;
+
+                    // This gives us an ohmic resistance Rov of the G-APD at the set-point
+                    const double Rest = (Ubd+1.1+fBiasOffset)/Iov;
+
+                    // This lets us estimate the total resistance Rtot of the circuit at the set-point
+                    const double R3b  = R4 + (R5+Rest)/N;
+                    const double Rtot = R2 + 1/(1/R1 + 1/R3b);
+
+                    // From this we can estimate the output voltage we need to get the
+                    // over-voltage at the G-APD as anticipated
+                    const double r    = 1 + R3/R1 - (R2 + R3 + R3*R2/R1)/Rtot;
+                    const double Uset = (Ubd+1.1+fBiasOffset)/r;
+
+                    Uoff[i] = Uset - fVoltGapd[i];
+                }
+
+                 // Calculate statistics only for channels with a valid calibration
+                 if (Uov>0)
+                 {
+                     const int g = hv.group();
+
+                     med[g][num[g]] = Uov;
+                     avg[g] += Uov;
+                     num[g]++;
+
+                     if (Uov<min[g])
+                         min[g] = Uov;
+                     if (Uov>max[g])
+                         max[g] = Uov;
+                 }
+            }
+
+            sort(med[0].begin(), med[0].begin()+num[0]);
+            sort(med[1].begin(), med[1].begin()+num[1]);
+
+            fCurrentsAvg.assign(BIAS::kNumChannels, 0);
+            fCursorCur = 0;
+        }
+
+        fDimDeviation.setQuality(fControlType);
+        fDimDeviation.Update(vec);
+
+        // Warning: Here it is assumed that the ramp up and down is done properly
+        // within the time between two new temperatures and that the calibration
+        // is finished within that time.
+        if (GetCurrentState()!=Feedback::State::kCalibrating ||
+            fDimBias.state()!=BIAS::State::kVoltageOff ||
+            fCursorTemp!=1 || !fOutputEnabled)
+        {
+            if (!fOutputEnabled || fDimBias.state()!=BIAS::State::kVoltageOn)
+                return GetCurrentState();
+
+            // Trigger calibration
+            if (GetCurrentState()==Feedback::State::kCalibrating && fCursorTemp==2)
+            {
+                DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
+                return GetCurrentState();
+            }
+        }
+
+        ostringstream msg;
+        msg << setprecision(4) << "Sending new absolute offset (" << fAppliedOffset << "V+" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0) << "V) to biasctrl.";
+        Info(msg);
+
+        if (fControlType==kCurrents && num[0]>0 && num[1]>0)
+        {
+            msg.str("");
+            msg << "   Avg0=" << setw(7) << avg[0]/num[0]    << "  |  Avg1=" << setw(7) << avg[1]/num[1];
+            Debug(msg);
+
+            msg.str("");
+            msg << "   Med0=" << setw(7) << med[0][num[0]/2] << "  |  Med1=" << setw(7) << med[1][num[1]/2];
+            Debug(msg);
+
+            msg.str("");
+            msg << "   Min0=" << setw(7) << min[0]           << "  |  Min1=" << setw(7) << min[1];
+            Debug(msg);
+
+            msg.str("");
+            msg << "   Max0=" << setw(7) << max[0]           << "  |  Max1=" << setw(7) << max[1];
+            Debug(msg);
+        }
+
+        DimClient::sendCommandNB("BIAS_CONTROL/SET_ALL_CHANNELS_OFFSET",
+                                 vec.data()+BIAS::kNumChannels, BIAS::kNumChannels*sizeof(float));
+
+        return GetCurrentState();
     }
 
@@ -806,5 +1044,5 @@
             HandleCalibration(evt);
 
-        if (fControlType==kFeedbackGlobal || fControlType==kCurrents)
+        if (fControlType==kFeedbackGlobal || fControlType==kCurrents || fControlType==kCurrentsNew)
             AverageCurrents(evt);
 
@@ -953,5 +1191,5 @@
         fOutputEnabled = evt.GetBool();
 
-        if (fControlType==kCurrents)
+        if (fControlType==kCurrents || fControlType==kCurrentsNew)
             if (fCursorTemp>1)
                 fCursorTemp = 1;
@@ -1058,4 +1296,29 @@
         ostringstream out;
         out << "Starting current/temp feedback with an offset of " << fBiasOffset << "V";
+        Message(out);
+
+        return GetCurrentState();
+    }
+
+    int StartNewCurrentCtrl(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt.GetSize(), "StartNewCurrentCtrl", 4))
+            return kSM_FatalError;
+
+        if (fCalibration.size()==0)
+        {
+            Warn("Current control needs a bias crate calibration first... command ignored.");
+            return GetCurrentState();
+        }
+
+        WarnState(true, false);
+
+        fBiasOffset = evt.GetFloat();
+        fTempOffset = -3;
+        ResetData(0);
+        fControlType = kCurrentsNew;
+
+        ostringstream out;
+        out << "Starting new current/temp feedback with an offset of " << fBiasOffset << "V";
         Message(out);
 
@@ -1248,5 +1511,5 @@
                 return fOutputEnabled ? Feedback::State::kTempCtrlRunning : Feedback::State::kTempCtrlIdle;
             }
-            if (fControlType==kCurrents)
+            if (fControlType==kCurrents || fControlType==kCurrentsNew)
             {
                 static Time past;
