diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/CNVConnection.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/CNVConnection.cpp
index 143a805dcbf6615657a3156c0f7b225a8d8f0803..5e3e73ab69ef945495197ea460100768ebf936c4 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/CNVConnection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/CNVConnection.cpp
@@ -24,7 +24,6 @@
 #include <silecs-communication/interface/utility/SilecsException.h>
 #include <silecs-communication/interface/utility/SilecsLog.h>
 #include <silecs-communication/interface/utility/StringUtilities.h>
-#include <silecs-communication/protocol/core/silecs.h>
 
 namespace Silecs
 {
@@ -98,6 +97,17 @@ namespace Silecs
 		return errorCode;
 	}
 
+    int CNVConnection::readMemory(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+    {
+    return readData(thePLC, address, offset, size, pBuffer);
+    }
+    int CNVConnection::writeMemory(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+    {
+    return writeData(thePLC, address, offset, size, pBuffer);
+    }
+    int CNVConnection::readInput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer) {return 0;}
+    int CNVConnection::writeOutput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer) {return 0;}
+
 	bool CNVConnection::open(PLC* thePLC)
 	{
         //Controller is reachable at this stage (ping done from doOpen)
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/CNVConnection.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/CNVConnection.h
index e161ceafe14a5bfdd54e408e64cfa23886158f51..bb3fa70c0222868064c0490b7a86595c4782f44c 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/CNVConnection.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/CNVConnection.h
@@ -78,6 +78,10 @@ namespace Silecs
 							 unsigned long offset,
 							 unsigned long size,
 							 unsigned char* buffer){return -1;};
+        int readMemory(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int writeMemory(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int readInput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int writeOutput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
 
 	private:
 		// Subscriber
@@ -100,6 +104,8 @@ namespace Silecs
          */
 		bool close(PLC* thePLC);
 
+        bool checkError(PLC* thePLC, int err, bool retry){ return false; }
+
 	};
 
 } // namespace
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp
index ccceca4bafe1849e9d57b06140f22063ad016bec..ed4960f1a1e4e01595ee1c7434bdac9bc193c516 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp
@@ -19,7 +19,6 @@
 #include <silecs-communication/interface/equipment/SilecsPLC.h>
 #include <silecs-communication/interface/communication/MBConnection.h>
 #include <silecs-communication/interface/utility/SilecsException.h>
-#include <silecs-communication/protocol/modbus/iemdb.h>
 
 //Modbus max data size definition (byte counting)
 #define MAX_WRITE_DATA_SIZE MODBUS_MAX_WRITE_REGISTERS*2
