Index: trunk/MagicSoft/Cosy/Changelog
===================================================================
--- trunk/MagicSoft/Cosy/Changelog	(revision 1726)
+++ trunk/MagicSoft/Cosy/Changelog	(revision 1727)
@@ -1,3 +1,79 @@
                                                                   -*-*- END -*-*-
+
+ 2003/01/23 - Thomas Bretz:
+ 
+   * cosy.cc:
+     - changed baudrate to 125kbps
+   
+   * base/msgqueue.cc:
+     - changed output
+     - ignore pending messages
+   
+   * candrv/canopen.[h,cc]:
+     - added Emergency Message
+     - added EnableNodeguard
+     - added SendNodeguard
+     
+   * candrv/network.[h,cc]:
+     - call handles only if Fnodes[node]!=NULL
+     - added time to HandleSDOOK
+     - changed output
+     - added HandleNodeguard
+     - added HandleEmergency
+
+   * candrv/nodedrv.[h,cc]:
+     - added fTimeout for Nodeguarding
+     - Enable Nodeguard and Emergency messages
+     - added time to HandleSDOOK
+     - added SendNodeguard
+     - added StartGuarding
+     - added StopGuarding
+     - added HandleTimer
+     - added HandleNodeguard
+     - added SetZombie
+
+   * candrv/vmodican.[h,cc]:
+     - fixed a typo
+     - added rtr to SendCanFrame
+   
+   * devdrv/macs.[h,cc]:
+     - removed guarding stuff (moved to nodedrv)
+     - changed 0x4000 handling to 0.63 style
+     - added check for software version
+     - added time to HandleSDOOk
+     - set node to Zombie in case of error
+     - don't do any error handling for the moment
+     - removed ReqTimeoutTime
+     - overload SendNodeguard
+     - removed EnableTimeout
+     - removed HandleTimer
+     - removed ResetTimeout
+     - added Start/StopHostGuarding
+
+   * devdrv/shaftencoder.[h,cc]:
+     - added 0x100c, 0x100d, 0x100e
+     - added Start/StopGuarding to Init
+
+   * gui/MGCosy.cc:
+     - enhanced labels for Offset
+     - changed 'soll' to 'nominal'
+     - changed the demo mode for tests
+   
+   * gui/MGSkyPosition.[h,cc]:
+     - added saturn
+     - changed the colors a bit
+
+
+
+ 2003/01/20 - Thomas Bretz:
+
+   * aposs/Manual.m
+     - added support for the elevation axis brake 
+     - enabled check for operation mode (remote control/pc)      
+     - added 'reset' label                                       
+     - moved syncv/cstart to setting rf                          
+
+
+
  2003/01/14 - Thomas Bretz:
 
Index: trunk/MagicSoft/Cosy/base/msgqueue.cc
===================================================================
--- trunk/MagicSoft/Cosy/base/msgqueue.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/base/msgqueue.cc	(revision 1727)
@@ -77,5 +77,6 @@
     while(1)
     {
-        while (!fStart) usleep(1);
+        while (!fStart)
+            usleep(1);
         fStart = 0;
 
@@ -88,8 +89,8 @@
         pthread_mutex_unlock(&fMuxMsg);
 
-        cout << "Processing Msg 0x" << hex << fMsg << endl;
+        cout << "MsgQueue::Thread: Processing Msg 0x" << hex << fMsg << endl;
         // --- bool quit = fMsg==WM_QUIT;
         fRc=Proc(fMsg, fMp);
-        cout << "Msg 0x" << hex << fMsg << " processed." << endl;
+        cout << "MsgQueue::PostMsg: Msg 0x" << hex << fMsg << " processed (rc=" << fRc << ")" << endl;
 
         // --- if (quit)
@@ -118,5 +119,5 @@
     // stopped and the messages are processed serialized
     //
-    cout << "Locking MsgQueue mutex..." << flush;
+    cout << "MsgQueue::PostMsg: Locking MsgQueue mutex..." << flush;
     pthread_mutex_lock(&fMuxMsg);
     cout << "done." << endl;
@@ -129,4 +130,13 @@
     // This is some kind of controlled user break without using signals
     //
+    /**** NEW 20/01/2003 ****/
+    if (fBreak)
+    {
+        pthread_mutex_unlock(&fMuxMsg);
+        cout << "------------> MsgQueue::PostMsg: Proc still pending... Message IGNORED." << endl;
+        return NULL;
+    }
+    /**** NEW 20/01/2003 ****/
+    cout << "MsgQueue::PostMsg: ---> Break <---" << endl;
     fBreak = 1;
 
@@ -146,13 +156,55 @@
     // Start Proc()
     //
+    cout << "MsgQueue::PostMsg: Releasing MsgQueue mutex..." << flush;
     fStart = 1;
-    cout << "Releasing MsgQueue mutex..." << flush;
     pthread_mutex_unlock(&fMuxMsg);
     cout << "done." << endl;
-    while (fStart)
-        usleep(1);
-
-    cout << "Returning rc = 0x" << hex << rc << endl;
+
+    /*
+     * **** NEW 20/01/2003 ***
+     *
+     * This can halt the main thread, because it is waiting until
+     * Proc has finished its execution which can take a while
+     *
+     * A side effect is, because you don't wait for the end of
+     * the execution of Proc, if a new message is posted fBreak
+     * and fStart is set again, new values are copied to fMsg and
+     * fMp (FIXME? Harmefull?) and the message is not processed at all.
+     */
+    //while (fStart)
+    //    usleep(1);
+ 
+    cout << "MsgQueue::PostMsg: Returning rc = " << hex << rc << endl;
     return rc;
 }
-
+/*
+Start positioning.
+MsgQueue::PostMsg: Locking MsgQueue mutex...done.
+MsgQueue::PostMsg: ---> Break <---
++++++ MsgQueue::PostMsg: Releasing MsgQueue mutex...done.
+
+===== MsgQueue::PostMsg: Returning rc = (nil)
+PostMsg (WM_Position) returned.
+done.
+Stopping movement...Movement stopped.
+WM_Position: done. (return 0x7777)
+MsgQueue::PostMsg: Msg 0x1001 processed (rc=0x7777)
+MsgQueue::Thread: Processing Msg 0x1001
+WM_Position: start.
+Positioning to Target...
+ */
+/*
+Start positioning.
+MsgQueue::PostMsg: Locking MsgQueue mutex...done.
+MsgQueue::PostMsg: ---> Break <---
++++++ MsgQueue::PostMsg: Releasing MsgQueue mutex...done.
+
+done.
+Stopping movement...Movement stopped.
+WM_Position: done. (return 0x7777)
+MsgQueue::PostMsg: Msg 0x1001 processed (rc=0x7777)
+MsgQueue::Thread: Processing Msg 0x1001
+WM_Position: start.
+Positioning to Target...
+===== MsgQueue::PostMsg: Returning rc = (nil)
+*/
Index: trunk/MagicSoft/Cosy/candrv/canopen.cc
===================================================================
--- trunk/MagicSoft/Cosy/candrv/canopen.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/candrv/canopen.cc	(revision 1727)
@@ -16,7 +16,7 @@
 !
 !
