From 693f41d8a13cba951a83d58c44a18430c210dd4a Mon Sep 17 00:00:00 2001
From: Xavier Elattaoui <xavier.elattaoui@synchrotron-soleil.fr>
Date: Tue, 16 Jan 2018 16:33:37 +0000
Subject: [PATCH] Release preparation : threaded version (update device for a
 channel every second while gathering channel data every 500ms)

---
 include/ChannelData.hpp                   |  97 ++++++
 include/SocketLecroy.h                    |  28 +-
 include/Waveform.h                        | 138 ++++----
 include/WaveformMgr.hpp                   |  97 ++++++
 pom.xml                                   |   2 +-
 src/AcquireWaveformLecroy.cpp             | 387 ++++++++++++----------
 src/AcquireWaveformLecroy.h               |  47 ++-
 src/AcquireWaveformLecroyClass.cpp        |   4 +-
 src/AcquireWaveformLecroyClass.h          |   2 +-
 src/AcquireWaveformLecroyStateMachine.cpp |   4 +-
 src/ClassFactory.cpp                      |   2 +-
 src/LinuxSocketLecroy.cpp                 |  84 +++--
 src/Waveform.cpp                          | 367 ++++++++------------
 src/WaveformMgr.cpp                       | 353 ++++++++++++++++++++
 14 files changed, 1061 insertions(+), 551 deletions(-)
 create mode 100644 include/ChannelData.hpp
 create mode 100644 include/WaveformMgr.hpp
 create mode 100644 src/WaveformMgr.cpp

diff --git a/include/ChannelData.hpp b/include/ChannelData.hpp
new file mode 100644
index 0000000..9fd59c9
--- /dev/null
+++ b/include/ChannelData.hpp
@@ -0,0 +1,97 @@
+// ============================================================================
+//
+// = CONTEXT
+//    ChannelData
+//
+// = File
+//    ChannelData.hpp
+//
+// = AUTHOR
+//    X. Elattaoui Synchrotron Soleil France
+//
+// ============================================================================
+
+#ifndef _CHANNEL_DATA_H
+#define _CHANNEL_DATA_H
+
+// ============================================================================
+// DEPENDENCIES
+// ============================================================================
+#include <vector>
+#include <string>
+
+/**
+*  ChannelData class description:
+*    This class handles a specific channel data.
+*/
+
+// ============================================================================
+// class: ChannelData
+// ============================================================================
+class ChannelData 
+{
+public:
+  //- ctor ---------------------------------
+  ChannelData(std::string chName) : channel_name_(chName) 
+  {
+    reset(chName);
+  }
+  
+  //- reset : initialize members
+  void reset(std::string channelName)
+  {
+	channel_name_		= channelName;
+    trigger_time_       = "NaN";
+    wave_array_count_   = 0;
+    vertical_offset_    = 0.;
+    vertical_gain_      = 0.;
+    horizontal_offset_  = 0.;
+    horizontal_interval_= 0.;
+    nominal_bits_       = 0;
+    wave_array_1_       = 0;
+    wave_array_2_       = 0;
+    vertical_scaled_data_.clear();
+    raw_waveform_data_.clear();
+  }
+
+  //- operator=
+  ChannelData& operator=(const ChannelData& src)
+  {
+    this->channel_name_         = src.channel_name_;
+    this->trigger_time_         = src.trigger_time_;
+    this->wave_array_count_     = src.wave_array_count_;
+    this->vertical_offset_      = src.vertical_offset_;
+    this->vertical_gain_        = src.vertical_gain_;
+    this->horizontal_offset_    = src.horizontal_offset_;
+    this->horizontal_interval_  = src.horizontal_interval_;
+    this->nominal_bits_         = src.nominal_bits_;
+    this->wave_array_1_         = src.wave_array_1_;
+    this->wave_array_2_         = src.wave_array_2_;
+    this->vertical_scaled_data_ = src.vertical_scaled_data_;
+    this->raw_waveform_data_    = src.raw_waveform_data_;
+    
+    return *this;
+  }
+  
+  std::string channel_name_;
+  
+  std::string trigger_time_;
+  
+  long wave_array_count_;
+  
+  double vertical_offset_;
+  double vertical_gain_;
+  
+  double horizontal_offset_;
+  double horizontal_interval_;
+  
+  short nominal_bits_;
+  long wave_array_1_;
+  long wave_array_2_;
+  
+  std::vector < double > vertical_scaled_data_;
+  std::vector < short >  raw_waveform_data_;
+
+};
+
+#endif //- _CHANNEL_DATA_H
diff --git a/include/SocketLecroy.h b/include/SocketLecroy.h
index 83342c7..81f13c4 100644
--- a/include/SocketLecroy.h
+++ b/include/SocketLecroy.h
@@ -27,7 +27,7 @@
 #include <winsock2.h>
 #endif
 #include "SocketException.h"
-
+#include <yat/threading/Mutex.h>
 ////////////////////////////////////////////////////////////////////
 //
 //		SocketLecroy :: DEFINITION
@@ -49,11 +49,11 @@ const int SERVER_PORT	= 1861;			//- It's the same port number for all Lecroy sco
 const int EOI_FLAG		= 0x01;
 const int SRQ_FLAG		= 0x08;
 const int CLEAR_FLAG	= 0x10;
-const int LOCKOUT_FLAG= 0x20;
+const int LOCKOUT_FLAG	= 0x20;
 const int REMOTE_FLAG	= 0x40;
 const int DATA_FLAG		= 0x80;
 
-const int TCP_MINIMUM_PACKET_SIZE = 64;
+const unsigned int TCP_MINIMUM_PACKET_SIZE = 64;
 
 class SocketLecroy  
 {
@@ -62,18 +62,28 @@ private:
 	SocketLecroy();						//- just one instance of SocketLecroy must be done for all waveforms of a same Lecroy device
 	~SocketLecroy();
 
+	yat::Mutex lock_;
+	
 	static SocketLecroy* SL_instance;	//- ptr on the SocketLecroy instance
 
+	static bool sConnectedFlag;
+
 public:
 	
 	static SocketLecroy* get_instance(void);
-	static void delete_instance(SocketLecroy*);
+	static void delete_instance();
+	
+	bool is_connected() {
+	  return sConnectedFlag;
+	}
+	
+	void write_read			(char* in_buf, unsigned int in_length, char* out_buf, int* out_length, bool eoi_flag);
 	
-	void TCP_WriteDevice	(char *buf, int length,bool eoi_flag)	         throw (lecroy::SocketException);	//- send a cmd to the device
-	void TCP_ReadDevice		(char *buf, int length, int* nb_byte_received) throw (lecroy::SocketException);	//- read the device replie
-	void TCP_Connect		  (char *ip_address)			throw (lecroy::SocketException);		//- build TCP/IP connection
-	void TCP_Disconnect		(void)									throw (lecroy::SocketException);		//- disconnect the device
-	void TCP_ClearDevice	(void)									throw (lecroy::SocketException);		//- disconnect and reconnect the device
+	void TCP_WriteDevice	(char *buf, int length,bool eoi_flag)	       throw (lecroy::SocketException);	//- send a cmd to the device
+	void TCP_ReadDevice		(char *buf, unsigned int length, int* nb_byte_received) throw (lecroy::SocketException);	//- read the device replie
+	void TCP_Connect		(char *ip_address)		throw (lecroy::SocketException);		//- build TCP/IP connection
+	void TCP_Disconnect		(void)					throw (lecroy::SocketException);		//- disconnect the device
+	void TCP_ClearDevice	(void)					throw (lecroy::SocketException);		//- disconnect and reconnect the device
 
 };
 
diff --git a/include/Waveform.h b/include/Waveform.h
index 428fb0b..19afd7a 100644
--- a/include/Waveform.h
+++ b/include/Waveform.h
@@ -21,6 +21,8 @@
 
 #include <string>
 #include "WaveformException.h"
+#include "ChannelData.hpp"
+#include "SocketLecroy.h"
 
 const long MAX_WAVEFORM_DATA_LENGTH = 1500000;
 
@@ -42,52 +44,52 @@ const long MAX_WAVEFORM_DATA_LENGTH = 1500000;
 //- Structure to store the acquired data
 typedef struct
 {
-	char	descriptor_name [16];   //- descriptor name (always begin with WAVEDESC string)
-	char	template_name	[16];
-	short	comm_type;              //- 0 = BYTE ; 1 = WORD  format
-	short	comm_order;             //- 0 = HIFIRST ; 1 = LOFIRST
+  char	descriptor_name [16];   //- descriptor name (always begin with WAVEDESC string)
+  char	template_name	[16];
+  short	comm_type;              //- 0 = BYTE ; 1 = WORD  format
+  short	comm_order;             //- 0 = HIFIRST ; 1 = LOFIRST
 //- Blocks :
-	long	wave_descriptor;        //- length (in bytes) of block WAVEDESC
-	long	user_text;              //- length (in bytes) of block USERTEXT
-	long	reserved_res_desc1;			//- RESERVED
+  long	wave_descriptor;        //- length (in bytes) of block WAVEDESC
+  long	user_text;              //- length (in bytes) of block USERTEXT
+  long	reserved_res_desc1;		//- RESERVED
 //- Arrays :
-	long	trigtime_array;         //- length (in bytes) of TRIGTIME
-	long	ris_time_array;         //- length (in bytes) of RIS_TIME
-	long	res_array1;             //- RESERVED
-	long	wave_array_1;           //- length (in bytes) of 1st simple data array
-	long	wave_array_2;           //- length (in bytes) of 2nd simple data array
+  long	trigtime_array;         //- length (in bytes) of TRIGTIME
+  long	ris_time_array;         //- length (in bytes) of RIS_TIME
+  long	res_array1;             //- RESERVED
+  long	wave_array_1;           //- length (in bytes) of 1st simple data array
+  long	wave_array_2;           //- length (in bytes) of 2nd simple data array
 //- Instrument identification : NOT USED
-	char	reserved_1[48];         //- RESERVED
+  char	reserved_1[48];         //- RESERVED
 //- Waveform description and time at which the waveform was generated
-	long	wave_array_count;       //- nb of data points in the data array
-	long	points_per_screen;      //- nominal number of data points on the screen
-	long	res_first_pnt_val;      //- RESERVED
-	long	res_last_pnt_val;       //- RESERVED
-	long	first_point;            //- indicates the offset relative to the beginning of the trace buffer
-	char	reserved_2[20];         //- RESERVED
-	float	vertical_gain;          //-
-	float	vertical_offset;        //- to get floating value from raw data : V_gain * data - V_offset
-	char	reserved_3[8];          //- RESERVED
-	short	nominal_bits;           //- intrinsic presision
-	char	reserved_4[2];          //- RESERVED
-	float	horizontal_interval;    //- sampling interval for time domain waveforms
-	double	horizontal_offset;    //- trigger offset for the first sweep of the trigger, seconds between
-											             //- the trigger and the first data point
-	double	pixel_offset;         //- needed to know how to display the waveform
-	char	vertical_unit[48];      //- units of the vertical axis
-	char	horizontal_unit[48];    //- units of the horizontal axis
-	float	reserved_5;
+  long	wave_array_count;       //- nb of data points in the data array
+  long	points_per_screen;      //- nominal number of data points on the screen
+  long	res_first_pnt_val;      //- RESERVED
+  long	res_last_pnt_val;       //- RESERVED
+  long	first_point;            //- indicates the offset relative to the beginning of the trace buffer
+  char	reserved_2[20];         //- RESERVED
+  float	vertical_gain;          //-
+  float	vertical_offset;        //- to get floating value from raw data : V_gain * data - V_offset
+  char	reserved_3[8];          //- RESERVED
+  short	nominal_bits;           //- intrinsic presision
+  char	reserved_4[2];          //- RESERVED
+  float	horizontal_interval;    //- sampling interval for time domain waveforms
+  double	horizontal_offset;  //- trigger offset for the first sweep of the trigger, seconds between
+                                                        //- the trigger and the first data point
+  double	pixel_offset;       //- needed to know how to display the waveform
+  char	vertical_unit[48];      //- units of the vertical axis
+  char	horizontal_unit[48];    //- units of the horizontal axis
+  float	reserved_5;
 //- Trigger infos
-	double	trigger_time_seconds; //- time (in sec) of the trigger
-	char	trigger_time_minutes;   //- time (in min) of the trigger
-	char	trigger_time_hours;     //- time (in hours) of the trigger
-	char	trigger_time_days;      //- day of the trigger
-	char	trigger_time_months;    //- month of the trigger
-	short	trigger_time_year;      //- year of the trigger
-	short	trigger_time_unused;    //- RESERVED
-	float	acq_duration;           //- duration of the acquisition (in sec) in multi-trigger waveforms
-	char	reserved_6[30];         //- RESERVED for the moment
-	//- TODO :  timebase, ... till wavesource (from the lecroy doc).
+  double	trigger_time_seconds; //- time (in sec) of the trigger
+  char	trigger_time_minutes;   //- time (in min) of the trigger
+  char	trigger_time_hours;     //- time (in hours) of the trigger
+  char	trigger_time_days;      //- day of the trigger
+  char	trigger_time_months;    //- month of the trigger
+  short	trigger_time_year;      //- year of the trigger
+  short	trigger_time_unused;    //- RESERVED
+  float	acq_duration;           //- duration of the acquisition (in sec) in multi-trigger waveforms
+  char	reserved_6[30];         //- RESERVED for the moment
+  //- TODO :  timebase, ... till wavesource (from the lecroy doc).
 } WAVEDESC_BLOCK;
 
 //- RESTORE DEFAULT ALIGNEMENT
