Index: /trunk/MagicSoft/Cosy/Changelog
===================================================================
--- /trunk/MagicSoft/Cosy/Changelog	(revision 8864)
+++ /trunk/MagicSoft/Cosy/Changelog	(revision 8865)
@@ -1,3 +1,33 @@
                                                                   -*-*- END -*-*-
+
+ 2008/02/20 Thomas Bretz (La Palma)
+
+   * candrv/ethernet.[h,cc]:
+     - return kFALSE even if RecvRaw return a value <0
+
+   * devdrv/macs.[h,cc]:
+     - added setting and reseeting of an armed state disallowing
+       all movements
+     - set fPosActive if positiong has been started to prevent lags
+       in the program flow
+     - added fArmed to PDO1
+     - added some debug output
+
+   * gui/MGCosy.[h,cc]:
+     - added "Arm" button to the display in expert mode
+     - added armed state to the Update member function
+
+   * main/MCosy.[h,cc]:
+     - commented out all accesses to the third MACS
+     - added code to allow the armed state to be set from the gui
+     - pipe the armed state to the gui
+
+   * tcpip/MTcpIpIO.[h,cc]:
+     - added a timeout to MTcpIpI when waiting for new data
+       which is set to 5s by default
+     - return kFALSE even if RecvRaw return a value <0
+     - wait for new connection in case of timeout
+
+
 
  2008/02/17 Thomas Bretz (La Palma)
Index: /trunk/MagicSoft/Cosy/candrv/ethernet.cc
===================================================================
--- /trunk/MagicSoft/Cosy/candrv/ethernet.cc	(revision 8864)
+++ /trunk/MagicSoft/Cosy/candrv/ethernet.cc	(revision 8865)
@@ -90,13 +90,10 @@
         const Int_t len = rx.RecvRaw(&c, 1);
 
-        // No data received (non-blocking mode)
-        if (len<0)
-        {
-            usleep(1);
-            continue;
-        }
-
-        // Data received with zero length! (Connection lost)
-        if (len==0)
+        // For details see TSocket::RecvRaw
+        // -1: // ERROR
+        // EINVAL, EWOULDBLOCK
+        // -5: // EPIPE || ECONNRESET = Pipe broken or connection reset by peer
+        //  0: Data received with zero length! (Connection lost/call interrupted)
+        if (len<=0)
             return kFALSE;
 
@@ -112,5 +109,5 @@
             if (c>=MSGLEN)
             {
-                cout << "Data received from " << address << " too long (> " << MSGLEN << ")" << endl;
+                gLog << err << "Data received from " << address << " too long (> " << MSGLEN << ")" << endl;
                 continue;
             }
Index: /trunk/MagicSoft/Cosy/devdrv/macs.cc
===================================================================
--- /trunk/MagicSoft/Cosy/devdrv/macs.cc	(revision 8864)
+++ /trunk/MagicSoft/Cosy/devdrv/macs.cc	(revision 8865)
@@ -34,5 +34,5 @@
     : NodeDrv(nodeid, name), fMacId(2*nodeid+1),
     fPos(0), fPdoPos(0), fPosActive(0), fRpmActive(0),
