Touch driver for companion boards (VKLCD50RTA & VKLCD70RT)

Files at this revision

API Documentation at this revision

Comitter:
tvendov
Date:
Fri Nov 03 08:52:07 2017 +0000
Commit message:
Touch panel driver initial release

Changed in this revision

Touch.cpp Show annotated file Show diff for this revision Revisions of this file
Touch.hpp Show annotated file Show diff for this revision Revisions of this file
stmpe811iic.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 0383b9f88d72 Touch.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Touch.cpp	Fri Nov 03 08:52:07 2017 +0000
@@ -0,0 +1,511 @@
+#include "Touch.hpp"
+
+
+
+namespace Vekatech {
+
+#define DISABLED	0
+#define LAST_SAMPLE	1
+#define ALL_SAMPLES	2
+
+//Debug is disabled by default
+#define TOUCH_DBG	DISABLED
+//#define MORE_DETAILS
+
+#ifndef FUNCTION_NAME
+//#define FUNCTION_NAME ""
+//#define FUNCTION_NAME __func__
+//#define FUNCTION_NAME __FUNCTION__
+#define FUNCTION_NAME __PRETTY_FUNCTION__
+#endif
+
+#if (TOUCH_DBG > DISABLED)
+#ifdef MORE_DETAILS
+	#define DBG(x, ...) printf("[DBG: %s:%s:%d] " x "\r\n", __FILE__, FUNCTION_NAME, __LINE__, ##__VA_ARGS__)
+#else
+	#define DBG(x, ...) printf("[DBG:] " x "\r\n", ##__VA_ARGS__)
+#endif
+#else
+	#define DBG(x, ...)
+#endif
+
+#if (TOUCH_DBG > LAST_SAMPLE)
+#ifdef MORE_DETAILS
+	#define DBG_MORE(x, ...) printf("[DBG_MORE: %s:%s:%d] " x "\r\n", __FILE__, FUNCTION_NAME, __LINE__,  ##__VA_ARGS__)
+#else
+	#define DBG_MORE(x, ...) printf("[DBG_MORE:] " x "\r\n", ##__VA_ARGS__)
+#endif
+#else
+	#define DBG_MORE(x, ...)
+#endif
+
+#if (TOUCH_DBG > ALL_SAMPLES)
+#ifdef MORE_DETAILS
+	#define DBG_ALL(x, ...) printf("[DBG_ALL: %s:%s:%d] " x "\r\n", __FILE__, FUNCTION_NAME, __LINE__,  ##__VA_ARGS__)
+#else
+	#define DBG_ALL(x, ...) printf("[DBG_ALL:] " x "\r\n", ##__VA_ARGS__)
+#endif
+#else
+	#define DBG_ALL(x, ...)
+#endif
+
+
+
+#define NEW_TOUCH_DATA	0x1
+
+const touch_config_t  STMPE811_cfg = {
+	"STMPE811", LCD_VDC5_CH0_PANEL, RESISTIVE,
+    {I_2_C, TPIIC_SDA, TPIIC_SCL, NC, NC, NC, NC, 100000},
+    {INT_ON_EDGE, FALLING_OR_ACTIVE_LO, TPIRQ_PIN}
+};
+
+osThreadId			TouchThreadID;
+
+/**************************************************************************//**
+ * @brief       Constructor of the Touch class
+ * @param[in]   pointer to Config structure (touch_config_t)
+******************************************************************************/
+//SPI(tp_cfg->interface.mosi, tp_cfg->interface.miso, tp_cfg->interface.sclk, tp_cfg->interface.ssel),
+Touch::Touch( const touch_config_t * tp_cfg ) : I2C(tp_cfg->interface.sda, tp_cfg->interface.scl), InterruptIn(tp_cfg->activity_irq.pin)
+{
+	if(tp_cfg == NULL)
+		touch_cfg = &STMPE811_cfg;
+	else
+		touch_cfg = tp_cfg;
+
+	x = y = z = 0;	  adc_x = adc_y = adc_z = 0;
+	xyz_data = screen_data; adc_data = raw_data;
+	last_xyz_idx = FIFO_DEPTH-1;
+
+	dot_thd = 0;
+	fraction = 0;
+	calib.data.flag = 0;
+} /* End of constructor */
+
+
+/**************************************************************************//**
+ * @brief       Destructor of the Touch class
+******************************************************************************/
+Touch::~Touch( )
+{
+	Thread::State S = thd.get_state();
+
+	disable_irq();
+
+	if((S != Thread::Inactive) && (S != Thread::Deleted))
+	{
+		thd.terminate();
+		thd.join();
+	}
+
+	touch_cfg = NULL;
+	xyz_data = NULL;
+	adc_data = NULL;
+}
+
+
+/**************************************************************************//**
+ * @brief       Touch controller initialization
+ * @retval      error code
+******************************************************************************/
+Touch::init_err_t Touch::Init( void )
+{
+	init_err_t tp_err;
+
+	if(touch_cfg->type == RESISTIVE)
+	{
+		tp_err = Clb_Setup();
+
+		if(tp_err != TOUCH_OK)
+			return tp_err;
+	}
+
+	if(touch_cfg->interface.type == I_2_C)
+		I2C::frequency(touch_cfg->interface.freq);
+	//else
+		//SPI::frequency(touch_cfg->interface.freq);
+
+	tp_err = Drv_Setup();
+
+	if(tp_err != TOUCH_OK)
+		return tp_err;
+	else
+	{
+		thd.start(callback(this, &Touch::Handle_touch));
+
+		if(touch_cfg->activity_irq.polarity == FALLING_OR_ACTIVE_LO)
+		{
+			rise(NULL);
+			fall(Irq_Alert);
+		}
+		else
+		{
+			rise(Irq_Alert);
+			fall(NULL);
+		}
+
+		enable_irq();
+	}
+
+	return tp_err;
+} /* End of method Init() */
+
+
+/**************************************************************************//**
+ * @brief       Set Calibration data
+ * @retval      error code
+******************************************************************************/
+Touch::init_err_t Touch::Clb_Setup()
+{
+	if(touch_cfg->name == "STMPE811")
+	{
+		#ifndef __USE_DEFAULT_CALIBRATION_DATA__
+			// extract calibration info from lcdpanel EEPROM
+			char adr = 0;
+
+			if( (touch_cfg->interface.sda == EEIIC_SDA) || (touch_cfg->interface.scl == EEIIC_SCL))
+			{	// lcdpanel EEPROM is on the same I2C channel no need to initialize a new one !
+				if(I2C::write(EE_CALIB_DEVICE_ADDR, (const char *)&adr, 1, true) != 0)
+					return TOUCH_INIT_ERR;
+				if(I2C::read(EE_CALIB_DEVICE_ADDR, (char*)calib.KX08, sizeof(calib.KX08)) != 0)
+					return TOUCH_INIT_ERR;
+			}
+			else
+			{	// lcdpanel EEPROM is on different I2C channel so initialize a new one !
+				I2C clb_eeprom(EEIIC_SDA, EEIIC_SCL);
+
+				clb_eeprom.frequency(100000);
+				if(clb_eeprom.write(EE_CALIB_DEVICE_ADDR, (const char *)&adr, 1, true) != 0)
+					return TOUCH_INIT_ERR;
+				if(clb_eeprom.read(EE_CALIB_DEVICE_ADDR, (char*)calib.KX08, sizeof(calib.KX08)) != 0)
+					return TOUCH_INIT_ERR;
+			}
+		#endif
+
+		if(calib.data.flag != 1)
+		{	// load default calibration info
+			unsigned char clb[] = {TPCALIBRATION_DATA};
+			memcpy(calib.KX08, clb, sizeof(clb));
+		}
+
+		return TOUCH_OK;
+	}
+	else
+		return TOUCH_UNSUPP_ERR;
+} /* End of method Clb_Setup() */
+
+
+/**************************************************************************//**
+ * @brief       Set Touch Controller settings
+ * @retval      error code
+******************************************************************************/
+Touch::init_err_t Touch::Drv_Setup()
+{
+	if(touch_cfg->name == "STMPE811")
+	{
+		unsigned char i, initdata[][2] = { INIT_DATA };
+
+		for(i=0; i<(sizeof(initdata)>>1); i++)
+		{
+			if(initdata[i][0] == INT_CTRL)
+			{	// reconfigure interrupt if needed
+				initdata[i][1] = 0x01;
+				initdata[i][1] |= (touch_cfg->activity_irq.trigger == INT_ON_EDGE)? 0x02 : 0x00;
+				initdata[i][1] |= (touch_cfg->activity_irq.polarity == RISING_OR_ACTIVE_HI)? 0x04 : 0x00;
+			}
+
+			if(initdata[i][0] == FIFO_TH)
+			{	// save threshold
+				if(initdata[i][1] < 2)
+					initdata[i][1] = 2;
+
+				dot_thd = initdata[i][1]-1;
+			}
+
+			if(initdata[i][0] == TSC_FRACT_Z)
+				fraction = initdata[i][1];	// save z precision
+
+			if ((I2C::write(STMPE811_DEVICE_ADDR, (const char *)&initdata[i][0], 2)) != 0)
+				return TOUCH_INIT_ERR;
+
+			while (I2C::write(STMPE811_DEVICE_ADDR, (const char *)initdata, 0) != 0);  // ACK polling
+		}
+
+		return TOUCH_OK;
+	}
+	else
+		return TOUCH_UNSUPP_ERR;
+}
+
+
+/**************************************************************************//**
+ * @brief       Get Status of the pen
+ * @retval     	true	: StylusDown
+ * 				false	: StyluUp
+******************************************************************************/
+bool Touch::Get_Pen_Status()
+{
+	if(touch_cfg->name == "STMPE811")
+	{
+		unsigned char pen = TSC_CTRL;
+
+	  	I2C::write(STMPE811_DEVICE_ADDR, (const char *)&pen, 1, true);
+	  	pen = 0;
+	  	I2C::read(STMPE811_DEVICE_ADDR, (char *)&pen, 1);
+
+	  	return (pen & TSC_STA)? true : false;
+	}
+	else
+		return false;
+} /* End of method Get_Pen_Status() */
+
+
+/**************************************************************************//**
+ * @brief       Get one sample of data
+ * @param[in]   * raw	: pointer to ring buffer to store the samples
+******************************************************************************/
+void Touch::Get_Data( unsigned long long * raw )
+{
+	if(touch_cfg->name == "STMPE811")
+	{
+		int idx = last_xyz_idx;
+		unsigned char  i, packed_sample[dot_thd * 4];
+		unsigned short raw_x, raw_y;
+		unsigned char  raw_z;
+
+		i = TSC_DATA_FIFO;
+		I2C::write(STMPE811_DEVICE_ADDR, (const char *)&i, 1, true);
+		I2C::read(STMPE811_DEVICE_ADDR, (char *)packed_sample, sizeof(packed_sample));
+		for(i=0; i<dot_thd; i++)
+		{
+			raw_x = (unsigned short)((packed_sample[(i*4)+0]<<4) | (packed_sample[(i*4)+1]>>4));
+			raw_y = (unsigned short)(((0x0F & packed_sample[(i*4)+1])<<8) | packed_sample[(i*4)+2]);
+			raw_z = packed_sample[(i*4)+3];
+
+			idx = ((idx+1) < FIFO_DEPTH)? idx+1 : 0;
+		    ((touch_raw_data_t*)raw)[idx].axis.x = raw_x;
+		    ((touch_raw_data_t*)raw)[idx].axis.y = raw_y;
+		    ((touch_raw_data_t*)raw)[idx].axis.z = raw_z;
+		}
+	}
+} /* End of method Get_Data() */
+
+
+/**************************************************************************//**
+ * @brief       Get all available samples of data
+ * @param[in]   * raw	: pointer to ring buffer to store the samples
+ * @retval      		  samples count
+******************************************************************************/
+int Touch::Get_Fifo( unsigned long long * raw )
+{
+	if(touch_cfg->name == "STMPE811")
+	{
+	  int idx = last_xyz_idx;
+	  unsigned char packets;
+
+	  packets = FIFO_SIZE;
+	  I2C::write(STMPE811_DEVICE_ADDR, (const char *)&packets, 1, true);
+	  packets = 0;
+	  I2C::read(STMPE811_DEVICE_ADDR, (char *)&packets, 1);
+	  if(packets)
+	  {
+		unsigned char  packed_sample[packets * 4];
+		unsigned short raw_x, raw_y, i;
+		unsigned char  raw_z;
+
+		raw_z = TSC_DATA_FIFO;
+		I2C::write(STMPE811_DEVICE_ADDR, (const char *)&raw_z, 1, true);
+		I2C::read(STMPE811_DEVICE_ADDR, (char *)packed_sample, packets*4);
+
+	    for(i=0; i<packets; i++)
+	    {
+	      raw_x = (unsigned short)((packed_sample[(i*4)+0]<<4) | (packed_sample[(i*4)+1]>>4));
+	      raw_y = (unsigned short)(((0x0F & packed_sample[(i*4)+1])<<8) | packed_sample[(i*4)+2]);
+	      raw_z = packed_sample[(i*4)+3];
+
+	      idx = ((idx+1) < FIFO_DEPTH)? idx+1 : 0;
+	      ((touch_raw_data_t*)raw)[idx].axis.x = raw_x;
+	      ((touch_raw_data_t*)raw)[idx].axis.y = raw_y;
+	      ((touch_raw_data_t*)raw)[idx].axis.z = raw_z;
+	    }
+
+	    return packets;
+	  }
+	  return 0;
+	}
+	else
+		return 0;
+} /* End of method Get_Fifo() */
+
+
+/**************************************************************************//**
+ * @brief       Coordinates Transfer function
+ * @param[in]   points		: number of samples which have to become meaningful
+******************************************************************************/
+void Touch::Get_XYZ( int points)
+{
+	if(touch_cfg->name == "STMPE811")
+	{
+		int i, idx;
+
+		for(i=0; i<points; i++)
+		{
+			idx = ((last_xyz_idx+1) < FIFO_DEPTH)? last_xyz_idx+1 : 0;
+			screen_data[idx].axis.x = (signed short)(calib.data.KX1*((signed short)raw_data[idx].axis.x)+calib.data.KX2*((signed short)raw_data[idx].axis.y)+calib.data.KX3+0.5);
+			screen_data[idx].axis.y = (signed short)(calib.data.KY1*((signed short)raw_data[idx].axis.x)+calib.data.KY2*((signed short)raw_data[idx].axis.y)+calib.data.KY3+0.5);
+			screen_data[idx].axis.z = ((float)(raw_data[idx].axis.z >> fraction)) + (((float)(raw_data[idx].axis.z & ((0x1<<fraction)-1)))*(1.0f/float(0x1<<fraction)));
+			last_xyz_idx = idx;
+			#ifdef MORE_DETAILS
+				DBG_MORE("TH_No: (%d)   X-> %d (%d), Y-> %d (%d), Z-> %f (%d), dots-> %d/%d", idx, screen_data[idx].axis.x, raw_data[idx].axis.x, screen_data[idx].axis.y, raw_data[idx].axis.y, screen_data[idx].axis.z, raw_data[idx].axis.z, i+1, points);
+			#else
+				DBG_MORE("TH_No: (%d)   X-> %d, Y-> %d, Z-> %f, dots-> %d/%d", idx, screen_data[idx].axis.x, screen_data[idx].axis.y, screen_data[idx].axis.z, i+1, points);
+			#endif
+		}
+
+		x = screen_data[last_xyz_idx].axis.x; adc_x = raw_data[last_xyz_idx].axis.x;
+		y = screen_data[last_xyz_idx].axis.y; adc_y = raw_data[last_xyz_idx].axis.y;
+		z = screen_data[last_xyz_idx].axis.z; adc_z = raw_data[last_xyz_idx].axis.z;
+			#ifdef MORE_DETAILS
+				DBG("S_No: (%d)   X-> %d (%d), Y-> %d (%d), Z-> %f (%d), dots-> %d", last_xyz_idx, x, adc_x, y, adc_y, z, adc_z, points);
+			#else
+				DBG("S_No: (%d)   X-> %d, Y-> %d, Z-> %f, dots-> %d", last_xyz_idx, x, y, z, points);
+			#endif
+	}
+} /* End of method Get_XYZ() */
+
+
+/**************************************************************************//**
+ * @brief       IRQ interrupt handler : indicates "New Touch Data available" which activates i2c data transfer in Handle_touch()
+******************************************************************************/
+void Touch::Irq_Alert()
+{
+	// Execute the time critical part first
+
+	// Then the rest can execute later in user context (and can contain code that's not interrupt safe).
+	osSignalSet(TouchThreadID, NEW_TOUCH_DATA);
+}
+
+
+/**************************************************************************//**
+ * @brief       Get index of the last sample in the ring buffer
+ * @retval      idx
+******************************************************************************/
+int Touch::Get_Last_Idx() { return last_xyz_idx; }
+
+/**************************************************************************//**
+ * @brief       Get dot collection threshold
+ * @retval      threshold
+******************************************************************************/
+int Touch::Get_Dot_thd() { return dot_thd; }
+
+/**************************************************************************//**
+ * @brief       Pull the new samples if new touch data is available
+******************************************************************************/
+void Touch::Handle_touch()
+{
+	bool Stylus = false;
+	bool Click_send = false;
+	unsigned short idx_on = 0;
+	unsigned char TP_IntStat = 0, rec[2];
+	int dots = 0;
+	osEvent evt;
+
+	TouchThreadID = thd.gettid();
+
+	while (true)
+	{
+		evt = thd.signal_wait(NEW_TOUCH_DATA);
+
+		if(evt.status == osEventSignal)
+		{
+			if(touch_cfg->name == "STMPE811")
+			{
+				TP_IntStat = INT_STA;
+				I2C::write(STMPE811_DEVICE_ADDR, (const char *)&TP_IntStat, 1, true);
+				TP_IntStat = 0;
+				I2C::read(STMPE811_DEVICE_ADDR, (char *)&TP_IntStat, 1);
+
+				if(TP_IntStat & INT_FIFO_TH)
+				{
+					Get_Data(&raw_data[0].dot);
+					Get_XYZ(dot_thd);
+					if(Stylus)
+					{
+						if(!Click_send)
+						{
+							MSG(EV_STYLUS_DOWN, idx_on, 0);
+							Click_send = true;
+						}
+						MSG(EV_STYLUS_HOLD, idx_on, last_xyz_idx);
+					}
+				}
+
+				if(TP_IntStat & INT_TOUCH_DET)
+				{
+					Stylus = Get_Pen_Status();
+					DBG("Pen: %s", (Stylus)? "DOWN" : "UP");
+
+					dots = Get_Fifo(&raw_data[0].dot);
+					if(dots)
+					{
+						Get_XYZ(dots);
+
+						if(Stylus)
+						{
+							int on = (last_xyz_idx+1) - dots;
+							idx_on = (on<0)? (FIFO_DEPTH-on) : on;
+							MSG(EV_STYLUS_DOWN, idx_on, 0);
+							Click_send = true;
+						}
+						else
+						{
+							if(!Click_send)
+							{
+								MSG(EV_STYLUS_DOWN, idx_on, 0);
+								Click_send = true;
+							}
+							MSG(EV_STYLUS_UP, idx_on, last_xyz_idx);
+						}
+					}
+					else
+					{
+						if(Stylus)
+						{
+							Click_send = false;
+							idx_on = (last_xyz_idx == (FIFO_DEPTH-1))? 0 : last_xyz_idx+1;
+						}
+						else
+						{
+							if(Click_send)
+								MSG( EV_STYLUS_UP, idx_on, last_xyz_idx);
+						}
+					}
+				}
+
+				if(TP_IntStat & INT_FIFO_OFLOW)
+				{
+					DBG("Overflow !!!");
+
+					rec[0] = FIFO_STA;
+					rec[1] = 0x01;		// Clear FIFO
+					I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2);
+
+					rec[1] = 0x00;		// Reset FIFO
+					I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2);
+				}
+
+				rec[0] = INT_STA;
+				rec[1] = TP_IntStat;
+				I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2);
+			}
+		}
+		else
+		{
+			DBG("Abnormal Touch Thread Status: 0x%X", evt.status);
+		}
+	}
+}
+
+} // namespace Vekatech
+
+/* End of file */
diff -r 000000000000 -r 0383b9f88d72 Touch.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Touch.hpp	Fri Nov 03 08:52:07 2017 +0000
@@ -0,0 +1,277 @@
+/**************************************************************************//**
+ * @file         Touch.h
+ * @brief        Touch driver class for VK-LCD panels
+******************************************************************************/
+
+#ifndef MBED_TOUCH_H
+#define MBED_TOUCH_H
+
+#include "mbed.h"
+#include "stmpe811iic.h"
+#include <string>
+
+
+
+namespace Vekatech {
+
+    /*! @enum Touch_type_t
+    	@brief Type of the touch controller
+    */
+    typedef enum {
+    	RESISTIVE = 0, /*!< Resistive */
+    	CAPACITIVE     /*!< Capacitive */
+    } Touch_type_t;
+
+    /*! @enum Touch_interface_type_t
+        @brief Communication interface
+    */
+    typedef enum {
+    	I_2_C = 0, 		 /*!< I2C */
+    	S_P_I     		 /*!< SPI */
+    } Touch_communication_type_t;
+
+    /*! @enum IRQ_trigger_t
+    	@brief Type of the interrupt
+    */
+    typedef enum {
+    	INT_ON_EDGE  = 0,   /*!< generate INT on front change */
+    	INT_ON_LEVEL        /*!< generate INT on active level */
+    } IRQ_trigger_t;
+
+    /*! @enum IRQ_polarity_t
+        @brief Edge of a signal
+    */
+    typedef enum {
+    	RISING_OR_ACTIVE_HI  = 0, /*!< Rising edge/HI level     */
+    	FALLING_OR_ACTIVE_LO      /*!< Falling edge/LOW level   */
+    } IRQ_polarity_t;
+
+    /*! @struct touch_config_t
+    	@brief Touch Config structure
+    */
+    typedef struct {
+    	string			name;				/*!< Name of the Touch driver */
+        int				screen;				/*!< reserved				  */
+        Touch_type_t	type;				/*!< Resistive or Capacitive  */
+        struct {							/*!< I2C or SPI & the pins of selected periphery */
+        	Touch_communication_type_t type;
+        	PinName sda;
+        	PinName scl;
+        	PinName mosi;
+        	PinName miso;
+        	PinName sclk;
+        	PinName ssel;
+        	int 	freq;
+        }interface;
+        struct {							/*!< IRQ : front and pin of selected periphery */
+        	IRQ_trigger_t	trigger;
+            IRQ_polarity_t	polarity;
+            PinName			pin;
+        }activity_irq;
+    }touch_config_t;
+
+extern const touch_config_t STMPE811_cfg;
+
+
+
+/*! @class Touch
+ *  @brief Touch driver class for VK-LCD panels
+ *
+ *  Example:
+ *
+ *  @code
+ *  #include "mbed.h"
+ *  #include "Touch.hpp"
+ *
+ *  using namespace Vekatech;
+ *
+ *  Touch   STMPE811;
+ *
+ *  // main() runs in its own thread in the OS
+ *  int main()
+ *  {
+ *     osEvent evt;
+ *
+ *     STMPE811.Init();
+ *
+ *     while (true)
+ *     {
+ *          evt = STMPE811.Wait_MSG();
+ *          if (evt.status == osEventMail)
+ *          {
+ *              Touch::MSGQ_t* msg = (Touch::MSGQ_t*)evt.value.p;
+ *              printf("[EV (%d)], start_idx: %d end_idx: %d\r\n", msg->event, msg->start_idx, msg->stop_idx);
+ *
+ *              switch(msg->event)
+ *              {
+ *                  case Touch::EV_STYLUS_UP:
+ *                      printf("[UP (%d)] X: %d Y: %d Z: %f\r\n", msg->stop_idx, STMPE811.xyz_data[msg->stop_idx].axis.x, STMPE811.xyz_data[msg->stop_idx].axis.y, STMPE811.xyz_data[msg->stop_idx].axis.z );
+ *                  break;
+ *
+ *                  case Touch::EV_STYLUS_DOWN:
+ *                      printf("[DOWN (%d)] X: %d Y: %d Z: %f\r\n", msg->start_idx, STMPE811.xyz_data[msg->start_idx].axis.x, STMPE811.xyz_data[msg->start_idx].axis.y, STMPE811.xyz_data[msg->start_idx].axis.z );
+ *                  break;
+ *
+ *                  case Touch::EV_STYLUS_HOLD:
+ *                      if(msg->stop_idx >= (STMPE811.Get_Dot_thd()-1) )
+ *                          for(int i = (msg->stop_idx+1 - STMPE811.Get_Dot_thd()); i<=msg->stop_idx; i++)
+ *                              printf("[HOLD (%d)] X: %d Y: %d Z: %f\r\n", i, STMPE811.xyz_data[i].axis.x, STMPE811.xyz_data[i].axis.y, STMPE811.xyz_data[i].axis.z );
+ *                  break;
+ *
+ *                  default: break;
+ *              }
+ *
+ *              STMPE811.Del_MSG((Touch::MSGQ_t*)evt.value.p);
+ *          }
+ *      }
+ *   }
+ *  @endcode
+ */
+class Touch : public I2C, public InterruptIn
+{
+public:
+    /*! @enum Init_err_t
+        @brief Error codes
+     */
+    typedef enum {
+        TOUCH_OK = 0,                   /*!< Initialization successful      */
+        TOUCH_INIT_ERR = -1,           	/*!< Communication interface err while configuring driver */
+		TOUCH_UNSUPP_ERR = -2,			/*!< Unsupported driver */
+        TOUCH_ERR = -3,         		/*!< unknown error */
+    } init_err_t;
+
+    /*! @enum EVENTLIST_t
+        @brief Type of the Event:
+     */
+    typedef enum {
+    	EV_STYLUS_UP =0,
+		EV_STYLUS_DOWN,
+		EV_STYLUS_HOLD,
+		//EV_STYLUS_MOVE,
+		NEVENTS
+    }EVENTLIST_t;
+
+    /*! @struct MSGQ_t
+        @brief Touch Message structure
+     */
+    typedef	struct {
+    	EVENTLIST_t			event;
+    	unsigned short 		start_idx;
+    	unsigned short 		stop_idx;
+    }MSGQ_t;
+
+    /** Constructor method of Touch object
+    */
+    Touch( const touch_config_t * tp_cfg = &STMPE811_cfg );
+
+    /** Destructor method of Touch object
+    */
+    virtual ~Touch( void );
+
+    /** Touch controller initialization
+     *  @retval       Error code
+     */
+    init_err_t Init();
+
+    /** Set Calibration data (raw data interpretation)
+     *  @retval       Error code
+     */
+    virtual init_err_t Clb_Setup();
+
+    /** Set Touch Controller settings
+    *  @retval       Error code
+    */
+    virtual init_err_t Drv_Setup();
+
+    /** Get Status of the pen
+     * @retval     	true	: StylusDown
+     * 				false	: StyluUp
+     */
+    virtual bool Get_Pen_Status();
+
+    /** Get one sample of data
+     *  @param[in]   raw: pointer to ring buffer to store the samples
+     */
+    virtual void Get_Data( unsigned long long * raw );
+
+    /** Get all available samples of data
+     *  @param[in]   raw: pointer to ring buffer to store the samples
+     *  @retval           samples count
+     */
+    virtual int Get_Fifo( unsigned long long * raw );
+
+    /** Transfer function (from raw coordinates to screen coordinates)
+     *  @param[in]	 points : number of samples to transfer
+     */
+    virtual void Get_XYZ( int points );
+
+    /** New Data available
+     */
+    static void Irq_Alert();
+
+    /** Pull the new samples if new data is available
+     */
+    virtual void Handle_touch();
+
+    /** Get index of the last sample in the ring buffer
+     */
+    virtual int Get_Last_Idx();
+
+    /** Get the minimum amounts of dots when pen is hold down
+     */
+    virtual int Get_Dot_thd();
+
+    /** Wait message from the touch thread
+     */
+    virtual osEvent Wait_MSG( uint32_t millisec=osWaitForever ) { return mail.get( millisec ); };
+
+    /** Delete message from the mail queue
+    */
+    virtual osStatus Del_MSG( MSGQ_t *ptr ) { return mail.free( ptr ); };
+
+    /** raw coordinates of the last received dot
+     */
+	unsigned short adc_x;
+	unsigned short adc_y;
+	unsigned short adc_z;
+
+    /** Coordinates of the last received dot
+     */
+    short x;
+	short y;
+	float z;
+
+	/** Raw History of the received dots
+	*/
+	const touch_raw_data_t *adc_data;
+
+	/** History of the received dots
+	*/
+	const touch_screen_data_t *xyz_data;
+
+protected:
+	/** Send message to the main application
+	 */
+	osStatus MSG(EVENTLIST_t touch_msg, unsigned short touch_on, unsigned short touch_off)
+	{
+		MSGQ_t * msg = mail.alloc();
+	    msg->event = touch_msg;
+	    msg->start_idx = touch_on;
+	   	msg->stop_idx = touch_off;
+	    return mail.put(msg);
+	};
+
+    int					 last_xyz_idx;
+    int					 dot_thd;
+    unsigned char		 fraction;
+    touch_raw_data_t	 raw_data[FIFO_DEPTH];
+    touch_screen_data_t  screen_data[FIFO_DEPTH];
+    const touch_config_t *touch_cfg;
+    touch_calib_data_t	 calib;
+    Thread		 		 thd;
+    Mail<MSGQ_t, 32> 	 mail;
+};
+
+} // namespace Vekatech
+
+#endif /* MBED_TOUCH_H */
diff -r 000000000000 -r 0383b9f88d72 stmpe811iic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stmpe811iic.h	Fri Nov 03 08:52:07 2017 +0000
@@ -0,0 +1,200 @@
+/*******************************************************************************
+
+*******************************************************************************/
+/******************************************************************************
+* File Name    : tpiic.h
+* Description  : TPIIC header
+******************************************************************************/
+#ifndef STMPE811IIC_H
+#define STMPE811IIC_H
+
+#ifdef LCD_PANEL_H
+#include "lcd_panel.h"
+#else
+/* TOUCH panels: */
+#define     LCD_CH0_PANEL_VKLCD50RTA            (1) /* 16bitRGB(565) [HVGA 480x272] */
+#define     LCD_CH0_PANEL_VKLCD70RT             (2) /* LVDS          [WSVGA 1024x600] */
+
+#define     LCD_VDC5_CH0_PANEL                  LCD_CH0_PANEL_VKLCD70RT
+#endif
+
+/******************************************************************************
+Includes   <System Includes> , "Project Includes"
+******************************************************************************/
+
+#define __USE_DEFAULT_CALIBRATION_DATA__
+
+#define STMPE811_DEVICE_ADDR   (0x82)
+//#define STMPE811_DEVICE_ADDR	(0x88)
+//#define EE_LPC11U35_DEVICE_ADDR (0xA0)
+
+#define TPIIC_CH      	3
+#define TPIIC_SCL		P1_6
+#define TPIIC_SDA		P1_7
+
+#if  (LCD_VDC5_CH0_PANEL==LCD_CH0_PANEL_VKLCD70RT)
+  #define TPIRQ_CH      1
+  #define TPIRQ_PIN     P7_8
+
+  #define EEIIC_CH	3
+  #define EEIIC_SCL	P1_6
+  #define EEIIC_SDA	P1_7
+  #define EE_CALIB_DEVICE_ADDR  0xA8
+
+  #define TPCALIBRATION_DATA				0x38,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\
+    0x50,0xb4,0x52,0x38,0xec,0x97,0xd0,0x3f,0xd7,0xfe,0x58,0xc5,0x10,0xb2,0x52,0x3f,\
+	0xde,0x09,0xc6,0x87,0xaa,0x7d,0xbb,0x3e,0x65,0xaa,0xb4,0xd2,0x56,0x04,0xc5,0xbf,\
+	0x02,0xb3,0x33,0x61,0x9b,0x1e,0x34,0xc0,0x88,0x87,0xc3,0x39,0x38,0x7d,0x83,0x40
+#else
+  #define TPIRQ_CH      2
+  #define TPIRQ_PIN     P1_2
+
+  #define EEIIC_CH		0
+  #define EEIIC_SCL		P1_0
+  #define EEIIC_SDA		P1_1
+  #define EE_CALIB_DEVICE_ADDR  0xA8
+
+  #define TPCALIBRATION_DATA				0x38,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\
+	0x66,0x44,0x6c,0xe9,0x11,0xa1,0xbf,0xbf,0x70,0x8f,0x61,0x1c,0x3f,0x5e,0x20,0x3f,\
+	0xad,0x80,0xca,0x76,0x62,0xb9,0x8a,0x3e,0xae,0x95,0xef,0x7e,0xa7,0x8d,0xb2,0xbf,\
+	0x24,0x37,0x82,0x68,0xe6,0xc1,0x7e,0x40,0xf4,0xb6,0xa8,0xe8,0x88,0xa3,0x71,0x40
+#endif
+
+#define FIFO_DEPTH     128      // packets, which means 12bit x + 12bit y +8bit = 32bit for 1 data packet
+
+//sys regs
+#define CHIP_ID        0x00     // 16 R 0x0811 Device identification
+#define ID_VER         0x02     // 8 R 0x01 Revision number 0x01 for engineering sample for final silicon
+#define SYS_CTRL1      0x03     // 8 R/W 0x00 Reset control
+#define SYS_CTRL2      0x04     // 8 R/W 0x0F Clock control
+#define SPI_CFG        0x08     // 8 R/W 0x01 SPI interface configuration
+#define INT_CTRL       0x09     // 8 R/W 0x00 Interrupt control register
+#define INT_EN         0x0A     // 8 R/W 0x00 Interrupt enable register
+#define INT_STA        0x0B     // 8 R 0x10 interrupt status register
+#define GPIO_EN        0x0C     // 8 R/W 0x00 GPIO interrupt enable register
+#define GPIO_INT_STA   0x0D     // 8 R 0x00 GPIO interrupt status register
+#define ADC_INT_EN     0x0E     // 8 R/W 0x00 ADC interrupt enable register
+#define ADC_INT_STA    0x0F     // 8 R 0x00 ADC interrupt status register
+#define GPIO_SET_PIN   0x10     // 8 R/W 0x00 GPIO set pin register
+#define GPIO_CLR_PIN   0x11     // 8 R/W 0x00 GPIO clear pin register
+#define GPIO_MP_STA    0x12     // 8 R/W 0x00 GPIO monitor pin state register
+#define GPIO_DIR       0x13     // 8 R/W 0x00 GPIO direction register
+#define GPIO_ED        0x14     // 8 R/W 0x00 GPIO edge detect register
+#define GPIO_RE        0x15     // 8 R/W 0x00 GPIO rising edge register
+#define GPIO_FE        0x16     // 8 R/W 0x00 GPIO falling edge register
+#define GPIO_AF        0x17     // 8 R/W 0x00 Alternate function register
+
+//ADC regs
+#define ADC_CTRL1      0x20     // 8 R/W 0x9C ADC control
+#define ADC_CTRL2      0x21     // 8 R/W 0x01 ADC control
+#define ADC_CAPT       0x22     // 8 R/W 0xFF To initiate ADC data acquisition
+#define ADC_DATA_CH0   0x30     // 16 R 0x0000 ADC channel 0
+#define ADC_DATA_CH1   0x32     // 16 R 0x0000 ADC channel 1
+#define ADC_DATA_CH2   0x34     // 16 R 0x0000 ADC channel 2
+#define ADC_DATA_CH3   0x36     // 16 R 0x0000 ADC channel 3
+#define ADC_DATA_CH4   0x38     // 16 R 0x0000 ADC channel 4
+#define ADC_DATA_CH5   0x3A     // 16 R 0x0000 ADC channel 5
+#define ADC_DATA_CH6   0x3C     // 16 R 0x0000 ADC channel 6
+#define ADC_DATA_CH7   0x3E     // 16 R 0x0000 ADC channel 7
+
+//touch regs
+#define TSC_CTRL       0x40     // 8 R/W 0x90 4-wire touchscreen controller setup
+#define TSC_CFG        0x41     // 8 R/W 0x00 Touchscreen controller configuration
+#define WDW_TR_X       0x42     // 16 R/W 0x0FFF Window setup for top right X
+#define WDW_TR_Y       0x44     // 16 R/W 0x0FFF Window setup for top right Y
+#define WDW_BL_X       0x46     // 16 R/W 0x0000 Window setup for bottom left X
+#define WDW_BL_Y       0x48     // 16 R/W 0x0000 Window setup for bottom left Y
+#define FIFO_TH        0x4A     // 8 R/W 0x00 FIFO level to generate interrupt
+#define FIFO_STA       0x4B     // 8 R/W 0x20 Current status of FIFO
+#define FIFO_SIZE      0x4C     // 8 R 0x00 Current filled level of FIFO
+#define TSC_DATA_X     0x4D     // 16 R 0x0000 Data port for touchscreen controller data access
+#define TSC_DATA_Y     0x4F     // 16 R 0x0000 Data port for touchscreen controller data access
+#define TSC_DATA_Z     0x51     // 8 R 0x0000 Data port for touchscreen controller data access
+#define TSC_DATA_XYZ   0x52     // 32 R 0x00000000 Data port for touchscreen controller data access
+#define TSC_FRACT_Z    0x56     // 8 0x00
+#define TSC_DATA_AI    0x57     // 8 R 0x00 Data port for touchscreen controller data access AUTO_INCREMENT
+#define TSC_DATA_NAI   0x07     // 8 R 0x00 Data port for touchscreen controller data access NONE_AUTO_INCREMENT
+#define TSC_DATA_FIFO  0xD7     //
+#define TSC_I_DRIVE    0x58     // 8 R/W 0x00
+#define TSC_SHIELD     0x59     // 8 R/W 0x00
+
+//temperature regs
+#define TEMP_CTRL      0x60     // 8 R/W 0x00 Temperature sensor setup
+#define TEMP_DATA      0x61     // 8 R 0x00 Temperature data access port
+#define TEMP_TH        0x62     // 8 R/W 0x00 Threshold for temperature controlled interrupt
+
+//interrupt status & enable bits
+#define INT_GPIO	   0x80
+#define INT_ADC        0x40
+#define INT_TEMP_SENS  0x20
+#define INT_FIFO_EMPTY 0x10
+#define INT_FIFO_FULL  0x08
+#define INT_FIFO_OFLOW 0x04
+#define INT_FIFO_TH    0x02
+#define INT_TOUCH_DET  0x01
+
+//other bits
+#define TSC_STA		   0x80
+
+//Z axis accuracy
+#define _8_0		   0x00
+#define _7_1		   0x01
+#define _6_2		   0x02
+#define _5_3		   0x03
+#define _4_4		   0x04
+#define _3_5		   0x05
+#define _2_6		   0x06
+#define _1_7		   0x07
+
+#define INIT_DATA											/* {register, value}, ...	*/																				\
+{SYS_CTRL1, 0x02},											/* 0. Reset touchscreen controller	*/																		\
+{SYS_CTRL2, 0x0C},											/* 1. Disable the clock gating for the touchscreen controller and ADC in the SYS_CFG2 register*/			\
+{INT_EN, (INT_FIFO_OFLOW | INT_FIFO_TH | INT_TOUCH_DET)},	/* 2. Configure which interrupts to be outputed */															\
+{ADC_CTRL1, 0x49},											/* 3. Write: register Add = 0x20 ADC_CTRL1, data = 0x49 delay, 2mS */										\
+{ADC_CTRL2, 0x01},											/* 4. Write: register Add = 0x21 ADC_CTRL2, data = 0x01 */													\
+{GPIO_AF,   0x00},											/* 5. Write: register Add = 0x17 GPIO_AF, data = 0x00 */													\
+{TSC_CFG,   0x6C},											/* 6. 5ms panel voltage setting time, 1ms touch detection delay, averaging on every 2-nd sample */			\
+{FIFO_TH,   0x05},											/* 7. Group points reading (if more than 4 points collected generate interrupt) */							\
+{FIFO_STA,  0x01},											/* 8a. Clear FIFO */																						\
+{FIFO_STA,  0x00},											/* 8b. Reset FIFO */																						\
+{TSC_FRACT_Z, _8_0},										/* 9. Choose the appropriate accurency of the measured pressure of the touch 7 fractional bits & 1 int */ 	\
+{TSC_I_DRIVE, 0x00},										/* 10. Write: register Add = 0x58 TSC_I_DRIVE, data = 0x01 */												\
+{TSC_CTRL,  0x01},											/* 11. Configure the operating mode and the window tracking index, start touch detection & data acquisition*/\
+{INT_STA,   0xFF},											/* 12. Clear Interrupt register*/ 																			\
+{INT_CTRL,  0x03},											/* 13. Configure the interrupt signal and enable the interrupts //int-> Edge interrupt -> falling edge*/
+
+/******************************************************************************
+Variable Externs
+******************************************************************************/
+
+typedef union __CALIB {
+	struct __DATA
+	{
+	 unsigned long len;
+	 unsigned long flag;
+		   double KX1, KY1, KX2, KY2, KX3, KY3;
+	}data;
+	unsigned char KX08[sizeof(struct __DATA)];
+}touch_calib_data_t;
+
+typedef union RAW_SAMPLE__ {
+	struct AXIS__
+    {
+		unsigned short x;
+        unsigned short y;
+        unsigned long  z;
+    }axis;
+    unsigned long long dot;
+}touch_raw_data_t;
+
+typedef union SCREEN_SAMPLE__ {
+	struct AXIS_
+    {
+		short x;
+        short y;
+        float z;
+    }axis;
+    unsigned long long dot;
+}touch_screen_data_t;
+
+#endif  /* STMPE811IIC_H */