@@ -97,53 +99,29 @@ class WaveForm_data
 {
 private:
 
-	char ptrRawData[MAX_WAVEFORM_DATA_LENGTH];   //- ptr on the received waveform data
+  char ptrRawData[MAX_WAVEFORM_DATA_LENGTH];   //- ptr on the received waveform data
 
-	std::string	channel_name;
+  SocketLecroy*   ptr_com;
 
-	//- Waveform data :
-	short*  sh_raw_waveform_data;
-	double* vertical_scaled_waveform_data;
+  //- Waveform description :
+  WAVEDESC_BLOCK *waveBlockData;               //- ptr on the struct WAVEDESC_BLOCK
 
-	//- time of the trigger in format "Date = month, day, year ; Time = hours:minutes:seconds"
-	std::string	trigger_time_value;
+  //- time info to acquire waveform data
+  std::string time_to_get_waveformData;
 
-	//- Waveform description :
-	WAVEDESC_BLOCK *waveBlockData;               //- ptr on the struct WAVEDESC_BLOCK
-
-	//- time info to acquire waveform data
-	std::string time_to_get_waveformData;
+  void get_waveform_data (ChannelData* channelData)
+    throw (lecroy::WaveformException);         //- acquire the waveform data from the scope
 
+  void get_trigger_time_value (ChannelData* channelData);
+    
 public:
 
-	//- CTOR
-	WaveForm_data(std::string channel_name);
-	//- DTOR
-	~WaveForm_data();
-
-	//- Getters & Setters
-	std::string	get_channel_name ()
-		throw (lecroy::WaveformException);
-
-	void set_channel_name (std::string);
-
-	WAVEDESC_BLOCK *get_wavedesc_descriptor	()
-		throw (lecroy::WaveformException);
-
-	void get_waveform_data ()
-		throw (lecroy::WaveformException);         //- acquire the waveform data from the scope
-
-	short*	get_raw_waveform_data	()
-		throw (lecroy::WaveformException);         //- return the ptr on sh_raw_waveform_data
-
-	double* get_vertical_scaled_waveform_data	()
-		throw (lecroy::WaveformException);
-
-	std::string	get_trigger_time_value ();
+  //- CTOR
+  WaveForm_data(char* lecroyIpAddress);
+  //- DTOR
+  ~WaveForm_data();
 
-	std::string	get_times_to_get_waveformData () {
-		return time_to_get_waveformData;
-	}
+  void update_channel_data(ChannelData*);
 
 };
 
diff --git a/include/WaveformMgr.hpp b/include/WaveformMgr.hpp
new file mode 100644
index 0000000..a6cd474
--- /dev/null
+++ b/include/WaveformMgr.hpp
@@ -0,0 +1,97 @@
+// ============================================================================
+//
+// = CONTEXT
+//    WaveformMgr
+//
+// = File
+//    WaveformMgr.hpp
+//
+// = AUTHOR
+//    X. Elattaoui Synchrotron Soleil France
+//
+// ============================================================================
+
+#ifndef _WAVEFORM_MGR_H
+#define _WAVEFORM_MGR_H
+
+// ============================================================================
+// DEPENDENCIES
+// ============================================================================
+#include <tango.h>
+#include <string>
+#include "ChannelData.hpp"
+#include "Waveform.h"
+#include <yat4tango/DeviceTask.h>
+#include "SocketException.h"
+
+/**
+*  WaveformMgr class description:
+*    This class updates channels data.
+*/
+
+// ============================================================================
+// class: WaveformMgr
+// ============================================================================
+class WaveformMgr : public yat4tango::DeviceTask 
+{
+public:
+  //- ctor ---------------------------------
+  WaveformMgr(Tango::DeviceImpl * host_device, char* lecroyIPAddress);
+  
+  //- dtor ---------------------------------
+  ~WaveformMgr();
+  
+  //- add a channel to gather data
+  void add_channel(std::string);
+  
+  //- getters ------------------------------
+  ChannelData* get_channel_data();
+  
+  //- Lecroy direct communication
+  std::string write_read(std::string);
+  
+  //- check socket is opened
+  bool is_connected() {
+	return connected_;
+  }
+  
+  std::string get_errors() {
+	yat::AutoMutex<> guard(this->error_mutex_);
+	return errors_;
+  }
+  
+protected:
+    
+  //- process_message (implements yat4tango::DeviceTask pure virtual method)
+  virtual void process_message (yat::Message& msg) throw (Tango::DevFailed);
+  
+  //- internal mutex
+  yat::Mutex  data_mutex_;
+  yat::Mutex  error_mutex_;
+    
+private:
+  
+  //- waveform data access
+  WaveForm_data*  waveform_ptr_;
+  
+  //- channel name and its VALUEs
+  ChannelData* channel_data_;
+  
+  //- Lecroy Write Read response
+  std::string lecroy_resp_;
+  
+  //- Lecroy IP address to connect to
+  char* ipAddress_;
+  
+  //- lecroy socket connection
+  bool connected_;
+  
+  //- error handling
+  std::string errors_;
+  
+  //- Method to convert all lecroy exceptions (type Waveform or Socket exceptions) on Tango exception
+  Tango::DevFailed lecroy_to_tango_exception(const lecroy::LecroyException& de);
+  
+};
+
+#endif //- _WAVEFORM_MGR_H
diff --git a/pom.xml b/pom.xml
index 8b5d98c..b89ee77 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
 
    <groupId>fr.soleil.device</groupId>
    <artifactId>AcquireWaveformLecroy-${aol}-${mode}</artifactId>
-   <version>1.1.20-SNAPSHOT</version>
+   <version>1.2.0</version>
    <packaging>nar</packaging>
    <name>AcquireWaveformLecroy</name>
    <description>AcquireWaveformLecroy device</description>
diff --git a/src/AcquireWaveformLecroy.cpp b/src/AcquireWaveformLecroy.cpp
index 53552c5..ae47d2f 100644
--- a/src/AcquireWaveformLecroy.cpp
+++ b/src/AcquireWaveformLecroy.cpp
@@ -98,16 +98,14 @@ static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentatio
 //
 //===================================================================
 
-
 #include <AcquireWaveformLecroy.h>
 #include <AcquireWaveformLecroyClass.h>
 #include <yat/time/Timer.h>
 
