Touch driver for companion boards (VKLCD50RTA & VKLCD70RT)
Revision 0:0383b9f88d72, committed 2017-11-03
- Comitter:
- tvendov
- Date:
- Fri Nov 03 08:52:07 2017 +0000
- Commit message:
- Touch panel driver initial release
Changed in this revision
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 */