-!   Author(s): Thomas Bretz <mailto:tbretz@uni-sw.gwdg.de>, 2001
-!
-!   Copyright: MAGIC Software Development, 2000-2001
+!   Author(s): Thomas Bretz <mailto:tbretz@astro.uni-wuerzburg.de>, 2003
+!
+!   Copyright: MAGIC Software Development, 2000-2003
 !
 !
@@ -84,4 +84,5 @@
 {
     const WORD_t fcode = cobid >> 7;
+    const BYTE_t  node = cobid & 0x1f;
 
     switch (fcode)
@@ -94,11 +95,21 @@
         return;
 
-    case kSYNC:
-        cout << "Sync" << endl;
+    case kEMERGENCY: // also case kSYNC:
+        if (cobid==0)
+            cout << "Sync" << endl;
+        else
+        {
+            cout << "EMERGENCY Node #" << dec << (int)data[1] << endl;
+            HandleEmergency(node, tv);
+        }
+        return;
+
+    case kNodeguard:
+        //cout << "Nodeguard Node #" << dec << (int)node << endl;
+        HandleNodeguard(node, tv);
         return;
 
     case kSDO_RX:
         {
-            const BYTE_t  node   = cobid & 0x1f;
             const BYTE_t  cmd    = data[0];
             const LWORD_t dat    = data[4] | (data[5]<<8) | (data[6]<<16) | (data[7]<<24);
@@ -114,5 +125,4 @@
     case kPDO1_TX:
         {
-            const BYTE_t node = cobid & 0x1f;
             HandlePDO1(node, data, tv);
             pthread_cond_broadcast(&fPdoCond[node-1][0]);
@@ -122,5 +132,4 @@
     case kPDO2_TX:
         {
-            const BYTE_t node = cobid & 0x1f;
             HandlePDO2(node, data, tv);
             pthread_cond_broadcast(&fPdoCond[node-1][1]);
@@ -130,5 +139,4 @@
     case kPDO3_TX:
         {
-            const BYTE_t node = cobid & 0x1f;
             HandlePDO3(node, data, tv);
             pthread_cond_broadcast(&fPdoCond[node-1][2]);
@@ -138,5 +146,4 @@
     case kPDO4_TX:
         {
-            const BYTE_t node = cobid & 0x1f;
             HandlePDO4(node, data, tv);
             pthread_cond_broadcast(&fPdoCond[node-1][3]);
@@ -145,6 +152,5 @@
     }
 
-    const BYTE_t node = cobid & 0x1f;
-    cout << "Function Code: 0x" << hex << fcode << "  Node: " << dec << (int)node << endl;
+    cout << "CanOpen::HandleCanMessage - Unhandled Message: Function Code=0x" << hex << fcode << "  Node #" << dec << (int)node << endl;
 }
 
@@ -168,4 +174,13 @@
 {
     EnableCanMsg(node, kEMERGENCY);
+}
+
+// --------------------------------------------------------------------------
+//
+// Enables Nodeguard messages for a given node
+//
+void CanOpen::EnableNodeguard(BYTE_t node)
+{
+    EnableCanMsg(node, kNodeguard);
 }
 
@@ -372,5 +387,5 @@
 // --------------------------------------------------------------------------
 //
-// Send an NMT Message to the given node with command cmd
+// Send a NMT Message to the given node with command cmd
 //
 void CanOpen::SendNMT(BYTE_t node, BYTE_t cmd)
@@ -381,4 +396,14 @@
 // --------------------------------------------------------------------------
 //
+// Send a Nodeguard Message to the given node with command cmd
+//
+void CanOpen::SendNodeguard(BYTE_t node)
+{
+    BYTE_t msg[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+    SendCanFrame(CobId(node, kNodeguard), msg, 1);
+}
+
+// --------------------------------------------------------------------------
+//
 // Decodes node and function code into a CobId
 //
Index: trunk/MagicSoft/Cosy/candrv/network.cc
===================================================================
--- trunk/MagicSoft/Cosy/candrv/network.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/candrv/network.cc	(revision 1727)
@@ -89,48 +89,30 @@
 void Network::HandleSDO(BYTE_t node, BYTE_t cmd, WORD_t idx, BYTE_t subidx, LWORD_t data, timeval_t *tv)
 {
-    switch (cmd)
-    {
-    case kSDO_TX4:       // answer to 0x40 with 4 bytes of data
-        if (fNodes[node])
+    if (fNodes[node])
+        switch (cmd)
         {
+        case kSDO_TX4:       // answer to 0x40 with 4 bytes of data
             fNodes[node]->HandleSDO(idx, subidx, data, tv);
             return;
+
+        case kSDO_TX3:       // answer to 0x40 with 2 bytes of data
+            fNodes[node]->HandleSDO(idx, subidx, data>>16, tv);
+            return;
+
+        case kSDO_TX1:       // answer to 0x40 with 1 byte  of data
+            fNodes[node]->HandleSDO(idx, subidx, data>>24, tv);
+            return;
+
+        case kSDO_TX_OK:     // answer to a SDO_TX message
+            fNodes[node]->HandleSDOOK(idx, subidx, tv);
+            return;
+
+        case kSDO_TX_ERROR:  // error message (instead of 0x60)
+            fNodes[node]->HandleSDOError(data);
+            return;
         }
-        break;
-
-    case kSDO_TX3:       // answer to 0x40 with 2 bytes of data
-        if (fNodes[node])
-        {
-            fNodes[node]->HandleSDO(idx, subidx, data>>16, tv);
-            return;
-        }
-        break;
-
-    case kSDO_TX1:       // answer to 0x40 with 1 byte  of data
-        if (fNodes[node])
-        {
-            fNodes[node]->HandleSDO(idx, subidx, data>>24, tv);
-            return;
-        }
-        break;
-
-    case kSDO_TX_OK:     // answer to a SDO_TX message
-        if (fNodes[node])
-        {
-            fNodes[node]->HandleSDOOK(idx, subidx);
-            return;
-        }
-        break;
-
-    case kSDO_TX_ERROR:  // error message (instead of 0x60)
-        if (fNodes[node])
-        {
-            fNodes[node]->HandleSDOError(data);
-            return;
-        }
-        break;
-    }
+
     cout << dec << setfill('0');
-    cout << "Node=" << (int)node  << " Cmd=0x" << hex << (int)cmd << ": ";
+    cout << "Network::HandleSDO: Node=" << (int)node  << " Cmd=0x" << hex << (int)cmd << ": ";
     cout << "Sdo=" << idx  << "/" << (int)subidx << ": 0x" << setw(8) << data;
     cout << endl;
@@ -145,5 +127,5 @@
     if (!fNodes[node])
     {
-        cout << "Node " << dec << (int)node << ", PDO1: " << hex;
+        cout << "Network::HandlePDO1: Node #" << dec << (int)node << " not found - PDO1: " << hex;
         for (int i=0; i<8; i++)
             cout << " 0x" << (int)data[i];
@@ -163,5 +145,5 @@
     if (!fNodes[node])
     {
-        cout << "Node " << dec << (int)node << ", PDO2: " << hex;
+        cout << "Network::HandlePDO2: Node #" << dec << (int)node << " not found - PDO2: " << hex;
         for (int i=0; i<8; i++)
             cout << " 0x" << (int)data[i];
@@ -181,5 +163,5 @@
     if (!fNodes[node])
     {
-        cout << "Node " << dec << (int)node << ", PDO3: " << hex;
+        cout << "Network::HandlePDO3: Node #" << dec << (int)node << " not found - PDO3: " << hex;
         for (int i=0; i<8; i++)
             cout << " 0x" << (int)data[i];
@@ -199,5 +181,5 @@
     if (!fNodes[node])
     {
-        cout << "Node " << dec << (int)node << ", PDO4: " << hex;
+        cout << "Network::HandlePDO4: Node #" << dec << (int)node << " not found - PDO4: " << hex;
         for (int i=0; i<8; i++)
             cout << " 0x" << (int)data[i];
@@ -208,4 +190,37 @@
     fNodes[node]->HandlePDO4(data, tv);
 }
+
+// --------------------------------------------------------------------------
+//
+// Distributes Nodeguard messages to the correspoding node calling
+// HandleNodeguard
+//
+void Network::HandleNodeguard(BYTE_t node, timeval_t *tv)
+{
+    if (!fNodes[node])
+    {
+        cout << "Network::HandleNodeguard: Node #" << dec << (int)node << " not found: Nodeguard." << endl;
+        return;
+    }
+
+    fNodes[node]->HandleNodeguard(tv);
+}
+
+// --------------------------------------------------------------------------
+//
+// Distributes Emergency messages to the correspoding node calling
+// HandleEmergency
+//
+void Network::HandleEmergency(BYTE_t node, timeval_t *tv)
+{
+    if (!fNodes[node])
+    {
+        cout << "Network::HandleEmergency: Node #" << dec << (int)node << " not found: Emergency." << endl;
+        return;
+    }
+
+    fNodes[node]->HandleEmergency(tv);
+}
+
 
 // --------------------------------------------------------------------------
@@ -281,6 +296,6 @@
             continue;
 
-        lout << "- Node #" << dec << i << " '" << fNodes[i]->GetNodeName();
-        lout << "' has error #" << fNodes[i]->GetError() << endl;
+        //lout << "- Node #" << dec << i << " '" << fNodes[i]->GetNodeName();
+        //lout << "' has error #" << fNodes[i]->GetError() << endl;
     }
 
Index: trunk/MagicSoft/Cosy/candrv/network.h
===================================================================
--- trunk/MagicSoft/Cosy/candrv/network.h	(revision 1726)
+++ trunk/MagicSoft/Cosy/candrv/network.h	(revision 1727)
@@ -16,4 +16,6 @@
     void HandlePDO3(BYTE_t node, BYTE_t *data, timeval_t *tv);
     void HandlePDO4(BYTE_t node, BYTE_t *data, timeval_t *tv);
+    void HandleNodeguard(BYTE_t node, timeval_t *tv);
+    void HandleEmergency(BYTE_t node, timeval_t *tv);
 
     void InitNodes();
Index: trunk/MagicSoft/Cosy/candrv/nodedrv.cc
===================================================================
--- trunk/MagicSoft/Cosy/candrv/nodedrv.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/candrv/nodedrv.cc	(revision 1727)
@@ -33,5 +33,5 @@
 //  virtual void StopDevice()
 //  virtual void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, timeval_t *tv)
-//  virtual void HandleSDOOK(WORD_t idx, BYTE_t subidx)
+//  virtual void HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv)
 //  virtual void HandleSDOError(LWORD_t data)
 //  virtual void HandlePDO1(BYTE_t *data, timeval_t *tv)
@@ -48,4 +48,7 @@
 #include <iostream.h>
 
+#include <TTimer.h>
+
+#include "base/timer.h"
 #include "network.h"
 #include "MLogManip.h"
@@ -76,13 +79,19 @@
     }
 
+    fTimerOn = kFALSE;
+    fTimeout = new TTimer(this, 100, kFALSE); // 100ms, asynchronous
+
     lout << "- Node #" << (int)nodeid << " (" << name << ") initialized." << endl;
-}
-
-// --------------------------------------------------------------------------
-//
-// Empty destructor
+
+}
+
+// --------------------------------------------------------------------------
+//
+// destructor
 //
 NodeDrv::~NodeDrv()
 {
+    fTimerOn = kFALSE;
+    delete fTimeout;
 }
 
@@ -122,4 +131,6 @@
     EnableCanMsg(kSDO_RX);
     EnableCanMsg(kSDO_TX);
+    EnableCanMsg(kNodeguard);
+    EnableCanMsg(kEMERGENCY);
 
     fIsZombie = kFALSE;
@@ -135,5 +146,5 @@
 // This output is never redirected to the GUI
 //
-void NodeDrv::HandleSDOOK(WORD_t idx, BYTE_t subidx)
+void NodeDrv::HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv)
 {
     const Bool_t gui = lout.IsOutputDeviceEnabled(MLog::eGui);
@@ -367,5 +378,5 @@
 // --------------------------------------------------------------------------
 //
-// Send an NMT message (command) to this device
+// Send a NMT message (command) to this device
 //
 // The message is not send if the node has the status Zombie.
@@ -377,4 +388,13 @@
         fNetwork->SendNMT(fId, cmd);
     return !fIsZombie;
+}
+
+// --------------------------------------------------------------------------
+//
+// Send a Nodeguard message (command) to this device
+//
+void NodeDrv::SendNodeguard()
+{
+    fNetwork->SendNodeguard(fId);
 }
 
@@ -404,6 +424,15 @@
 
     if (!rc)
+    {
+        lout << "NodeDrv::WaitForSdo: 0x" << hex << idx << "/" << dec << (int)subidx << " " << GetNodeName() << " --> ZOMBIE!" << endl;
+        SetZombie();
+    }
+/*
+    if (HasError())
+    {
+        lout << "NodeDrv::WaitForSdo: HasError 0x" << hex << idx << "/" << dec << (int)subidx << " " << GetNodeName() << " --> ZOMBIE!" << endl;
         fIsZombie = kTRUE;
-
+    }
+*/
     return fIsZombie ? false : rc;
 }
@@ -453,2 +482,128 @@
 }
 
+// --------------------------------------------------------------------------
+//
+// Start the standard CANopen guarding of the device.
+// While ms is the guard time in millisec. This is the time between
+// two requests for a Nodeguard message.
+// ltf is the LifeTimeFactor. This means how often it is checked, that at
+// least one Nodeguard message was answered.
+//
+void NodeDrv::StartGuarding()
+{
+    if (fTimerOn)
+        return;
+
+    SendNodeguard();
+
+    fTimerOn = kTRUE;
+    fTimeout->SetTime(fGuardTime);
+    fTimeout->Reset();
+    fTimeout->TurnOn();
+    //fTimeout->Start(fGuardTime, kTRUE);
+
+    lout << "- " << GetNodeName() << ": Guarding (" << dec;
+    lout << fLifeTimeFactor << "*" << fGuardTime << "ms) started." << endl;
+}
+
+void NodeDrv::StartGuarding(Int_t ms, Int_t ltf)
+{
+    if (fTimerOn)
+    {
+        lout << "- " << GetNodeName() << ": ERROR - Guarding already started." << endl;
+        return;
+    }
+    fGuardTime      = ms;
+    fLifeTimeFactor = ltf;
+
+    StartGuarding();
+}
+
+void NodeDrv::StopGuarding()
+{
+    fTimeout->TurnOff();
+    fTimerOn = kFALSE;
+
+    lout << "- " << GetNodeName() << ": Guarding stopped." << endl;
+}
+
+// --------------------------------------------------------------------------
+//
+// Handle the Nodeguard-Timer Event.
+// It checks whether the node timed out. If it timed out it is set to
+// the Zombie state.
+// A new Nodeguard request is send and a new timer event is triggered.
+//
+Bool_t NodeDrv::HandleTimer(TTimer *t)
+{
+    //
+    // WARNING:
+    //           It seems, that you should never access ANY output from
+    //           here. Neither the GUI, nor COUT. This can result in
+    //           'unexpected async reply'
+    //
+
+   /*
+     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.
+       */
+    if (fIsZombie)
+        return kTRUE;
+
+    Timer time;
+    Double_t now = time.Now();
+    if (now > fTimeoutTime)
+    {
+        //cout << "ERROR - " << GetNodeName() << " didn't respond in timeout window." << endl;
+        //lout << "ERROR - " << GetNodeName() << " didn't respond in timeout window." << endl;
+        //cout << dec << "+" << (int)GetId() << ": Handle: " << fmod(now, 500) << endl;
+        //cout << dec << "+" << (int)GetId() << ": Handle: " << fmod(fTimeoutTime, 500) << endl;
+        //cout << fGuardTime << endl;
+        fIsZombie = true;
+        //SetZombie();
+
+        return kTRUE;
+    }
+
+    SendNodeguard();
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// Set the timeout timer to the time the event was received plus the
+// guard time times lifetimefactor.
+//
+void NodeDrv::HandleNodeguard(timeval_t *tv)
+{
+    Timer t(tv);
+    fTimeoutTime = t + (fGuardTime*fLifeTimeFactor/1000.);
+}
+
+void NodeDrv::SetZombie()
+{
+    fIsZombie = true;
+    StopGuarding();
+}
Index: trunk/MagicSoft/Cosy/candrv/nodedrv.h
===================================================================
--- trunk/MagicSoft/Cosy/candrv/nodedrv.h	(revision 1726)
+++ trunk/MagicSoft/Cosy/candrv/nodedrv.h	(revision 1727)
@@ -20,5 +20,5 @@
 class Network;
 
-class NodeDrv : public Log
+class NodeDrv : public Log, public TObject
 {
 private:
@@ -30,9 +30,22 @@
     int fError;
 
+    Bool_t fIsZombie; // A Zombie node is a node which doesn't answer...
+
+    TTimer  *fTimeout;
+    Int_t    fGuardTime;      // Guardtime [ms]
+    Int_t    fLifeTimeFactor;
+    Double_t fTimeoutTime;
+    Bool_t   fTimerOn;
+
+    Bool_t HandleTimer(TTimer *t);
+
 protected:
     void SetError(int err) { fError = err; }
     void DelError()        { fError = 0; }
 
-    Bool_t fIsZombie; // A Zombie node is a node which doesn't answer...
+    Int_t GetLifeTimeFactor() const { return fLifeTimeFactor; }
+    Int_t GetGuardTime() const      { return fGuardTime; }
+
+    virtual void SetZombie();
 
 public:
@@ -56,11 +69,13 @@
 
     virtual void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, timeval_t *tv);
-    virtual void HandleSDOOK(WORD_t idx, BYTE_t subidx);
+    virtual void HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv);
     virtual void HandleSDOError(LWORD_t data);
 
-    virtual void HandlePDO1(BYTE_t *data, timeval_t *tv) {};
-    virtual void HandlePDO2(BYTE_t *data, timeval_t *tv) {};
-    virtual void HandlePDO3(BYTE_t *data, timeval_t *tv) {};
-    virtual void HandlePDO4(BYTE_t *data, timeval_t *tv) {};
+    virtual void HandlePDO1(BYTE_t *data, timeval_t *tv) {}
+    virtual void HandlePDO2(BYTE_t *data, timeval_t *tv) {}
+    virtual void HandlePDO3(BYTE_t *data, timeval_t *tv) {}
+    virtual void HandlePDO4(BYTE_t *data, timeval_t *tv) {}
+    virtual void HandleNodeguard(timeval_t *tv);
+    virtual void HandleEmergency(timeval_t *tv) {}
 
     bool SendPDO1(BYTE_t data[8]);
@@ -80,4 +95,5 @@
 
     bool SendNMT(BYTE_t cmd);
+    virtual void SendNodeguard();
 
     bool RequestSDO(WORD_t idx, BYTE_t subidx=0);
@@ -93,4 +109,8 @@
     void EnableCanMsg(BYTE_t fcode);
 
+    void StartGuarding();
+    void StartGuarding(Int_t ms, Int_t ltf);
+    void StopGuarding();
+
     ClassDef(NodeDrv, 0) // base class for an object describing hardware
 };
Index: trunk/MagicSoft/Cosy/candrv/vmodican.cc
===================================================================
--- trunk/MagicSoft/Cosy/candrv/vmodican.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/candrv/vmodican.cc	(revision 1727)
@@ -409,5 +409,5 @@
     while (!Send(&msg));      /* transmitt to module */
 
-    lout << "- Baudrate set to " << rate << "bps" << endl;
+    lout << "- Baudrate set to " << rate << "kbps" << endl;
 }
 
