Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Touch.cpp
00001 #include "Touch.hpp" 00002 00003 00004 00005 namespace Vekatech { 00006 00007 #define DISABLED 0 00008 #define LAST_SAMPLE 1 00009 #define ALL_SAMPLES 2 00010 00011 //Debug is disabled by default 00012 #define TOUCH_DBG DISABLED 00013 //#define MORE_DETAILS 00014 00015 #ifndef FUNCTION_NAME 00016 //#define FUNCTION_NAME "" 00017 //#define FUNCTION_NAME __func__ 00018 //#define FUNCTION_NAME __FUNCTION__ 00019 #define FUNCTION_NAME __PRETTY_FUNCTION__ 00020 #endif 00021 00022 #if (TOUCH_DBG > DISABLED) 00023 #ifdef MORE_DETAILS 00024 #define DBG(x, ...) printf("[DBG: %s:%s:%d] " x "\r\n", __FILE__, FUNCTION_NAME, __LINE__, ##__VA_ARGS__) 00025 #else 00026 #define DBG(x, ...) printf("[DBG:] " x "\r\n", ##__VA_ARGS__) 00027 #endif 00028 #else 00029 #define DBG(x, ...) 00030 #endif 00031 00032 #if (TOUCH_DBG > LAST_SAMPLE) 00033 #ifdef MORE_DETAILS 00034 #define DBG_MORE(x, ...) printf("[DBG_MORE: %s:%s:%d] " x "\r\n", __FILE__, FUNCTION_NAME, __LINE__, ##__VA_ARGS__) 00035 #else 00036 #define DBG_MORE(x, ...) printf("[DBG_MORE:] " x "\r\n", ##__VA_ARGS__) 00037 #endif 00038 #else 00039 #define DBG_MORE(x, ...) 00040 #endif 00041 00042 #if (TOUCH_DBG > ALL_SAMPLES) 00043 #ifdef MORE_DETAILS 00044 #define DBG_ALL(x, ...) printf("[DBG_ALL: %s:%s:%d] " x "\r\n", __FILE__, FUNCTION_NAME, __LINE__, ##__VA_ARGS__) 00045 #else 00046 #define DBG_ALL(x, ...) printf("[DBG_ALL:] " x "\r\n", ##__VA_ARGS__) 00047 #endif 00048 #else 00049 #define DBG_ALL(x, ...) 00050 #endif 00051 00052 00053 00054 #define NEW_TOUCH_DATA 0x1 00055 00056 const touch_config_t STMPE811_cfg = { 00057 "STMPE811", LCD_VDC5_CH0_PANEL, RESISTIVE, 00058 {I_2_C, TPIIC_SDA, TPIIC_SCL, NC, NC, NC, NC, 100000}, 00059 {INT_ON_EDGE, FALLING_OR_ACTIVE_LO, TPIRQ_PIN} 00060 }; 00061 00062 osThreadId TouchThreadID; 00063 00064 /**************************************************************************//** 00065 * @brief Constructor of the Touch class 00066 * @param[in] pointer to Config structure (touch_config_t) 00067 ******************************************************************************/ 00068 //SPI(tp_cfg->interface.mosi, tp_cfg->interface.miso, tp_cfg->interface.sclk, tp_cfg->interface.ssel), 00069 Touch::Touch( const touch_config_t * tp_cfg ) : I2C(tp_cfg->interface.sda, tp_cfg->interface.scl), InterruptIn(tp_cfg->activity_irq.pin) 00070 { 00071 if(tp_cfg == NULL) 00072 touch_cfg = &STMPE811_cfg; 00073 else 00074 touch_cfg = tp_cfg; 00075 00076 x = y = z = 0; adc_x = adc_y = adc_z = 0; 00077 xyz_data = screen_data; adc_data = raw_data; 00078 last_xyz_idx = FIFO_DEPTH-1; 00079 00080 dot_thd = 0; 00081 fraction = 0; 00082 calib.data.flag = 0; 00083 } /* End of constructor */ 00084 00085 00086 /**************************************************************************//** 00087 * @brief Destructor of the Touch class 00088 ******************************************************************************/ 00089 Touch::~Touch( ) 00090 { 00091 Thread::State S = thd.get_state(); 00092 00093 disable_irq(); 00094 00095 if((S != Thread::Inactive) && (S != Thread::Deleted)) 00096 { 00097 thd.terminate(); 00098 thd.join(); 00099 } 00100 00101 touch_cfg = NULL; 00102 xyz_data = NULL; 00103 adc_data = NULL; 00104 } 00105 00106 00107 /**************************************************************************//** 00108 * @brief Touch controller initialization 00109 * @retval error code 00110 ******************************************************************************/ 00111 Touch::init_err_t Touch::Init( void ) 00112 { 00113 init_err_t tp_err; 00114 00115 if(touch_cfg->type == RESISTIVE) 00116 { 00117 tp_err = Clb_Setup(); 00118 00119 if(tp_err != TOUCH_OK ) 00120 return tp_err; 00121 } 00122 00123 if(touch_cfg->interface.type == I_2_C) 00124 I2C::frequency(touch_cfg->interface.freq); 00125 //else 00126 //SPI::frequency(touch_cfg->interface.freq); 00127 00128 tp_err = Drv_Setup(); 00129 00130 if(tp_err != TOUCH_OK ) 00131 return tp_err; 00132 else 00133 { 00134 thd.start(callback(this, &Touch::Handle_touch)); 00135 00136 if(touch_cfg->activity_irq.polarity == FALLING_OR_ACTIVE_LO) 00137 { 00138 rise(NULL); 00139 fall(Irq_Alert); 00140 } 00141 else 00142 { 00143 rise(Irq_Alert); 00144 fall(NULL); 00145 } 00146 00147 enable_irq(); 00148 } 00149 00150 return tp_err; 00151 } /* End of method Init() */ 00152 00153 00154 /**************************************************************************//** 00155 * @brief Set Calibration data 00156 * @retval error code 00157 ******************************************************************************/ 00158 Touch::init_err_t Touch::Clb_Setup() 00159 { 00160 if(touch_cfg->name == "STMPE811") 00161 { 00162 #ifndef __USE_DEFAULT_CALIBRATION_DATA__ 00163 // extract calibration info from lcdpanel EEPROM 00164 char adr = 0; 00165 00166 if( (touch_cfg->interface.sda == EEIIC_SDA) || (touch_cfg->interface.scl == EEIIC_SCL)) 00167 { // lcdpanel EEPROM is on the same I2C channel no need to initialize a new one ! 00168 if(I2C::write(EE_CALIB_DEVICE_ADDR, (const char *)&adr, 1, true) != 0) 00169 return TOUCH_INIT_ERR ; 00170 if(I2C::read(EE_CALIB_DEVICE_ADDR, (char*)calib.KX08, sizeof(calib.KX08)) != 0) 00171 return TOUCH_INIT_ERR ; 00172 } 00173 else 00174 { // lcdpanel EEPROM is on different I2C channel so initialize a new one ! 00175 I2C clb_eeprom(EEIIC_SDA, EEIIC_SCL); 00176 00177 clb_eeprom.frequency(100000); 00178 if(clb_eeprom.write(EE_CALIB_DEVICE_ADDR, (const char *)&adr, 1, true) != 0) 00179 return TOUCH_INIT_ERR ; 00180 if(clb_eeprom.read(EE_CALIB_DEVICE_ADDR, (char*)calib.KX08, sizeof(calib.KX08)) != 0) 00181 return TOUCH_INIT_ERR ; 00182 } 00183 #endif 00184 00185 if(calib.data.flag != 1) 00186 { // load default calibration info 00187 unsigned char clb[] = {TPCALIBRATION_DATA}; 00188 memcpy(calib.KX08, clb, sizeof(clb)); 00189 } 00190 00191 return TOUCH_OK ; 00192 } 00193 else 00194 return TOUCH_UNSUPP_ERR ; 00195 } /* End of method Clb_Setup() */ 00196 00197 00198 /**************************************************************************//** 00199 * @brief Set Touch Controller settings 00200 * @retval error code 00201 ******************************************************************************/ 00202 Touch::init_err_t Touch::Drv_Setup() 00203 { 00204 if(touch_cfg->name == "STMPE811") 00205 { 00206 unsigned char i, initdata[][2] = { INIT_DATA }; 00207 00208 for(i=0; i<(sizeof(initdata)>>1); i++) 00209 { 00210 if(initdata[i][0] == INT_CTRL) 00211 { // reconfigure interrupt if needed 00212 initdata[i][1] = 0x01; 00213 initdata[i][1] |= (touch_cfg->activity_irq.trigger == INT_ON_EDGE)? 0x02 : 0x00; 00214 initdata[i][1] |= (touch_cfg->activity_irq.polarity == RISING_OR_ACTIVE_HI)? 0x04 : 0x00; 00215 } 00216 00217 if(initdata[i][0] == FIFO_TH) 00218 { // save threshold 00219 if(initdata[i][1] < 2) 00220 initdata[i][1] = 2; 00221 00222 dot_thd = initdata[i][1]-1; 00223 } 00224 00225 if(initdata[i][0] == TSC_FRACT_Z) 00226 fraction = initdata[i][1]; // save z precision 00227 00228 if ((I2C::write(STMPE811_DEVICE_ADDR, (const char *)&initdata[i][0], 2)) != 0) 00229 return TOUCH_INIT_ERR ; 00230 00231 while (I2C::write(STMPE811_DEVICE_ADDR, (const char *)initdata, 0) != 0); // ACK polling 00232 } 00233 00234 return TOUCH_OK ; 00235 } 00236 else 00237 return TOUCH_UNSUPP_ERR ; 00238 } 00239 00240 00241 /**************************************************************************//** 00242 * @brief Get Status of the pen 00243 * @retval true : StylusDown 00244 * false : StyluUp 00245 ******************************************************************************/ 00246 bool Touch::Get_Pen_Status() 00247 { 00248 if(touch_cfg->name == "STMPE811") 00249 { 00250 unsigned char pen = TSC_CTRL; 00251 00252 I2C::write(STMPE811_DEVICE_ADDR, (const char *)&pen, 1, true); 00253 pen = 0; 00254 I2C::read(STMPE811_DEVICE_ADDR, (char *)&pen, 1); 00255 00256 return (pen & TSC_STA)? true : false; 00257 } 00258 else 00259 return false; 00260 } /* End of method Get_Pen_Status() */ 00261 00262 00263 /**************************************************************************//** 00264 * @brief Get one sample of data 00265 * @param[in] * raw : pointer to ring buffer to store the samples 00266 ******************************************************************************/ 00267 void Touch::Get_Data( unsigned long long * raw ) 00268 { 00269 if(touch_cfg->name == "STMPE811") 00270 { 00271 int idx = last_xyz_idx; 00272 unsigned char i, packed_sample[dot_thd * 4]; 00273 unsigned short raw_x, raw_y; 00274 unsigned char raw_z; 00275 00276 i = TSC_DATA_FIFO; 00277 I2C::write(STMPE811_DEVICE_ADDR, (const char *)&i, 1, true); 00278 I2C::read(STMPE811_DEVICE_ADDR, (char *)packed_sample, sizeof(packed_sample)); 00279 for(i=0; i<dot_thd; i++) 00280 { 00281 raw_x = (unsigned short)((packed_sample[(i*4)+0]<<4) | (packed_sample[(i*4)+1]>>4)); 00282 raw_y = (unsigned short)(((0x0F & packed_sample[(i*4)+1])<<8) | packed_sample[(i*4)+2]); 00283 raw_z = packed_sample[(i*4)+3]; 00284 00285 idx = ((idx+1) < FIFO_DEPTH)? idx+1 : 0; 00286 ((touch_raw_data_t*)raw)[idx].axis.x = raw_x; 00287 ((touch_raw_data_t*)raw)[idx].axis.y = raw_y; 00288 ((touch_raw_data_t*)raw)[idx].axis.z = raw_z; 00289 } 00290 } 00291 } /* End of method Get_Data() */ 00292 00293 00294 /**************************************************************************//** 00295 * @brief Get all available samples of data 00296 * @param[in] * raw : pointer to ring buffer to store the samples 00297 * @retval samples count 00298 ******************************************************************************/ 00299 int Touch::Get_Fifo( unsigned long long * raw ) 00300 { 00301 if(touch_cfg->name == "STMPE811") 00302 { 00303 int idx = last_xyz_idx; 00304 unsigned char packets; 00305 00306 packets = FIFO_SIZE; 00307 I2C::write(STMPE811_DEVICE_ADDR, (const char *)&packets, 1, true); 00308 packets = 0; 00309 I2C::read(STMPE811_DEVICE_ADDR, (char *)&packets, 1); 00310 if(packets) 00311 { 00312 unsigned char packed_sample[packets * 4]; 00313 unsigned short raw_x, raw_y, i; 00314 unsigned char raw_z; 00315 00316 raw_z = TSC_DATA_FIFO; 00317 I2C::write(STMPE811_DEVICE_ADDR, (const char *)&raw_z, 1, true); 00318 I2C::read(STMPE811_DEVICE_ADDR, (char *)packed_sample, packets*4); 00319 00320 for(i=0; i<packets; i++) 00321 { 00322 raw_x = (unsigned short)((packed_sample[(i*4)+0]<<4) | (packed_sample[(i*4)+1]>>4)); 00323 raw_y = (unsigned short)(((0x0F & packed_sample[(i*4)+1])<<8) | packed_sample[(i*4)+2]); 00324 raw_z = packed_sample[(i*4)+3]; 00325 00326 idx = ((idx+1) < FIFO_DEPTH)? idx+1 : 0; 00327 ((touch_raw_data_t*)raw)[idx].axis.x = raw_x; 00328 ((touch_raw_data_t*)raw)[idx].axis.y = raw_y; 00329 ((touch_raw_data_t*)raw)[idx].axis.z = raw_z; 00330 } 00331 00332 return packets; 00333 } 00334 return 0; 00335 } 00336 else 00337 return 0; 00338 } /* End of method Get_Fifo() */ 00339 00340 00341 /**************************************************************************//** 00342 * @brief Coordinates Transfer function 00343 * @param[in] points : number of samples which have to become meaningful 00344 ******************************************************************************/ 00345 void Touch::Get_XYZ( int points) 00346 { 00347 if(touch_cfg->name == "STMPE811") 00348 { 00349 int i, idx; 00350 00351 for(i=0; i<points; i++) 00352 { 00353 idx = ((last_xyz_idx+1) < FIFO_DEPTH)? last_xyz_idx+1 : 0; 00354 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); 00355 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); 00356 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))); 00357 last_xyz_idx = idx; 00358 #ifdef MORE_DETAILS 00359 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); 00360 #else 00361 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); 00362 #endif 00363 } 00364 00365 x = screen_data[last_xyz_idx].axis.x; adc_x = raw_data[last_xyz_idx].axis.x; 00366 y = screen_data[last_xyz_idx].axis.y; adc_y = raw_data[last_xyz_idx].axis.y; 00367 z = screen_data[last_xyz_idx].axis.z; adc_z = raw_data[last_xyz_idx].axis.z; 00368 #ifdef MORE_DETAILS 00369 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); 00370 #else 00371 DBG("S_No: (%d) X-> %d, Y-> %d, Z-> %f, dots-> %d", last_xyz_idx, x, y, z, points); 00372 #endif 00373 } 00374 } /* End of method Get_XYZ() */ 00375 00376 00377 /**************************************************************************//** 00378 * @brief IRQ interrupt handler : indicates "New Touch Data available" which activates i2c data transfer in Handle_touch() 00379 ******************************************************************************/ 00380 void Touch::Irq_Alert() 00381 { 00382 // Execute the time critical part first 00383 00384 // Then the rest can execute later in user context (and can contain code that's not interrupt safe). 00385 osSignalSet(TouchThreadID, NEW_TOUCH_DATA); 00386 } 00387 00388 00389 /**************************************************************************//** 00390 * @brief Get index of the last sample in the ring buffer 00391 * @retval idx 00392 ******************************************************************************/ 00393 int Touch::Get_Last_Idx() { return last_xyz_idx; } 00394 00395 /**************************************************************************//** 00396 * @brief Get dot collection threshold 00397 * @retval threshold 00398 ******************************************************************************/ 00399 int Touch::Get_Dot_thd() { return dot_thd; } 00400 00401 /**************************************************************************//** 00402 * @brief Pull the new samples if new touch data is available 00403 ******************************************************************************/ 00404 void Touch::Handle_touch() 00405 { 00406 bool Stylus = false; 00407 bool Click_send = false; 00408 unsigned short idx_on = 0; 00409 unsigned char TP_IntStat = 0, rec[2]; 00410 int dots = 0; 00411 osEvent evt; 00412 00413 TouchThreadID = thd.gettid(); 00414 00415 while (true) 00416 { 00417 evt = thd.signal_wait(NEW_TOUCH_DATA); 00418 00419 if(evt.status == osEventSignal) 00420 { 00421 if(touch_cfg->name == "STMPE811") 00422 { 00423 TP_IntStat = INT_STA; 00424 I2C::write(STMPE811_DEVICE_ADDR, (const char *)&TP_IntStat, 1, true); 00425 TP_IntStat = 0; 00426 I2C::read(STMPE811_DEVICE_ADDR, (char *)&TP_IntStat, 1); 00427 00428 if(TP_IntStat & INT_FIFO_TH) 00429 { 00430 Get_Data(&raw_data[0].dot); 00431 Get_XYZ(dot_thd); 00432 if(Stylus) 00433 { 00434 if(!Click_send) 00435 { 00436 MSG(EV_STYLUS_DOWN, idx_on, 0); 00437 Click_send = true; 00438 } 00439 MSG(EV_STYLUS_HOLD, idx_on, last_xyz_idx); 00440 } 00441 } 00442 00443 if(TP_IntStat & INT_TOUCH_DET) 00444 { 00445 Stylus = Get_Pen_Status(); 00446 DBG("Pen: %s", (Stylus)? "DOWN" : "UP"); 00447 00448 dots = Get_Fifo(&raw_data[0].dot); 00449 if(dots) 00450 { 00451 Get_XYZ(dots); 00452 00453 if(Stylus) 00454 { 00455 int on = (last_xyz_idx+1) - dots; 00456 idx_on = (on<0)? (FIFO_DEPTH-on) : on; 00457 MSG(EV_STYLUS_DOWN, idx_on, 0); 00458 Click_send = true; 00459 } 00460 else 00461 { 00462 if(!Click_send) 00463 { 00464 MSG(EV_STYLUS_DOWN, idx_on, 0); 00465 Click_send = true; 00466 } 00467 MSG(EV_STYLUS_UP, idx_on, last_xyz_idx); 00468 } 00469 } 00470 else 00471 { 00472 if(Stylus) 00473 { 00474 Click_send = false; 00475 idx_on = (last_xyz_idx == (FIFO_DEPTH-1))? 0 : last_xyz_idx+1; 00476 } 00477 else 00478 { 00479 if(Click_send) 00480 MSG( EV_STYLUS_UP, idx_on, last_xyz_idx); 00481 } 00482 } 00483 } 00484 00485 if(TP_IntStat & INT_FIFO_OFLOW) 00486 { 00487 DBG("Overflow !!!"); 00488 00489 rec[0] = FIFO_STA; 00490 rec[1] = 0x01; // Clear FIFO 00491 I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2); 00492 00493 rec[1] = 0x00; // Reset FIFO 00494 I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2); 00495 } 00496 00497 rec[0] = INT_STA; 00498 rec[1] = TP_IntStat; 00499 I2C::write(STMPE811_DEVICE_ADDR, (const char *)rec, 2); 00500 } 00501 } 00502 else 00503 { 00504 DBG("Abnormal Touch Thread Status: 0x%X", evt.status); 00505 } 00506 } 00507 } 00508 00509 } // namespace Vekatech 00510 00511 /* End of file */
Generated on Tue Jul 12 2022 21:44:43 by
1.7.2