-static const int MAX_RESPONSE_LENGTH = 150000;
+static const std::size_t MAX_STRING_LENGTH  = 1024;
 
 namespace AcquireWaveformLecroy_ns
 {
-
 //+----------------------------------------------------------------------------
 //
 // method :     AcquireWaveformLecroy::AcquireWaveformLecroy(string &s)
@@ -135,6 +133,7 @@ AcquireWaveformLecroy::AcquireWaveformLecroy(Tango::DeviceClass *cl,const char *
 {
   init_device();
 }
+
 //+----------------------------------------------------------------------------
 //
 // method :     AcquireWaveformLecroy::delete_device()
@@ -145,14 +144,14 @@ AcquireWaveformLecroy::AcquireWaveformLecroy(Tango::DeviceClass *cl,const char *
 void AcquireWaveformLecroy::delete_device()
 {
   //- Delete device's allocated object
-  //if (attr_rawWaveformData_read) {
-  // delete [] attr_rawWaveformData_read;
-  // attr_rawWaveformData_read = 0;
-  //}
-  //if (attr_verticalScaledData_read) {
-  // delete [] attr_verticalScaledData_read;
-  // attr_verticalScaledData_read = 0;
-  //}
+  if (attr_rawWaveformData_read) {
+   delete [] attr_rawWaveformData_read;
+   attr_rawWaveformData_read = 0;
+  }
+  if (attr_verticalScaledData_read) {
+   delete [] attr_verticalScaledData_read;
+   attr_verticalScaledData_read = 0;
+  }
   if (attr_waveArray1_read) {
     delete attr_waveArray1_read;
     attr_waveArray1_read = 0;
@@ -189,30 +188,25 @@ void AcquireWaveformLecroy::delete_device()
     delete attr_triggerTime_read;
     attr_triggerTime_read = 0;
   }
-
-  //- close the socket
-  ptr_com->TCP_Disconnect();
-
-  //- delete the SocketLecroy obj
-  SocketLecroy::delete_instance(ptr_com);
-
+  
   //- delete the Waveform_Data obj
-  if(waveform_ptr)
+  if (waveform_mgr_)
   {
-    delete waveform_ptr;
-    waveform_ptr = 0;
+    //- ask the task to quit
+     this->waveform_mgr_->exit();
+    //- !!!!! NEVER TRY TO <delete> a yat4tango::DeviceTask, it commits suicide
+    //- upon return of its main function (i.e. entry point)!!!!!!
+     this->waveform_mgr_ = 0;
   }
-  if(_deviceResponse)
-  {
-    delete [] _deviceResponse;
-    _deviceResponse = 0;
-  }
-
-  DEBUG_STREAM << "Remove the InnerAppender." << endl;
-  yat4tango::InnerAppender::release(this);
-
-  DEBUG_STREAM << "Remove the YatLogAdapter." << endl;
-  yat4tango::YatLogAdapter::release();
+  
+/*std::cout << "removing log" << std::endl;
+	// DEBUG_STREAM << "Remove the InnerAppender." << endl;
+	yat4tango::InnerAppender::release(this);
+
+	// DEBUG_STREAM << "Remove the YatLogAdapter." << endl;
+	yat4tango::YatLogAdapter::release();
+	
+std::cout << "removed log : " << log_deleted << std::endl;*/
 }
 
 //+----------------------------------------------------------------------------
@@ -228,14 +222,9 @@ void AcquireWaveformLecroy::init_device()
 
   //- create read attributes
   //--------------------------------------------
+  attr_rawWaveformData_read = new short[MAX_WAVEFORM_DATA_LENGTH];
 
-  //- The memory allocation is done in read_attr_hardware( ) method,
-  //-   because the length of the received data block is not known here
-  attr_rawWaveformData_read = 0;
-
-  //- The memory allocation is done in read_attr_hardware( ) method,
-  //-   because the length of the received data block is not known here
-  attr_verticalScaledData_read = 0;
+  attr_verticalScaledData_read =  new double[MAX_WAVEFORM_DATA_LENGTH];
 
   attr_waveArray1_read = new Tango::DevLong;
   *attr_waveArray1_read = 0;
@@ -265,59 +254,59 @@ void AcquireWaveformLecroy::init_device()
   *attr_triggerTime_read = new char[MAX_STRING_LENGTH];
   ::memset(*attr_triggerTime_read, 0, MAX_STRING_LENGTH * sizeof(char));
 
-  _deviceResponse = new char[MAX_RESPONSE_LENGTH];
-
   //- Initialise variables to default values
   //--------------------------------------------
-  ptr_com     = 0;
-  waveform_ptr= 0;
-  _deviceResponse = new char[MAX_RESPONSE_LENGTH];
-  data_value  = 0;
-  data_length = 0;
-  _is_communication_opened = false;
+  waveform_mgr_ = 0;
+  channel_data_ = 0;
+  data_length_  = 0;
 
   get_device_property();
 
-   //---------------------------------------------------------
+  //---------------------------------------------------------
   //- instanciate the log_adapter & inner_appender in order to manage logs
   //---------------------------------------------------------
-  try
+//   try
+//   {
+//     DEBUG_STREAM << "Create the YatLogAdapter in order to use logs from third party library." << endl;
+//     yat4tango::YatLogAdapter::initialize(this);
+// 
+//     DEBUG_STREAM << "Create the InnerAppender in order to manage logs." << endl;
+//     yat4tango::InnerAppender::initialize(this, 512);
+//   }
+//   catch (Tango::DevFailed& df)
+//   {
+//     ERROR_STREAM << df << endl;
+//     set_state(Tango::FAULT);
+//     set_status("OUT OF MEMORY : Failed to create log manager !");
+//     return;
+//   }
+
+  char * ipAdd = 0;
+  if (!waveform_mgr_)
   {
-      DEBUG_STREAM << "Create the YatLogAdapter in order to use logs from third party library." << endl;
-      yat4tango::YatLogAdapter::initialize(this);
-
-      DEBUG_STREAM << "Create the InnerAppender in order to manage logs." << endl;
-      yat4tango::InnerAppender::initialize(this, 512);
+	//- transform string to char*
+	std::size_t length = iPaddress.size();
+	ipAdd = new char[length+1];
+	for(std::size_t i=0; i<length; i++)
+	  ipAdd[i] = iPaddress[i];
+	ipAdd[length] = '\0';
+	//- create the waveform obj
+	waveform_mgr_ = new WaveformMgr(this, ipAdd);
   }
-  catch (Tango::DevFailed& df)
+  //- prepare task
+  if ( waveform_mgr_ )
   {
-      ERROR_STREAM << df << endl;
-      set_state(Tango::FAULT);
-      set_status("OUT OF MEMORY : Failed to create log manager !");
-      return;
+	//- add channel to monitor
+	waveform_mgr_->add_channel(channelName);
+	//- start thread (if not already started)
+	if ( !waveform_mgr_->periodic_msg_enabled() )
+	  waveform_mgr_->go();
   }
-
- //- create the com obj
-  ptr_com = SocketLecroy::get_instance();
-
-  if ( !ptr_com )
-  {
-    set_state(Tango::FAULT);
-    set_status("OUT OF MEMORY : communication link cannot be created !");
-    return;
-  }
-
-  //- create the waveform obj
-  waveform_ptr = new WaveForm_data(channelName);
-  if ( !waveform_ptr )
-  {
-    set_state(Tango::FAULT);
-    set_status("OUT OF MEMORY : objects cannot be created !");
-  }
-  else
+  //- release temporary allocation
+  if (ipAdd)
   {
-    set_state(Tango::ALARM);
-    set_status("Communication is not yet opened.");
+	delete [] ipAdd;
+	ipAdd = 0;
   }
 }
 
@@ -403,31 +392,7 @@ void AcquireWaveformLecroy::get_device_property()
 //-----------------------------------------------------------------------------
 void AcquireWaveformLecroy::always_executed_hook()
 {
-  //- init communication
-  if ( !_is_communication_opened && ptr_com )
-  {
-    try
-    {
-      ptr_com->TCP_Connect( (char*)iPaddress.c_str() );
-      _is_communication_opened = true;
-      set_state(Tango::OPEN);
-      set_status("The communication is OK.");
-    }
-    catch(const lecroy::SocketException & se)
-    {
-      _is_communication_opened = false;
-      set_state(Tango::FAULT);
-      set_status("The communication is not well opened.");
-      Tango::DevFailed df = lecroy_to_tango_exception(se);
-      FATAL_STREAM << df << std::endl;
-      Tango::Except::re_throw_exception(df,
-                                         "TCP_CONNECTION_FAILED",
-                                         "Cannot built a socket connection.",
-                                         "AcquireWaveformLecroy::init_device()",
-                                        Tango::PANIC
-                                       );
-    }
-  }
+
 }
 
 //+----------------------------------------------------------------------------
@@ -442,56 +407,51 @@ void AcquireWaveformLecroy::read_attr_hardware(vector<long> &attr_list)
   //- DEBUG_STREAM << "In read_attr_hardware for " << attr_list.size();
   //- DEBUG_STREAM << " attribute(s)" << endl;
 yat::Timer t;
-    DEBUG_STREAM << "\nREAD attr HW ENTERING ..." << std::endl;
 
-  //- Get the waveform data and description( ADC resolution, horizontal and vertical infos, data length ...)
+  //- check
+  if ( !waveform_mgr_ )
+  {
+	FATAL_STREAM << "read_attr_hardware : device initialization failed!" << std::endl;
+    Tango::Except::throw_exception("COMMUNICATION_BROKEN",
+                                   "Device initialization failed : no Waveform manager.",
+                                   "AcquireWaveformLecroy::read_attr_hardware()"
+                                   );
+  }
+  //- get waveform data 
   try
   {
-    // First do a real read on the hardware
-    //
-    waveform_ptr->get_waveform_data();
-    set_state(Tango::ON);
-    set_status("Waveform data acquired.");
-    INFO_STREAM << "\nTimes infos to get waveform data :\n" << waveform_ptr->get_times_to_get_waveformData() << std::endl;
+    channel_data_ = waveform_mgr_->get_channel_data();
+	if (channel_data_)
+	{
+	  data_length_ = channel_data_->wave_array_count_;
+	}
   }
-  catch(const lecroy::WaveformException &we)
+  catch(const lecroy::WaveformException& we)
   {
-    set_state(Tango::ALARM);
-    set_status("Failed to acquire waveform.");
+    FATAL_STREAM << "R ATTR HW -> caught Lecroy exception!" << std::endl;
     Tango::DevFailed df = lecroy_to_tango_exception(we);
     FATAL_STREAM << df << std::endl;
     Tango::Except::re_throw_exception(df,
-                                       "COMMUNICATION_BROKEN",
-                                       "Cannot call get_waveform_data.",
-                                       "AcquireWaveformLecroy::always_executed_hook()",
+                                      "COMMUNICATION_BROKEN",
+                                      "Cannot call get_waveform_data.",
+                                      "AcquireWaveformLecroy::read_attr_hardware()",
                                       Tango::ERR
-                                     );
-  }
-
-  //- get the waveform length
-  try
-  {
-    //- TODO : retirer les copies dans les attr !!!!
-    data_length = waveform_ptr->get_wavedesc_descriptor()->wave_array_count;
-    //- check data does not exceed the MAX defined :
-    if ( data_length > MAX_WAVEFORM_DATA_LENGTH )
-        data_length = MAX_WAVEFORM_DATA_LENGTH;
-    //- get waveform data
-    attr_rawWaveformData_read    = waveform_ptr->get_raw_waveform_data();
-    attr_verticalScaledData_read = waveform_ptr->get_vertical_scaled_waveform_data();
+                                      );
   }
-  catch(const lecroy::WaveformException &we)
+  catch(Tango::DevFailed& df)
   {
-    set_state(Tango::ALARM);
-    set_status("Cannot acquire the waveform data.");
-    Tango::DevFailed df = lecroy_to_tango_exception(we);
-
+    FATAL_STREAM << "R ATTR HW -> caught DevFailed exception :\n" << df << std::endl;
     Tango::Except::re_throw_exception(df,
-                                       "GET_FAILED",
-                                       "Cannot acquire the total length of the waveform data.",
-                                       "AcquireWaveformLecroy::read_attr_hardware()",
+                                      "COMMUNICATION_BROKEN",
+                                      "Failed to update channel data.",
+                                      "AcquireWaveformLecroy::read_attr_hardware()",
                                       Tango::ERR
-                                     );
+                                      );
+  }
+  catch(...)
+  {
+    FATAL_STREAM << "R ATTR HW -> caught [...] exception!" << std::endl;
+    throw;
   }
 
   INFO_STREAM << "READ_HW : all data are now updated. DONE in " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
@@ -509,11 +469,13 @@ void AcquireWaveformLecroy::read_verticalScaledData(Tango::Attribute &attr)
   //- DEBUG_STREAM << "AcquireWaveformLecroy::read_verticalScaledData(Tango::Attribute &attr) entering... "<< endl;
 yat::Timer t;
 
-  //  Add your own code here
-  attr_verticalScaledData_read = waveform_ptr->get_vertical_scaled_waveform_data();
+//   for(std::size_t idx = 0; idx < data_length_; idx++)
+//     attr_verticalScaledData_read[idx] = channel_data_->vertical_scaled_data_[idx];
+//   attr.set_value(attr_verticalScaledData_read, data_length_);
 
-  attr.set_value(attr_verticalScaledData_read, data_length);
-  INFO_STREAM << "read_verticalScaledData : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
+  if ( data_length_ )
+	attr.set_value(&channel_data_->vertical_scaled_data_[0], data_length_);
+  DEBUG_STREAM << "read_verticalScaledData : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
 }
 
 //+----------------------------------------------------------------------------
@@ -529,7 +491,7 @@ void AcquireWaveformLecroy::read_triggerTime(Tango::Attribute &attr)
 yat::Timer t;
 
   //  Add your own code here
-  std::string response = waveform_ptr->get_trigger_time_value();
+  std::string response = channel_data_->trigger_time_;
   strcpy(*attr_triggerTime_read, response.c_str());
 
   attr.set_value(attr_triggerTime_read);
@@ -549,7 +511,7 @@ void AcquireWaveformLecroy::read_verticalOffset(Tango::Attribute &attr)
 yat::Timer t;
 
   //- Add your own code here
- *attr_verticalOffset_read = waveform_ptr->get_wavedesc_descriptor()->vertical_offset;
+ *attr_verticalOffset_read = channel_data_->vertical_offset_;
 
   attr.set_value(attr_verticalOffset_read);
   DEBUG_STREAM << "read_verticalOffset : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