@@ -904,7 +904,7 @@
 //   */
 //
-void VmodIcan::SendCanFrame(WORD_t cobid, BYTE_t m[8])
-{
-    const WORD_t desc = MsgDescr(cobid, 8);
+void VmodIcan::SendCanFrame(WORD_t cobid, BYTE_t m[8], BYTE_t rtr)
+{
+    const WORD_t desc = MsgDescr(cobid, 8, rtr);
 
     Message msg;
Index: trunk/MagicSoft/Cosy/candrv/vmodican.h
===================================================================
--- trunk/MagicSoft/Cosy/candrv/vmodican.h	(revision 1726)
+++ trunk/MagicSoft/Cosy/candrv/vmodican.h	(revision 1727)
@@ -73,5 +73,5 @@
     void EnableCobId(WORD_t cobid, int flag=TRUE);
 
-    void SendCanFrame(WORD_t cobid, BYTE_t m[8]);
+    void SendCanFrame(WORD_t cobid, BYTE_t m[8], BYTE_t rtr=0);
     void SendCanFrame(WORD_t cobid,
                       BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0,
Index: trunk/MagicSoft/Cosy/cosy.cc
===================================================================
--- trunk/MagicSoft/Cosy/cosy.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/cosy.cc	(revision 1727)
@@ -73,5 +73,5 @@
         }
 
-    MCosy *cosy = new MCosy(mode, "/dev/dpm_00", 500, lout);
+    MCosy *cosy = new MCosy(mode, "/dev/dpm_00", 125, lout);
 
     clog("- Starting MCosy.");
Index: trunk/MagicSoft/Cosy/devdrv/macs.cc
===================================================================
--- trunk/MagicSoft/Cosy/devdrv/macs.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/devdrv/macs.cc	(revision 1727)
@@ -33,11 +33,11 @@
     fPosActive(0), fRpmActive(0)
 {
-    fTimeout = new TTimer(this, 100, kFALSE); // 100ms, asynchronous
+//    fTimeout = new TTimer(this, 100); //, kFALSE); // 100ms, asynchronous
 }
 
 Macs::~Macs()
 {
-    fTimerOn = kFALSE;
-    delete fTimeout;
+    //fTimerOn = kFALSE;
+  //  delete fTimeout;
 }
 
@@ -60,16 +60,4 @@
         fVel = val;
         return;
-
-    case 0x4000:
-        switch (subidx)
-        {
-        case 1:
-            cout << GetNodeName() << ": Timeout timer is " << (val?"en":"dis") << "abled." << endl;
-            return;
-        case 2:
-            cout << GetNodeName() << ": Actual timeout time: " << dec << val << "ms" << endl;
-            return;
-        }
-        break;
 
     case 0x6004:
@@ -129,5 +117,5 @@
 }
 
-void Macs::HandleSDOOK(WORD_t idx, BYTE_t subidx)
+void Macs::HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv)
 {
     switch (idx)
@@ -137,32 +125,34 @@
         {
         case 0:
-            lout << ddev(MLog::eGui);
+            //lout << ddev(MLog::eGui);
             lout << "- " << GetNodeName() << ": Velocity set." << endl;
-            lout << edev(MLog::eGui);
+            //lout << edev(MLog::eGui);
             return;
         }
         break;
+
     case 0x2003:
         switch (subidx)
         {
         case 0:
-            lout << ddev(MLog::eGui);
+            //lout << ddev(MLog::eGui);
             lout << "- " << GetNodeName() << ": Acceleration set." << endl;
-            lout << edev(MLog::eGui);
+            //lout << edev(MLog::eGui);
             return;
         case 1:
-            lout << ddev(MLog::eGui);
+            //lout << ddev(MLog::eGui);
             lout << "- " << GetNodeName() << ": Decceleration set." << endl;
-            lout << edev(MLog::eGui);
+            //lout << edev(MLog::eGui);
             return;
         }
         break;
+
     case 0x3006:
         switch (subidx)
         {
         case 0:
-            lout << ddev(MLog::eGui);
+            //lout << ddev(MLog::eGui);
             lout << "- " << GetNodeName() << ": RPM mode switched." << endl;
-            lout << edev(MLog::eGui);
+            //lout << edev(MLog::eGui);
             return;
 
@@ -176,24 +166,22 @@
         }
         break;
+
     case 0x4000:
-        if (subidx==0 && fTimerOn)
-        {
-            ResetTimeout();
-            return;
-        }
-        break;
+        HandleNodeguard(tv);
+        return;
+
     case 0x6004:
         switch (subidx)
         {
         case 0:
-            lout << ddev(MLog::eGui);
+            //lout << ddev(MLog::eGui);
             lout << "- " << GetNodeName() << ": Absolute positioning started." << endl;
-            lout << edev(MLog::eGui);
+            //lout << edev(MLog::eGui);
             return;
 
         case 1:
-            lout << ddev(MLog::eGui);
+            //lout << ddev(MLog::eGui);
             lout << "- " << GetNodeName() << ": Relative positioning started." << endl;
-            lout << edev(MLog::eGui);
+            //lout << edev(MLog::eGui);
             return;
         }
@@ -202,5 +190,5 @@
 
     }