-    fStatusPdo3(0xff)
+    fStatusPdo3(0xff), fArmed(false)
 {
 //    fTimeout = new TTimer(this, 100); //, kFALSE); // 100ms, asynchronous
@@ -72,5 +72,5 @@
     case 0xa149: return "Drive controlled interpolated relative positioning lagless with encoder 2";
     case 0xa150: return "Drive controlled positioning with encoder 1";
-    case 0xa151: return "Drive controlled positioning with encoder 2";
+    case 0xa151: return "Drive controlled positioning with encoder 1, lagless";
     case 0xa208: return "Jog mode positive";
     case 0xa218: return "Jog mode negative";
@@ -91,4 +91,5 @@
     case 0xe264: return "Target position out of numerical range";
     case 0xe834: return "Emergency-Stop";
+    case 0xe842: return "Both end-switches activated";
     case 0xe843: return "Positive end-switch activated";
     case 0xe844: return "Negative end-switch activated";
@@ -150,4 +151,12 @@
     switch (idx)
     {
+    case 0x1000:
+        if (subidx==1)
+        {
+            gLog << inf2 << "- " << GetNodeName() << ": Node is" << (val?" ":" not ") << "armed." << endl;
+            fArmed = val==1;
+        }
+        return;
+
     case 0x1003:
         // FIXME, see Init
@@ -382,4 +391,5 @@
             //lout << ddev(MLog::eGui);
             gLog << inf2 << "- " << GetNodeName() << ": Absolute positioning started." << endl;
+            fPosActive = kTRUE; // Make sure that the status is set correctly already before the first PDO
             //lout << edev(MLog::eGui);
             return;
@@ -388,4 +398,5 @@
             //lout << ddev(MLog::eGui);
             gLog << inf2 << "- " << GetNodeName() << ": Relative positioning started." << endl;
+            fPosActive = kTRUE; // Make sure that the status is set correctly already before the first PDO
             //lout << edev(MLog::eGui);
             return;
@@ -428,4 +439,16 @@
     gLog << inf2 << "- " << GetNodeName() << ": Starting Node." << endl;
     SendSDO(0x1000, 1, (LWORD_t)1);
+    WaitForSdo(0x1000, 1);
+}
+
+void Macs::Arm()
+{
+    StartNode();
+}
+
+void Macs::Disarm()
+{
+    gLog << inf2 << "- " << GetNodeName() << ": Stopping Node." << endl;
+    SendSDO(0x1000, 1, (LWORD_t)0);
     WaitForSdo(0x1000, 1);
 }
@@ -490,5 +513,10 @@
     //StartHostGuarding();
 
-    StartNode();
+    // REMOVE THIS AND LET CC START THE NODE
+    //StartNode();
+
+    gLog << inf2 << "- " << GetNodeName() << ": Checking armed status." << endl;
+    RequestSDO(0x1000, 1);
+    WaitForSdo(0x1000, 1);
 }
 /*
@@ -571,21 +599,21 @@
 void Macs::SetVelocity(LWORD_t vel)
 {
+    gLog << dbg << "- Setting velocity to: " << vel << endl;
     SendSDO(0x2002, vel);     // velocity
     WaitForSdo(0x2002, 0);
-    cout << "SET VEL: " << vel << endl;
 }
 
 void Macs::SetAcceleration(LWORD_t acc)
 {
+    gLog << dbg << "- Setting acceleration to: " << vel << endl;
     SendSDO(0x2003, 0, acc);  // acceleration
     WaitForSdo(0x2003, 0);
-    cout << "SET ACC: " << acc << endl;
 }
 
 void Macs::SetDeceleration(LWORD_t dec)
 {
-    SendSDO(0x2003, 1, dec);  // acceleration
+    gLog << dbg << "- Setting deceleration to: " << vel << endl;
+    SendSDO(0x2003, 1, dec);
     WaitForSdo(0x2003, 1);
-    cout << "SET DEC: " << dec << endl;
 }
 
@@ -607,12 +635,25 @@
 void Macs::StartRelPos(LWORDS_t pos)
 {
+    if (!fIsArmed)
+    {
+        gLog << err << GetNodeName() << ": ERROR - Moving without being armed is not allowed." << endl;
+        return;
+    }
+
+    gLog << dbg << GetNodeName() << ": Starting abolsute positioning to " << (LWORD_t)pos << " ticks." << endl;
     SendSDO(0x6004, 1, (LWORD_t)pos);
-    cout << "REL POS: " << (LWORD_t)pos << endl;
+    fPosActive = kTRUE; // Make sure that the status is set correctly already before the first PDO
 }
 
 void Macs::StartAbsPos(LWORDS_t pos)
 {
+    if (!fIsArmed)
+    {
+        gLog << err << GetNodeName() << ": ERROR - Moving without being armed is not allowed." << endl;
+        return;
+    }
+    gLog << dbg << GetNodeName() << ": Starting relative positioning by " << (LWORD_t)pos << " ticks." << endl;
     SendSDO(0x6004, 0, (LWORD_t)pos);
-    cout << "ABS POS: " << (LWORD_t)pos << endl;
+    fPosActive = kTRUE; // Make sure that the status is set correctly already before the first PDO
 }
 
@@ -681,4 +722,6 @@
     fInControl = data[3]&0x40; // motor uncontrolled
               // data[3]&0x80; // axis resetted (after errclr, motor stop, motor on)
+
+    fArmed     = data[2]&kIsArmed==kIsArmed;
 
     fStatus = data[3];
Index: /trunk/MagicSoft/Cosy/devdrv/macs.h
===================================================================
--- /trunk/MagicSoft/Cosy/devdrv/macs.h	(revision 8864)
+++ /trunk/MagicSoft/Cosy/devdrv/macs.h	(revision 8865)
@@ -34,4 +34,6 @@
 
     BYTE_t   fStatusPdo3;
+
+    bool fArmed;
 
     void Init();
@@ -73,4 +75,5 @@
     enum
     {
+        kIsArmed   = BIT(0),    // Macs will accept movement commands
         kNotMoving = BIT(0),    // motor not moving
         kPosActive = BIT(1),    // positioning active
@@ -121,4 +124,8 @@
     void StartNode();
 
+    bool IsArmed() const { return fArmed; }
+    void Arm();
+    void Disarm();
+
     int IsPositioning() const { return fPosActive; }
     BYTE_t GetStatus() const { return fStatus; }
Index: /trunk/MagicSoft/Cosy/gui/MGCosy.cc
===================================================================
--- /trunk/MagicSoft/Cosy/gui/MGCosy.cc	(revision 8864)
+++ /trunk/MagicSoft/Cosy/gui/MGCosy.cc	(revision 8865)
@@ -58,4 +58,5 @@
     kPB_TPOINT,
     kPB_ENDSWITCH,
+    kPB_ARM,
     kPB_START,
     kPB_DISPLAY1,
@@ -529,4 +530,14 @@
 
 #ifdef EXPERT
+    but = new TGTextButton(tf1, "Arm", kPB_ARM);
+    but->MoveResize(204, 213, 62, 25);
+    but->SetToolTipText("Arm the telescop (allow for movement).");
+    but->Associate(this);
+    fList->Add(but);
+
+    ULong_t col;
+    gClient->GetColorByName("Magenta", col);
+    but->SetBackgroundColor(col);
+
     but= new TGTextButton(tf1, "New Position",  kPB_SavePreDef);
     but->MoveResize(165, 197, 80, 25);
@@ -554,5 +565,5 @@
 
     but = new TGTextButton(tf4, "Load", kPB_LoadBending);
-    but->ResizeMove(151, 185, 50, 25);
+    but->MoveResize(151, 185, 50, 25);
     but->SetToolTipText("Load bending corrections from file 'bending.txt'");
     but->Associate(this);
@@ -1030,5 +1041,5 @@
 
 void MGCosy::Update(ZdAz pos, ZdAz acc, ZdAz vel, /*ZdAz off,*/ RaDec radec,