@@ -568,7 +530,7 @@ void AcquireWaveformLecroy::read_verticalGain(Tango::Attribute &attr)
 yat::Timer t;
 
   //- Add your own code here
- *attr_verticalGain_read = (double) (waveform_ptr->get_wavedesc_descriptor()->vertical_gain);
+ *attr_verticalGain_read = channel_data_->vertical_gain_;
 
   attr.set_value(attr_verticalGain_read);
   DEBUG_STREAM << "read_verticalGain : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
@@ -586,8 +548,9 @@ void AcquireWaveformLecroy::read_horizontalOffset(Tango::Attribute &attr)
   //- DEBUG_STREAM << "AcquireWaveformLecroy::read_horizontalOffset(Tango::Attribute &attr) entering... "<< endl;
  yat::Timer t;
 
- //- Add your own code here
-  *attr_horizontalOffset_read = waveform_ptr->get_wavedesc_descriptor()->horizontal_offset;
+  //- Add your own code here
+  *attr_horizontalOffset_read = channel_data_->horizontal_offset_;
+  
   attr.set_value(attr_horizontalOffset_read);
   DEBUG_STREAM << "read_horizontalOffset : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
 }
@@ -604,8 +567,9 @@ void AcquireWaveformLecroy::read_horizontalInterval(Tango::Attribute &attr)
   //- DEBUG_STREAM << "AcquireWaveformLecroy::read_horizontalInterval(Tango::Attribute &attr) entering... "<< endl;
  yat::Timer t;
 
- //- Add your own code here
-  *attr_horizontalInterval_read = (double) (waveform_ptr->get_wavedesc_descriptor()->horizontal_interval);
+  //- Add your own code here
+  *attr_horizontalInterval_read = channel_data_->horizontal_interval_;
+  
   attr.set_value(attr_horizontalInterval_read);
   DEBUG_STREAM << "read_horizontalInterval : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
 }
@@ -622,7 +586,8 @@ void AcquireWaveformLecroy::read_nominalBits(Tango::Attribute &attr)
   //- DEBUG_STREAM << "AcquireWaveformLecroy::read_nominalBits(Tango::Attribute &attr) entering... "<< endl;
 yat::Timer t;
   //- Add your own code here
-  *attr_nominalBits_read = waveform_ptr->get_wavedesc_descriptor()->nominal_bits;
+  *attr_nominalBits_read = channel_data_->nominal_bits_;
+  
   attr.set_value(attr_nominalBits_read);
   DEBUG_STREAM << "read_nominalBits : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
 }
@@ -639,7 +604,8 @@ void AcquireWaveformLecroy::read_waveArrayCount(Tango::Attribute &attr)
   //- DEBUG_STREAM << "AcquireWaveformLecroy::read_waveArrayCount(Tango::Attribute &attr) entering... "<< endl;
 yat::Timer t;
   //- Add your own code here
-  *attr_waveArrayCount_read = data_length;
+  *attr_waveArrayCount_read = data_length_;
+  
   attr.set_value(attr_waveArrayCount_read);
   DEBUG_STREAM << "read_waveArrayCount : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
 }
@@ -656,7 +622,8 @@ void AcquireWaveformLecroy::read_waveArray2(Tango::Attribute &attr)
   //- DEBUG_STREAM << "AcquireWaveformLecroy::read_waveArray2(Tango::Attribute &attr) entering... "<< endl;
 yat::Timer t;
   //  Add your own code here
-  *attr_waveArray2_read = waveform_ptr->get_wavedesc_descriptor()->wave_array_2;
+  *attr_waveArray2_read = channel_data_->wave_array_2_;
+  
   attr.set_value(attr_waveArray2_read);
   DEBUG_STREAM << "read_waveArray2 : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
 }
@@ -673,7 +640,8 @@ void AcquireWaveformLecroy::read_waveArray1(Tango::Attribute &attr)
   //- DEBUG_STREAM << "AcquireWaveformLecroy::read_waveArray1(Tango::Attribute &attr) entering... "<< endl;
 yat::Timer t;
   //- Add your own code here
-  *attr_waveArray1_read = waveform_ptr->get_wavedesc_descriptor()->wave_array_1;
+  *attr_waveArray1_read = channel_data_->wave_array_1_;
+  
   attr.set_value(attr_waveArray1_read);
   DEBUG_STREAM << "read_waveArray1 : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
 }
@@ -691,9 +659,13 @@ void AcquireWaveformLecroy::read_rawWaveformData(Tango::Attribute &attr)
   //- Add your own code here
   yat::Timer t;
   //- get waveform data
-  attr_rawWaveformData_read = waveform_ptr->get_raw_waveform_data();
-  attr.set_value(attr_rawWaveformData_read, data_length);
-  INFO_STREAM << "read_rawWaveformData : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
+  //-for(std::size_t idx = 0; idx < data_length_; idx++)
+  //-  attr_rawWaveformData_read[idx] = channel_data_->raw_waveform_data_[idx];
+  //-attr.set_value(attr_rawWaveformData_read, data_length_);
+  
+  if ( data_length_ )
+	attr.set_value(&channel_data_->raw_waveform_data_[0], data_length_);
+  DEBUG_STREAM << "read_rawWaveformData : " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
 }
 
 //+----------------------------------------------------------------------------
@@ -753,27 +725,82 @@ Tango::DevString AcquireWaveformLecroy::write_read(Tango::DevString argin)
   //    (chapter : Writing a TANGO DS / Exchanging data)
   //------------------------------------------------------------
   //- DEBUG_STREAM << "AcquireWaveformLecroy::write_read(): entering... !" << endl;
-
-  //  Add your own code to control device here
-  std::string cmd_to_send(argin);
-  int bytes_received = -1;
-
-  ptr_com->TCP_WriteDevice(argin, cmd_to_send.size(), true);
-
-  //- check if a response is expected (must found ? character)
-  strcpy(_deviceResponse, "No response");
-  if( cmd_to_send.find('?') != std::string::npos )
-  {
-#ifdef WIN32
-    Sleep(100); //- milliseconds
-#else
-    usleep(100000);
-#endif
-    ptr_com->TCP_ReadDevice(_deviceResponse, MAX_RESPONSE_LENGTH, &bytes_received);
-  }
-
-  return _deviceResponse;
+yat::Timer t;
+  Tango::DevString argout;
+  
+  std::string resp = waveform_mgr_->write_read(argin);
+  
+  std::size_t length = resp.size();
+
+  if ( length > MAX_STRING_LENGTH )
+	length = MAX_STRING_LENGTH;
+   
+  argout = new char[length+1];
+  ::strcpy(argout, resp.c_str());
+  
+  INFO_STREAM << "WRITE_READ DONE in " << t.elapsed_msec() << " milliseconds.\n" << std::endl;
+
+  return argout;
 }
 
+//+------------------------------------------------------------------
+/**
+ *	method:	AcquireWaveformLecroy::dev_state
+ *
+ *	description:	method to execute "State"
+ *	This command gets the device state (stored in its <i>device_state</i> data member) and returns it to the caller.
+ *
+ * @return	State Code
+ *
+ */
+//+------------------------------------------------------------------
+Tango::DevState AcquireWaveformLecroy::dev_state()
+{
+	Tango::DevState	argout = Tango::UNKNOWN;
+	DEBUG_STREAM << "AcquireWaveformLecroy::dev_state(): entering... !" << endl;
+
+	//	Add your own code to control device here
+	if ( !waveform_mgr_ )
+	{
+	  argout = Tango::FAULT;
+	  set_status("Initialization failed : no manager to gather channel data.");
+	}
+	
+	if ( !waveform_mgr_->periodic_msg_enabled() )
+	{
+	  argout = Tango::ALARM;
+	  set_status("Task is not started : cannot gather channel data.");
+	}
+	
+	if ( !waveform_mgr_->is_connected() )
+	{
+	  argout = Tango::ALARM;
+	  set_status("No socket connection with Lecroy.");
+	}
+	
+	if ( !data_length_ )
+	{
+	  argout = Tango::ALARM;
+	  set_status("Failed to gather channel data : no data.");
+	}
+	
+	if ( argout != Tango::FAULT && argout != Tango::ALARM )
+	{
+	  errors_ = waveform_mgr_->get_errors();
+	  if ( errors_.empty() )
+	  {
+		argout = Tango::ON;
+		set_status("No error(s).");
+	  }
+	  else
+	  {
+		argout = Tango::ALARM;
+		set_status(errors_.c_str());
+	  }
+	}
+	
+	set_state(argout);
+	return argout;
+}
 
 }	//	namespace
diff --git a/src/AcquireWaveformLecroy.h b/src/AcquireWaveformLecroy.h
index 3ee8b1a..b21b464 100644
--- a/src/AcquireWaveformLecroy.h
+++ b/src/AcquireWaveformLecroy.h
@@ -63,13 +63,12 @@
 #define _ACQUIREWAVEFORMLECROY_H
 
 #include <tango.h>
-#include <yat4tango/InnerAppender.h>
-#include <yat4tango/YatLogAdapter.h>
+// #include <yat4tango/InnerAppender.h>
+// #include <yat4tango/YatLogAdapter.h>
 //using namespace Tango;
-#include "SocketLecroy.h"
 #include "SocketException.h"
-#include "Waveform.h"
-#include "WaveformException.h"
+#include "WaveformMgr.hpp"
+#include "ChannelData.hpp"
 
 /**
  * @author	$Author: xavela $
@@ -78,8 +77,6 @@
 
  //	Add your own constants definitions here.
  //-----------------------------------------------
-const int MAX_STRING_LENGTH = 256;
-const int MAX_SIZE			= 150000;
 
 
 namespace AcquireWaveformLecroy_ns
@@ -129,12 +126,12 @@ public :
 		Tango::DevDouble	*attr_verticalGain_read;
 		Tango::DevDouble	*attr_horizontalOffset_read;
 		Tango::DevDouble	*attr_horizontalInterval_read;
-		Tango::DevShort	*attr_nominalBits_read;
-		Tango::DevLong	*attr_waveArrayCount_read;
-		Tango::DevLong	*attr_waveArray2_read;
-		Tango::DevLong	*attr_waveArray1_read;
+		Tango::DevShort		*attr_nominalBits_read;
+		Tango::DevLong		*attr_waveArrayCount_read;
+		Tango::DevLong		*attr_waveArray2_read;
+		Tango::DevLong		*attr_waveArray1_read;
 		Tango::DevDouble	*attr_verticalScaledData_read;
-		Tango::DevShort	*attr_rawWaveformData_read;
+		Tango::DevShort		*attr_rawWaveformData_read;
 //@}
 
 /**
@@ -192,7 +189,7 @@ public :
 /**
  * The object desctructor.
  */	
-	~AcquireWaveformLecroy() {delete_device();};
+	~AcquireWaveformLecroy() {delete_device();}
 /**
  *	will be called at device destruction or at init command.
  */
@@ -314,6 +311,12 @@ public :
  *	Execution allowed for WriteRead command.
  */
 	virtual bool is_WriteRead_allowed(const CORBA::Any &any);