-    NodeDrv::HandleSDOOK(idx, subidx);
+    NodeDrv::HandleSDOOK(idx, subidx, tv);
 }
 
@@ -231,8 +219,4 @@
     RequestSDO(0x100b);
     WaitForSdo(0x100b);
-
-    // FIXME! Not statically linked!
-    //    if (fSoftVersion<0x00000035)
-    //        fIsZombie = true;
 }
 
@@ -240,9 +224,20 @@
 void Macs::Init()
 {
+    if (HasError())
+    {
+        lout << "Macs::Init: " << GetNodeName() << " has error --> ZOMBIE!" << endl;
+        SetZombie();
+    }
+
+    StopHostGuarding();
+    StopGuarding();
+
+    usleep(2000.*GetGuardTime());
+
     lout << "- " << GetNodeName() << ": Requesting Mac Software Version." << endl;
     RequestSDO(0x100a);
     WaitForSdo(0x100a);
 
-    if (fIsZombie)
+    if (IsZombieNode())
     {
         lout << GetNodeName() << " - InitDevice failed!" << endl;
@@ -250,5 +245,12 @@
     }
 
-    EnableTimeout(kFALSE);
+    // FIXME! Not statically linked!
+    if (fSoftVersion<0x00000042) // 00.66
+    {
+        lout << GetNodeName() << " - Software Version too old!" << endl;
+        SetZombie();
+        return;
+    }
+
     SetRpmMode(FALSE);
 
@@ -270,4 +272,7 @@
 
     SetNoWait(TRUE);
+
+    StartGuarding(100, 2);
+    StartHostGuarding();
 }
 
