Index: /trunk/FACT++/src/biasctrl.cc
===================================================================
--- /trunk/FACT++/src/biasctrl.cc	(revision 11936)
+++ /trunk/FACT++/src/biasctrl.cc	(revision 11937)
@@ -881,5 +881,5 @@
     }
 
-    void PrintLine(int b, int ch)
+    void PrintLineA(int b, int ch)
     {
         Out() << setw(2) << b << "|";
@@ -898,7 +898,7 @@
     }
 
-    void Print()
-    {
-        Out() << dec << setprecision(2) << fixed;
+    void PrintA()
+    {
+        Out() << dec << setprecision(2) << fixed << setfill(' ');
         for (int b=0; b<kNumBoards; b++)
         {
@@ -909,8 +909,74 @@
             }
 
-            PrintLine(b,  0);
-            PrintLine(b,  8);
-            PrintLine(b, 16);
-            PrintLine(b, 24);
+            PrintLineA(b,  0);
+            PrintLineA(b,  8);
+            PrintLineA(b, 16);
+            PrintLineA(b, 24);
+        }
+    }
+
+    void PrintLineV(int b, int ch)
+    {
+        Out() << setw(2) << b << "|";
+
+        for (int c=ch; c<ch+4; c++)
+        {
+            const int id = c+kNumChannelsPerBoard*b;
+            Out() << " ";
+            Out() << setw(5) << fVolt[id]*90/4096. << '/';
+            Out() << setw(5) << fVoltRef[id]*90/4096.;
+        }
+        Out() << endl;
+    }
+
+    void PrintV()
+    {
+        Out() << dec << setprecision(2) << fixed << setfill(' ');
+        for (int b=0; b<kNumBoards; b++)
+        {
+            if (!fPresent[b])
+            {
+                Out() << setw(2) << b << "-" << endl;
+                continue;
+            }
+
+            PrintLineV(b,  0);
+            PrintLineV(b,  4);
+            PrintLineV(b,  8);
+            PrintLineV(b, 12);
+            PrintLineV(b, 16);
+            PrintLineV(b, 20);
+            PrintLineV(b, 24);
+            PrintLineV(b, 28);
+        }
+    }
+
+    void PrintLineGapd(int b, int ch)
+    {
+        Out() << setw(2) << b << "|";
+
+        for (int c=ch; c<ch+8; c++)
+        {
+            const int id = c+kNumChannelsPerBoard*b;
+            Out() << " " << setw(5) << fVoltGapd[id]*90/4096.;
+        }
+        Out() << endl;
+    }
+
+    void PrintGapd()
+    {
+        Out() << dec << setprecision(2) << fixed << setfill(' ');
+        for (int b=0; b<kNumBoards; b++)
+        {
+            if (!fPresent[b])
+            {
+                Out() << setw(2) << b << "-" << endl;
+                continue;
+            }
+
+            PrintLineGapd(b,  0);
+            PrintLineGapd(b,  8);
+            PrintLineGapd(b, 16);
+            PrintLineGapd(b, 24);
         }
     }
@@ -953,4 +1019,6 @@
         kConnected,
         kRamping,
+        kOverCurrent,
+        kAtReference,
         kExpertMode // 'forward' declaration to be used in StateMachineBias
     };
@@ -970,5 +1038,13 @@
             return kRamping;
 
-        return kConnected;
+        for (int ch=0; ch<kNumChannels; ch++)
+            if (fPresent[ch/kNumChannelsPerBoard] && fCurrent[ch]<0)
+                return kOverCurrent;
+
+        for (int ch=0; ch<kNumChannels; ch++)
+            if (fPresent[ch/kNumChannelsPerBoard] && fVolt[ch]!=fVoltRef[ch])
+                return kConnected;
+
+        return kAtReference;
     }
 };
@@ -1231,4 +1307,10 @@
                         "USB connection to bias-power supply established.");
 
+        T::AddStateName(ConnectionBias::kAtReference, "Referenced",
+                        "Internal reference voltage matches last sent voltage.");
+
+        T::AddStateName(ConnectionBias::kOverCurrent, "OverCurrent",
+                        "At least one channel is in over current state.");
+
         T::AddStateName(ConnectionBias::kExpertMode, "ExpertMode",
                         "Special (risky!) mode to directly send command to the bias-power supply.");
@@ -1244,9 +1326,9 @@
 
         // Conenction commands
-        T::AddEvent("DISCONNECT", ConnectionBias::kConnected)
+        T::AddEvent("DISCONNECT", ConnectionBias::kConnected, ConnectionBias::kAtReference)
             (bind(&StateMachineBias::Disconnect, this))
             ("disconnect from ethernet");
 