+/**
+ * This command gets the device state (stored in its <i>device_state</i> data member) and returns it to the caller.
+ *	@return	State Code
+ *	@exception DevFailed
+ */
+	virtual Tango::DevState	dev_state();
 /**
  * Command to send a specific command to the Lecroy device
  *	@param	argin	command to send
@@ -331,22 +334,18 @@ public :
 	//	Here is the end of the automatic code generation part
 	//-------------------------------------------------------------	
 
-
-
 protected :	
 	//	Add your own data members here
 	//-----------------------------------------
-	SocketLecroy*	  ptr_com;
-	WaveForm_data*	waveform_ptr;
-	char*			      _deviceResponse;
-	short*			    data_value;
-	long			      data_length;
-	bool			      _is_communication_opened;
+  WaveformMgr*    waveform_mgr_;
+  ChannelData*    channel_data_;
 
-	//- Method to convert all lecroy exceptions (type Waveform or Socket exceptions) on Tango exception
-	Tango::DevFailed lecroy_to_tango_exception(const lecroy::LecroyException& de);
+  std::size_t	  data_length_;
+  
+  std::string	  errors_;
 
-	void reallocate_spectrums(long new_data_size);
+  //- Method to convert all lecroy exceptions (type Waveform or Socket exceptions) on Tango exception
+  Tango::DevFailed lecroy_to_tango_exception(const lecroy::LecroyException& de);
 };
 
 }	// namespace_ns
diff --git a/src/AcquireWaveformLecroyClass.cpp b/src/AcquireWaveformLecroyClass.cpp
index 87ff1f7..a6daa57 100644
--- a/src/AcquireWaveformLecroyClass.cpp
+++ b/src/AcquireWaveformLecroyClass.cpp
@@ -68,9 +68,9 @@ static const char *RCSfile = "$RCSfile: AcquireWaveformLecroyClass.cpp,v $";
 //=============================================================================
 
 
-#include <tango.h>
+// #include <tango.h>
 
-#include <AcquireWaveformLecroy.h>
+// #include <AcquireWaveformLecroy.h>
 #include <AcquireWaveformLecroyClass.h>
 
 
diff --git a/src/AcquireWaveformLecroyClass.h b/src/AcquireWaveformLecroyClass.h
index 11b483e..885e72c 100644
--- a/src/AcquireWaveformLecroyClass.h
+++ b/src/AcquireWaveformLecroyClass.h
@@ -56,7 +56,7 @@
 #ifndef _ACQUIREWAVEFORMLECROYCLASS_H
 #define _ACQUIREWAVEFORMLECROYCLASS_H
 
-#include <tango.h>
+// #include <tango.h>
 #include <AcquireWaveformLecroy.h>
 
 
diff --git a/src/AcquireWaveformLecroyStateMachine.cpp b/src/AcquireWaveformLecroyStateMachine.cpp
index 0920a58..9dcf749 100644
--- a/src/AcquireWaveformLecroyStateMachine.cpp
+++ b/src/AcquireWaveformLecroyStateMachine.cpp
@@ -37,8 +37,8 @@ static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentatio
 //         (c) - Software Engineering Group - ESRF
 //=============================================================================
 
-#include <tango.h>
-#include <AcquireWaveformLecroy.h>
+// #include <tango.h>
+// #include <AcquireWaveformLecroy.h>
 #include <AcquireWaveformLecroyClass.h>
 
 /*====================================================================
diff --git a/src/ClassFactory.cpp b/src/ClassFactory.cpp
index 7536c69..a12c481 100644
--- a/src/ClassFactory.cpp
+++ b/src/ClassFactory.cpp
@@ -54,7 +54,7 @@ static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentatio
 //=============================================================================
 
 
-#include <tango.h>
+// #include <tango.h>
 #include <AcquireWaveformLecroyClass.h>
 
 /**
diff --git a/src/LinuxSocketLecroy.cpp b/src/LinuxSocketLecroy.cpp
index 2a6e05c..8e948e8 100644
--- a/src/LinuxSocketLecroy.cpp
+++ b/src/LinuxSocketLecroy.cpp
@@ -40,11 +40,13 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <cstdio>
+//- perf!!!
+#include <yat/time/Timer.h>
 
 static int  hSocket;
-static int  sTimeout = 1;       //- second(s)
+static int  sTimeout = 2;       		//- second(s)
 static char sCurrentAddress[256];
-static int  sConnectedFlag = false;
+bool SocketLecroy::sConnectedFlag = false;
 
 const int CMD_BUF_LEN = 8192;
 static char   sCommandBuffer[CMD_BUF_LEN];
@@ -61,14 +63,15 @@ SocketLecroy* SocketLecroy::get_instance()
 
 }
 
-void SocketLecroy::delete_instance(SocketLecroy* SL_instance)
+void SocketLecroy::delete_instance()
 {
+// std::cout << "\t\t\tSocketLecroy::deleted_instance ... SL_instance = " << SL_instance << std::endl;
   if(SL_instance)
   {
-    delete SL_instance ;
+    delete SL_instance;
     SL_instance = 0;
   }
-
+// std::cout << "\t\t\tSocketLecroy::deleted_instance DONE -> SL_instance = " << SL_instance << std::endl;
 }
 
 //- CTOR
@@ -76,16 +79,19 @@ SocketLecroy::SocketLecroy()
 {
   sConnectedFlag=false;
 }
+
 //- DTOR
 SocketLecroy::~SocketLecroy()
 {
+// std::cout << "\t\t\tSocketLecroy::DTOR SocketLecroy ..." << std::endl;
   TCP_Disconnect();
-
+// std::cout << "\t\t\tSocketLecroy::DTOR DONE." << std::endl;
 }
 
 //- Build the connection
 void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException)
 {
+yat::Timer t;
   struct sockaddr_in serverAddr;
   int result;
   const int resp = 1;
@@ -101,14 +107,14 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException)
     return;
 
   strcpy(sCurrentAddress, ip_address);
-  tval.tv_sec = sTimeout;
+  tval.tv_sec = 1;
   tval.tv_usec = 0;
 
   //- build server socket address
   serverAddr.sin_family = AF_INET;
   serverAddr.sin_port = htons(SERVER_PORT);
 
-  if ((serverAddr.sin_addr.s_addr = inet_addr(ip_address)) == -1)
+  if ((serverAddr.sin_addr.s_addr = inet_addr(ip_address)) == INADDR_NONE)
   {
     throw lecroy::SocketException("COMMUNICATION_BROKEN ",
                                   "Bad server address.",
@@ -122,6 +128,14 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException)
                                   "Unable to create client's socket.",
                                   "SocketLecroy::TCP_Connect( ).");
   }
+  
+  //- set Timeout for read operations
+  if (setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tval, sizeof(struct timeval)) != 0)
+  {
+    throw lecroy::SocketException("COMMUNICATION_BROKEN ",
+                                  "Unable to set socket option to TCP_NODELAY.",
+                                  "SocketLecroy::TCP_Connect( ).");
+  }
 
   if (setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&resp, sizeof(resp)) != 0)
   {
@@ -158,7 +172,7 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException)
           if(errno == EALREADY) // This is the right error !
           {
             time_to_sleep.tv_sec = 0;
-            time_to_sleep.tv_nsec = 15000000L;
+            time_to_sleep.tv_nsec = 150000000L;
             nanosleep(&time_to_sleep, &time_remaining);  // Sleep for 150 ms
           }
         }// Connection is OK.
@@ -168,9 +182,8 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException)
     }// TODO : throw ; // Not the right error, so failure !
   }// Connected at first attempt !
 
-
   result = select(hSocket, NULL, &wr_set, NULL, &tval);
-  argp = 0;//-blocking mode
+  argp   = 0;	//-blocking mode
   ioctl(hSocket, FIONBIO, &argp);
   //- connect to server (scope)
   if (result < 0)
@@ -182,16 +195,21 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException)
   }
 
   sConnectedFlag = true;
+// std::cout << "\t\t\t SocketLecroy::TCP_Connect done in " << t.elapsed_msec() << " ms" << std::endl;
 }
 
 //- DisconnectFromScope: disconnect from a network device
 void SocketLecroy::TCP_Disconnect(void) throw (lecroy::SocketException)
 {
+// std::cout << "\t\t\tSocketLecroy::comm closing socket ENTREING ...." << std::endl;
   if (sConnectedFlag)
   {
+// 	std::cout << "\t\t\tSocketLecroy::comm closing socket ...." << std::endl;
     close(hSocket);
+// 	std::cout << "\t\t\tSocketLecroy::comm closed." << std::endl;
     sConnectedFlag = false;
   }
+// std::cout << "\t\t\tSocketLecroy::comm closing socket DONE ...." << std::endl;
 }
 
 //- Clear a connection
@@ -206,13 +224,23 @@ void SocketLecroy::TCP_ClearDevice(void) throw (lecroy::SocketException)
   TCP_Connect(sCurrentAddress);
 }
 
+void SocketLecroy::write_read(char* in_buf, unsigned int in_length, char* out_buf, int* out_length, bool eoi_flag)
+{
+yat::Timer t;
+   yat::AutoMutex<> guard(lock_);
+   TCP_WriteDevice(in_buf, in_length, eoi_flag);
+// std::cout << "\t\t\t SocketLecroy::write_read WRITE done in " << t.elapsed_msec() << " ms" << std::endl;
+   TCP_ReadDevice(out_buf, *out_length, out_length);
+// std::cout << "\t\t\t SocketLecroy::write_read done in " << t.elapsed_msec() << " ms" << std::endl;
+}
+	
 //- Send commands to the remote device
 void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lecroy::SocketException)
 {
   TCP_HEADER header;
   int result, bytes_more, bytes_xferd;
   char *idxPtr;
-
+// std::cout << "\t\t\t TCP_WriteDevice -> ENTERING ..." << std::endl;
   //- test connection
   if ( !sConnectedFlag )
     throw lecroy::SocketException("COMMUNICATION_BROKEN ",
@@ -230,6 +258,7 @@ void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lec
   header.reserved[2] = 0;
   header.iLength = htonl(len);
 
+// std::cout << "\t\t\t TCP_WriteDevice -> send ..." << std::endl;
   //- write the header first
   if (send(hSocket, (char *) &header, sizeof(TCP_HEADER), 0) != sizeof(TCP_HEADER))
   {
@@ -238,6 +267,7 @@ void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lec
                                   "SocketLecroy::TCP_WriteDevice( ).");
   }
 
+// std::cout << "\t\t\t TCP_WriteDevice -> sent!" << std::endl;
   bytes_more = len;
   idxPtr = buf;
   bytes_xferd = 0;
@@ -248,6 +278,7 @@ void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lec
 
     if ((result = send(hSocket, (char *) idxPtr, bytes_more, 0)) < 0)
     {
+// std::cout << "\t\t\tFATAL TCP_WriteDevice -> send ..." << std::endl;
       throw lecroy::SocketException("COMMUNICATION_BROKEN ",
                                     "Unable to send data to the server.",
                                     "SocketLecroy::TCP_WriteDevice( ).");
@@ -258,10 +289,11 @@ void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lec
     if (bytes_more <= 0)
       break;
   }
+// std::cout << "\t\t\tFATAL TCP_WriteDevice -> DONE." << std::endl;
 }
 
 //- Read the device answer
-void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (lecroy::SocketException)
+void SocketLecroy::TCP_ReadDevice(char *buf, unsigned int len, int *recv_count) throw (lecroy::SocketException)
 {
   TCP_HEADER header;
   int result;
@@ -286,8 +318,8 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le
                                   "SocketLecroy::TCP_ReadDevice( ).");
 
   FD_SET(hSocket, &rd_set);
-  tval.tv_sec = sTimeout;
-  tval.tv_usec = 0;
+  tval.tv_sec = 0;
+  tval.tv_usec = 500000L;
 
   memset(buf, 0, len);
   buf_count = 0;
@@ -298,18 +330,20 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le
     result = select(hSocket, &rd_set, NULL, NULL, &tval);
     if (result < 0)
     {
+// std::cout << "\tSocketLecroy::TCP_ReadDevice -> result < 0." << std::endl;
       TCP_ClearDevice();
       throw lecroy::SocketException("COMMUNICATION_BROKEN ",
                                     "Read Timeout.",
                                     "SocketLecroy::TCP_ReadDevice( ).");
     }
-    //- get the header info first
+
+	//- get the header info first
     accum = 0;
     while (1)
     {
       memset(&header, 0, sizeof(TCP_HEADER));
 
-      if ((result = recv(hSocket, (char *) &header + accum, sizeof(header) - accum, 0)) < 0)
+      if ((result = recv(hSocket, (char *) &header + accum, sizeof(header) - accum, 0)) <= 0)
       {
         TCP_ClearDevice();
         throw lecroy::SocketException("COMMUNICATION_BROKEN ",
@@ -322,15 +356,16 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le
         break;
     }
 
-    header.iLength = ntohl(header.iLength);
+//     header.iLength = ntohl(header.iLength);
+    unsigned int headerLength = ntohl(header.iLength);
 
     //- only read to len amount
-    if (header.iLength > space_left)
+    if (headerLength > space_left)
     {
-      header.iLength = space_left;
-      throw lecroy::SocketException("COMMUNICATION_BROKEN ",
+      headerLength = space_left;
+/*      throw lecroy::SocketException("COMMUNICATION_BROKEN ",
                                     "Read buffer size is too small.",
-                                    "SocketLecroy::TCP_ReadDevice( ).");
+                                    "SocketLecroy::TCP_ReadDevice( ).");*/
     }
 
     //- read the rest of the block