-                    ZdAz soll, UInt_t stat, UInt_t stat2)
+                    ZdAz soll, UInt_t stat, UInt_t stat2, Bool_t armed)
 {
     // acc [rad]
@@ -1058,5 +1069,5 @@
     SetLabelColor(fAvailSe3,  stat2&0x20);
 
-    EnableLabel(fArmed, 1);//stat2&0x40);
+    EnableLabel(fArmed, armed);//stat2&0x40);
 
     if (stat&MDriveCom::kTracking)
@@ -1502,4 +1513,7 @@
                 StartTrackPos();
                 return kTRUE;
+            case kPB_ARM:
+                fQueue->PostMsg(WM_ARM);
+                return kTRUE;
             case kPB_DISPLAY1:
             case kPB_DISPLAY2:
Index: /trunk/MagicSoft/Cosy/gui/MGCosy.h
===================================================================
--- /trunk/MagicSoft/Cosy/gui/MGCosy.h	(revision 8864)
+++ /trunk/MagicSoft/Cosy/gui/MGCosy.h	(revision 8865)
@@ -137,5 +137,5 @@
     MGImage    *GetImage()     { return fImage; }
 
-    void Update(ZdAz pos, ZdAz acc, ZdAz vel, /*ZdAz off,*/ RaDec radec, ZdAz soll, UInt_t stat, UInt_t stat2);
+    void Update(ZdAz pos, ZdAz acc, ZdAz vel, /*ZdAz off,*/ RaDec radec, ZdAz soll, UInt_t stat, UInt_t stat2, Bool_t armed);
     void UpdateWeather(const MCeCoCom &com);
 
Index: /trunk/MagicSoft/Cosy/main/MCosy.cc
===================================================================
--- /trunk/MagicSoft/Cosy/main/MCosy.cc	(revision 8864)
+++ /trunk/MagicSoft/Cosy/main/MCosy.cc	(revision 8865)
@@ -406,6 +406,6 @@
 
 //#ifdef EXPERT
-//    point.SetAccDec(0.4, 0.4);
-//    point.SetVelocity(0.2); // fast: 0.6, slow: 0.2
+    //point.SetPointAccDec(0.3, 0.3);
+    //point.SetPointVelocity(0.3);
 //#else
 
@@ -413,13 +413,8 @@
 //
     point.SetPointAccDec(0.2, 0.1);
-
     point.SetPointVelocity(0.1);
 
 
 //#endif
-
-//    point.SetPointAccDec(0.4, 0.4);
-//    point.SetPointVelocity(0.4);
-
 
 // original
@@ -428,7 +423,4 @@
 // test
 //    return point.SetPosition(dst, kTRUE);
-
-
-
 }
 