@@ -27,9 +26,8 @@
 
 namespace Silecs
 {
-
-	MBConnection::MBConnection(PLC* thePLC) : Connection(thePLC)
-	{
+    MBConnection::MBConnection(PLC* thePLC) : Connection(thePLC)
+    {
         LOG(ALLOC) << "MBConnection (create): " << thePLC->getName();
 
         //Connection use IP address to limit the naming-server accesses
@@ -37,170 +35,215 @@ namespace Silecs
         writeCtx_ = modbus_new_tcp((char *) thePLC->getIPAddress().c_str(), MODBUS_TCP_DEFAULT_PORT /*=502*/);
 
         /*TODO: To be adjusted with the next stable libmodbus release (>3.1.1)
-          which will fix the current timeout response time issue (see libmodbus forum).
+         which will fix the current timeout response time issue (see libmodbus forum).
 
-        Define Modbus response timeout
-        struct timeval response_timeout;
-        response_timeout.tv_sec = 0;
-        response_timeout.tv_usec = 10000;
+         Define Modbus response timeout
+         struct timeval response_timeout;
+         response_timeout.tv_sec = 0;
+         response_timeout.tv_usec = 10000;
 
-        modbus_set_response_timeout(readCtx_ , &response_timeout);
-        modbus_set_response_timeout(writeCtx_ , &response_timeout);
-        */
+         modbus_set_response_timeout(readCtx_ , &response_timeout);
+         modbus_set_response_timeout(writeCtx_ , &response_timeout);
+         */
 
         modbus_set_slave(readCtx_, 1);
         //modbus_set_debug(readCtx_, TRUE);
-	}
-
+    }
 
-	MBConnection::~MBConnection()
-	{
-		//Close the connection before removing resources
-		//disable(); must be done before removing resource
+    MBConnection::~MBConnection()
+    {
+        //Close the connection before removing resources
+        //disable(); must be done before removing resource
         modbus_free(writeCtx_);
         modbus_free(readCtx_);
-	}
+    }
 
-
-	bool MBConnection::open(PLC* thePLC)
-	{
+    bool MBConnection::open(PLC* thePLC)
+    {
         int readErr = modbus_connect(readCtx_);
         int writeErr = modbus_connect(writeCtx_);
         return ((readErr != -1) && (writeErr != -1));
-	}
-
+    }
 
-	bool MBConnection::close(PLC* thePLC)
-	{
+    bool MBConnection::close(PLC* thePLC)
+    {
         modbus_close(readCtx_);
         modbus_close(writeCtx_);
         return true;
-	}
-
-
-	int MBConnection::readData(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
-	{
-		//Schneider uses 16bit alignment memory. Block address is expressed in bytes, must be an even value!
-		if (address % 2) throw SilecsException(__FILE__, __LINE__, PARAM_INCORRECT_BLOCK_ADDRESS, StringUtilities::toString(address));
-
-	   /* . There is one read-channel per PLC connection. It must be protected against concurrent access.
-		* . The write-channel is independent and can be accessed in parallel.
-		* . The global action (open,close,etc.) must be protected from any concurrent access.
-		* Attention!
-		* Mutexes are defined with recursive option. It allows doOpen method re-calling readData
-		* method by executing register synchronization if required.
-		*/
-
-		//(re)connect the PLC if needed and (re)synchronize the retentive registers
-		if (doOpen(thePLC))
-		{
-			//connection is established then acquire data
-			Lock lock(readMux_);
-			//Schneider uses 16bit alignment memory. Block address is expressed in bytes (==> /2)
-			unsigned short addr = ((unsigned short)address + (unsigned short)offset)/2;
-
-			//DATA topic makes sense with RECV one
-			if (RECV & Log::topics_) LOG(DATA) << "Read data, address: %MW" << addr << ", byte-size: " << size;
-
-            int err = mbReadData(readCtx_, addr, (unsigned short)size, pBuffer);
-	        if(error)
-	        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," ModBus Error: " + string(IeGetErrorMessage(error)));
-		}
-		return 0;
-	}
-
-
-	int MBConnection::writeData(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
-	{
-		//Schneider uses 16bit alignment memory. Block address is expressed in bytes, must be an even value!
-		if (address % 2) throw SilecsException(__FILE__, __LINE__, PARAM_INCORRECT_BLOCK_ADDRESS, StringUtilities::toString(address));
-
-	   /* . There is one read-channel per PLC connection. It must be protected against concurrent access.
-		* . The write-channel is independent and can be accessed in parallel.
-		* . The global action (open,close,etc.) must be protected from any concurrent access.
-		* Attention!
-		* Mutexes are defined with recursive option. It allows doOpen method re-calling sendData
-		* method by executing register synchronization if required.
-		*/
-
-		//(re)connect the PLC if needed and (re)synchronize the retentive registers
-		if (doOpen(thePLC))
-		{
-			//connection is established then send data
-
-			Lock lock(writeMux_);
-			//Schneider uses 16bit alignment memory. Block address is expressed in bytes (==> /2)
-			unsigned short addr = ((unsigned short)address + (unsigned short)offset)/2;
-
-			//DATA topic makes sense with SEND one
-			if (SEND & Log::topics_) LOG(DATA) << "Write data, address: %MW" << addr << ", byte-size: " << size;
-
-			int error = mbWriteData(writeCtx_, (unsigned short)addr, (unsigned short)size, pBuffer);
-	        if(error)
-	        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," ModBus Error: " + string(IeGetErrorMessage(error)));
-		}
-		return 0;
-	}
-
-	  /*----------------------------------------------------------*/
-	  int MBConnection::mbWriteData(modbus_t* ctx, uint16_t start_addr, uint16_t count, uint8_t* data)
-	  {
-	      uint16_t *srcp = (uint16_t*)data;
-	      int word_count, byte_count;
-
-	      while(count)
-	      {
-	          word_count = (count > MAX_WRITE_DATA_SIZE) ? MAX_WRITE_DATA_SIZE/2 : (count/2)+(count%2);
-	          byte_count = (word_count * 2);
-
-	          if (modbus_write_registers(ctx, start_addr, word_count, srcp) != word_count)
-	          {
-	              return errno;
-	          }
-
-	          //srcp += byte_count-(count%2);
-	          srcp += word_count;
-	          start_addr += word_count;
-	          count -= (byte_count - (count%2));
-	      }
-
-	      return 0;
-	  }
-
-	  /*----------------------------------------------------------*/
-	  int MBConnection::mbReadData(modbus_t* ctx, uint16_t start_addr, uint16_t count, uint8_t* data)
-	  {
-	    uint16_t *destp = (uint16_t*)data;
-	    int word_count, byte_count;
-
-	    while(count) {
-
-	        if (count > MAX_READ_DATA_SIZE)
-	        {
-	           /*'word_count' is a word counter*/
-	           word_count = MAX_READ_DATA_SIZE/2;
-	        }
-	        else
-	        {
-	          /*'word_count' is a word counter*/
-	          word_count = (count/2) + (count%2);
-	        }
-
-	        byte_count = (word_count * 2);
-
-	        if (modbus_read_registers(ctx, start_addr, word_count, destp) != word_count)
-	        {
-	            return errno;
-	        }
-
-	        //destp += (byte_count-(count%2));
-	        destp += word_count;
-	        start_addr += word_count;
-	        count -= (byte_count - (count%2));
-	    }
-
-	    return 0;
-	  }
+    }
+
+    int MBConnection::readData(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+    {
+        int rc = 0;
+
+        //Schneider uses 16bit alignment memory. Block address is expressed in bytes, must be an even value!
+        if (address % 2) throw SilecsException(__FILE__, __LINE__, PARAM_INCORRECT_BLOCK_ADDRESS, StringUtilities::toString(address));
+
+        /* . There is one read-channel per PLC connection. It must be protected against concurrent access.
+         * . The write-channel is independent and can be accessed in parallel.
+         * . The global action (open,close,etc.) must be protected from any concurrent access.
+         * Attention!
+         * Mutexes are defined with recursive option. It allows doOpen method re-calling readData
+         * method by executing register synchronization if required.
+         */
+
+        //(re)connect the PLC if needed and (re)synchronize the retentive registers
+        if (doOpen(thePLC))
+        {
+            //connection is established then acquire data
+            readLock();
+            //Schneider uses 16bit alignment memory. Block address is expressed in bytes (==> /2)
+            unsigned short addr = ((unsigned short)address + (unsigned short)offset)/2;
+
+            //DATA topic makes sense with RECV one
+            if (RECV & Log::topics_) LOG(DATA) << "Read data, address: %MW" << addr << ", byte-size: " << size;
+
+            rc = mbReadData(readCtx_, addr, (unsigned short)size, pBuffer);
+            checkError(thePLC, rc, false);// close the connection, will try again at the next access
+            readUnlock();
+        }
+        return rc;
+    }
+
+    int MBConnection::writeData(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+    {
+        int rc = 0;
+
+        //Schneider uses 16bit alignment memory. Block address is expressed in bytes, must be an even value!
+        if (address % 2) throw SilecsException(__FILE__, __LINE__, PARAM_INCORRECT_BLOCK_ADDRESS, StringUtilities::toString(address));
+
+        /* . There is one read-channel per PLC connection. It must be protected against concurrent access.
+         * . The write-channel is independent and can be accessed in parallel.
+         * . The global action (open,close,etc.) must be protected from any concurrent access.
+         * Attention!
+         * Mutexes are defined with recursive option. It allows doOpen method re-calling sendData
+         * method by executing register synchronization if required.
+         */
+
+        //(re)connect the PLC if needed and (re)synchronize the retentive registers
+        if (doOpen(thePLC))
+        {
+            //connection is established then send data
+            writeLock();
+            //Schneider uses 16bit alignment memory. Block address is expressed in bytes (==> /2)
+            unsigned short addr = ((unsigned short)address + (unsigned short)offset)/2;
+
+            //DATA topic makes sense with SEND one
+            if (SEND & Log::topics_) LOG(DATA) << "Write data, address: %MW" << addr << ", byte-size: " << size;
+
+            rc = mbWriteData(writeCtx_, (unsigned short)addr, (unsigned short)size, pBuffer);
+            checkError(thePLC, rc, false);// close the connection, will try again at the next access
+            writeUnlock();
+        }
+        return rc;
+    }
+
+    int MBConnection::readMemory(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+    {
+        return readData(thePLC, address, offset, size, pBuffer);
+    }
+
+    int MBConnection::writeMemory(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+    {
+        return writeData(thePLC, address, offset, size, pBuffer);
+    }
+
+    int MBConnection::readInput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+    {
+        return readData(thePLC, address, offset, size, pBuffer);
+    }
+
+    int MBConnection::writeOutput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+    {
+        return writeData(thePLC, address, offset, size, pBuffer);
+    }
+
+    /*----------------------------------------------------------*/
+    int MBConnection::mbWriteData(modbus_t* ctx, uint16_t start_addr, uint16_t count, uint8_t* data)
+    {
+        uint16_t *srcp = (uint16_t*)data;
+        int word_count, byte_count;
+        int rc;
+
+        while(count)
+        {
+            word_count = (count > MAX_WRITE_DATA_SIZE) ? MAX_WRITE_DATA_SIZE/2 : (count/2)+(count%2);
+            byte_count = (word_count * 2);
+
+            if ((rc = modbus_write_registers(ctx, start_addr, word_count, srcp)) != word_count)
+            {
+                return rc;
+            }
+
+            //srcp += byte_count-(count%2);
+            srcp += word_count;
+            start_addr += word_count;
+            count -= (byte_count - (count%2));
+        }
+
+        return rc;
+    }
+
+    /*----------------------------------------------------------*/
+    int MBConnection::mbReadData(modbus_t* ctx, uint16_t start_addr, uint16_t count, uint8_t* data)
+    {
+        uint16_t *destp = (uint16_t*)data;
+        int word_count, byte_count;
+        int rc;
+
+        while(count)
+        {
+
+            if (count > MAX_READ_DATA_SIZE)
+            {
+                /*'word_count' is a word counter*/
+                word_count = MAX_READ_DATA_SIZE/2;
+            }
+            else
+            {
+                /*'word_count' is a word counter*/
+                word_count = (count/2) + (count%2);
+            }
+
+            byte_count = (word_count * 2);
+
+            if ((rc = modbus_read_registers(ctx, start_addr, word_count, destp)) != word_count)
+            {
+                return rc;
+            }
+
+            //destp += (byte_count-(count%2));
+            destp += word_count;
+            start_addr += word_count;
+            count -= (byte_count - (count%2));
+        }
+
+        return rc;
+    }
+
+//-------------------------------------------------------------------------------------------------------------------
+    bool MBConnection::checkError(PLC* thePLC, int rc, bool retry)
+    {
+
+        if (rc == -1)
+        {
+            LOG(COMM) << "Transaction failure with PLC: " << thePLC->getName() << " " << modbus_strerror(errno);
+
+            if (retry)
+            {
+                LOG(COMM) << "Try to reconnect the PLC: " << thePLC->getName();
+                if (reOpen(thePLC))
+                { // can repeat the request after the connection was successfully reopened
+                    return true;
+                }
+                // reconnection has failed again, just close the connection
+                LOG(COMM) << "Unable to reconnect the PLC: " << thePLC->getName();
+            }
+            // no retry, we just want to close (use default case)
+            doClose(thePLC, /*withLock =*/true);
+        }
+        return false;
+    }
 
 } // namespace
 #endif //MODBUS_SUPPORT_ENABLED
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.h
index 0cfc8de1fd3000af914ac843785b7623ccd5ffe1..46317ec6a920a7e32b86a4b5b32e48c98e7630f0 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.h
@@ -21,32 +21,36 @@
 
 namespace Silecs
 {
-	class PLC;
-
-	/*!
-	 * \class MBConnection
-	 * \brief Plc-communication object for specific Modbus protocol
-	 */
-	class MBConnection : public Connection
-	{
-
-	public:
-		MBConnection(PLC* thePLC);
- 		virtual ~MBConnection();
-
- 		int readData(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
- 		int writeData(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
-
-	private:
+    class PLC;
+    class Connection;
+
+    /*!
+     * \class MBConnection
+     * \brief Plc-communication object for specific Modbus protocol
+     */
+    class MBConnection : public Connection
+    {
+
+    public:
+        MBConnection(PLC* thePLC);
+        virtual ~MBConnection();
+
+        int readMemory(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int writeMemory(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int readInput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int writeOutput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+
+    private:
         modbus_t* readCtx_;
         modbus_t* writeCtx_;
-		bool open(PLC* thePLC);
-		bool close(PLC* thePLC);
-	    int mbWriteData(modbus_t* ctx, uint16_t dataAddr, uint16_t dataSize, uint8_t* dataBuffer);
-	    int mbReadData(modbus_t* ctx, uint16_t dataAddr, uint16_t dataSize, uint8_t* dataBuffer);
-	    bool checkError(PLC* thePLC, int err, bool retry);
-
-	};
+        bool open(PLC* thePLC);
+        bool close(PLC* thePLC);
+        int readData(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int writeData(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int mbWriteData(modbus_t* ctx, uint16_t dataAddr, uint16_t dataSize, uint8_t* dataBuffer);
+        int mbReadData(modbus_t* ctx, uint16_t dataAddr, uint16_t dataSize, uint8_t* dataBuffer);
+        bool checkError(PLC* thePLC, int err, bool retry);
+    };
 
 } // namespace
 
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.h
index c436c29f784da54177421450997625e4a3610b17..402f6447f9ea01976a62d00e7d1e8eb4759552cf 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.h
@@ -16,7 +16,7 @@
 #ifndef _MBHARDWARE_H_
 #define _MBHARDWARE_H_
 
-#include <silecs-communication/protocol/core/ietype.h>
+#include <silecs-communication/interface/communication/ietype.h>
 #include <modbus.h>
 
 /*----------------------------------------------------------*/
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp
index 02859a615c71b92b8135d179e44e17d4e3bf7976..065bdc619ce39392c1d7bdbfc25d3bc474bbd316 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp
@@ -20,7 +20,7 @@
 #include <silecs-communication/interface/equipment/SilecsPLC.h>
 #include <silecs-communication/interface/communication/SNAP7Connection.h>
 #include <silecs-communication/interface/utility/SilecsException.h>
-#include <silecs-communication/protocol/core/silecs.h>
+#include <silecs-communication/interface/utility/Mutex.h>
 
 namespace Silecs
 {
@@ -239,6 +239,75 @@ int SNAP7Connection::writeData(PLC* thePLC, unsigned long DBn, unsigned long off
     return err;
 }
 
+
+int SNAP7Connection::readMemory(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+{
+      int err = 0;
+  //(re)connect the PLC if needed and (re)synchronize the retentive registers
+  if (doOpen(thePLC))
+  {
+    //connection is established then acquire data
+    Lock lock(readMux_);
+    //DATA topic makes sense with RECV one
+    if (RECV & Log::topics_) LOG(DATA) << "Read data, DBn: " << DBn << ", ofs: " << offset << ", byte-size: " << size;
+
+    err = Cli_DBRead(recvClient_, (int)DBn, (int)offset, (int)size, (void *)pBuffer);
+    checkError(thePLC, err, false); // close the connection, will try again at the next access
+  }
+      return err;
+}
+int SNAP7Connection::writeMemory(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+{
+      int err = 0;
+      //(re)connect the PLC if needed and (re)synchronize the retentive registers
+      if (doOpen(thePLC))
+      {
+          //connection is established then send data
+          Lock lock(writeMux_);
+    //DATA topic makes sense with SEND one
+    if (SEND & Log::topics_) LOG(DATA) << "Write data, DBn: " << DBn << ", ofs: " << offset << ", byte-size: " << size;
+
+    err = Cli_DBWrite(sendClient_, (int)DBn, (int)offset, (int)size, (void *)pBuffer);
+    checkError(thePLC, err, false); // close the connection, will try again at the next access
+      }
+      return err;
+}
+
+int SNAP7Connection::readInput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+{
+      int err = 0;
+  //(re)connect the PLC if needed and (re)synchronize the retentive registers
+  if (doOpen(thePLC))
+  {
+    //connection is established then acquire data
+      Lock lock(readMux_);
+    //DATA topic makes sense with RECV one
+    if (RECV & Log::topics_) LOG(DATA) << "Read data, address: " << address << ", ofs: " << offset << ", byte-size: " << size;
+
+    err = Cli_EBRead(recvClient_, (int)address, (int)size, (void *)pBuffer);
+    checkError(thePLC, err, false); // close the connection, will try again at the next access
+  }
+      return err;
+}
+
+int SNAP7Connection::writeOutput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+{
+      int err = 0;
+      //(re)connect the PLC if needed and (re)synchronize the retentive registers
+      if (doOpen(thePLC))
+      {
+            //connection is established then send data
+            Lock lock(writeMux_);
+            //DATA topic makes sense with SEND one
+            if (SEND & Log::topics_) LOG(DATA) << "Write data, address: " << address << ", ofs: " << offset << ", byte-size: " << size;
+
+            Cli_ConnectTo(sendClient_, "10.11.34.77", 0, 2);
+            err = Cli_ABWrite(sendClient_, (int)address, (int)size, (void *)pBuffer);
+            checkError(thePLC, err, false); // close the connection, will try again at the next access
+      }
+      return err;
+}
+
 //-------------------------------------------------------------------------------------------------------------------
 bool SNAP7Connection::checkError(PLC* thePLC, int err, bool retry)
 {
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h
index ea2b9ced9a258af7c7ccf4588f0a5d1f664a0e84..d09d02fa3bfde7cd9d5197b819a45822bdf7650b 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h
@@ -43,6 +43,10 @@ namespace Silecs
 
  		int readData(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer);
  		int writeData(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int readMemory(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int writeMemory(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int readInput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
+        int writeOutput(PLC* thePLC, unsigned long address, unsigned long offset, unsigned long size, unsigned char* pBuffer);
 
  		//Extension Silecs methods
  		int coldRestart(PLC* thePLC);
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.h
index 87336b642d015f787a2d188b5537cfc645f3e26d..4db42be4b9940b4f5746146afa4411d1361c7f85 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.h
@@ -15,7 +15,7 @@
 #ifndef _SNAP7HARDWARE_H_
 #define _SNAP7HARDWARE_H_
 
-#include <silecs-communication/protocol/core/ietype.h>
+#include <silecs-communication/interface/communication/ietype.h>
 
 /*----------------------------------------------------------*/
 /* Time funtion
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.cpp
index 7c4eaabf368e8578107feb73c154492b15aeba31..7d560e3c79e6073c15e243197ecbbb230d7bdd07 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.cpp
@@ -20,7 +20,7 @@
 #include <silecs-communication/interface/utility/SilecsLog.h>
 #include <silecs-communication/interface/communication/SilecsConnection.h>
 #include <silecs-communication/interface/equipment/SilecsPLC.h>
-#include <silecs-communication/protocol/core/silecs.h>
+#include <silecs-communication/interface/communication/ietype.h>
 
 namespace Silecs
 {
@@ -297,38 +297,6 @@ namespace Silecs
                return -1;
            }
 
-
-	//-------------------------------------------------------------------------------------------------------------------
-	bool Connection::checkError(PLC* thePLC, int err, bool retry)
-	{
-		if (err < 0)
-		{
-			LOG(COMM) << "Transaction failure with PLC: " << thePLC->getName() << ". SILECS[" << err << "]: " << IeGetErrorMessage(err);
-
-			switch(err)
-			{
-			case IE_TIMEOUT_ERROR:
-			case IE_EPIPE_ERROR:
-			case IE_DISCONNECT_ERROR:
-				if (retry)
-				{
-					LOG(COMM) << "Try to reconnect the PLC: " << thePLC->getName();
-					if (reOpen(thePLC))
-					{   // can repeat the request after the connection was successfully reopened
-						return true;
-					}
-					// reconnection has failed again, just close the connection
-					LOG(COMM) << "Unable to reconnect the PLC: " << thePLC->getName();
-				}
-				// else { // no retry, we just want to close (use default case)
-			default:
-				doClose(thePLC, /*withLock =*/true);
-			}
-		}
-		return false; // no particular error
-	}
-
-
 	//------------------------------------------------------------------------------------------------------------------------------------------------
 	void Connection::updateStatus(PLC* thePLC)
 	{
@@ -414,20 +382,6 @@ namespace Silecs
 	  #define _DISABLE_SIGPIPE sigpipeHandler = signal(SIGPIPE, SIG_IGN)
 	  #define _ENABLE_SIGPIPE signal(SIGPIPE, sigpipeHandler)
 
-	  /*----------------------------------------------------------*/
-	  /* This is a function used to connect an host on a port.
-	   * 'ip' is the ip address string
-	   * 'port' is the port number (102 for rfc1006 server)
-	   * 'dst' is the TSAP destination string (exp: "TCP-1")
-	   * 'src' is the TSAP source string (exp: "TCP-1")
-	   * 'ts' timeout in second (1s minimum)
-	   * return a socket descriptor or <0 on error
-	   * (see constant error)
-	   *
-	   * Details:
-	   * intermediate connect_nonb() function is used to perform a non-blockant connection.
-	   * intermediate rfcPing() function is used to check if PLC is ON
-	   */
 	  int connect_nonb(int sockfd, struct sockaddr *saptr, socklen_t salen, int nsec)
 	  {
 	    int             flags, n, error;
@@ -542,14 +496,20 @@ namespace Silecs
 	  }
 
 	  /*..........................................................*/
-	  int ping(char *hostName, char *plcIP)
+	  int Connection::ping(char *hostName, char *plcIP)
 	  {
 	    struct in_addr addr;
 	    struct hostent *hp;
 	    char *ipstr = plcIP;
+	    std::string errorMsg;
+	    std::ostringstream os;
 
 	    if ((hostName == NULL) && (plcIP == NULL))
-	      return(IE_PARAM_ERROR);
+	    {
+	      os << errorMsg << "Bad parameter(s) value/format";
+	      LOG(COMM) << os.str();
+	      return -1;
+	    }
 
 	    // use hostName reference in priority else plcIP
 	    if (hostName)
@@ -563,7 +523,11 @@ namespace Silecs
 	    }
 
 	    if (ipstr == NULL)
-	    return(IE_HOST_UNKNOWN_ERROR);
+	    {
+	      os << errorMsg << "PLC hostname unknown";
+	      LOG(COMM) << os.str();
+	      return -1;
+	    }
 
 	    /*trying to connect PLC (1 second max)*/
 	    return (rfcPing(ipstr, 1));
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.h
index c87cf3adf5259e7fe0710cb7c7b734f6696a528c..62c19c7c939f0ea99a2c2fc519ebcacf04b046b4 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.h
@@ -35,23 +35,6 @@ namespace Silecs
     typedef int ChannelID;     //pointer is 32bits word
 #endif
 
-    class Lock
-    {
-
-	public:
-
-    	Lock(Mutex* mutex): mutex_(mutex)
-    	{
-    		mutex_->lock();
-    	}
-
-    	~Lock()
-    	{
-    		mutex_->unlock();
-    	}
-    	Mutex* mutex_;
-    };
-
 	class Connection
 	{
 
@@ -71,6 +54,29 @@ namespace Silecs
 							 unsigned long size,
 							 unsigned char* buffer) = 0;
 
+        virtual int readMemory(PLC* thePLC,
+                             unsigned long address,
+                         unsigned long offset,
+                         unsigned long size,
+                         unsigned char* buffer) = 0;
+
+        virtual int writeMemory(PLC* thePLC,
+                          unsigned long address,
+                          unsigned long offset,
+                          unsigned long size,
+                          unsigned char* buffer) = 0;
+
+        virtual int readInput(PLC* thePLC,
+                           unsigned long address,
+                           unsigned long offset,
+                           unsigned long size,
+                           unsigned char* buffer) = 0;
+
+        virtual int writeOutput(PLC* thePLC,
+                          unsigned long address,
+                          unsigned long offset,
+                          unsigned long size,
+                          unsigned char* buffer) = 0;
         /*!
          * \fn enable/disable
 		 * \brief The client can suspend the data transmission by disabling the connection if required.
@@ -116,16 +122,11 @@ namespace Silecs
 
         /*!
          * \fn checkError
-		 * \brief This method attempts to reconnect the PLC in case of "expected" transaction failure.
-		 * If the returned value is true the request must be repeated.
-		 * The retry flag defines whether the transaction will be repeated or not
-		 * IE_CONNECT_ERROR - TCP/IP connect() failed: IeOpen() (PLC is off or the max. number of open connection is reached)
-		 * Retry required:
-		 * IE_DISCONNECT_ERROR -  Explicit/unexpected disconnect request (when the connection has been unactive for some time)
-		 * IE_EPIPE_ERROR - TCP/IP send/recv failed (when one of the channel (get/set) has been unactive for some time or PLC is off)
-		 * IE_TIMEOUT_ERROR - PLC is connected but does not reply (In mean time the PLC gets off or data is lost)
+         * \brief This method attempts to reconnect the PLC in case of "expected" transaction failure.
+         * If the returned value is true the request must be repeated.
+         * The retry flag defines whether the transaction will be repeated or not
          */
-		virtual bool checkError(PLC* thePLC, int err, bool retry);
+        virtual bool checkError(PLC* thePLC, int err, bool retry) = 0;
 
         /*!
          * \fn updatePLCStatus
@@ -163,7 +164,21 @@ namespace Silecs
 	    /* ping function is a function used to check
 	     * if PLC is ON (~ping) before trying to connect it.
 	     */
-	    static int ping(char *hostName, char *plcIP);
+	    /*----------------------------------------------------------*/
+	    /* This is a function used to connect an host on a port.
+	     * 'ip' is the ip address string
+	     * 'port' is the port number (102 for rfc1006 server)
+	     * 'dst' is the TSAP destination string (exp: "TCP-1")
+	     * 'src' is the TSAP source string (exp: "TCP-1")
+	     * 'ts' timeout in second (1s minimum)
+	     * return a socket descriptor or <0 on error
+	     * (see constant error)
+	     *
+	     * Details:
+	     * intermediate connect_nonb() function is used to perform a non-blockant connection.
+	     * intermediate rfcPing() function is used to check if PLC is ON
+	     */
+	    int ping(char *hostName, char *plcIP);
 
 		// Communication Diagnostic & Monitoring
 		static bool isAlive_; // PLC has repliyed to the ping: true/false
diff --git a/silecs-communication-cpp/src/silecs-communication/protocol/core/ietype.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/ietype.h
similarity index 82%
rename from silecs-communication-cpp/src/silecs-communication/protocol/core/ietype.h
rename to silecs-communication-cpp/src/silecs-communication/interface/communication/ietype.h
index 6d07415e9e7dd02861deb7055664797685caefbb..d7d75ca09fad78a5c2b4efbdc8384471474d304b 100644
--- a/silecs-communication-cpp/src/silecs-communication/protocol/core/ietype.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/ietype.h
@@ -13,36 +13,37 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-
 /*
+ * Tab stop value: 2 (number of space used in place of tabs)
+ *
  * Revision : v1.0
  * Date     : 08/2003 - F.Locci
  * Objet    : original version for SCHNEIDER and SIMATIC PLCs
- * Action   : 
+ * Action   :
  *
  * Revision : v1.1
  * Date     : 10/2003 - F.Locci
  * Objet    : original version for SCHNEIDER and SIMATIC PLCs
- * Action   : 
+ * Action   :
  *
  * Revision : v1.2
  * Date     : 10/2005 - F.Locci
- * Objet    : Allow absolute offset for eveyr protocol       
- * Action   : To prevent interface modification we use 
+ * Objet    : Allow absolute offset for eveyr protocol
+ * Action   : To prevent interface modification we use
  *          : following convention:
- *		    : . negative constant to use relative offset (BLK_..)
- *		    : . positive value to use absolute offset
+ *          : . negative constant to use relative offset (BLK_..)
+ *          : . positive value to use absolute offset
  *
  * Revision : v1.3
  * Date     : 03/2007 - F.Locci
  * Objet    : Increase receive buffer size (MAX_DATA_REP_..) to 64kb
- * Action   : Increase cosntant from 21504 to 64kb to fulfill some      
+ * Action   : Increase cosntant from 21504 to 64kb to fulfill some
  *          : specific user requirement (BOFISOP class) - adjust timeout
  *
  * Revision : v1.4
  * Date     : 04/2007 - F.Locci
- * Objet    : Prevent SIEMENS PLC disconnection                       
- * Action   : Provide Keep-Alive transaction to be called periodically  
+ * Objet    : Prevent SIEMENS PLC disconnection
+ * Action   : Provide Keep-Alive transaction to be called periodically
  *
 */
 
@@ -50,7 +51,7 @@
 #define _IETYPE_H_
 
 /* ---------------------------------------------------------*/
-/* INCLUDE FILES																						*/
+/* INCLUDE FILES                                                                                        */
 /* ---------------------------------------------------------*/
 #include <stdio.h>
 #include <stdlib.h>
@@ -80,20 +81,20 @@
   allow large command for fetch/write & modbus protocol.
 */
 /*v1.1 modif. (previous one, still valid)
-  DATA_CMD_DEFER_SIZE: 8192 --> 4096 (RFC) to support deferred 
-  mode with S7-300 PLC. This modification was necessary to avoid 
+  DATA_CMD_DEFER_SIZE: 8192 --> 4096 (RFC) to support deferred
+  mode with S7-300 PLC. This modification was necessary to avoid
   S7-341 ethernet coupler crashing when receiving to big command
   defer frame.
   Size = 8192 had been choosen for S7-400 ISOLDE project but is too
-  large for S7-300 memory. 
-  Attention! This v1.1 modification double the number of 
+  large for S7-300 memory.
+  Attention! This v1.1 modification double the number of
   deferred transation with pisobeam if we recompile 'plcgenrt' process
   with this new version (normally we woudln't have to do it)
 */
-#define MAX_RFC_CMD_DEFER_SIZE   4096  /*byte - see PLC code      				 */
-#define MAX_FEW_CMD_DEFER_SIZE   16384 /*byte - no constraint on PLC side		 */
-#define MAX_MDB_CMD_DEFER_SIZE   16384 /*byte - no constraint on PLC side		 */
-#define MAX_S7_CMD_DEFER_SIZE    16384 /*byte - no constraint on PLC side		 */
+#define MAX_RFC_CMD_DEFER_SIZE   4096  /*byte - see PLC code                     */
+#define MAX_FEW_CMD_DEFER_SIZE   16384 /*byte - no constraint on PLC side        */
+#define MAX_MDB_CMD_DEFER_SIZE   16384 /*byte - no constraint on PLC side        */
+#define MAX_S7_CMD_DEFER_SIZE    16384 /*byte - no constraint on PLC side        */
 #define MAX_DATA_CMD_DEFER_SIZE  16384 /*byte - MUST BE the max 3 above constants*/
 
 #define MAX_DATA_REP_DEFER_SIZE  65536 /*v1.3, byte - see PLC code*/
@@ -102,13 +103,13 @@
 /* error constant */
 // silecs internal error ...................................
 // don't forget to modify IeGetErrorMessage(..) function
-#define RFC_SYS_ERROR			(int)-1
-#define RFC_PARAM_ERROR			(int)-2
-#define RFC_CONNECT_ERROR		(int)-3
-#define RFC_DISCONNECT_ERROR	(int)-4
-#define RFC_TIMEOUT_ERROR		(int)-5
-#define RFC_EPIPE_ERROR			(int)-6
-#define RFC_FRAME_ERROR			(int)-7
+#define RFC_SYS_ERROR           (int)-1
+#define RFC_PARAM_ERROR         (int)-2
+#define RFC_CONNECT_ERROR       (int)-3
+#define RFC_DISCONNECT_ERROR    (int)-4
+#define RFC_TIMEOUT_ERROR       (int)-5
+#define RFC_EPIPE_ERROR         (int)-6
+#define RFC_FRAME_ERROR         (int)-7
 
 #define IE_SYS_ERROR              RFC_SYS_ERROR
 #define IE_PARAM_ERROR            RFC_PARAM_ERROR
@@ -136,11 +137,11 @@
 #define IE_KEEP_ALIVE_IOCTL_ERROR   (int)-207 // PLC keep-alive transaction failed
 
 /* protocol parameters */
-#define MAX_CONNECT_TIMEOUT					2  /*s  */
-#define MAX_DATA_TIMEOUT					12 /*s  v1.3*/
+#define MAX_CONNECT_TIMEOUT                 2  /*s  */
+#define MAX_DATA_TIMEOUT                    12 /*s  v1.3*/
 
 /* ---------------------------------------------------------*/
-/* MACRO DEFINITIONS					  													  */
+/* MACRO DEFINITIONS                                                                          */
 /* ---------------------------------------------------------*/
 
 // Used to convert DT PLC format to/from DSC time format
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/core/CNVRecvAction.cpp b/silecs-communication-cpp/src/silecs-communication/interface/core/CNVRecvAction.cpp
index 57b425983494f0c96636d0c8f26704db3af60e74..175dc5540eef003fb1481e3c0be27f626e46d12a 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/core/CNVRecvAction.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/core/CNVRecvAction.cpp
@@ -81,22 +81,22 @@ namespace Silecs
                         }
                     }
 
-                    bufferLock();
+                    { //critical section
+                        Lock lock(bufferMux_);
 
-                    // read data from the buffer subscriber
-                    CNVBufferedSubscriber* handle = ((CNVInputBlock*)theBlock_)->getHandle(pDev->getLabel());
-                    errorCode = ((CNVConnection*)pConn)->readData(theBlock_->getPLC(), handle,&buffer);
+                        // read data from the buffer subscriber
+                        CNVBufferedSubscriber* handle = ((CNVInputBlock*)theBlock_)->getHandle(pDev->getLabel());
+                        errorCode = ((CNVConnection*)pConn)->readData(theBlock_->getPLC(), handle,&buffer);
 
-                    if (pConn->isConnected() && (errorCode == 0))
-                    {   //Data have just been received: get time-of-day to time-stamp the registers
-                        gettimeofday(&tod, 0);
+                        if (pConn->isConnected() && (errorCode == 0))
+                        {   //Data have just been received: get time-of-day to time-stamp the registers
+                            gettimeofday(&tod, 0);
 
-                        //Device context: Extract all the device registers from that block
-                        pDev->importRegisters(theBlock_, &buffer, tod, pContext);
+                            //Device context: Extract all the device registers from that block
+                            pDev->importRegisters(theBlock_, &buffer, tod, pContext);
+                        }
                     }
 
-                    bufferUnlock();
-
                     //Deleting Null Data object raised a CNV exception
                     if (errorCode != CNVEmptyDataError) errChk(CNVDisposeData(buffer));
 
@@ -117,22 +117,21 @@ namespace Silecs
                             }
                         }
 
-                        bufferLock();
-
-                        // read data from the buffer subscriber
-                        CNVBufferedSubscriber* handle = ((CNVInputBlock*)theBlock_)->getHandle(pDev->getLabel());
-                        errorCode = ((CNVConnection*)pConn)->readData(theBlock_->getPLC(), handle,&buffer);
+                        { //critical section
+                            Lock lock(bufferMux_);
+                            // read data from the buffer subscriber
+                            CNVBufferedSubscriber* handle = ((CNVInputBlock*)theBlock_)->getHandle(pDev->getLabel());
+                            errorCode = ((CNVConnection*)pConn)->readData(theBlock_->getPLC(), handle,&buffer);
 
-                        if (pConn->isConnected() && (errorCode == 0))
-                        {   //Data have just been received: get time-of-day to time-stamp the registers
-                            gettimeofday(&tod, 0);
+                            if (pConn->isConnected() && (errorCode == 0))
+                            {   //Data have just been received: get time-of-day to time-stamp the registers
+                                gettimeofday(&tod, 0);
 
-                            //PLC context: Extract all registers value of the current device of the PLC from that block
-                            pDev->importRegisters(theBlock_, &buffer, tod, pContext);
+                                //PLC context: Extract all registers value of the current device of the PLC from that block
+                                pDev->importRegisters(theBlock_, &buffer, tod, pContext);
+                            }
                         }
 
-                        bufferUnlock();
-
                         //Deleting Null Data object raised a CNV exception
                         if (errorCode != CNVEmptyDataError) errChk(CNVDisposeData(buffer));
 
@@ -142,8 +141,6 @@ namespace Silecs
             }
             catch (const SilecsException& ex)
             {
-                bufferUnlock();
-
                 errorCode = ex.getCode();
             }
         } //doOpen
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/core/CNVSendAction.cpp b/silecs-communication-cpp/src/silecs-communication/interface/core/CNVSendAction.cpp
index 3e22bc39e9ce70bdab9947ce9ca3967be380d4bd..7b6c53b48a7ff31f3ff7ce87694800d94d61cd87 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/core/CNVSendAction.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/core/CNVSendAction.cpp
@@ -74,25 +74,24 @@ namespace Silecs
 
                     pBuffer = (CNVData*)theBlock_->getBuffer();
 
-                    bufferLock();
-
-                    if (pConn->isEnabled())
-                    {
-                        LOG(SEND) << "SendAction (execute/ DeviceMode): " << theBlock_->getName() << ", device: " << pDev->getLabel();
-
-                        //Device context: Export all the device registers to that block
-                        pDev->exportRegisters(theBlock_, pBuffer, pContext);
-                    }
+                    { //critical section
+                        Lock lock(bufferMux_);
+                        if (pConn->isEnabled())
+                        {
+                            LOG(SEND) << "SendAction (execute/ DeviceMode): " << theBlock_->getName() << ", device: " << pDev->getLabel();
 
-                    // compute the block address
-                    std::string blockAddress = "\\\\"+pDev->getPLC()->getName()+"\\'"
-                            +pDev->getPLC()->theCluster_->getClassName()+"-"+pDev->getPLC()->theCluster_->getClassVersion()+"'\\"
-                            + pDev->getLabel()+"\\"+theBlock_->getName();
+                            //Device context: Export all the device registers to that block
+                            pDev->exportRegisters(theBlock_, pBuffer, pContext);
+                        }
 
-                    // call CNV write
-                    ((CNVConnection*)pConn)->writeData(theBlock_->getPLC(), blockAddress.c_str(),*pBuffer);
+                        // compute the block address
+                        std::string blockAddress = "\\\\"+pDev->getPLC()->getName()+"\\'"
+                                +pDev->getPLC()->theCluster_->getClassName()+"-"+pDev->getPLC()->theCluster_->getClassVersion()+"'\\"
+                                + pDev->getLabel()+"\\"+theBlock_->getName();
 
-                    bufferUnlock();
+                        // call CNV write
+                        ((CNVConnection*)pConn)->writeData(theBlock_->getPLC(), blockAddress.c_str(),*pBuffer);
+                    }
 
                     if (SEND & Log::topics_)
                     {
@@ -113,24 +112,23 @@ namespace Silecs
 
                         pBuffer = (CNVData*)theBlock_->getBuffer();
 
-                        bufferLock();
+                        { //critical section
+                            Lock lock(bufferMux_);
+                            if (pConn->isEnabled())
+                            {	LOG(SEND) << "SendAction (execute/ DeviceMode): " << theBlock_->getName() << ", device:" << pDev->getLabel();
 
-                        if (pConn->isEnabled())
-                        {	LOG(SEND) << "SendAction (execute/ DeviceMode): " << theBlock_->getName() << ", device:" << pDev->getLabel();
-
-                            //PLC context: Export all registers value of the current device of the PLC to that block
-                            pDev->exportRegisters(theBlock_, pBuffer, pContext);
-                        }
-
-                        // compute the block address
-                        std::string blockAddress = "\\\\"+pDev->getPLC()->getName()+"\\'"
-                                +pDev->getPLC()->theCluster_->getClassName()+"-"+pDev->getPLC()->theCluster_->getClassVersion()+"'\\"
-                                + pDev->getLabel()+"\\"+theBlock_->getName();
+                                //PLC context: Export all registers value of the current device of the PLC to that block
+                                pDev->exportRegisters(theBlock_, pBuffer, pContext);
+                            }
 
-                        // call CNV write
-                        ((CNVConnection*)pConn)->writeData(theBlock_->getPLC(), blockAddress.c_str(),*pBuffer);
+                            // compute the block address
+                            std::string blockAddress = "\\\\"+pDev->getPLC()->getName()+"\\'"
+                                    +pDev->getPLC()->theCluster_->getClassName()+"-"+pDev->getPLC()->theCluster_->getClassVersion()+"'\\"
+                                    + pDev->getLabel()+"\\"+theBlock_->getName();
 
-                        bufferUnlock();
+                            // call CNV write
+                            ((CNVConnection*)pConn)->writeData(theBlock_->getPLC(), blockAddress.c_str(),*pBuffer);
+                        }
 
                         if (SEND & Log::topics_)
                         { 	if (pConn->isEnabled())
@@ -142,8 +140,6 @@ namespace Silecs
             }
             catch (const SilecsException& ex)
             {
-                bufferUnlock();
-
                 //LOG(DEBUG) << "CNV SendAction (execute/ DeviceMode) failed: "<< ex.getMessage();
                 //errorCode = ex.getCode();
                 LOG(DEBUG) << "CNV SendAction (execute/ DeviceMode) failed";
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCAction.h b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCAction.h
index b3fa2806dd7415a89a54c30571a8831bfd8def14..95d874506abde701cf493aa6c5d682b27c13715d 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCAction.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCAction.h
@@ -50,10 +50,6 @@ namespace Silecs
 	protected:
         //The frame buffer update (import/export registers) and related read/write data must be done
         //in a critical section (the same buffer is used to send/recv data to all devices).
-        inline void bufferLock()      { bufferMux_->lock();   }
-        inline void bufferUnlock()    { bufferMux_->unlock(); }
-
-	private:
         Mutex* bufferMux_;
 
 	};
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCRecvAction.cpp b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCRecvAction.cpp
index 3bf18c7efb1e5399165c3dc3d9d7f6c7531fa5ab..8b34eecf8eb3d00a0a602dba2c0bcb96c533d4f5 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCRecvAction.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCRecvAction.cpp
@@ -23,7 +23,6 @@
 #include <silecs-communication/interface/equipment/PLCBlock.h>
 #include <silecs-communication/interface/core/Context.h>
 #include <silecs-communication/interface/utility/SilecsLog.h>
-#include <silecs-communication/protocol/core/silecs.h>
 
 namespace Silecs
 {
@@ -83,15 +82,43 @@ namespace Silecs
 					}
 				}
 
-                bufferLock();
-
-				errorCode = pConn->readData(
-				    theBlock_->getPLC(),
-				    usedAddress, 	            //Base address (or DBn) of the block
-					usedDeviceOffset, 		    //Device data address within the block
-					usedSize,	                //Get one device-block only
-					pBuffer						//Buffer to store the data
-				);
+                //begin critical section
+                Lock lock(bufferMux_);
+                switch (theBlock_->getAccessArea()) {
+                case Memory: {
+                  errorCode = pConn->readMemory(
+                    theBlock_->getPLC(),
+                    usedAddress,                //Base address (or DBn) of the block
+                    usedDeviceOffset,           //Device data address within the block
+                    usedSize,                   //Get one device-block only
+                    pBuffer                     //Buffer to store the data
+                    );
+                  break;
+                }
+                case Digital:
+                case Analog:
+                {
+                  errorCode = pConn->readInput(
+                    theBlock_->getPLC(),
+                    usedAddress,                //Base address (or DBn) of the block
+                    usedDeviceOffset,           //Device data address within the block
+                    usedSize,                   //Get one device-block only
+                    pBuffer                     //Buffer to store the data
+                    );
+                  break;
+                }
+                default:
+                {
+                  errorCode = pConn->readData(
+                    theBlock_->getPLC(),
+                    usedAddress,                //Base address (or DBn) of the block
+                    usedDeviceOffset,           //Device data address within the block
+                    usedSize,                   //Get one device-block only
+                    pBuffer                     //Buffer to store the data
+                    );
+                  break;
+                }
+                }
 
                 if (pConn->isConnected() && (errorCode == 0))
 				{	//Data have just been received: get time-of-day to time-stamp the registers
@@ -102,9 +129,7 @@ namespace Silecs
 
 					LOG_DELAY(RECV) << "done for block: " << theBlock_->getName();
 				}
-
-                bufferUnlock();
-
+                //end critical section
 			}
 			else
 			{
@@ -123,15 +148,43 @@ namespace Silecs
 					}
 				}
 
-                bufferLock();
-
-				errorCode = pConn->readData(
-	                theBlock_->getPLC(),
-					theBlock_->getAddress(),	//Base address (or DBn) of the block
-					0,							//Get all devices from the first one
-					((PLCBlock*)theBlock_)->getBufferSize(),	//Get blocks of all devices (full buffer size)
-					(unsigned char*)theBlock_->getBuffer()  	//Buffer to store the data (full buffer)
-				);
+                //begin critical section
+                Lock lock(bufferMux_);
+                switch (theBlock_->getAccessArea()) {
+                case Memory: {
+                  errorCode = pConn->readMemory(
+                    theBlock_->getPLC(),
+                    theBlock_->getAddress(),    //Base address (or DBn) of the block
+                    0,                          //Get all devices from the first one
+                    ((PLCBlock*)theBlock_)->getBufferSize(),    //Get blocks of all devices (full buffer size)
+                    (unsigned char*)theBlock_->getBuffer()      //Buffer to store the data (full buffer)
+                    );
+                  break;
+                }
+                case Digital:
+                case Analog:
+                {
+                  errorCode = pConn->readInput(
+                    theBlock_->getPLC(),
+                    theBlock_->getAddress(),    //Base address (or DBn) of the block
+                    0,                          //Get all devices from the first one
+                    ((PLCBlock*)theBlock_)->getBufferSize(),    //Get blocks of all devices (full buffer size)
+                    (unsigned char*)theBlock_->getBuffer()      //Buffer to store the data (full buffer)
+                    );
+                  break;
+                }
+                default:
+                {
+                  errorCode = pConn->readData(
+                    theBlock_->getPLC(),
+                    theBlock_->getAddress(),    //Base address (or DBn) of the block
+                    0,                          //Get all devices from the first one
+                    ((PLCBlock*)theBlock_)->getBufferSize(),    //Get blocks of all devices (full buffer size)
+                    (unsigned char*)theBlock_->getBuffer()      //Buffer to store the data (full buffer)
+                    );
+                  break;
+                }
+                }
 
                 if (pConn->isConnected() && (errorCode == 0))
 				{	//Data have just been received: get time-of-day to time-stamp the registers
@@ -148,16 +201,12 @@ namespace Silecs
 
 					LOG_DELAY(RECV) << "done for block: " << theBlock_->getName();
 				}
-
-                bufferUnlock();
-
 			}
 		}
 		catch (const SilecsException& ex)
 		{
-            bufferUnlock();
 			LOG(ERROR) << ex.what();
-			LOG(ERROR) << "RecvAction (execute/ BlockMode) for block " << theBlock_->getName() << " has failed";
+			LOG(ERROR) << "RecvAction (execute/ BlockMode) for block " << theBlock_->getName() << " has failed.";
 			return ex.getCode();
 		}
 		return 0;
@@ -195,15 +244,43 @@ namespace Silecs
 					}
 				}
 
-				bufferLock();
-
-				errorCode = pConn->readData(
-	                theBlock_->getPLC(),
-				    usedDeviceAddress,		//Base address (or DBn) of the device
-					usedBlockAddress,	    //Block data address within the device
-					usedSize,	            //Get one device-block only
-					(unsigned char*)theBlock_->getBuffer()  	//Buffer to store the data
-				);
+                //begin critical section
+                Lock lock(bufferMux_);
+		        switch (theBlock_->getAccessArea()) {
+		        case Memory: {
+		          errorCode = pConn->readMemory(
+		            theBlock_->getPLC(),
+		            usedDeviceAddress,      //Base address (or DBn) of the device
+		            usedBlockAddress,       //Block data address within the device
+		            usedSize,               //Get one device-block only
+		            (unsigned char*)theBlock_->getBuffer()      //Buffer to store the data
+		            );
+		          break;
+		        }
+		        case Digital:
+		        case Analog:
+		        {
+		          errorCode = pConn->readInput(
+		            theBlock_->getPLC(),
+		            usedDeviceAddress,      //Base address (or DBn) of the device
+		            usedBlockAddress,       //Block data address within the device
+		            usedSize,               //Get one device-block only
+		            (unsigned char*)theBlock_->getBuffer()      //Buffer to store the data
+		            );
+		          break;
+		        }
+		        default:
+		        {
+		          errorCode = pConn->readData(
+		            theBlock_->getPLC(),
+		            usedDeviceAddress,      //Base address (or DBn) of the device
+		            usedBlockAddress,       //Block data address within the device
+		            usedSize,               //Get one device-block only
+		            (unsigned char*)theBlock_->getBuffer()      //Buffer to store the data
+		            );
+		          break;
+		        }
+		        }
 
 				if (pConn->isConnected() && (errorCode == 0))
 				{	//Data have just been received: get time-of-day to time-stamp the registers
@@ -214,9 +291,6 @@ namespace Silecs
 
 					LOG_DELAY(RECV) << "done for block: " << theBlock_->getName();
 				}
-
-                bufferUnlock();
-
 			}
 			else
 			{
@@ -240,16 +314,42 @@ namespace Silecs
 	                    { Log(RECV).getLog() << "RecvAction (execute/ DeviceMode): device: " << pDev->getLabel() << ", block: " << theBlock_->getName();
 						}
 					}
-
-	                bufferLock();
-
-					errorCode = pConn->readData(
-		                theBlock_->getPLC(),
-					    pDev->getAddress(),		        //Base address (or DBn) of the device
-					    theBlock_->getAddress(),	    //Block data address within the device
-					    theBlock_->getMemSize(),	    //Get one device-block only
-						(unsigned char*)theBlock_->getBuffer()		//Buffer to store the data
-					);
+                    //begin critical section
+	                Lock lock(bufferMux_);
+	                switch (theBlock_->getAccessArea()) {
+	                case Memory: {
+	                  errorCode = pConn->readMemory(
+	                    theBlock_->getPLC(),
+	                    pDev->getAddress(),               //Base address (or DBn) of the device
+	                    theBlock_->getAddress(),      //Block data address within the device
+	                    theBlock_->getMemSize(),      //Get one device-block only
+	                    (unsigned char*)theBlock_->getBuffer()        //Buffer to store the data
+	                    );
+	                  break;
+	                }
+	                case Digital:
+	                case Analog:
+	                {
+	                  errorCode = pConn->readInput(
+	                    theBlock_->getPLC(),
+	                    pDev->getAddress(),               //Base address (or DBn) of the device
+	                    theBlock_->getAddress(),      //Block data address within the device
+	                    theBlock_->getMemSize(),      //Get one device-block only
+	                    (unsigned char*)theBlock_->getBuffer()        //Buffer to store the data
+	                    );
+
+	                } default:
+	                {
+	                  errorCode = pConn->readData(
+	                    theBlock_->getPLC(),
+	                    pDev->getAddress(),               //Base address (or DBn) of the device
+	                    theBlock_->getAddress(),      //Block data address within the device
+	                    theBlock_->getMemSize(),      //Get one device-block only
+	                    (unsigned char*)theBlock_->getBuffer()        //Buffer to store the data
+	                    );
+	                  break;
+	                }
+	                }
 
 	                if (pConn->isConnected() && (errorCode == 0))
 					{	//Data have just been received: get time-of-day to time-stamp the registers
@@ -260,17 +360,13 @@ namespace Silecs
 
 						LOG_DELAY(RECV) << "done for block: " << theBlock_->getName();
 					}
-
-	                bufferUnlock();
-
 				}
 			}
 		}
 		catch (const SilecsException& ex)
 		{
-            bufferUnlock();
 			LOG(ERROR) << ex.what();
-			LOG(ERROR) << "RecvAction (execute/ DeviceMode) failed";
+			LOG(ERROR) << "RecvAction (execute/ DeviceMode) failed.";
 			return ex.getCode();
 		}
 		return 0;
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCSendAction.cpp b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCSendAction.cpp
index 2c9a9f93807fed82a24920dc2f931c7afd6a6650..a1cad4081cac0c5e7ba45c1dad2096de6dc8ea7f 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCSendAction.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCSendAction.cpp
@@ -24,7 +24,6 @@
 #include <silecs-communication/interface/equipment/PLCBlock.h>
 #include <silecs-communication/interface/core/Context.h>
 #include <silecs-communication/interface/utility/SilecsLog.h>