@@ -338,7 +373,7 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le
     while (1)
     {
       idxPtr = buf + (buf_count + accum);
-      bytes_more = header.iLength - accum;
+      bytes_more = headerLength - accum;
       if ((space_left-accum) < TCP_MINIMUM_PACKET_SIZE)
       {
         TCP_ClearDevice();
@@ -358,7 +393,7 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le
       }
 
       accum += result;
-      if (accum >= header.iLength)
+      if (accum >= headerLength)
         break;
       if ((accum + buf_count) >= len)
         break;
@@ -374,4 +409,3 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le
 
   *recv_count = buf_count;
 }
-
diff --git a/src/Waveform.cpp b/src/Waveform.cpp
index 366242c..6606017 100644
--- a/src/Waveform.cpp
+++ b/src/Waveform.cpp
@@ -21,261 +21,176 @@
 #include <Xstring.h>
 #include <string.h>
 #include "Waveform.h"
-#include "SocketLecroy.h"
 #include <yat/time/Timer.h>
 
 //- CTOR
-WaveForm_data::WaveForm_data(std::string ch_name)
+WaveForm_data::WaveForm_data(char* lecroyIPAdd)
+: ptr_com(0),
+  time_to_get_waveformData("")
 {
-	//- initialisation of all Waveform attributes
-	::memset (ptrRawData, 0, MAX_WAVEFORM_DATA_LENGTH);
-	channel_name = ch_name;
-	sh_raw_waveform_data = 0;
-	vertical_scaled_waveform_data = 0;
-	trigger_time_value = "Not available";
-	waveBlockData = 0;
+  //- initialisation of all Waveform attributes
+  ::memset (ptrRawData, 0, MAX_WAVEFORM_DATA_LENGTH);
+  //- struct which contains all Lecroy data
+  waveBlockData = 0;
+  //- communcation link
+  ptr_com = SocketLecroy::get_instance();
+  //- connect to Lecroy
+  ptr_com->TCP_Connect(lecroyIPAdd);
 }
+
 //- DTOR
 WaveForm_data::~WaveForm_data()
 {
-	if(sh_raw_waveform_data)
-	{
-		delete [] sh_raw_waveform_data;
-		sh_raw_waveform_data = 0;
-	}
-	if(vertical_scaled_waveform_data)
-	{
-		delete [] vertical_scaled_waveform_data;
-		vertical_scaled_waveform_data = 0;
-	}
-
-}
-
-//- Method to return the channel name
-std::string  WaveForm_data::get_channel_name( ) throw (lecroy::WaveformException)
-{
-	if( channel_name.empty() )
-		throw lecroy::WaveformException("DATA_OUT_OF_RANGE ",
-										"get_channel_name( ) failed : channel_name is not initialized.",
-										"WaveForm_data::get_channel_name( ).");
-
-	return channel_name;
+//   std::cout << "\t\tWaveForm_data::DTOR." << std::endl;
+  //- close the socket
+//   ptr_com->TCP_Disconnect();
+//   std::cout << "\t\tWaveForm_data::TCP_Disconnect DNE." << std::endl;
+  //- delete the SocketLecroy obj
+  if ( ptr_com )
+	SocketLecroy::delete_instance();
+//   std::cout << "\t\tWaveForm_data::delete_instance DNE." << std::endl;
+//   std::cout << "\t\tWaveForm_data::ptrRawData DNE => ptr_com add = " << ptr_com << std::endl;
 }
 
-//- Method to set the channel name
-void WaveForm_data::set_channel_name (std::string name)
+void WaveForm_data::update_channel_data(ChannelData* chdata)
 {
-	if( !name.empty() )
-		channel_name = name;
-}
-
-//- Method to return the ptr on the WAVEDESC struct
-WAVEDESC_BLOCK* WaveForm_data::get_wavedesc_descriptor( ) throw (lecroy::WaveformException)
-{
-	if(!waveBlockData)
-		throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ",
-										"get_waveform_data( ) method must be called before.",
-										"WaveForm_data::get_wavedesc_descriptor( ).");
-
-	return waveBlockData;
+//   yat::Timer t;
+  get_waveform_data(chdata);
+  get_trigger_time_value(chdata);
+// std::cout << "\t\tWaveForm_data::update_channel_data -> DONE in " << t.elapsed_msec() << " ms." << std::endl;
 }
 
 //- Method to return the raw data of the acquired waveform