@@ -283,5 +288,5 @@
 void Macs::StopDevice()
 {
-    EnableTimeout(kFALSE);
+    //EnableTimeout(kFALSE);
 
     SetNoWait(FALSE);
@@ -348,5 +353,5 @@
 {
     SendSDO(0x2002, vel);     // velocity
-    WaitForSdo(0x2002);
+    WaitForSdo(0x2002, 0);
 }
 
@@ -466,4 +471,6 @@
     {
         lout << "- " << GetNodeName() << ": reports Error occursion." << endl;
+        lout << "Macs::HandlePDO2: " << GetNodeName() << " --> ZOMBIE!" << endl;
+        SetZombie();
         SetError(-1);
         return;
@@ -537,6 +544,6 @@
 
     case 100:
-        lout << "Connection timed out." << endl;
-        EnableTimeout(false);
+        //lout << "Connection timed out." << endl;
+        //EnableTimeout(false);
         return;
 
@@ -562,6 +569,6 @@
     // FIXME: Timeout???
     //
-    while (GetError()<0)
-        usleep(1);
+//  while (GetError()<0)
+//      usleep(1);
 
     //
@@ -569,5 +576,5 @@
     // we can go on working 'as usual' Eg. Initialize a Display Update
     //
-    cout << GetNodeName() << " Handling Error #" << GetError() << endl;
+    cout << GetNodeName() << " Handling Error #" << dec << GetError() << endl;
     switch (GetError())
     {
@@ -576,17 +583,24 @@
     case   9: // zero idx
     case  84: // ON TIME
-        // Stop program?
+        lout << "- " << GetNodeName() << ": Cannot handle error #" << GetError() << endl;
         return;
 
     case 11:  // software endswitch
     case 25:  // hardware endswitch
+        lout << "- " << GetNodeName() << ": Cannot handle error 'Endswitch!'" << endl;
+        return;
+
     case 100: // timeout (movement has been stopped, so we can go on)
         DelError();
         return;
-
+/*
     case 101:
-        lout << "Warning: " << GetNodeName() << " didn't respond in timeout window - try again." << endl;
+        //lout << "Warning: " << GetNodeName() << " didn't respond in timeout window - try again." << endl;
         DelError();
         return;
+        */
+    default:
+        lout << "- " << GetNodeName() << ": Cannot handle error #" << GetError() << endl;
+ 
     }
 }
@@ -633,129 +647,40 @@
 }
 