@@ -565,6 +557,6 @@
         fMac1->HandleError();
         fMac2->HandleError();
-        if (fMac3)
-            fMac3->HandleError();
+        //if (fMac3)
+        //    fMac3->HandleError();
         if (HasError() || HasZombie())
             return false;
@@ -700,28 +692,28 @@
         //cout << "WM_TrackPosition: done. (return 0xabcd)" << endl;
         return 0xabcd;
-/*
+
     case WM_ARM:
         //cout << "WM_Position: start." << endl;
         {
             if (!CheckNetwork())
-                return (void*)0xebb0;
-
-            const bool arm = *((bool*)mp);
-            if (arm)
-            {
+                return 0xebb0;
+
+            //const bool arm = *((bool*)mp);
+            //if (arm)
+            //{
                 fMac1->Arm();
                 fMac2->Arm();
-                cout << "ARMED" << endl;
-            }
-            else
-            {
-                fMac1->Disarm();
-                fMac2->Disarm();
-                cout << "DISARMED" << endl;
-            }
+                //cout << "ARMED" << endl;
+            //}
+            //else
+            //{
+            //    fMac1->Disarm();
+            //    fMac2->Disarm();
+                //cout << "DISARMED" << endl;
+            //}
         }
         //cout << "WM_Position: done. (return 0x7777)" << endl;
-        return (void*)0x9999;
-  */
+        return 0x9999;
+
     case WM_POSITION:
         //cout << "WM_Position: start." << endl;
@@ -963,5 +955,5 @@
     Bool_t mac1 = fMac1 && !fMac1->IsZombieNode();
     Bool_t mac2 = fMac2 && !fMac2->IsZombieNode();
-    Bool_t mac3 = fMac3 && !fMac3->IsZombieNode();
+    //Bool_t mac3 = fMac3 && !fMac3->IsZombieNode();
 
     Bool_t zd1  = fZd1  && !fZd1->IsZombieNode();
@@ -971,5 +963,6 @@
     Double_t x = 0;
     Double_t y = 0;
-    y = mac1 ? fMac1->GetRes() : (mac3 ? fMac3->GetRes() : env.GetValue("Az_ResRE[re/U_mot]", 1500));
+//    y = mac1 ? fMac1->GetRes() : (mac3 ? fMac3->GetRes() : env.GetValue("Az_ResRE[re/U_mot]", 1500));
+    y = mac1 ? fMac1->GetRes() : env.GetValue("Az_ResRE[re/U_mot]", 1500);
     x = mac2 ? fMac2->GetRes() : env.GetValue("Zd_ResRE[re/U_mot]", 1500);
     kResRE.Set(x,y);