-void WaveForm_data::get_waveform_data( ) throw (lecroy::WaveformException)
+void WaveForm_data::get_waveform_data(ChannelData* channelData ) throw (lecroy::WaveformException)
 {
 std::string	cmd("");
 char*	cmdStr = 0;
-//int	ulTrace_Size = 0;
-int		response_length=0;
 unsigned short	OFFSET_STRUCT = 0;
 std::ostringstream oss;
 
 //- FOR DEBUG : comment out Timer and STD::COUT !!
-yat::Timer t;
-double time_to_write_data;
-double time_to_read_data;
-double time_to_copy_data;
-
-oss << "WaveForm_data::get_waveform_data( ) -> ENTERING ..." << std::endl;
+// yat::Timer t;
 
-	//- init ptr WaveBlocData which point on WAVEDESC_BLOCS structure
-	waveBlockData = 0;
+//  std::cout << "\t\t\tget_waveform_data ENTERING ..." << std::endl;
 
-	//- get channel name
-	std::string ch_name("") ;
+  //- init ptr waveblocdata which point on wavedesc_blocs structure
+  waveBlockData = 0;
 
-	ch_name = get_channel_name();
-	//- prepare the cmd to get the waveform data
-	cmd = ch_name + ":WF? ALL";
-	int length = cmd.size()+1;
-	cmdStr = new(std::nothrow) char[length];
-	::strcpy(cmdStr, cmd.c_str());
+  //- get channel name
+  std::string ch_name("") ;
+  ch_name = channelData->channel_name_;
+//  std::cout << "\t\t\tget_waveform_data -> ch name = " << ch_name << std::endl;
 
-	//- send the request
-	SocketLecroy::get_instance( )->TCP_WriteDevice(cmdStr,length,true);
-	time_to_write_data = t.elapsed_msec();
-oss << "\tTime to WRITE command : " << time_to_write_data << std::endl;
-
-	//- delete cmd allocation
-	if(cmdStr)
-	{
-		delete [] cmdStr;
-		cmdStr = 0;
-	}
+  //- prepare the cmd to get the waveform data
+  cmd = ch_name + std::string(":WF? ALL");
+  std::size_t in_length = cmd.size() + 1;
+  cmdStr = new(std::nothrow) char[in_length];
+  ::strncpy(cmdStr, cmd.c_str(), in_length);
 
+  //- send the request
+// std::cout << "\t\tget_waveform_data -> write cmd..." << ptr_com << std::endl;
+  int out_length = MAX_WAVEFORM_DATA_LENGTH;
+  try
+  {
 	//- erase previsous data
-	::memset (ptrRawData, 0, MAX_WAVEFORM_DATA_LENGTH);
-
-	//- delete previous raw data
-	if(sh_raw_waveform_data)
-	{
-		delete [] sh_raw_waveform_data;
-		sh_raw_waveform_data = 0;
-	}
-
-	//- delete previous scaled data
-	if(vertical_scaled_waveform_data)
-	{
-			delete [] vertical_scaled_waveform_data;
-			vertical_scaled_waveform_data = 0;
-	}
-
-	if(!ptrRawData)
-		throw lecroy::WaveformException("OUT_OF_MEMORY",
-										"The pointer (ptrRawData) for the receive data can't be allocated before the read operation.",
-										"WaveForm_data::get_waveform_data( ).");
-
-	length = MAX_WAVEFORM_DATA_LENGTH;
-
-	//- read the response
-	try
-	{
-		SocketLecroy::get_instance( )->TCP_ReadDevice(ptrRawData,length,&response_length);
-		time_to_read_data = t.elapsed_msec() - time_to_write_data;
-oss << "\tTime to READ " << response_length << " data : " << time_to_read_data << std::endl;
-//std::cout << "\t WaveForm_data::get_waveform_data( ) -> READ DONE, respLgth = " << response_length << std::endl;
-	}
-	catch(const lecroy::WaveformException &)
-	{
-		//- XE :
-		throw lecroy::WaveformException("OPERATION_FAILED",
-										"The TCP_ReadDevice() method failed.",
-										"WaveForm_data::get_waveform_data( ).");
-	}
-
-	//- calculation of the offset of the structure (it can be 15 or 21)
-	unsigned short i = 0;
-	for(i=0; i < 22 ; i++)
-	{
-		if(ptrRawData[i] == 'W' && ptrRawData[i+1] == 'A')
-		{
-			//- the offset of the structure which contains the context of the waveform acquisition
-			OFFSET_STRUCT = i;
-//std::cout << "\t WaveForm_data::get_waveform_data( ) -> OFFSET AT = " << OFFSET_STRUCT << std::endl;
-			break;
-		}
-	}
-
-	//- test if the OFFSET_STRUCT is found
-	if(!OFFSET_STRUCT)
-		throw lecroy::WaveformException("DATA_OUT_OF_RANGE",
-					"The offset of the structure is not found.",
-					"WaveForm_data::get_waveform_data( ).");
-
-
-	//- update the struct WAVEDESC_BLOC
-	waveBlockData = (WAVEDESC_BLOCK*) (ptrRawData+OFFSET_STRUCT);
-	if(!waveBlockData)
-		throw lecroy::WaveformException("OUT_OF_MEMORY",
-										"The pointer for the receive data can't be allocated before the read operation.",
-										"WaveForm_data::get_waveform_data( ).");
-
-	//- allocate memory for the raw data
-	sh_raw_waveform_data = new(std::nothrow) short[waveBlockData->wave_array_count];
-	if(!sh_raw_waveform_data)
-		throw lecroy::WaveformException("OUT_OF_MEMORY",
-										"The pointer for the receive data can't be allocated before the read operation.",
-										"WaveForm_data::get_waveform_data( ).");
-
-	//- allocate memory for the vertical scaled data
-	vertical_scaled_waveform_data = new(std::nothrow) double[waveBlockData->wave_array_count];
-	if(!vertical_scaled_waveform_data)
-		throw lecroy::WaveformException("OUT_OF_MEMORY",
-										"The pointer for the scaled data can't be allocated before the read operation.",
-										"WaveForm_data::get_waveform_data( ).");
-
-	//- copy the data before sending them
-//std::cout << "\t WaveForm_data::get_waveform_data( ) -> DATA Lgth = " << waveBlockData->wave_array_count << std::endl;
-//std::cout << "\t WaveForm_data::get_waveform_data( ) -> descriptor idx = " << waveBlockData->wave_descriptor << std::endl;
-
-	for(size_t idx=0; idx<waveBlockData->wave_array_count ; idx++)
-	{
-		sh_raw_waveform_data[idx] =  (ptrRawData + OFFSET_STRUCT + waveBlockData->wave_descriptor)[idx];
-		//- Found in the "Remote Control Manual" : calculation of the vertical scaled data
-		vertical_scaled_waveform_data[idx] = (waveBlockData->vertical_gain * sh_raw_waveform_data[idx]) - waveBlockData->vertical_offset;
-//std::cout << "\t WaveForm_data::get_waveform_data( ) -> LOOP idx = " << idx << std::endl;
-	}
-	time_to_copy_data = t.elapsed_msec() - time_to_read_data;
-oss << "\tTime to COPY " << response_length << " data : " << time_to_copy_data << std::ends;
-
-time_to_get_waveformData = oss.str();
-//std::cout << "\t WaveForm_data::get_waveform_data( ) -> DONE in " << t.elapsed_msec() << " milliseconds." << std::endl;
-}
-
-//- return the ptr on sh_raw_waveform_data ( = the waveform data acquired)
-short* WaveForm_data::get_raw_waveform_data () throw (lecroy::WaveformException)
-{
-	if ( !sh_raw_waveform_data )
-		throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ",
-										"get_waveform_data( ) method must be called before.",
-										"WaveForm_data::get_raw_waveform_data( ).");
-
-	return sh_raw_waveform_data;
-}
-
-
-//- Method to return the scaled data of the acquired waveform
-double* WaveForm_data::get_vertical_scaled_waveform_data( ) throw (lecroy::WaveformException)
-{
-	if ( !vertical_scaled_waveform_data )
-		throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ",
-										"get_waveform_data( ) method must be called before.",
-										"WaveForm_data::get_vertical_scaled_waveform_data( ).");
-
-	return vertical_scaled_waveform_data;
+	::memset (ptrRawData, 0, out_length);
+	ptr_com->write_read(cmdStr, in_length, ptrRawData, &out_length, true);
+//    time_to_read_data = t.elapsed_msec();
+// std::cout << "\t\tWaveForm_data::Time to WRITE_READ resp lgth = " << out_length << " data : " << t.elapsed_msec() << std::endl;
+  }
+  catch(const lecroy::WaveformException &)
+  {
+    //- XE :
+    throw lecroy::WaveformException("OPERATION_FAILED",
+                                    "The TCP_ReadDevice() method failed.",
+                                    "WaveForm_data::get_waveform_data( ).");
+  }
+  
+  //- delete cmd allocation
+  if(cmdStr)
+  {
+      delete [] cmdStr;
+      cmdStr = 0;
+  }
+
+  //- calculation of the offset of the structure (it can be 15 or 21)
+  unsigned short i = 0;
+  for(i=0; i < 22 ; i++)
+  {
+    if(ptrRawData[i] == 'W' && ptrRawData[i+1] == 'A')
+    {
+      //- the offset of the structure which contains the context of the waveform acquisition
+      OFFSET_STRUCT = i;
+      break;
+    }
+  }
+
+  //- test if the OFFSET_STRUCT is found
+  if(!OFFSET_STRUCT)
+      throw lecroy::WaveformException("DATA_OUT_OF_RANGE",
+									  "The offset of the structure is not found.",
+									  "WaveForm_data::get_waveform_data( ).");
+// std::cout << "\t\tOFFSET of struct = " << OFFSET_STRUCT << std::endl;
+
+  //- update the struct WAVEDESC_BLOC
+  waveBlockData = (WAVEDESC_BLOCK*) (ptrRawData+OFFSET_STRUCT);
+  if(!waveBlockData)
+      throw lecroy::WaveformException("OUT_OF_MEMORY",
+                                      "The pointer for the receive data can't be allocated before the read operation.",
+                                      "WaveForm_data::get_waveform_data( ).");
+
+  //- copy data
+  channelData->wave_array_count_    = waveBlockData->wave_array_count;
+  channelData->vertical_gain_       = waveBlockData->vertical_gain;
+  channelData->vertical_offset_     = waveBlockData->vertical_offset;
+  channelData->horizontal_interval_ = waveBlockData->horizontal_interval;
+  channelData->horizontal_offset_   = waveBlockData->horizontal_offset;
+  channelData->nominal_bits_        = waveBlockData->nominal_bits;
+  channelData->wave_array_1_        = waveBlockData->wave_array_1;
+  channelData->wave_array_2_        = waveBlockData->wave_array_2;
+  //- resize vectors
+  channelData->raw_waveform_data_.resize(waveBlockData->wave_array_count);
+  channelData->vertical_scaled_data_.resize(waveBlockData->wave_array_count);
+  //- populate vectors
+  for(long idx=0; idx < waveBlockData->wave_array_count; idx++)
+  {
+    //- raw data
+    channelData->raw_waveform_data_[idx] =  (ptrRawData + OFFSET_STRUCT + waveBlockData->wave_descriptor)[idx];
+    //- compute and copy scaled data
+    channelData->vertical_scaled_data_[idx] = (waveBlockData->vertical_gain * channelData->raw_waveform_data_[idx]) - waveBlockData->vertical_offset;
+  }
+  
+// std::cout << "\t\tWaveForm_data::get_waveform_data done in : " << t.elapsed_msec() << " ms." << std::endl;
 }
 
 //- Method to return the trigger time of the acquired waveform
-
-std::string	WaveForm_data::get_trigger_time_value ( )
+void	WaveForm_data::get_trigger_time_value (ChannelData* channelData)
 {
-	//- The format is : "Date = month, day, year ; Time = hours:minutes:seconds"
-	std::string str_seconds("");
-	std::string str_minutes("");
-	std::string str_hours  ("");
-	std::string str_days   ("");
-	std::string str_months ("");
-	std::string str_years  ("");
-
-	//- hours, min, sec with 2 digits
-	str_seconds = XString<double>::convertToString(waveBlockData->trigger_time_seconds);
-	if(waveBlockData->trigger_time_seconds<10)
-		str_seconds = "0" + str_seconds;
-
-	str_minutes = XString<int>::convertToString((int)waveBlockData->trigger_time_minutes);
-	if(waveBlockData->trigger_time_minutes<10)
-		str_minutes = "0" + str_minutes;
-
-	str_hours	= XString<int>::convertToString(waveBlockData->trigger_time_hours);
-	if(waveBlockData->trigger_time_hours<10)
-		str_hours = "0" + str_hours;
-
-	str_days	= XString<int>::convertToString(waveBlockData->trigger_time_days);
-	str_months	= XString<int>::convertToString(waveBlockData->trigger_time_months);
-	str_years	= XString<short>::convertToString(waveBlockData->trigger_time_year);
-
-	//- Construct the string Trigger Time:
-	trigger_time_value = "Date = " + str_months + "/" + str_days + "/" + str_years + " ; Time = " + str_hours + ":" + str_minutes + ":" + str_seconds;
-
-	return trigger_time_value;
+//- The format is : "Date = month, day, year ; Time = hours:minutes:seconds"
+std::string str_seconds("");
+std::string str_minutes("");
+std::string str_hours  ("");
+std::string str_days   ("");
+std::string str_months ("");
+std::string str_years  ("");
+
+  //- hours, min, sec with 2 digits
+  str_seconds = XString<double>::convertToString(waveBlockData->trigger_time_seconds);
+  if(waveBlockData->trigger_time_seconds<10)
+      str_seconds = "0" + str_seconds;
+
+  str_minutes = XString<int>::convertToString((int)waveBlockData->trigger_time_minutes);
+  if(waveBlockData->trigger_time_minutes<10)
+      str_minutes = "0" + str_minutes;
+
+  str_hours	= XString<int>::convertToString(waveBlockData->trigger_time_hours);
+  if(waveBlockData->trigger_time_hours<10)
+      str_hours = "0" + str_hours;
+
+  str_days	= XString<int>::convertToString(waveBlockData->trigger_time_days);
+  str_months= XString<int>::convertToString(waveBlockData->trigger_time_months);
+  str_years	= XString<short>::convertToString(waveBlockData->trigger_time_year);
+
+  //- Construct the string Trigger Time:
+  channelData->trigger_time_ = "Date = " + str_months + "/" + str_days + "/" + str_years + " ; Time = " + str_hours + ":" + str_minutes + ":" + str_seconds;
 }
