diff --git a/src/TactiloController/ovpCBoxAlgorithmTactiloController.cpp b/src/TactiloController/ovpCBoxAlgorithmTactiloController.cpp
new file mode 100644
index 0000000..8a7cfcd
--- /dev/null
+++ b/src/TactiloController/ovpCBoxAlgorithmTactiloController.cpp
@@ -0,0 +1,120 @@
+///-------------------------------------------------------------------------------------------------
+/// 
+/// \file ovpCBoxAlgorithmTactiloController.cpp
+/// \brief Functions of the Box Tactilo Controller.
+/// \author Tobias Baumann (TH-Nürnberg).
+/// \version 1.0.
+/// \date Mon Feb 21 14:59:56 2022.
+/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
+/// 
+///-------------------------------------------------------------------------------------------------
+
+//includes
+#include "ovpCBoxAlgorithmTactiloController.h"
+#include <string>
+
+using namespace OpenViBE;
+using namespace /*OpenViBE::*/Kernel;
+using namespace /*OpenViBE::*/Plugins;
+using namespace /*OpenViBE::Plugins::*/Tactilebci;
+
+/*******************************************************************************/
+
+bool CBoxAlgorithmTactiloController::initialize()
+{
+	m_input0Decoder.initialize(*this, 0);
+	m_output0Encoder.initialize(*this, 0);
+	
+	//get Box Settings
+	m_PortName         = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
+	m_RowBase          = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
+	m_StartStimulation = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
+	m_StopStimulation  = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
+	
+	//open serial port
+	m_Port.open(m_PortName.toASCIIString());
+	
+	if(m_Port.is_open())
+	{
+		this->getLogManager() << LogLevel_Info << "Connected to Serial Port: " << m_PortName << "\n";
+	}
+	
+	return true;
+}
+
+/*******************************************************************************/
+
+bool CBoxAlgorithmTactiloController::uninitialize()
+{
+	m_input0Decoder.uninitialize();
+	m_output0Encoder.uninitialize();
+	
+	m_Port.close();
+
+	return true;
+}
+
+/*******************************************************************************/
+
+bool CBoxAlgorithmTactiloController::processInput(const size_t index)
+{
+	// some pre-processing code if needed...
+
+	// ready to process !
+	getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
+
+	return true;
+}
+
+/*******************************************************************************/
+bool CBoxAlgorithmTactiloController::process()
+{
+	
+	// the static box context describes the box inputs, outputs, settings structures
+	const IBox& staticBoxContext = this->getStaticBoxContext();
+	// the dynamic box context describes the current state of the box inputs and outputs (i.e. the chunks)
+	IBoxIO& boxContext       = this->getDynamicBoxContext();
+	
+	uint64_t TactiloNr       = 0;
+	uint64_t StimulationID   = 0;
+	uint64_t ChunkStartTime  = 0;
+	uint64_t ChunkEndTime    = 0;
+	uint64_t Size            = 0;
+	const uint8_t*  Buffer   = nullptr;    
+
+	//iterate over all chunk on input 0
+	for (uint64_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
+	{
+		// decode the chunk i
+		m_StimDecoder.decode(i);
+		if(m_StimDecoder.isBufferReceived())
+		{
+			//check received stimulations
+			IStimulationSet* StimSet = m_StimDecoder.getOutputStimulationSet();
+            for(uint64_t j=0; j<StimSet->getStimulationCount(); j++)
+            {
+                StimulationID   = StimSet->getStimulationIdentifier(j);
+				
+				if(StimulationID >= m_RowBase && StimulationID < (m_RowBase + NumberofTactilos))
+				{				
+					this->getLogManager() << LogLevel_Debug << "Tactilo Nr. " << (StimulationID-m_RowBase+1) << "\n";
+					TactiloNr = StimulationID-m_RowBase+1;
+				}
+				if(StimulationID == m_StartStimulation || StimulationID == m_StopStimulation)
+				{
+					this->getLogManager() << LogLevel_Debug << "Toggle Tactilo Nr. " << (StimulationID-m_RowBase+1) << "\n";
+					boost::asio::write::async_write(m_Port, boost::asio::buffer(std::to_string(TactiloNr));
+				}
+			}
+		}
+		// forward input chunks
+		boxContext.getInputChunk(0, i, ChunkStartTime, ChunkEndTime, Size, Buffer);
+		boxContext.appendOutputChunkData(0, Buffer, Size);
+		boxContext.markOutputAsReadyToSend(0, ChunkStartTime, ChunkEndTime);
+		boxContext.markInputAsDeprecated(0, i);
+	}
+
+	return true;
+}
+
+/*******************************************************************************/
\ No newline at end of file
diff --git a/src/TactiloController/ovpCBoxAlgorithmTactiloController.h b/src/TactiloController/ovpCBoxAlgorithmTactiloController.h
new file mode 100644
index 0000000..a0f6889
--- /dev/null
+++ b/src/TactiloController/ovpCBoxAlgorithmTactiloController.h
@@ -0,0 +1,112 @@
+///-------------------------------------------------------------------------------------------------
+/// 
+/// \file ovpCBoxAlgorithmTactiloController.h
+/// \brief Classes of the Box Tactilo Controller.
+/// \author Tobias Baumann (TH-Nürnberg).
+/// \version 1.0.
+/// \date Mon Feb 21 14:59:56 2022.
+/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
+/// 
+///-------------------------------------------------------------------------------------------------
+
+//includes
+#pragma once
+
+#include "../ovp_defines.h"
+
+#include <openvibe/ov_all.h>
+#include <toolkit/ovtk_all.h>
+#include <boost/asio.hpp>
+#include <string>
+
+namespace OpenViBE
+{
+	namespace Plugins
+	{
+		namespace Tactilebci
+		{
+			/// <summary> The class CBoxAlgorithmTactiloController describes the box Tactilo Controller. </summary>
+			class CBoxAlgorithmTactiloController final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
+			{
+			public:
+				void release() override { delete this; }
+
+				bool initialize() override;
+				bool uninitialize() override;
+				bool processInput(const size_t index) override;
+				bool process() override;
+
+				// As we do with any class in openvibe, we use the macro below to associate this box to an unique identifier. 
+				// The inheritance information is also made available, as we provide the superclass Toolkit::TBoxAlgorithm < IBoxAlgorithm >
+				_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_TactiloController)
+
+			protected:
+				// Input decoder:
+				Toolkit::TStimulationDecoder<CBoxAlgorithmTactiloController> m_input0Decoder;
+				// Output decoder:
+				Toolkit::TStimulationEncoder<CBoxAlgorithmTactiloController> m_output0Encoder;
+				
+			private:
+				//Box Settings
+				CString   m_PortName;
+				uint64_t  m_RowBase;
+				uint64_t  m_StartStimulation;
+				uint64_t  m_StopStimulation;
+				
+				//Serial Port
+				boost::asio::io_service m_IO;
+				boost::asio::serial_port m_Port{m_IO};
+			};
+
+			/// <summary> Descriptor of the box Tactilo Controller. </summary>
+			class CBoxAlgorithmTactiloControllerDesc final : virtual public IBoxAlgorithmDesc
+			{
+			public:
+
+				void release() override { }
+
+				CString getName() const override { return CString("Tactile Stimulation"); }
+				CString getAuthorName() const override { return CString("Tobias Baumann"); }
+				CString getAuthorCompanyName() const override { return CString("TH-Nürnberg"); }
+				CString getShortDescription() const override { return CString("Controls the Tactilos on the Lattepandas GPIOs"); }
+				CString getDetailedDescription() const override { return CString("Communicates with the Arduino Coprocessor of the Lattepanda over a Serial Inteface, to control the Tactilos connected to the Arduinos GPIOs"); }
+				CString getCategory() const override { return CString("TactileBCI"); }
+				CString getVersion() const override { return CString("1.0"); }
+				CString getStockItemName() const override { return CString("gtk-network"); }
+
+				CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_TactiloController; }
+				IPluginObject* create() override { return new CBoxAlgorithmTactiloController; }
+
+				/*
+				IBoxListener* createBoxListener() const override { return new CBoxAlgorithmTactiloControllerListener; }
+				void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
+				*/
+				bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
+				{
+					prototype.addInput("StimInput",OV_TypeId_Stimulations);
+
+					//prototype.addFlag(Kernel::BoxFlag_CanModifyInput);
+					//prototype.addFlag(Kernel::BoxFlag_CanAddInput);
+
+					prototype.addOutput("StimOutput",OV_TypeId_Stimulations);
+
+					//prototype.addFlag(Kernel::BoxFlag_CanModifyOutput);
+					//prototype.addFlag(Kernel::BoxFlag_CanAddOutput);
+
+					//Box Settings
+					prototype.addSetting("Serial Port Name",OV_TypeId_String,"/dev/ttyACM0");
+					prototype.addSetting("Row Stimulation Base",OV_TypeId_Stimulation,"OVTK_StimulationId_Label_01");
+					prototype.addSetting("Flash Start Stimulation",OV_TypeId_Stimulation,"OVTK_StimulationId_VisualStimulationStart");
+					prototype.addSetting("Flash Stop Stimulation",OV_TypeId_Stimulation,"OVTK_StimulationId_VisualStimulationStop");
+					//prototype.addFlag(Kernel::BoxFlag_CanModifySetting);
+					//prototype.addFlag(Kernel::BoxFlag_CanAddSetting);
+
+					prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
+
+					return true;
+				}
+				_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_TactiloControllerDesc)
+			};
+		}  // namespace Tactilebci
+	}  // namespace Plugins
+}  // namespace OpenViBE