Index: trunk/lib/FlairSensorActuator/src/EmulatedController.cpp
===================================================================
--- trunk/lib/FlairSensorActuator/src/EmulatedController.cpp	(revision 38)
+++ trunk/lib/FlairSensorActuator/src/EmulatedController.cpp	(revision 38)
@@ -0,0 +1,153 @@
+//  created:    2015/03/30
+//  filename:   EmulatedController.cpp
+//
+//  author:     Gildas Bayard
+//              Copyright Heudiasyc UMR UTC/CNRS 7253
+//
+//  version:    $Id: $
+//
+//  purpose:    class that emulate a remote control.
+//              Typical use case: run a demo without any reliable communication channel
+//
+/*********************************************************************/
+#include "EmulatedController.h"
+#include <Controller.h>
+#include <FrameworkManager.h>
+#include <TcpSocket.h>
+#include <Socket.h>
+#include <cstring>
+#include <string>
+#include <cvmatrix.h>
+#include <stdexcept>
+
+#include <unistd.h> // for sleep (debug)
+
+using namespace flair::core;
+using namespace flair::gui;
+using std::string;
+
+namespace flair { namespace sensor {
+
+EmulatedController::EmulatedController(const FrameworkManager* parent,string name,uint8_t priority) :
+    TargetController(parent,name,priority) {
+}
+
+EmulatedController::~EmulatedController() {
+    //TargetController calls TargetEthController methods in its run
+    //we must stop the thread now
+    SafeStop();
+    Join();
+}
+
+bool EmulatedController::IsConnected() const {
+    return true;
+}
+
+bool EmulatedController::IsDataFrameReady(){
+    return true;
+}
+
+template<typename T> void EmulatedController::fillVectorNoMutex(cvmatrix &vector,T data[],unsigned int size) {
+    for (unsigned int i=0; i<size; i++) {
+        vector.SetValueNoMutex(i,0,data[i]);
+    }
+}
+
+void EmulatedController::fillVectorNoMutex(cvmatrix &destination,cvmatrix &source,unsigned int size) {
+    for (unsigned int i=0; i<size; i++) {
+        destination.SetValueNoMutex(i,0,source.Value(i,0));
+    }
+}
+
+void EmulatedController::StepData::Print() {
+    Printf("<StepData %s, duration=%d, axisData={%f,%f,%f,%f}, buttonData={%c,%c,%c,%c,%c,%c,%c,%c,%c,%c,%c,%c,%c,%c,%c,%c} />\n",description.c_str(),durationMs,
+      axisData->Value(0,0),axisData->Value(1,0),axisData->Value(2,0),axisData->Value(3,0),
+      buttonData->Value(0,0)?'X':'-',buttonData->Value(1,0)?'X':'-',buttonData->Value(2,0)?'X':'-',buttonData->Value(3,0)?'X':'-',
+      buttonData->Value(4,0)?'X':'-',buttonData->Value(5,0)?'X':'-',buttonData->Value(6,0)?'X':'-',buttonData->Value(7,0)?'X':'-',
+      buttonData->Value(8,0)?'X':'-',buttonData->Value(9,0)?'X':'-',buttonData->Value(10,0)?'X':'-',buttonData->Value(11,0)?'X':'-',
+      buttonData->Value(12,0)?'X':'-',buttonData->Value(13,0)?'X':'-',buttonData->Value(14,0)?'X':'-',buttonData->Value(15,0)?'X':'-'
+    );
+}
+
+void EmulatedController::AddStep(unsigned int durationMs,string description,uint16_t buttonPressed, float leftAxisX, float leftAxisY, float rightAxisX, float rightAxisY) {
+    cvmatrix *axisMatrix=new cvmatrix((IODevice *)this,4,1,floatType);
+    axisMatrix->SetValueNoMutex(0,0,leftAxisX);
+    axisMatrix->SetValueNoMutex(1,0,leftAxisY);
+    axisMatrix->SetValueNoMutex(2,0,rightAxisX);
+    axisMatrix->SetValueNoMutex(3,0,rightAxisY);
+
+    cvmatrix *buttonMatrix=new cvmatrix((IODevice *)this,16,1,SignedIntegerType(8));
+    if (buttonPressed&(uint16_t)ButtonType::start) buttonMatrix->SetValueNoMutex(0,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::select) buttonMatrix->SetValueNoMutex(1,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::square) buttonMatrix->SetValueNoMutex(2,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::triangle) buttonMatrix->SetValueNoMutex(3,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::circle) buttonMatrix->SetValueNoMutex(4,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::cross) buttonMatrix->SetValueNoMutex(5,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::left1) buttonMatrix->SetValueNoMutex(6,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::left2) buttonMatrix->SetValueNoMutex(7,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::left3) buttonMatrix->SetValueNoMutex(8,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::right1) buttonMatrix->SetValueNoMutex(9,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::right2) buttonMatrix->SetValueNoMutex(10,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::right3) buttonMatrix->SetValueNoMutex(11,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::up) buttonMatrix->SetValueNoMutex(12,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::down) buttonMatrix->SetValueNoMutex(13,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::left) buttonMatrix->SetValueNoMutex(14,0,1);
+    if (buttonPressed&(uint16_t)ButtonType::right) buttonMatrix->SetValueNoMutex(15,0,1);
+
+    StepData step={durationMs,axisMatrix,buttonMatrix,description};
+    //step.Print();
+    steps.push_back(step);
+}
+
+void EmulatedController::ComputeControllerData(DataType dataType, cvmatrix &data) {
+    static Time startStepTime=GetTime();
+
+    Time now=GetTime();
+
+    axis->GetMutex();
+    button->GetMutex();
+
+    if (steps.empty()) {
+        if (dataType==DataType::axis) {
+            float values[]={0.,0.,0.,0.};
+            fillVectorNoMutex(data,values,4);
+        }
+        if (dataType==DataType::button) {
+            int values[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+            fillVectorNoMutex(data,values,16);
+        }
+    } else {
+        StepData currentStep=steps.front();
+        if (dataType==DataType::axis) fillVectorNoMutex(data,*(currentStep.axisData),4);
+        if (dataType==DataType::button) fillVectorNoMutex(data,*(currentStep.buttonData),16);
+        if (now-startStepTime>(Time)currentStep.durationMs*1000*1000) {
+            Thread::Info("Step '%s' done\n",currentStep.description.c_str());
+            startStepTime=now;
+            steps.pop_front();
+        }
+    }
+
+    button->ReleaseMutex();
+    axis->ReleaseMutex();
+}
+
+void EmulatedController::AcquireAxisData(core::cvmatrix &axis) {
+    ComputeControllerData(DataType::axis,axis);
+}
+
+void EmulatedController::AcquireButtonData(core::cvmatrix &button) {
+    ComputeControllerData(DataType::button,button);
+}
+
+bool EmulatedController::ProcessMessage(Message *msg) {
+    return false;
+}
+
+bool EmulatedController::ControllerInitialization() {
+    axisNumber=4;
+    buttonNumber=16;
+    return true;
+}
+
+} // end namespace sensor
+} // end namespace flair
Index: trunk/lib/FlairSensorActuator/src/EmulatedController.h
===================================================================
--- trunk/lib/FlairSensorActuator/src/EmulatedController.h	(revision 38)
+++ trunk/lib/FlairSensorActuator/src/EmulatedController.h	(revision 38)
@@ -0,0 +1,76 @@
+//  created:    2015/04/14
+//  filename:   EmulatedController.h
+//
+//  author:     Gildas Bayard
+//              Copyright Heudiasyc UMR UTC/CNRS 7253
+//
+//  version:    $Id: $
+//
+//  purpose:    class that emulate a remote control.
+//              Typical use case: run a demo without any reliable communication channel
+//
+//
+/*********************************************************************/
+
+#ifndef EMULATEDCONTROLLER_H
+#define EMULATEDCONTROLLER_H
+
+#include <TargetController.h>
+#include <list>
+
+namespace flair {
+    namespace core {
+        class FrameworkManager;
+        class cvmatrix;
+    }
+    namespace gui {
+        class Tab;
+        class TabWidget;
+        class DataPlot1D;
+    }
+}
+
+namespace flair { namespace sensor {
+    /*! \class EmulatedController
+    *
+    * \brief Emulated remote control
+    *
+    */
+    class EmulatedController : public TargetController {
+    public:
+        EmulatedController(const core::FrameworkManager* parent,std::string name,uint8_t priority=0);
+        ~EmulatedController();
+        enum class ButtonType : uint16_t {
+            start=0x0001,select=0x0002,square=0x0004,triangle=0x0008,
+            circle=0x0010,cross=0x0020,left1=0x0040,left2=0x0080,
+            left3=0x0100,right1=0x0200,right2=0x0400,right3=0x0800,
+            up=0x1000,down=0x2000,left=0x4000,right=0x8000
+        };
+        void AddStep(unsigned int durationMs,std::string description,uint16_t buttonPressed, float leftAxisX, float leftAxisY, float rightAxisX, float rightAxisY);
+    protected :
+        bool IsConnected() const;
+        //controller state stuff
+        bool ProcessMessage(core::Message *msg);
+        bool IsDataFrameReady();
+        void AcquireAxisData(core::cvmatrix &axis); //responsible for getting the axis data from the hardware
+        void AcquireButtonData(core::cvmatrix &button); //responsible for getting the button data from the hardware
+        bool ControllerInitialization();
+
+    private:
+        enum class DataType { axis,button };
+        void ComputeControllerData(DataType dataType, core::cvmatrix &data);
+        template<typename T> void fillVectorNoMutex(core::cvmatrix &vector,T data[],unsigned int size);
+        void fillVectorNoMutex(core::cvmatrix &destination,core::cvmatrix &source,unsigned int size);
+        struct StepData {
+            unsigned int durationMs; //milliseconds
+            core::cvmatrix *axisData;
+            core::cvmatrix *buttonData;
+            std::string description;
+            void Print();
+        };
+        std::list<StepData> steps;
+    };
+
+}}
+
+#endif // EMULATEDCONTROLLER_H
Index: trunk/lib/FlairSensorActuator/src/TargetController.cpp
===================================================================
--- trunk/lib/FlairSensorActuator/src/TargetController.cpp	(revision 16)
+++ trunk/lib/FlairSensorActuator/src/TargetController.cpp	(revision 38)
@@ -34,10 +34,10 @@
 namespace sensor {
 
-TargetController::TargetController(const FrameworkManager *parent, string name,
-                                   uint8_t priority)
-    : Thread(parent, name, priority), IODevice(parent, name) {
-  main_tab = new Tab(getFrameworkManager()->GetTabWidget(), name);
-  TabWidget *tab = new TabWidget(main_tab->NewRow(), name);
-  setup_tab = new Tab(tab, "Reglages");
+TargetController::TargetController(const FrameworkManager* parent,string name,uint8_t priority) :
+    Thread(parent,name,priority),IODevice(parent,name) {
+    main_tab=new Tab(getFrameworkManager()->GetTabWidget(),name);
+    TabWidget* tab=new TabWidget(main_tab->NewRow(),name);
+    setup_tab=new Tab(tab,"Reglages");
+    SetPeriodMS(20);; //50Hz
 }
 
@@ -150,8 +150,6 @@
           }
         }
-      } else {
-        // Thread::Info("Debug: relax...\n");
-        usleep(20000); // 20ms
       }