-void Macs::ReqTimeoutTime()
-{
-    RequestSDO(0x4000, 2);
-    WaitForSdo(0x4000, 2);
-}
-
-void Macs::EnableTimeout(bool enable, LWORDS_t ms)
-{
-    lout << "- " << GetNodeName() << ": " << (enable?"En":"Dis") << "able timeout, " << dec << ms << "ms." << endl;
-    if (!enable)
-    {
-        SendSDO(0x4000, 1, string('o', 'f', 'f'));
-        WaitForSdo(0x4000, 1);
-
-        lout << "- " << GetNodeName() << ": Stopping handshake (PC)." << endl;
-
-        fTimeout->Stop(); //kTRUE);
-
-        fTimerOn = kFALSE;
-    }
-    else
-    {
-        if (ms>0)
-            SetTimeoutTime(ms);
-
-        ResetTimeout();
-
-        fTimerOn = kTRUE;
-        fTimeout->Start(fGuardTime/*/3*2*/, kTRUE); //kFALSE); //TRUE);
-
-        //
-        // Start with kFALSE would be a continous timer, but this
-        // timer seems to stop it's activity at some stage without
-        // any reason
-        //
-        lout << "- " << GetNodeName() << ": starting handshake." << endl;
-        SendSDO(0x4000, 1, string('o', 'n'));
-        WaitForSdo(0x4000, 1);
-    }
-    lout << "- " << GetNodeName() << ": Timeout timer turned "
-        << (enable?"on.":"off.") << endl;
-}
-
-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.
-       */
-
-    //
-    //  FIXME! Use NMT!
-    //
-    // --- lout << ddev(MLog::eGui);
-    // --- lout << "Send 0x4000: " << GetNodeName() << endl;
-
+void Macs::SendNodeguard()
+{
     SendSDO(0x4000, 0, (LWORD_t)0, false);
-
-    // --- lout << "Done 0x4000: " << GetNodeName() << endl;
-
-    Timer time;
-
-    // --- lout << "dT " << GetNodeName() << ": " <<  dec <<(int)((fTimeoutTime-time.Now())*1000) << endl;
-    // --- lout << edev(MLog::eGui);
-
-    if (time.Now() > fTimeoutTime)
-    {
-        lout << ddev(MLog::eGui);
-        lout << "Warning: " << GetNodeName() << " didn't respond in timeout window." << endl;
-        lout << edev(MLog::eGui);
-        SetError(101);
-    }
-
-    //WaitForSdo(0x4000, 0, kDontWait);
-    //
-    // Would not be necessary if I would Start the timer with
-    // kFALSE. This would be a continous timer, but this
-    // timer seems to stop it's activity at some stage without
-    // any reason
-    //
-    if (fTimerOn)
-        fTimeout->Start(fGuardTime/*/3*2*/, kTRUE);
-
-    return kTRUE;
-}
-
-void Macs::ResetTimeout()
-{
-    Timer time;
-
-    // --- lout << ddev(MLog::eGui);
-    // --- lout << "Reset " << GetNodeName() << ": " << dec << (int)((fTimeoutTime-time.Now())*1000) << endl;
-    // --- lout << edev(MLog::eGui);
-
-    fTimeoutTime = time.Now() + 3.*fGuardTime/1000.;
-}
-
-void Macs::SetTimeoutTime(LWORD_t ms)
-{
-    // FIXME: Is '/2' the best choose?
-    fGuardTime = ms/3;      // how often do we send/request the handshake
-
-    SendSDO(0x4000, 2, ms*2); // How often do we check for the handshake
-    WaitForSdo(0x4000, 2);
-}
-
+}
+
+// --------------------------------------------------------------------------
+//
+// This starts the host guarding. The host guarding is only available
+// if the node guarding is running. The host guarding works with the
+// guardtime and the lifetimefactor from the nodeguarding.
+//
+void Macs::StartHostGuarding()
+{
+    SendSDO(0x100c, 0, (LWORD_t)GetGuardTime());
+    WaitForSdo(0x100c);
+
+    SendSDO(0x100d, 0, (LWORD_t)GetLifeTimeFactor());
+    WaitForSdo(0x100d);
+
+    lout << "- " << GetNodeName() << ": Hostguarding started (" << dec;
+    lout << GetLifeTimeFactor() << "*" << GetGuardTime() << "ms)" << endl;
+}
+
+// --------------------------------------------------------------------------
+//
+// Stop the host guarding.
+//
+void Macs::StopHostGuarding()
+{
+    SendSDO(0x100c, 0, (LWORD_t)0);
+    WaitForSdo(0x100c);
+
+    SendSDO(0x100d, 0, (LWORD_t)0);
+    WaitForSdo(0x100d);
+
+    lout << "- " << GetNodeName() << ": Hostguarding stopped." << endl;
+}
+
Index: trunk/MagicSoft/Cosy/devdrv/macs.h
===================================================================
--- trunk/MagicSoft/Cosy/devdrv/macs.h	(revision 1726)
+++ trunk/MagicSoft/Cosy/devdrv/macs.h	(revision 1727)
@@ -1,11 +1,9 @@
 #ifndef MACS_H
 #define MACS_H
-
-#include <TObject.h>
 
 #include "nodedrv.h"
 #include "base/timer.h"
 
-class Macs : public NodeDrv, public TObject
+class Macs : public NodeDrv
 {
 private:
@@ -30,9 +28,4 @@
     BYTE_t   fStatus;
 
-    TTimer  *fTimeout;
-    Bool_t   fTimerOn;
-    LWORD_t  fGuardTime;
-    double   fTimeoutTime;
-
     LWORD_t string(BYTE_t b0=0, BYTE_t b1=0, BYTE_t b2=0, BYTE_t b3=0)
     {
@@ -40,21 +33,16 @@
     }
 
-    void ResetTimeout();
-    Bool_t HandleTimer(TTimer *t);
-
     void Init();
-    //bool Reboot();
-
-    //bool InitDevice(Network *);
-
-    //void StartDevice();
     void StopDevice();
 
     void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, timeval_t *tv);
-    void HandleSDOOK(WORD_t idx, BYTE_t subidx);
-    void HandleSDOError(LWORD_t data)           { NodeDrv::HandleSDOError(data); }
+    void HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv);
+    //void HandleSDOError(LWORD_t data) { NodeDrv::HandleSDOError(data); }
 
     void HandlePDO1(BYTE_t *data, timeval_t *tv);
     void HandlePDO2(BYTE_t *data, timeval_t *tv);
+    //void HandleNodeguard(timeval_t *tv);
+
+    void SendNodeguard();
 
     void CheckConnection();
@@ -108,9 +96,4 @@
     void StartAbsPos(LWORDS_t pos);
 
-    void SetTimeoutTime(LWORD_t ms);
-    void ReqTimeoutTime();
-
-    void EnableTimeout(bool enable=true, LWORDS_t ms=-1);
-
     void StopMotor();
 