@@ -1278,5 +1271,5 @@
     avail |= (fMac1 && !fMac1->IsZombieNode()) ? 0x01 : 0;
     avail |= (fMac2 && !fMac2->IsZombieNode()) ? 0x02 : 0;
-    avail |= (fMac3 && !fMac3->IsZombieNode()) ? 0x04 : 0;
+    //avail |= (fMac3 && !fMac3->IsZombieNode()) ? 0x04 : 0;
     avail |= (fZd1  && !fZd1->IsZombieNode())  ? 0x08 : 0;
     avail |= (fZd2  && !fZd2->IsZombieNode())  ? 0x10 : 0;
@@ -1284,4 +1277,9 @@
 //    avail |= (!(fStatus&MDriveCom::kError) && 1 ? 0x40 : 0;
 
+    Bool_t armed = kTRUE;
+
+    armed &= fMac1 && fMac1->IsArmed();
+    armed &= fMac2 && fMac2->IsArmed();
+
     if (HasError())
         SetStatus(MDriveCom::kError);
@@ -1296,5 +1294,5 @@
     fWin->UpdateWeather(*fCom);
     fWin->Update(bendist, fTrackingError, fVelocity, /*fOffset,*/
-                 fRaDec, fZdAzSoll, fStatus, avail);
+                 fRaDec, fZdAzSoll, fStatus, avail, armed);
 
     gLog.UpdateGui();
@@ -1497,6 +1495,6 @@
     fMac1=new Macs(id1, "Mac/Az");
     fMac2=new Macs(id3, "Mac/Zd");
-    if (id2>=0)
-        fMac3=new Macs(id2, "Mac/Az-Sync");
+    //if (id2>=0)
+    //    fMac3=new Macs(id2, "Mac/Az-Sync");
 
     fZd1=new ShaftEncoder(id4, "SE/Zd1");
@@ -1519,6 +1517,6 @@
     SetNode(fMac1);
     SetNode(fMac2);
-    if (id2>=0)
-        SetNode(fMac3);
+    //if (id2>=0)
+    //    SetNode(fMac3);
     SetNode(fZd1);
     SetNode(fZd2);
@@ -1618,5 +1616,5 @@
 MCosy::MCosy(MEnv &env, const char *addr, const char *pointing)
 : Network(), fObservatory(MObservatory::kMagic1), fStarguider(NULL),
-fZd1(0), fZd2(0), fAz(0), fMac1(0), fMac2(0), fMac3(0),
+fZd1(0), fZd2(0), fAz(0), fMac1(0), fMac2(0), /*fMac3(0),*/
 fBackground(kBgdNone), fTriggerDisplay(kFALSE), fStatus(MDriveCom::kStopped),
 fOutTp(0), fOutRep(0)
@@ -1721,6 +1719,6 @@
     delete fMac1;
     delete fMac2;
-    if (fMac3)
-        delete fMac3;
+    //if (fMac3)
+    //    delete fMac3;
 
     gLog << inf2 << "Deleting MGCosy." << endl;
Index: /trunk/MagicSoft/Cosy/main/MCosy.h
===================================================================
--- /trunk/MagicSoft/Cosy/main/MCosy.h	(revision 8864)
+++ /trunk/MagicSoft/Cosy/main/MCosy.h	(revision 8865)
@@ -87,5 +87,5 @@
     Macs *fMac1;
     Macs *fMac2;
-    Macs *fMac3;
+    //Macs *fMac3;
 
     MGCosy    *fWin;
Index: /trunk/MagicSoft/Cosy/tcpip/MTcpIpIO.cc
===================================================================
--- /trunk/MagicSoft/Cosy/tcpip/MTcpIpIO.cc	(revision 8864)
+++ /trunk/MagicSoft/Cosy/tcpip/MTcpIpIO.cc	(revision 8865)
@@ -12,4 +12,5 @@
 
 #include "MString.h"
+#include "MTimeout.h"
 
 #undef DEBUG