-#include <silecs-communication/protocol/core/silecs.h>
 
 namespace Silecs
 {
@@ -75,24 +74,50 @@ namespace Silecs
                     usedDeviceOffset = theBlock_->getCustomOffset();
                 }
 
-                bufferLock();
-
-				if (pConn->isEnabled())
-                {   LOG(SEND) << "SendAction (execute/ BlockMode): device: " << pDev->getLabel() << ", block: " << theBlock_->getName();
-
-					//Device context: Export all the device registers to that block
-					pDev->exportRegisters(theBlock_, pBuffer, pContext);
-				}
-
-				errorCode = pConn->writeData(
-				    theBlock_->getPLC(),
-				    usedAddress, 	            //Base address (or DBn) of the block
-					usedDeviceOffset, 			//Device data address within the block
-					usedSize,	                //Set one device-block only
-					pBuffer 					//Buffer which contain the data
-				);
-
-                bufferUnlock();
+                { //critical section
+                    Lock lock(bufferMux_);
+                    if (pConn->isEnabled())
+                    {   LOG(SEND) << "SendAction (execute/ BlockMode): device: " << pDev->getLabel() << ", block: " << theBlock_->getName();
+
+                        //Device context: Export all the device registers to that block
+                        pDev->exportRegisters(theBlock_, pBuffer, pContext);
+                    }
+
+                    switch (theBlock_->getAccessArea()) {
+                    case Memory:
+                    {
+                      errorCode = pConn->writeMemory(
+                                theBlock_->getPLC(),
+                                usedAddress,                //Base address (or DBn) of the block
+                        usedDeviceOffset,           //Device data address within the block
+                        usedSize,                   //Set one device-block only
+                        pBuffer                     //Buffer which contain the data
+                        );
+                      break;
+                    }
+                    case Digital:
+                    case Analog:
+                    {
+                      errorCode = pConn->writeOutput(
+                                theBlock_->getPLC(),
+                                usedAddress,                //Base address (or DBn) of the block
+                        usedDeviceOffset,           //Device data address within the block
+                        usedSize,                   //Set one device-block only
+                        pBuffer                     //Buffer which contain the data
+                        );
+                      break;
+                    }
+                    default:
+                      errorCode = pConn->writeData(
+                                theBlock_->getPLC(),
+                                usedAddress,                //Base address (or DBn) of the block
+                        usedDeviceOffset,           //Device data address within the block
+                        usedSize,                   //Set one device-block only
+                        pBuffer                     //Buffer which contain the data
+                        );
+                      break;
+                    }
+                }
 
 				if (SEND & Log::topics_)
 				{ 	if (pConn->isEnabled())
@@ -106,34 +131,60 @@ namespace Silecs
                 if (theBlock_->withCustomAttributes() == true)
                     throw SilecsException(__FILE__, __LINE__, COMM_BLOCK_RESIZING_NOT_ALLOWED);
 
-                bufferLock();
-
-				if (pConn->isEnabled())
-				{	deviceVectorType::iterator pDeviceIter;
-					deviceVectorType& deviceCol = theBlock_->getPLC()->getDeviceMap();
-
-					//Cluster/PLC context: set block of all devices in one go ===========================
-					LOG(SEND) << "SendAction (execute/ BlockMode): block: " << theBlock_->getName() << ", " << deviceCol.size() << " device(s)";
-
-					//PLC context: Export all registers value of all devices of the PLC to that block
-					for(pDeviceIter = deviceCol.begin(); pDeviceIter != deviceCol.end(); ++pDeviceIter)
-					{
-						Device* pDev = pDeviceIter->second;
-						unsigned long deviceOffset = pDev->getAddress() * theBlock_->getMemSize();
-						unsigned char* pBuffer = ((unsigned char*)theBlock_->getBuffer()) + deviceOffset;
-						pDev->exportRegisters(theBlock_, pBuffer, pContext);
-					}
-				}
-
-				errorCode = pConn->writeData(
-	                theBlock_->getPLC(),
-					theBlock_->getAddress(),	//Base address (or DBn) of the block
-					0,							//Set all devices from the first one
-					((PLCBlock*)theBlock_)->getBufferSize(),	//Set blocks of all devices (full buffer size)
-					(unsigned char*)theBlock_->getBuffer()  	//Buffer which contain the data (full buffer)
-				);
-
-                bufferUnlock();
+                {//critical section
+                    Lock lock(bufferMux_);
+                    if (pConn->isEnabled())
+                    {	deviceVectorType::iterator pDeviceIter;
+                        deviceVectorType& deviceCol = theBlock_->getPLC()->getDeviceMap();
+
+                        //Cluster/PLC context: set block of all devices in one go ===========================
+                        LOG(SEND) << "SendAction (execute/ BlockMode): block: " << theBlock_->getName() << ", " << deviceCol.size() << " device(s)";
+
+                        //PLC context: Export all registers value of all devices of the PLC to that block
+                        for(pDeviceIter = deviceCol.begin(); pDeviceIter != deviceCol.end(); ++pDeviceIter)
+                        {
+                            Device* pDev = pDeviceIter->second;
+                            unsigned long deviceOffset = pDev->getAddress() * theBlock_->getMemSize();
+                            unsigned char* pBuffer = ((unsigned char*)theBlock_->getBuffer()) + deviceOffset;
+                            pDev->exportRegisters(theBlock_, pBuffer, pContext);
+                        }
+                    }
+
+                    switch (theBlock_->getAccessArea()) {
+                    case Memory:
+                    {
+                      errorCode = pConn->writeMemory(
+                        theBlock_->getPLC(),
+                        theBlock_->getAddress(),    //Base address (or DBn) of the block
+                        0,                          //Set all devices from the first one
+                        ((PLCBlock*)theBlock_)->getBufferSize(),    //Set blocks of all devices (full buffer size)
+                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data (full buffer)
+                        );
+                      break;
+                    }
+                    case Digital:
+                    case Analog:
+                    {
+                      errorCode = pConn->writeOutput(
+                        theBlock_->getPLC(),
+                        theBlock_->getAddress(),    //Base address (or DBn) of the block
+                        0,                          //Set all devices from the first one
+                        ((PLCBlock*)theBlock_)->getBufferSize(),    //Set blocks of all devices (full buffer size)
+                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data (full buffer)
+                        );
+                      break;
+                    }
+                    default:
+                      errorCode = pConn->writeData(
+                        theBlock_->getPLC(),
+                        theBlock_->getAddress(),    //Base address (or DBn) of the block
+                        0,                          //Set all devices from the first one
+                        ((PLCBlock*)theBlock_)->getBufferSize(),    //Set blocks of all devices (full buffer size)
+                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data (full buffer)
+                        );
+                      break;
+                    }
+                }
 
 				if (SEND & Log::topics_)
 				{ 	if (pConn->isEnabled())
@@ -144,7 +195,6 @@ namespace Silecs
 		}
 		catch (const SilecsException& ex)
 		{
-		    bufferUnlock();
 			LOG(ERROR) << ex.what();
 			LOG(ERROR) << "SendAction (execute/ DeviceMode) on block: " << theBlock_->getName() << " has failed";
 			return ex.getCode();
@@ -176,24 +226,50 @@ namespace Silecs
 	                usedSize = theBlock_->getCustomSize();
 	            }
 
-                bufferLock();
-
-				if (pConn->isEnabled())
-				{	LOG(SEND) << "SendAction (execute/ DeviceMode): device: " << pDev->getLabel() << ", block: " << theBlock_->getName();
-
-					//Device context: Export all the device registers to that block
-					pDev->exportRegisters(theBlock_, (unsigned char*)theBlock_->getBuffer(), pContext);
-				}
-
-				errorCode = pConn->writeData(
-	                theBlock_->getPLC(),
-				    usedDeviceAddress,			//Base address (or DBn) of the device
-					usedBlockAddress,	        //Block data address within the device
-					usedSize,	                //Set one device-block only
-					(unsigned char*)theBlock_->getBuffer()  	//Buffer which contain the data
-				);
-
-                bufferUnlock();
+	            {//critical section
+                    Lock lock(bufferMux_);
+                    if (pConn->isEnabled())
+                    {	LOG(SEND) << "SendAction (execute/ DeviceMode): device: " << pDev->getLabel() << ", block: " << theBlock_->getName();
+
+                        //Device context: Export all the device registers to that block
+                        pDev->exportRegisters(theBlock_, (unsigned char*)theBlock_->getBuffer(), pContext);
+                    }
+
+                    switch (theBlock_->getAccessArea()) {
+                    case Memory:
+                    {
+                      errorCode = pConn->writeMemory(
+                        theBlock_->getPLC(),
+                                usedDeviceAddress,          //Base address (or DBn) of the device
+                        usedBlockAddress,           //Block data address within the device
+                        usedSize,                   //Set one device-block only
+                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data
+                        );
+                      break;
+                    }
+                    case Digital:
+                    case Analog:
+                    {
+                      errorCode = pConn->writeOutput(
+                        theBlock_->getPLC(),
+                                usedDeviceAddress,          //Base address (or DBn) of the device
+                        usedBlockAddress,           //Block data address within the device
+                        usedSize,                   //Set one device-block only
+                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data
+                        );
+                      break;
+                    }
+                    default:
+                      errorCode = pConn->writeData(
+                        theBlock_->getPLC(),
+                                usedDeviceAddress,          //Base address (or DBn) of the device
+                        usedBlockAddress,           //Block data address within the device
+                        usedSize,                   //Set one device-block only
+                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data
+                        );
+                      break;
+                    }
+	            }
 
 				if (SEND & Log::topics_)
 				{ 	if (pConn->isEnabled())
@@ -214,24 +290,50 @@ namespace Silecs
 				{
 					Device* pDev = pDeviceIter->second;
 
-	                bufferLock();
-
-					if (pConn->isEnabled())
-	                {   LOG(SEND) << "SendAction (execute/ DeviceMode):  device: " << pDev->getLabel() << ", block: " << theBlock_->getName();
-
-						//PLC context: Export all registers value of the current device of the PLC to that block
-						pDev->exportRegisters(theBlock_, (unsigned char*)theBlock_->getBuffer(), pContext);
-					}
-
-					errorCode = pConn->writeData(
-		                theBlock_->getPLC(),
-	                    pDev->getAddress(),             //Base address (or DBn) of the device
-	                    theBlock_->getAddress(),        //Block data address within the device
-	                    theBlock_->getMemSize(),        //Set one device-block only
-						(unsigned char*)theBlock_->getBuffer()  	//Buffer which contain the data
-					);
-
-	                bufferUnlock();
+	                {//critical section
+                        Lock lock(bufferMux_);
+                        if (pConn->isEnabled())
+                        {   LOG(SEND) << "SendAction (execute/ DeviceMode):  device: " << pDev->getLabel() << ", block: " << theBlock_->getName();
+
+                            //PLC context: Export all registers value of the current device of the PLC to that block
+                            pDev->exportRegisters(theBlock_, (unsigned char*)theBlock_->getBuffer(), pContext);
+                        }
+
+                        switch (theBlock_->getAccessArea()) {
+                        case Memory:
+                        {
+                                    errorCode = pConn->writeMemory(
+                            theBlock_->getPLC(),
+                            pDev->getAddress(),             //Base address (or DBn) of the device
+                            theBlock_->getAddress(),        //Block data address within the device
+                            theBlock_->getMemSize(),        //Set one device-block only
+                                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data
+                            );
+                          break;
+                        }
+                        case Digital:
+                        case Analog:
+                        {
+                                    errorCode = pConn->writeOutput(
+                            theBlock_->getPLC(),
+                            pDev->getAddress(),             //Base address (or DBn) of the device
+                            theBlock_->getAddress(),        //Block data address within the device
+                            theBlock_->getMemSize(),        //Set one device-block only
+                                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data
+                            );
+                          break;
+                        }
+                        default:
+                                    errorCode = pConn->writeData(
+                            theBlock_->getPLC(),
+                            pDev->getAddress(),             //Base address (or DBn) of the device
+                            theBlock_->getAddress(),        //Block data address within the device
+                            theBlock_->getMemSize(),        //Set one device-block only
+                                        (unsigned char*)theBlock_->getBuffer()      //Buffer which contain the data
+                            );
+                          break;
+                        }
+	                }
 
 					if (SEND & Log::topics_)
 					{ 	if (pConn->isEnabled())
@@ -243,7 +345,6 @@ namespace Silecs
 		}
 		catch (const SilecsException& ex)
 		{
-            bufferUnlock();
 			LOG(ERROR) << ex.what();
 			LOG(ERROR) << "SendAction (execute/ DeviceMode) failed";
 			return ex.getCode();
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp
index 2c06112a60255c576ae70299b8f22b354b7f2e2d..f576e8b1e414b3e1d97f81bc2d57055c9e8bdc6d 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp
@@ -14,8 +14,6 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "PLCRegister.h"
-#include <silecs-communication/protocol/core/silecs.h>
-#include <silecs-communication/protocol/modbus/iemdb.h>
 #include <silecs-communication/interface/communication/MBHardware.h>
 #include <silecs-communication/interface/communication/SNAP7Hardware.h>
 
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
index 3929c08c84de2258b6ed144e6c0c2b7523bdd9c6..ec6ff934ed6c7cef010a1415d3ec7e4bfb84a386 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
@@ -21,7 +21,6 @@
 #include <silecs-communication/interface/utility/SilecsException.h>
 #include <silecs-communication/interface/utility/SilecsLog.h>
 #include <silecs-communication/interface/utility/StringUtilities.h>
-#include <silecs-communication/protocol/core/silecs.h>
 
 #include <arpa/inet.h>
 #include <math.h>
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/utility/Mutex.h b/silecs-communication-cpp/src/silecs-communication/interface/utility/Mutex.h
index ecf693deadb7276ec45697861bc7d9400cb82133..7d1f3ad1c02c1f723cd0c50042a9b354524e275f 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/utility/Mutex.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/utility/Mutex.h
@@ -50,6 +50,22 @@ namespace Silecs
 			pthread_mutexattr_t attr_;
 	};
 
+    // For automatic mutex-release on code-block exit ( e.g. if exceptions are used )
+    class Lock
+    {
+        public:
+            Lock(Mutex* mutex): mutex_(mutex)
+            {
+                mutex_->lock();
+            }
+
+            ~Lock()
+            {
+                mutex_->unlock();
+            }
+            Mutex* mutex_;
+    };
+
 } // namespace
 
 #endif /* _MUTEX_H_ */
diff --git a/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.cpp b/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.cpp
deleted file mode 100644
index ca0bbabe389cbd6c1c270a5cd5343529a3ec2fdd..0000000000000000000000000000000000000000
--- a/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2016 CERN and GSI
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-/*
- *
- * Revision : v1.0
- * Date     : 01/2010 - F.Locci
- * Objet    : Initial version - From previous Silecs-2
- * Action   :
- */
-
-/*
- * This library was developped to provide communication between
- * Linux/LynxOS active host (client) and a PLC passive server.
- * Based on S7 or MODBUS std. protocole, it defines generic
- * set and get functions to read and write data into/from PLC
- * memory.
- *
- */
-
-/* ---------------------------------------------------------*/
-/* INCLUDE FILES																						*/
-/* ---------------------------------------------------------*/
-#include <fcntl.h>
-#include <signal.h>
-
-#include <silecs-communication/protocol/core/silecs.h>
-
-/* ---------------------------------------------------------*/
-/* MACRO DEFINITION																				  */
-/* ---------------------------------------------------------*/
-
-/*----------------------------------------------------------*/
-/* This function return the string which describes the
- * error given by 'error' parameter.
- * 'error': error from ie library or PLC server (in)
- * return string pointer
- *
- * Details:
- */
-char *IeGetErrorMessage(int err)
-{
-  int i;
-
-  static struct
-  {
-    int ie_code;
-    char * ie_mes;
-  } errorMap[] =
-  {
-  {IE_SYS_ERROR, "[RFC lib.] function system error"}, //unused
-  {IE_PARAM_ERROR, "[IE/RFC lib.] bad parameter(s) value/format"}, //used by Silecs
-    {IE_CONNECT_ERROR, "[RFC lib.] PLC connection failed"}, //unused
-    {IE_DISCONNECT_ERROR, "[RFC lib.] PLC disconnection requested"}, //unused
-    {IE_TIMEOUT_ERROR, "[RFC lib.] communication (connect/send/recv) timeout occurred"}, //used by Snap7
-    {IE_HOST_UNKNOWN_ERROR, "[IE lib.] PLC hostname unknown"}, //used by Silecs, PlcSendAction and PlcRcvAction
-  };
-
-  static int errorMapSize = sizeof(errorMap)/sizeof(errorMap[0]);
-
-  if (err == 0)
-	return ("No error");
-
-  for (i=0; i<errorMapSize; i++)
-	if (errorMap[i].ie_code == err)
-	  return (errorMap[i].ie_mes);
-
-  return ("Unknown IE error");
-}
diff --git a/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.h b/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.h
deleted file mode 100644
index 50a466609940b49ec0f9648cc6b0d749db1d91e6..0000000000000000000000000000000000000000
--- a/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2016 CERN and GSI
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-/*
- *
- * Revision : v1.0
- * Date     : 01/2010 - F.Locci
- * Objet    : Initial version - From previous Silecs-2
- * Action   :
- */
-
-#ifndef _SILECS_H_
-#define _SILECS_H_
-
-/*
- * This library was developped to provide communication between
- * Linux/LynxOS active host (client) and a PLC passive server.
- * Based on S7 or MODBUS std. protocole, it defines generic
- * set and get functions to read and write data into/from PLC
- * memory.
- *
- */
-
-/* ---------------------------------------------------------*/
-/* INCLUDE FILES																						*/
-/* ---------------------------------------------------------*/
-#include "ietype.h"
-
-/*----------------------------------------------------------*/
-/* This function return the string which describes the
- * error given by 'error' parameter.
- * 'error': error from ie library or PLC server (in)
- * return string pointer
- *
- * Details:
- */
-char *IeGetErrorMessage(int err);
-
-#endif /* _SILECS_H_ */
diff --git a/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.cpp b/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.cpp
deleted file mode 100644
index 7439990ce71b77522195023ab88267183c93e84d..0000000000000000000000000000000000000000
--- a/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifdef MODBUS_SUPPORT_ENABLED
-#include "iemdb.h"
-#include <modbus.h>
-
-/* ---------------------------------------------------------*/
-/* FUNCTIONS CODE											*/
-/* ---------------------------------------------------------*/
-
-/*----------------------------------------------------------*/
-/* Local functions                                          */
-/* ---------------------------------------------------------*/
-
-/* Function to load a struct timeval correctly
- * from a double.
- */
-static inline struct timespec d_to_timespec(double time) {
-  struct timespec tmp;
-
-  tmp.tv_sec  = time;
-  tmp.tv_nsec = 1e9*(time - tmp.tv_sec);
-  return tmp;
-}
-
-/*----------------------------------------------------------*/
-/* Glocal functions                                         */
-/* ---------------------------------------------------------*/
-#endif //MODBUS_SUPPORT_ENABLED
diff --git a/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.h b/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.h
deleted file mode 100644
index c3822f68a2ee38f03511daadba5c39b00fe08841..0000000000000000000000000000000000000000
--- a/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifdef MODBUS_SUPPORT_ENABLED
-#ifndef _IEMDB_H_
-#define _IEMDB_H_
-
-#include <silecs-communication/protocol/core/ietype.h>
-#include <modbus.h>
-
-/*----------------------------------------------------------*/
-/* Time funtion
- * IeMdbSetTime: Convert time_t epoch date to PLC SCHNEIDER
- * format.
- *
- * Details:
- * PLC SCHNEIER format is coded on 8 bytes BCD
- * format:
- *
- *  0      1      2      3      4      5     6     7 
- *  SC     --     HH     MN     MM     DD    YY    YY
- *
- *  byte 1 is used by gateway to synchronize time setting.
- */
-void IeMdbSetTime(unsigned char *dt, time_t epoch);  // to PLC
-
-/*----------------------------------------------------------*/
-/* Time funtion
- * IeMdbGetTime: Convert PLC SCHNEIDER format to lynxOS 
- * time_t format.
- *
- * Details:
- * PLC SCHNEIER format is coded on 8 bytes BCD
- * format:
- *
- *  0      1        2      3      4      5     6     7 
- *  SC     SC/100   HH     MN     MM     DD    YY    YY
- *
- */
-double IeMdbGetTime(unsigned char *dt); // from PLC
-
-/*----------------------------------------------------------*/
-/* This function send a data segment to the PLC using the
- * MODBUS protocole.
- * 'ctx': write channel id of the MB connection
- * 'dataAddr': target address of the data segment within the PLC memory
- * 'dataSize': byte size of the data segment to be sent
- * 'dataBuffer': buffer of the data to be sent
- * return 0 or <0 on error (see constant error)
- */
-int IeMBwriteData(modbus_t* ctx, uint16_t dataAddr, uint16_t dataSize, uint8_t* dataBuffer);
-
-/*----------------------------------------------------------*/
-/* This function read a data segment from the PLC using the
- * MODBUS protocole.
- * 'ctx': read channel id of the MB connection
- * 'dataAddr': address of the data segment within the PLC memory
- * 'dataSize': byte size of the data segment to be read
- * 'dataBuffer': buffer to store the data
- * return 0 or <0 on error (see constant error)
- */
-int IeMBreadData(modbus_t* ctx, uint16_t dataAddr, uint16_t dataSize, uint8_t* dataBuffer);
-
-#endif /* _IEMDB_H_ */
-#endif //MODBUS_SUPPORT_ENABLED