@@ -131,4 +114,7 @@
     LWORD_t  GetRes()    const { return fRes; }    // Encoder resolution
 
+    void StartHostGuarding();
+    void StopHostGuarding();
+
     void HandleError();
 
Index: trunk/MagicSoft/Cosy/devdrv/shaftencoder.cc
===================================================================
--- trunk/MagicSoft/Cosy/devdrv/shaftencoder.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/devdrv/shaftencoder.cc	(revision 1727)
@@ -1,5 +1,5 @@
 #include "shaftencoder.h"
 
-#include "timer.h"
+#include "base/timer.h"
 #include "network.h"
 
@@ -17,8 +17,4 @@
 ShaftEncoder::ShaftEncoder(const BYTE_t nodeid, const char *name, MLog &out)
     : NodeDrv(nodeid, name, out), fLabel(NULL), fPosHasChanged(false)
-{
-}
-
-ShaftEncoder::~ShaftEncoder()
 {
 }
@@ -55,7 +51,19 @@
         return;
 
+    case 0x100c:
+        lout << "- Guardtime: " << dec << val << "ms" << endl;
+        return;
+
+    case 0x100d:
+        lout << "- Lifetimefactor: " << dec << val << endl;
+        return;
+
+    case 0x100e:
+        lout << "- CobId for guarding: 0x" << hex << val << endl;
+        return;
+
     case 0x6000:
     case 0x6500:
-        lout << "- Counting: " << (val&1   ?"anti-clockwise":"clockwise") << "  ";
+        lout << "- Counting: " << (val&1 ?"anti-clockwise":"clockwise") << "  ";
         lout << "HwTest: " <<   (val&2   ?"on":"off") << "  ";
         lout << "Scaling: " <<  (val&4   ?"on":"off") << "  ";
@@ -95,5 +103,5 @@
 void ShaftEncoder::DisplayVal()
 {
-    if (fIsZombie)
+    if (IsZombieNode())
     {
         fLabel[0]->SetText(new TGString(""));
@@ -162,4 +170,7 @@
 }
 
+//#include <fstream.h>
+//ofstream fout("log/shaftencoder.log");
+
 void ShaftEncoder::HandlePDOType2(BYTE_t *data, timeval_t *tv)
 {
@@ -188,4 +199,7 @@
     fPos  = pos;
     fTurn = turn;
+
+    //fout << dec << (int)GetId() << " " << turn << " " << pos << endl;
+
     fTime.SetTimer(tv);
     fPosHasChanged=true;
@@ -208,4 +222,6 @@
     //-----------------------------------------------------------------------
 
+    StopGuarding();
+
     //
     // Requesting and checking (FIXME) type of encoder
@@ -215,5 +231,5 @@
     WaitForSdo(0x1000);
 
-    if (fIsZombie)
+    if (IsZombieNode())
     {
         lout << GetNodeName() << " - Init failed!" << endl;
@@ -274,4 +290,6 @@
     lout << "- " << GetNodeName() << ": Start Node (NMT)." << endl;
     SendNMT(kNMT_START);
+
+    StartGuarding(125, 2);
 }
 
@@ -282,28 +300,4 @@
     WaitForSdo(0x100b);
 }
-/*
-bool ShaftEncoder::InitDevice(Network *net)
-{
-    NodeDrv::InitDevice(net);
-
-    Init();
-
-    return !fIsZombie;
-}
-
-// --------------------------------------------------------------------------
-//
-// This should be called from a master or main thread to get a node out
-// of the Zombie-Status. 
-//
-bool ShaftEncoder::Reboot()
-{
-    fIsZombie = false;
-
-    Init();
-
-    return !fIsZombie;
-}
-*/
 
 void ShaftEncoder::ReqPos()
@@ -321,5 +315,5 @@
     lout << "- " << GetNodeName() << ": Setting Preset." << endl;
 
-    SendSDO(0x6003, (LWORD_t)fPos);
+    SendSDO(0x6003, (LWORD_t)pre);
     if (!WaitForSdo(0x6003))
         return;
Index: trunk/MagicSoft/Cosy/devdrv/shaftencoder.h
===================================================================
--- trunk/MagicSoft/Cosy/devdrv/shaftencoder.h	(revision 1726)
+++ trunk/MagicSoft/Cosy/devdrv/shaftencoder.h	(revision 1727)
@@ -2,5 +2,5 @@
 #define SHAFTENCODER_H
 
-#include "timer.h"
+#include "base/timer.h"
 #include "nodedrv.h"
 
@@ -17,10 +17,10 @@
     WORD_t   fTurns; // Number of possible turns
 
-    TGLabel **fLabel;
-    LWORDS_t  fUpdPos;   // ticks
-    WORDS_t   fUpdVel;   // ticks per 5ms
-    WORDS_t   fUpdAcc;   // ticks per 25ms^2
+    TGLabel **fLabel;     //
+    LWORDS_t  fUpdPos;    // ticks
+    WORDS_t   fUpdVel;    // ticks per 5ms
+    WORDS_t   fUpdAcc;    // ticks per 25ms^2
 
-    bool fPosHasChanged;
+    bool fPosHasChanged;  //!
 
     Timer fTime;
@@ -37,10 +37,5 @@
 public:
     ShaftEncoder(const BYTE_t nodeid, const char *name=NULL, MLog &out=gLog);
-    virtual ~ShaftEncoder();
 
-    //bool InitDevice(Network *);
-    //bool Reboot();
-
-    //void StartDevice();
     void StopDevice();
 
@@ -48,11 +43,12 @@
 
     void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, timeval_t *tv);
-    void HandleSDOOK(WORD_t idx, BYTE_t subidx) { NodeDrv::HandleSDOOK(idx, subidx); }
-    void HandleSDOError(LWORD_t data)           { NodeDrv::HandleSDOError(data); }
-
+    /*
+     void HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv) { NodeDrv::HandleSDOOK(idx, subidx, tv); }
+     void HandleSDOError(LWORD_t data)           { NodeDrv::HandleSDOError(data); }
+     */
     void HandlePDO1(BYTE_t *data, timeval_t *tv) { HandlePDOType2(data, tv); }
     void HandlePDO2(BYTE_t *data, timeval_t *tv) { HandlePDOType2(data, tv); }
 
-    LWORDS_t GetPos() { return fIsZombie ? 0 : fPos+fTurn*fTicks; } // FIXME? 0?
+    LWORDS_t GetPos() { return IsZombieNode() ? 0 : fPos+fTurn*fTicks; } // FIXME? 0?
     LWORD_t  GetPhysRes() { return fTicks; }
 
Index: trunk/MagicSoft/Cosy/gui/MGCosy.cc
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGCosy.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/gui/MGCosy.cc	(revision 1727)
@@ -180,10 +180,10 @@
     fList->Add(l);
 
-    fOffsetZd = new TGLabel(f, "0000000");
-    fOffsetAz = new TGLabel(f, "0000000");
+    fOffsetZd = new TGLabel(f, "000000000");
+    fOffsetAz = new TGLabel(f, "000000000");
     fOffsetZd->SetTextJustify(kTextRight);
     fOffsetAz->SetTextJustify(kTextRight);
