Index: /trunk/FACT++/src/biasctrl.cc
===================================================================
--- /trunk/FACT++/src/biasctrl.cc	(revision 17511)
+++ /trunk/FACT++/src/biasctrl.cc	(revision 17512)
@@ -1605,4 +1605,7 @@
 
     bool fExpertMode;
+    bool fEmergencyShutdown;
+
+    Time fSunRise;
 
     // --------------------------------------------------------------------
@@ -1861,13 +1864,56 @@
     }
 
+    int Shutdown()
+    {
+        fBias.RampAllDacs(0);
+        fEmergencyShutdown = true;
+        T::Info("Emergency Sutdown initiated.");
+        return T::GetCurrentState();
+    }
+
+    int Unlock()
+    {
+        fEmergencyShutdown = false;
+        return T::GetCurrentState();
+    }
+
     int Execute()
     {
-        return fExpertMode && fBias.GetStatus()>=State::kConnected ?
-            State::kExpertMode : fBias.GetStatus();
+        const int state = fBias.GetStatus();
+
+        const Time now;
+        if (now>fSunRise)
+        {
+            if (state==State::kRamping       ||
+                state==State::kVoltageOn     ||
+                state==State::kNotReferenced)
+                return Shutdown();
+
+            if (state==State::kLocked)
+            {
+                fSunRise = now.GetNextSunRise(-6);
+
+                ostringstream msg;
+                msg << "Next sun-rise will be at " << fSunRise;
+                T::Info(msg);
+
+                return T::GetCurrentState();
+            }
+        }
+
+        if (T::GetCurrentState()==State::kVoltageOff && T::GetCurrentState()==State::kLocked)
+            return State::kLocked;
+ 
+        if (fExpertMode && state>=State::kLocked)
+            return State::kExpertMode;
+
+        return state;
     }
 
 public:
     StateMachineBias(ostream &out=cout) :
-        StateMachineAsio<T>(out, "BIAS_CONTROL"), fBias(*this, *this), fExpertMode(false)
+        StateMachineAsio<T>(out, "BIAS_CONTROL"), fBias(*this, *this),
+        fExpertMode(false), fEmergencyShutdown(false),
+        fSunRise(Time().GetNextSunRise(-6))
     {
         // State names
@@ -1901,4 +1947,7 @@
         T::AddStateName(State::kRamping, "Ramping",
                         "Voltage ramping in progress.");
+
+        T::AddStateName(State::kLocked, "Locked",
+                        "Locked, no commands accepted except UNLOCK.");
 
         // Verbosity commands
@@ -1939,10 +1988,10 @@
 
 
-        T::AddEvent("SET_CHANNEL_DAC", "S:1;S:1", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::kOverCurrent)
+        T::AddEvent("SET_CHANNEL_DAC", "S:1;S:1")(State::kConnected)(State::kVoltageOff)(State::kVoltageOn)(State::kNotReferenced)(State::kOverCurrent)(State::kRamping)
             (bind(&StateMachineBias::SetChannelDac, this, placeholders::_1))
             ("Set a new target value in DAC counts for a single channel. Starts ramping if necessary."
              "|channel[short]:Channel for which to set the target voltage [0-415]"
              "|voltage[dac]:Target voltage in DAC units for the given channel");
-        T::AddEvent("SET_GLOBAL_DAC", "S:1", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::kOverCurrent)
+        T::AddEvent("SET_GLOBAL_DAC", "S:1")(State::kConnected)(State::kVoltageOff)(State::kVoltageOn)(State::kNotReferenced)(State::kOverCurrent)(State::kRamping)
             (bind(&StateMachineBias::SetGlobalDac, this, placeholders::_1))
             ("Set a new target value for all channels in DAC counts. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)"
@@ -1950,14 +1999,14 @@
 
 
-        T::AddEvent("SET_CHANNEL_VOLTAGE", "S:1;F:1", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::kOverCurrent)
+        T::AddEvent("SET_CHANNEL_VOLTAGE", "S:1;F:1")(State::kConnected)(State::kVoltageOff)(State::kVoltageOn)(State::kNotReferenced)(State::kOverCurrent)(State::kRamping)
             (bind(&StateMachineBias::SetChannelVolt, this, placeholders::_1))
             ("Set a new target voltage for a single channel. Starts ramping if necessary."
              "|channel[short]:Channel for which to set the target voltage [0-415]"
              "|voltage[V]:Target voltage in volts for the given channel (will be converted to DAC units)");
-        T::AddEvent("SET_GLOBAL_VOLTAGE", "F:1", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::kOverCurrent)
+        T::AddEvent("SET_GLOBAL_VOLTAGE", "F:1")(State::kConnected)(State::kVoltageOff)(State::kVoltageOn)(State::kNotReferenced)(State::kOverCurrent)(State::kRamping)
             (bind(&StateMachineBias::SetGlobalVolt, this, placeholders::_1))
             ("Set a new target voltage for all channels. Starts ramping if necessary. (This command is not realized with the GLOBAL SET command.)"
              "|voltage[V]:Global target voltage in volts (will be converted to DAC units)");
-        T::AddEvent("SET_ALL_CHANNELS_VOLTAGE", "F:416", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::kOverCurrent)
+        T::AddEvent("SET_ALL_CHANNELS_VOLTAGE", "F:416")(State::kConnected)(State::kVoltageOff)(State::kVoltageOn)(State::kNotReferenced)(State::kOverCurrent)(State::kRamping)
             (bind(&StateMachineBias::SetAllChannelsVolt, this, placeholders::_1))
             ("Set all channels to the given new reference voltage. Starts ramping if necessary."
@@ -1982,7 +2031,14 @@
 
 
-        T::AddEvent("SET_ZERO_VOLTAGE", State::kConnected, State::kVoltageOff, State::kVoltageOn, State::kNotReferenced, State::kOverCurrent)
+        T::AddEvent("SET_ZERO_VOLTAGE")(State::kConnected)(State::kVoltageOff)(State::kVoltageOn)(State::kNotReferenced)(State::kOverCurrent)(State::kRamping)
             (Wrapper(bind(&ConnectionBias::RampAllDacs, &fBias, 0)))
             ("Set all channels to a zero reference voltage. Starts ramping if necessary.");
+        T::AddEvent("SHUTDOWN")(State::kConnected)(State::kVoltageOff)(State::kVoltageOn)(State::kNotReferenced)(State::kOverCurrent)(State::kRamping)
+            (bind(&StateMachineBias::Shutdown, this))
+            ("Same as SET_ZERO_VOLTAGE; but goes to locked state afterwards.");
+
+        T::AddEvent("UNLOCK", State::kLocked)
+            (bind(&StateMachineBias::Unlock, this))
+            ("Unlock if in locked state.");
 
 