diff --git a/src/WaveformMgr.cpp b/src/WaveformMgr.cpp
new file mode 100644
index 0000000..8552553
--- /dev/null
+++ b/src/WaveformMgr.cpp
@@ -0,0 +1,353 @@
+// ============================================================================
+//
+// = CONTEXT
+//    TANGO Project - Task to gather Lecroy channel(s) data
+//
+// = File
+//    WaveformMgr.cpp
+//
+// = AUTHOR
+//    X. Elattaoui - SOLEIL
+//
+// ============================================================================
+
+// ============================================================================
+// DEPENDENCIES
+// ============================================================================
+#include <yat/time/Time.h>
+#include "WaveformMgr.hpp"
+#include "SocketLecroy.h"		//- write/read
+
+const std::size_t MAX_RESPONSE_LENGTH = 150000;
+
+const std::size_t PERIODIC_MSG_PERIOD = 1100; //- (in ms) : time to update one channel data, it cannot be less than 1100 ms!
+
+const std::size_t MSG_TIMEOUT		  = 2000; //- in ms
+// ============================================================================
+// SOME USER DEFINED MESSAGES
+// ============================================================================
+const std::size_t WRITE_READ 		  = yat::FIRST_USER_MSG + 10;
+
+// ======================================================================
+// WaveformMgr::WaveformMgr
+// ======================================================================
+WaveformMgr::WaveformMgr (Tango::DeviceImpl* host_device, char* ipAdd)
+  : yat4tango::DeviceTask(host_device),
+    waveform_ptr_(0),
+    channel_data_(0),
+    lecroy_resp_(""),
+	ipAddress_(ipAdd),
+	connected_(false),
+	errors_("")
+{
+  //- noop
+}
+
+// ======================================================================
+// WaveformMgr::~WaveformMgr
+// ======================================================================
+WaveformMgr::~WaveformMgr (void)
+{
+//   std::cout << "\tWaveformMgr::~WaveformMgr ..." << std::endl;
+  //- noop
+//   std::cout << "\tWaveformMgr::~WaveformMgr -> DONE" << std::endl;
+}
+
+// ============================================================================
+// WaveformMgr::process_message
+// ============================================================================
+void WaveformMgr::process_message (yat::Message& _msg) throw (Tango::DevFailed)
+{
+  DEBUG_STREAM << "WaveformMgr::handle_message::receiving msg " << _msg.to_string() << std::endl;
+  
+  //- handle msg
+  switch (_msg.type())
+  {
+    //- THREAD_INIT ----------------------
+    case yat::TASK_INIT:
+    {
+      DEBUG_STREAM << "WaveformMgr::handle_message::THREAD_INIT::thread is starting up" << std::endl;   
+      //- "initialization" code goes here
+      //----------------------------------------------------
+      yat::Timer t;
+      
+	  if ( !waveform_ptr_ )
+		waveform_ptr_ = new WaveForm_data(ipAddress_);
+	  if (waveform_ptr_)
+	  {
+		//- check socket is up
+		connected_ = SocketLecroy::get_instance()->is_connected();
+		//- configure optional msg handling
+		this->enable_timeout_msg(false);
+		this->enable_periodic_msg(true);
+ 		this->set_periodic_msg_period(PERIODIC_MSG_PERIOD);
+		this->errors_.clear();
+		INFO_STREAM << "\tWaveformMgr::TASK_INIT finished in " << t.elapsed_msec() << " ms." << std::endl;
+	  }
+	  else
+	  {
+		yat::AutoMutex<> guard(this->error_mutex_);
+		errors_ = "Manager : failed to create channel structure to update data.";
+	  }
+    }
+    break;
+    //- THREAD_EXIT ----------------------
+    case yat::TASK_EXIT:
+    {
+      DEBUG_STREAM << "WaveformMgr::handle_message::THREAD_EXIT::thread is quitting" << std::endl;
+      //- "release" code goes here
+      //----------------------------------------------------
+//       yat::Timer t;
+	  if ( waveform_ptr_ )
+	  {
+		delete waveform_ptr_;
+		waveform_ptr_ = 0;
+	  }
+// 		std::cout << "\tWaveformMgr::TASK_EXIT -> waveform_ptr_ in " << t.elapsed_msec() << " ms." << std::endl;
+	  yat::AutoMutex<> guard(this->data_mutex_);
+	  if ( channel_data_ )
+	  {
+		delete channel_data_;
+		channel_data_ = 0;
+	  }
+// 		std::cout << "\tWaveformMgr::TASK_EXIT -> channel_data_" << t.elapsed_msec() << " ms." << std::endl;
+    }
+    break;
+    //- THREAD_PERIODIC ------------------
+    case yat::TASK_PERIODIC:
+    {
+      DEBUG_STREAM << "WaveformMgr::handle_message::handling THREAD_PERIODIC msg" << std::endl;   
+      //- code relative to the task's periodic job goes here
+      //----------------------------------------------------
+      yat::Timer t;
+      
+      if (waveform_ptr_)
+      {
+        try
+        {
+		  ChannelData tmp_channel(channel_data_->channel_name_);
+		  waveform_ptr_->update_channel_data(&tmp_channel);
+// std::cout << "\n\n\tWaveformMgr::TASK_PERIODIC -> update_channel_data in " << t.elapsed_msec() << " ms." << std::endl;
+		  {//- critical section
+			yat::AutoMutex<> guard(this->data_mutex_);
+			*channel_data_ = tmp_channel;
+		  }
+		  {//- no error
+			yat::AutoMutex<> guard(this->error_mutex_);
+			errors_.clear();
+		  }
+		  INFO_STREAM << "\tWaveformMgr::TASK_PERIODIC -> done in " << t.elapsed_msec() << " ms." << std::endl;
+        }
+        catch(const lecroy::WaveformException& we)
+        {
+          Tango::DevFailed df = lecroy_to_tango_exception(we);
+          FATAL_STREAM << df << std::endl;
+		  {
+			yat::AutoMutex<> guard(this->error_mutex_);
+			errors_ = "Manager : failed to update channel structure to update data.\n Caught a Lecroy exception -> check logs.";
+		  }
+//           std::cout << "[LECROY] WaveformMgr::handle_message::handling THREAD_PERIODIC -> [...]" << std::endl;            
+        }
+        catch(Tango::DevFailed& df)
+        {
+          ERROR_STREAM << "[DF] WaveformMgr::handle_message::handling THREAD_PERIODIC -> caught DF :\n" << df << std::endl;            
+		  {
+			yat::AutoMutex<> guard(this->error_mutex_);
+			errors_ = "Manager : failed to update channel structure to update data.\n Caught a DevFailed exception -> check logs.";
+		  }
+        }
+        catch(...)
+        {
+          ERROR_STREAM << "[...] WaveformMgr::handle_message::handling THREAD_PERIODIC -> [...]" << std::endl;            
+		  {
+			yat::AutoMutex<> guard(this->error_mutex_);
+			errors_ = "Manager : failed to update channel structure to update data.\n Caught a generic exception.";
+		  }
+        }
+      }
+      else
+	  {
+        ERROR_STREAM << "[ELSE] WaveformMgr::handle_message::handling THREAD_PERIODIC -> Cannot update channel data" << std::endl;
+		yat::AutoMutex<> guard(this->error_mutex_);
+		errors_ = "Failed to create channel structure to update data.";
+	  }
+      
+    }
+    break;
+	//- WRITE_READ
+	case WRITE_READ:
+    {
+      //- code relative to the task's STORE_DATA handling goes here
+      YAT_LOG("CurrentTrendFileTask::handle_message::handling WRITE_READ msg");
+// 	  std::cout << "\nCurrentTrendFileTask::handle_message::handling WRITE_READ msg" << std::endl;
+      yat::Timer t;
+	  
+	  try
+	  {
+		SocketLecroy* ptr_com = SocketLecroy::get_instance();
+		
+		std::string cmd = _msg.get_data<std::string>();
+		int bytes_received = -1;
+		char resp[MAX_RESPONSE_LENGTH];
+		char * command = 0;
+		
+		if(ptr_com)
+		{
+		  ::strcpy(resp, "No response");
+		  //- transform string to char*
+		  std::size_t length = cmd.size();
+		  command = new char[length+1];
+		  for(std::size_t i=0; i<length; i++)
+			command[i] = cmd[i];
+		  command[length] = '\0';
+
+		  ptr_com->TCP_WriteDevice(command, length, true);
+		  if( cmd.rfind('?') != std::string::npos )
+		  {
+  #ifdef WIN32
+			Sleep(10); //- milliseconds
+  #else
+			usleep(10000);
+  #endif
+			ptr_com->TCP_ReadDevice(resp, MAX_RESPONSE_LENGTH, &bytes_received);
+		  }
+		}
+		else
+		  ::strcpy(resp, "No communication with Lecroy device!");
+		
+		if (command)
+		{
+		  delete [] command;
+		  command = 0;
+		}
+
+		this->lecroy_resp_ = resp;
+		{//- no error
+		  yat::AutoMutex<> guard(this->error_mutex_);
+		  errors_.clear();
+		}
+		INFO_STREAM << "\t******WaveformMgr::WRITE_READ done in : " << t.elapsed_msec() << " ms.\n" << std::endl;
+	  }
+	  catch(const lecroy::WaveformException& we)
+	  {
+		Tango::DevFailed df = lecroy_to_tango_exception(we);
+		FATAL_STREAM << df << std::endl;
+		{
+		  yat::AutoMutex<> guard(this->error_mutex_);
+		  errors_ = "WriteRead command failed : caught a Lecroy exception -> check logs.";
+		}
+	  }
+	  catch(Tango::DevFailed& df)
+	  {
+		ERROR_STREAM << "WaveformMgr::handle_message::handling WRITE_READ -> caught DF :\n" << df << std::endl;            
+		{
+		  yat::AutoMutex<> guard(this->error_mutex_);
+		  errors_ = "WriteRead command failed : caught a DevFailed exception -> check logs.";
+		}
+	  }
+	  catch(...)
+	  {
+		ERROR_STREAM << "WaveformMgr::handle_message::handling WRITE_READ -> [...]" << std::endl;            
+		{
+		  yat::AutoMutex<> guard(this->error_mutex_);
+		  errors_ = "WriteRead command failed : caught a generic exception.";
+		}
+	  }
+    }
+    break;
+    //- THREAD_TIMEOUT -------------------
+    case yat::TASK_TIMEOUT:
+    {
+      //- code relative to the task's tmo handling goes here    
+      std::cout << "WaveformMgr::handle_message::handling THREAD_TIMEOUT msg" << std::endl;
+    }
+    break;
+    //- UNHANDLED MSG --------------------
+    default:
+      FATAL_STREAM << "WaveformMgr::handle_message::unhandled msg type received" << std::endl;
+      break;
+  }
+  
+  DEBUG_STREAM  << "WaveformMgr::handle_message::message_handler:msg "
+                << _msg.to_string()
+                << " successfully handled"
+                << std::endl;
+}
+
+// ============================================================================
+// WaveformMgr::add_channel
+// ============================================================================
+void WaveformMgr::add_channel(std::string ch_name)
+{
+  //- insert the new channel (in critical section)
+  yat::AutoMutex<> guard(this->data_mutex_);
+  if ( !channel_data_ )
+	channel_data_ = new ChannelData(ch_name);
+ 
+  //- allocate data memory
+  channel_data_->vertical_scaled_data_.reserve(MAX_WAVEFORM_DATA_LENGTH);
+  channel_data_->raw_waveform_data_.reserve(MAX_WAVEFORM_DATA_LENGTH);
+}
+
+// ============================================================================
+// WaveformMgr::get_channel_data
+// ============================================================================
+ChannelData* WaveformMgr::get_channel_data()
+{
+  yat::AutoMutex<> guard(this->data_mutex_);
+
+  return channel_data_;
+}
+
+// ============================================================================
+// WaveformMgr::write_read
+// ============================================================================
+std::string WaveformMgr::write_read(std::string cmd_to_send)
+{
+  //- in case you want to wait for the msg to be handled before returning (synchronous approach)
+  //- be sure to allocate a "waitable" message...
+  bool waitable = true;
+  yat::Message * msg = new yat::Message(WRITE_READ, MAX_USER_PRIORITY, waitable);
+
+  msg->attach_data(cmd_to_send);
+
+  this->wait_msg_handled(msg, MSG_TIMEOUT);
+  
+  return lecroy_resp_;
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : WaveformMgr::lecroy_to_tango_exception()
+//
+// description :  convert Lecroy exception to a DevFailed.
+//
+//-----------------------------------------------------------------------------
+Tango::DevFailed WaveformMgr::lecroy_to_tango_exception(const lecroy::LecroyException& de)
+{
+  Tango::DevErrorList error_list(de.errors.size());
+  error_list.length(de.errors.size());
+
+  for(size_t i = 0; i < de.errors.size(); i++)
+  {
+    error_list[i].reason = CORBA::string_dup(de.errors[i].reason.c_str());
+    error_list[i].desc   = CORBA::string_dup(de.errors[i].desc.c_str());
+    error_list[i].origin = CORBA::string_dup(de.errors[i].origin.c_str());
+
+    switch(de.errors[i].severity)
+    {
+    case lecroy::WARN:
+      error_list[i].severity = Tango::WARN;
+      break;
+    case lecroy::PANIC:
+      error_list[i].severity = Tango::PANIC;
+      break;
+    case lecroy::ERR:
+    default:
+      error_list[i].severity = Tango::ERR;
+      break;
+    }
+  }
+
+  return Tango::DevFailed(error_list);
+}
-- 
GitLab