-    fOffsetZd->Move(x, y+102);
-    fOffsetAz->Move(x, y+119);
+    fOffsetZd->Move(x+15, y+102);
+    fOffsetAz->Move(x+15, y+119);
     fList->Add(fOffsetZd);
     fList->Add(fOffsetAz);
@@ -193,5 +193,5 @@
     fList->Add(l);
 
-    l = new TGLabel(f, "Ra (soll):");
+    l = new TGLabel(f, "Ra (nominal):");
     l->Move(x-60, y+159);
     fList->Add(l);
@@ -201,13 +201,13 @@
     fList->Add(l);
 
-    l = new TGLabel(f, "Dec (soll):");
+    l = new TGLabel(f, "Dec (nominal):");
     l->Move(x-60, y+199);
     fList->Add(l);
 
-    l = new TGLabel(f, "Zd (soll):");
+    l = new TGLabel(f, "Zd (nominal):");
     l->Move(x-60, y+222);
     fList->Add(l);
 
-    l = new TGLabel(f, "Az (soll):");
+    l = new TGLabel(f, "Az (nominal):");
     l->Move(x-60, y+239);
     fList->Add(l);
@@ -836,5 +836,5 @@
     {
         zd = (int)test.Zd();
-        sprintf(text, "%c%dh %.1fm", soll.Zd()<0?'-':'+', abs((int)soll.Zd()), 0.1*(abs((int)test.Zd())%600));
+        sprintf(text, "%c%dd %.1fm", soll.Zd()<0?'-':'+', abs((int)soll.Zd()), 0.1*(abs((int)test.Zd())%600));
         fZdSoll->SetText(new TGString(text));
     }
@@ -984,5 +984,5 @@
             Timer tm;
             tm.Now();
-
+            /*
             Float_t h = 2.+tm.H()+(10.7+tm.M())/60.;
             RaDec dest(h*15, 129.7);
@@ -994,11 +994,12 @@
             int i = 0;
             while (!HasStopFlag() && i++<60)  // 2.5min
-                usleep(1000000);
+            usleep(1000000);
             if (HasStopFlag())
                 break;
+            */
 
             //fQueue->PostMsg(WM_STOP, 0, 0);
 
-            ZdAz dest1(fRand.Integer(36)+25, fRand.Integer(360));
+            ZdAz dest1((float)fRand.Integer(120)-60., 0);//fRand.Integer(25)+90);
 
             cout << "Demo: Zd=" << dest1.Zd() << "° Az=" << dest1.Az() << "°" << endl;
@@ -1006,6 +1007,6 @@
             fQueue->PostMsg(WM_POSITION, &dest1, sizeof(dest1));
 
-            i = 0;
-            while (!HasStopFlag() && i++<15)  // 30s
+            int i = 0;
+            while (!HasStopFlag() && i++<5/*5*/)  // 30s
                 usleep(1000000);
             if (HasStopFlag())
Index: trunk/MagicSoft/Cosy/gui/MGSkyPosition.cc
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGSkyPosition.cc	(revision 1726)
+++ trunk/MagicSoft/Cosy/gui/MGSkyPosition.cc	(revision 1727)
@@ -56,10 +56,16 @@
     fMoon    = new TArc(0, 0, 3, 290, 70);
     fSun     = new TArc(0, 0, 2);
-
-    InitArc(fMars,    1001, 13, 12);
+    fSaturn  = new TArc(0, 0, 1);
+
+    fSaturnRing = new TArc(0, 0, 2);
+    fSaturnRing->SetFillStyle(4000);      // (s. TAttFill)
+    fSaturnRing->SetLineColor(kRed);
+    fSaturnRing->Draw();
+
+    InitArc(fMars,    1001, kRed/*13*/, kRed/*12*/);
     InitArc(fVenus,   1001, 15, 14);
     InitArc(fJupiter, 1001, 17, 16);
     InitArc(fMoon,    1001, 19, 15);
-    InitArc(fSun,     1001, 10, 19);
+    InitArc(fSaturn,  1001, kYellow/*17*/, 16);
 
     for (int i=0; i<4; i++)
@@ -72,4 +78,5 @@
         fList->Add(fSunL[i]);
     }
+    InitArc(fSun, 1001, kYellow/*10*/, kYellow/*19*/);
 
     fList->Add(fMars);
@@ -78,4 +85,5 @@
     fList->Add(fMoon);
     fList->Add(fSun);
+    fList->Add(fSaturn);
 
     //
@@ -317,4 +325,5 @@
     UpdatePlanet(kEVenus,   fVenus);
     UpdatePlanet(kEMars,    fMars);
+    UpdatePlanet(kESaturn,  fSaturn);
 
     RaDec radec = fSlaStar->CalcRaDecFast(pos*kDeg2Rad);
@@ -363,18 +372,21 @@
     SetModified();
 
-    if (planet!=kESun)
-        return;
-
-    // cout << "Sun: x=" << x << " y=" << y;
-    // cout << "   Zd=" << deg << " Az=" << 360./D2PI*zdaz.Az() << endl;
-
-    fSunL[0]->SetX1(x-3.5); fSunL[0]->SetX2(x+3.5);
-    fSunL[1]->SetX1(x-2.5); fSunL[1]->SetX2(x+2.5);
-    fSunL[2]->SetX1(x-2.5); fSunL[2]->SetX2(x+2.5);
-    fSunL[3]->SetX1(x);     fSunL[3]->SetX2(x);
-
-    fSunL[0]->SetY1(y);     fSunL[0]->SetY2(y);
-    fSunL[1]->SetY1(y-2.5); fSunL[1]->SetY2(y+2.5);
-    fSunL[2]->SetY1(y+2.5); fSunL[2]->SetY2(y-2.5);
-    fSunL[3]->SetY1(y-3.5); fSunL[3]->SetY2(y+3.5);
-}
+    if (planet==kESaturn)
+    {
+        fSaturnRing->SetX1(x);
+        fSaturnRing->SetY1(y);
+    }
+
+    if (planet==kESun)
+    {
+        fSunL[0]->SetX1(x-3.5); fSunL[0]->SetX2(x+3.5);
+        fSunL[1]->SetX1(x-2.5); fSunL[1]->SetX2(x+2.5);
+        fSunL[2]->SetX1(x-2.5); fSunL[2]->SetX2(x+2.5);
+        fSunL[3]->SetX1(x);     fSunL[3]->SetX2(x);
+
+        fSunL[0]->SetY1(y);     fSunL[0]->SetY2(y);
+        fSunL[1]->SetY1(y-2.5); fSunL[1]->SetY2(y+2.5);
+        fSunL[2]->SetY1(y+2.5); fSunL[2]->SetY2(y-2.5);
+        fSunL[3]->SetY1(y-3.5); fSunL[3]->SetY2(y+3.5);
+    }
+}
Index: trunk/MagicSoft/Cosy/gui/MGSkyPosition.h
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGSkyPosition.h	(revision 1726)
+++ trunk/MagicSoft/Cosy/gui/MGSkyPosition.h	(revision 1727)
@@ -29,4 +29,7 @@
     TArc       *fMars;
     TArc       *fSun;
+    TArc       *fSaturn;
+
+    TArc       *fSaturnRing;
 
     TArc       *fDot[6];