+      WaitPeriod();
     }
   }
Index: trunk/lib/FlairSensorActuator/src/TargetEthController.cpp
===================================================================
--- trunk/lib/FlairSensorActuator/src/TargetEthController.cpp	(revision 16)
+++ trunk/lib/FlairSensorActuator/src/TargetEthController.cpp	(revision 38)
@@ -80,21 +80,21 @@
   bool fullDatagramReceived = false;
 
-  do {
-    received =
-        dataSocket->RecvMessage(receiveFrameBuffer + receiveCurrentPosition,
-                                bytesToReceive, TIME_NONBLOCK);
-    if (received > 0) {
-      bytesToReceive -= received;
-      if (bytesToReceive == 0) {
-        // a full datagram has been read in receiveFrameBuffer
-        fullDatagramReceived = true;
-        receiveCurrentPosition = 0;
-        // we swap the data and reception buffers to avoid copy
-        char *swapFrameBuffer = dataFrameBuffer;
-        dataFrameBuffer = receiveFrameBuffer;
-        receiveFrameBuffer = swapFrameBuffer;
-      }
-    }
-  } while (!received < 0);
+    do {
+        received=dataSocket->RecvMessage(receiveFrameBuffer+receiveCurrentPosition,bytesToReceive,TIME_NONBLOCK);
+        if (received>0) {
+            receiveCurrentPosition+=received;
+            bytesToReceive-=received;
+            if (bytesToReceive==0) {
+                //a full datagram has been read in receiveFrameBuffer
+                fullDatagramReceived=true;
+                //we swap the data and reception buffers to avoid copy
+                char *swapFrameBuffer=dataFrameBuffer;
+                dataFrameBuffer=receiveFrameBuffer;
+                receiveFrameBuffer=swapFrameBuffer;
+                receiveCurrentPosition=0;
+                bytesToReceive=dataFrameSize;
+            }
+        }
+    } while (!(received<0));
 
   return fullDatagramReceived;
