Index: trunk/MagicSoft/Cosy/devdrv/macs.cc
===================================================================
--- trunk/MagicSoft/Cosy/devdrv/macs.cc	(revision 924)
+++ trunk/MagicSoft/Cosy/devdrv/macs.cc	(revision 925)
@@ -12,8 +12,11 @@
     fPosActive(0), fRpmActive(0)
 {
+    fTimeout = new TTimer(this, 100, kFALSE); // 100ms
 }
 
 Macs::~Macs()
 {
+    fTimerOn = kFALSE;
+    delete fTimeout;
 }
 
@@ -30,4 +33,16 @@
         fVel = val;
         return;
+
+    case 0x4000:
+        switch (subidx)
+        {
+        case 1:
+            cout << "Timeout timer is " << (val?"en":"dis") << "abled." << endl;
+            return;
+        case 2:
+            cout << "Actual timeout time: " << dec << val << "ms" << endl;
+            return;
+        }
+        break;
 
     case 0x6004:
@@ -74,5 +89,5 @@
 
     case 0x6002:
-        lout << "- Velocity resolution #" << (int)GetId() << ": " << dec << val << " ticks/min" << endl;
+        lout << "- Velocity resolution Node#" << (int)GetId() << ": " << dec << val << " ticks/min" << endl;
         fVelRes = val;
         return;
@@ -82,7 +97,45 @@
 }
 
+void Macs::SetTimeoutTime(LWORD_t ms)
+{
+    fTimeoutTime = ms/2;
+
+    SendSDO(0x4000, 2, ms);
+    WaitForSdo(0x4000, 2);
+}
+
+void Macs::ReqTimeoutTime()
+{
+    RequestSDO(0x4000, 2);
+    WaitForSdo(0x4000, 2);
+}
+
+void Macs::EnableTimeout(bool enable, LWORDS_t ms)
+{
+    if (!enable)
+    {
+        SendSDO(0x4000, 1, string('o', 'f', 'f'));
+        WaitForSdo(0x4000, 1);
+
+        cout << "--> Turn Off. " << endl;
+        fTimerOn = kFALSE;
+    }
+    else
+    {
+        if (ms>0)
+            SetTimeoutTime(ms);
+
+        cout << "--> Turn On." << endl;
+        fTimerOn = kTRUE;
+        fTimeout->Start(fTimeoutTime, kTRUE);
+
+        SendSDO(0x4000, 1, string('o', 'n'));
+        WaitForSdo(0x4000, 1);
+    }
+}
+
 void Macs::ReqVelRes()
 {
-    lout << "- Requesting velocity resolution (velres, 0x3007) of " << (int)GetId() << endl;
+    lout << "- Requesting velocity resolution (velres, 0x6002) of " << (int)GetId() << endl;
     RequestSDO(0x6002);
     WaitForSdo(0x6002);
@@ -116,4 +169,5 @@
     WaitForSdo(0x2004);
     */
+    EnableTimeout(kFALSE);
 
     lout << "- Requesting Mac Software Version of " << (int)GetId() << endl;
@@ -126,5 +180,5 @@
 
     lout << "- Motor on of " << (int)GetId() << endl;
-    SendSDO(0x3000, string('O', 'N'));
+    SendSDO(0x3000, string('o', 'n'));
     WaitForSdo(0x3000);
 
@@ -147,5 +201,5 @@
     // Stop the motor and switch off the position control unit
     //
-    SendSDO(0x3000, string('S','T','O','P'));
+    SendSDO(0x3000, string('s','t','o','p'));
     WaitForSdo(0x3000);
 }
@@ -153,4 +207,6 @@
 void Macs::StopDevice()
 {
+    EnableTimeout(kFALSE);
+
     SetNoWait(FALSE);
 
@@ -164,5 +220,5 @@
 
     lout << "- Motor off of " << (int)GetId() << endl;
-    SendSDO(0x3000, string('O', 'F', 'F'));
+    SendSDO(0x3000, string('o', 'f', 'f'));
     WaitForSdo(0x3000);
 
@@ -227,5 +283,5 @@
     // SetRpmMode(FALSE) stop the motor, but lets the position control unit on
     //
-    SendSDO(0x3006, 0, mode ? string('S','T','R','T') : string('S','T','O','P'));
+    SendSDO(0x3006, 0, mode ? string('s','t','r','t') : string('s','t','o','p'));
     WaitForSdo(0x3006, 0);
 }