@@ -84,20 +85,20 @@
     }
 
-    const Int_t l = tx.SendRaw(msg, len);
-    if (l<0)
-    {
-        gLog << err << "ERROR - Sending TCP/IP frame to " << GetSocketAddress(tx) << endl;
-        return false;
-    }
-
-    if (l!=len)
-    {
-        gLog << err << "ERROR - Sent wrong number (" << l << ") of bytes to " << GetSocketAddress(tx) << endl;
-        return false;
-    }
-
 #ifdef DEBUG
     cout << "Tx: " << msg << flush;
 #endif
+
+    const Int_t l = tx.SendRaw(msg, len);
+    if (l<0)
+    {
+        gLog << err << "ERROR - Sending TCP/IP frame to " << GetSocketAddress(tx) << endl;
+        return false;
+    }
+
+    if (l!=len)
+    {
+        gLog << err << "ERROR - Sent wrong number (" << l << ") of bytes to " << GetSocketAddress(tx) << endl;
+        return false;
+    }
 
     return true;
@@ -164,14 +165,11 @@
         const Int_t len = rx.RecvRaw(&c, 1);
 
-        // No data received (non-blocking mode)
-        if (len<0)
-        {
-            usleep(1);
-            continue;
-        }
-
-        // Data received with zero length! (Connection lost)
-        if (len==0)
-            return kFALSE; // This break is for TEST PURPOSE FIXME!!!
+        // For details see TSocket::RecvRaw
+        // -1: // ERROR
+        // EINVAL, EWOULDBLOCK
+        // -5: // EPIPE || ECONNRESET = Pipe broken or connection reset by peer
+        //  0: Data received with zero length! (Connection lost/call interrupted)
+        if (len<=0)
+            return kFALSE;
 
         // Data received
@@ -208,4 +206,6 @@
     fConnectionEstablished = kTRUE;
 
+    MTimeout timeout;
+
     // Get connection on port fPortRx and redirected
     while (!IsThreadCanceled())
@@ -220,7 +220,15 @@
                 return kFALSE;
             }
-
-            // *FALLTHROUGH*
+            timeout.Start(fTimeout);
+
+            // Go on waiting for new data
+            continue;
+
         case kFALSE: // Time out, no data yet, go on waiting
+            if (timeout.HasTimedOut())
+            {
+                gLog << warn << "WARNING - Connection to " << MTcpIpO::GetSocketAddress(sock) << " timed out." << endl;
+                return kFALSE;
+            }
 
             // Go on waiting for new data
@@ -248,4 +256,5 @@
         while (!IsThreadCanceled())
         {
+            // Wait for a new connection on RX port
             socket = server.Accept();
 
@@ -271,4 +280,6 @@
         if ((Long_t)socket<=0)
             return;
+
+        gLog << all << "Connection established to " << MTcpIpO::GetSocketAddress(*socket) << "..." << endl;
 
         if (!WaitForData(*socket))
Index: /trunk/MagicSoft/Cosy/tcpip/MTcpIpIO.h
===================================================================
--- /trunk/MagicSoft/Cosy/tcpip/MTcpIpIO.h	(revision 8864)
+++ /trunk/MagicSoft/Cosy/tcpip/MTcpIpIO.h	(revision 8865)
@@ -18,5 +18,7 @@
 {
 private:
-    Int_t  fPortRx;
+    Int_t  fPortRx;     // Port on which to listen for connections
+    Int_t  fTimeout;    // [ms] Timeout to listen for data to be received
+
     Bool_t fConnectionEstablished;
 
@@ -29,5 +31,5 @@
 
 public:
-    MTcpIpI(Int_t rx) : MThread(Form("MTcpIpI::%d", rx)), fPortRx(rx), fConnectionEstablished(kFALSE) { /*RunThread();*/ }
+    MTcpIpI(Int_t rx, UInt_t timeout=5000) : MThread(Form("MTcpIpI::%d", rx)), fPortRx(rx), fTimeout(timeout), fConnectionEstablished(kFALSE) { /*RunThread();*/ }
     ~MTcpIpI() { CancelThread(); }
 