-        T::AddEvent("RECONNECT", "O", ConnectionBias::kDisconnected, ConnectionBias::kConnected)
+        T::AddEvent("RECONNECT", "O", ConnectionBias::kDisconnected, ConnectionBias::kConnected, ConnectionBias::kAtReference)
             (bind(&StateMachineBias::Reconnect, this, placeholders::_1))
             ("(Re)connect ethernet connection to FTM, a new address can be given"
@@ -1255,9 +1337,9 @@
 
 
-        T::AddEvent("REQUEST_STATUS", ConnectionBias::kConnected, ConnectionBias::kRamping)
+        T::AddEvent("REQUEST_STATUS", ConnectionBias::kConnected, ConnectionBias::kAtReference, ConnectionBias::kOverCurrent)
             (Wrapper(bind(&ConnectionBias::ReadAllChannels, &fBias, false)))
             ("Asynchronously request the status (current) of all channels.");
 
-        T::AddEvent("RESET_OVER_CURRENT_STATUS", ConnectionBias::kConnected)
+        T::AddEvent("RESET_OVER_CURRENT_STATUS", ConnectionBias::kOverCurrent)
             (Wrapper(bind(&ConnectionBias::OverCurrentReset, &fBias)))
             ("NOT YET TESTED");
@@ -1265,25 +1347,25 @@
 
 
-        T::AddEvent("SET_GLOBAL_VOLTAGE", "F:1", ConnectionBias::kConnected, ConnectionBias::kRamping)
+        T::AddEvent("SET_GLOBAL_VOLTAGE", "F:1", ConnectionBias::kConnected, ConnectionBias::kAtReference, ConnectionBias::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.)");
 
-        T::AddEvent("SET_GLOBAL_DAC", "S:1", ConnectionBias::kConnected, ConnectionBias::kRamping)
+        T::AddEvent("SET_GLOBAL_DAC", "S:1", ConnectionBias::kConnected, ConnectionBias::kAtReference, ConnectionBias::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.)");
 
-        T::AddEvent("SET_CHANNEL_VOLTAGE", "S:1;F:1", ConnectionBias::kConnected, ConnectionBias::kRamping)
+        T::AddEvent("SET_CHANNEL_VOLTAGE", "S:1;F:1", ConnectionBias::kConnected, ConnectionBias::kAtReference, ConnectionBias::kOverCurrent)
             (bind(&StateMachineBias::SetChannelVolt, this, placeholders::_1))
             ("Set a single channel a new reference voltage. Starts ramping if necessary.");
 
-        T::AddEvent("SET_CHANNEL_DAC", "S:1;S:1", ConnectionBias::kConnected, ConnectionBias::kRamping)
+        T::AddEvent("SET_CHANNEL_DAC", "S:1;S:1", ConnectionBias::kConnected, ConnectionBias::kAtReference, ConnectionBias::kOverCurrent)
             (bind(&StateMachineBias::SetChannelDac, this, placeholders::_1))
             ("Set a single channel a new DAC reference value. Starts ramping if necessary.");
 
-        T::AddEvent("SET_GAPD_REFERENCE_VOLTAGE", ConnectionBias::kConnected, ConnectionBias::kRamping)
+        T::AddEvent("SET_GAPD_REFERENCE_VOLTAGE", ConnectionBias::kConnected, ConnectionBias::kAtReference, ConnectionBias::kOverCurrent)
             (Wrapper(bind(&ConnectionBias::SetGapdVoltage, &fBias)))
             ("Set all channels to their G-APD reference voltage. Starts ramping if necessary.");
 
-        T::AddEvent("SET_ZERO_VOLTAGE", ConnectionBias::kConnected, ConnectionBias::kRamping)
+        T::AddEvent("SET_ZERO_VOLTAGE", ConnectionBias::kConnected, ConnectionBias::kAtReference, ConnectionBias::kOverCurrent)
             (Wrapper(bind(&ConnectionBias::SetZero, &fBias)))
             ("Set all channels to a zero reference voltage. Starts ramping if necessary.");
@@ -1291,9 +1373,9 @@
 
 
-        T::AddEvent("STOP", ConnectionBias::kConnected, ConnectionBias::kRamping)
+        T::AddEvent("STOP", ConnectionBias::kConnected, ConnectionBias::kRamping, ConnectionBias::kAtReference, ConnectionBias::kOverCurrent)
             (Wrapper(bind(&ConnectionBias::RampStop, &fBias)))
             ("");
 
-        T::AddEvent("START", ConnectionBias::kConnected)
+        T::AddEvent("START", ConnectionBias::kConnected, ConnectionBias::kOverCurrent)
             (Wrapper(bind(&ConnectionBias::RampStart, &fBias)))
             ("");
@@ -1301,6 +1383,12 @@
 
 
-        T::AddEvent("PRINT", ConnectionBias::kConnected, ConnectionBias::kExpertMode, ConnectionBias::kRamping)
-            (Wrapper(bind(&ConnectionBias::Print, &fBias)))
+        T::AddEvent("PRINT_CURRENTS")
+            (Wrapper(bind(&ConnectionBias::PrintA, &fBias)))
+            ("");
+        T::AddEvent("PRINT_VOLTAGES")
+            (Wrapper(bind(&ConnectionBias::PrintV, &fBias)))
+            ("");
+        T::AddEvent("PRINT_GAPD_REFERENCE_VOLTAGES")
+            (Wrapper(bind(&ConnectionBias::PrintGapd, &fBias)))
             ("");
 
@@ -1436,4 +1524,8 @@
         ("ramp-step",     var<uint16_t>(),  "")
         ;
+    // FIXME: Update interval
+    // FIXME: Synchronization interval
+    // FIXME: Make sure ramping / request and commands are not sent at the same time.
+    // FIXME: Add limit of 75V
 
     conf.AddOptions(control);