@@ -250,5 +306,5 @@
 {
     lout << "- Setting NOWAIT " << (flag?"ON":"OFF") << " #" << (int)GetId() << endl;
-    SendSDO(0x3008, flag ? string('O', 'N') : string('O', 'F', 'F'));
+    SendSDO(0x3008, flag ? string('o', 'n') : string('o', 'f', 'f'));
     WaitForSdo(0x3008);
 }
@@ -261,5 +317,5 @@
     //
     lout << "- Setting Vel Sync Mode #" << (int)GetId() << endl;
-    SendSDO(0x3007, 0, string('S', 'Y', 'N', 'C'));
+    SendSDO(0x3007, 0, string('s', 'y', 'n', 'c'));
     WaitForSdo(0x3007, 0);
 }
@@ -272,5 +328,5 @@
     //
     lout << "- Setting Pos Sync Mode #" << (int)GetId() << endl;
-    SendSDO(0x3007, 1, string('S', 'Y', 'N', 'C'));
+    SendSDO(0x3007, 1, string('s', 'y', 'n', 'c'));
     WaitForSdo(0x3007, 1);
 }
@@ -403,8 +459,9 @@
     switch (GetError())
     {
-    case  6: // home
-    case  8: // control dev
-    case  9: // zero idx
-    case 84: // ON TIME
+    case   6: // home
+    case   8: // control dev
+    case   9: // zero idx
+    case  84: // ON TIME
+    case 100: // timeout
         // Stop program?
         return;
@@ -457,2 +514,36 @@
     WaitForSdo(0x2000, 3);
 }
+
+Bool_t Macs::HandleTimer(TTimer *t)
+{
+    /*
+     Fons:
+     -----
+
+     timers never trigger at the same time or when in a TTimer::Notify.
+     Little explanation:
+
+     - there are two types of timers synchronous and a-synchronous.
+     - synchronous timers are only handled via the ROOT eventloop
+       (see TUnixSystem::DispatchOneEvent()). If there are no mouse/keyboard
+       events then the synchronous timer queue is checked. So if the processing
+       of a mouse/keyboard event takes a long time synchronous timers are not
+       called for a while. To prevent this from happening one can call in long
+       procedures gSystem->ProcessEvents(). The system schedules only the
+       next timer in the queue when the current one's Notify() has finished.
+     - a-synchronous timers are triggered via SIGALARM, i.e. the program is
+       interupted and execution jumps to the Notify() function. When the
+       notify is finished the next a-sync timer is scheduled and the system
+       resumes from the place where it was initially interrupted. One of the
+       things to remember when using a-sync timers is don't make any graphics
+       calls in them. X11 is not re-entrant and it might be that the SIGALARM
+       signal interrupted the system while being in X11. A-sync timers are best
+       used to set flags that you can test at a convenient and controlled
+       time.
+       */
+    SendSDO(0x4000);
+    WaitForSdo(0x4000, 0, kDontWait);
+    if (fTimerOn)
+        fTimeout->Start(fTimeoutTime, kTRUE);
+    return kTRUE;
+}
Index: trunk/MagicSoft/Cosy/devdrv/macs.h
===================================================================
--- trunk/MagicSoft/Cosy/devdrv/macs.h	(revision 924)
+++ trunk/MagicSoft/Cosy/devdrv/macs.h	(revision 925)
@@ -1,9 +1,11 @@
 #ifndef MACS_H
 #define MACS_H
+
+#include <TObject.h>
 
 #include "nodedrv.h"
 #include "base/timer.h"
 
-class Macs : public NodeDrv
+class Macs : public NodeDrv, public TObject
 {
 private:
@@ -22,8 +24,14 @@
     BYTE_t   fRpmActive;
 
+    TTimer  *fTimeout;
+    Bool_t   fTimerOn;
+    LWORD_t  fTimeoutTime;
+
     LWORD_t string(BYTE_t b0=0, BYTE_t b1=0, BYTE_t b2=0, BYTE_t b3=0)
     {
         return (LWORD_t)(b0<<24 | b1<<16 | b2<<8 | b3);
     }
+
+    Bool_t HandleTimer(TTimer *t);
 
 public:
@@ -70,4 +78,9 @@
     void StartAbsPos(LWORDS_t pos);
 
+    void SetTimeoutTime(LWORD_t ms);
+    void ReqTimeoutTime();
+
+    void EnableTimeout(bool enable=true, LWORDS_t ms=-1);
+
     void StopMotor();
 
