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.
Dependencies: DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos
Fork of DMSupport by
BiosTouch.cpp
00001 /* 00002 * Copyright 2014 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "BiosTouch.h" 00019 #include "BiosLoader.h" 00020 #include "DMBoard.h" 00021 #include "bios.h" 00022 #include "meas.h" 00023 00024 /****************************************************************************** 00025 * Defines and typedefs 00026 *****************************************************************************/ 00027 00028 #define NUM_COORDS 5 00029 #define NUM_MAILS 10 00030 typedef struct { 00031 touch_coordinate_t touch[NUM_COORDS]; 00032 int num; 00033 } touch_mail_t; 00034 00035 #define SIG_NEW_DATA 0x1 00036 class TouchHandler { 00037 public: 00038 TouchHandler(bios_header_t* bios, void* biosData, int num) : 00039 _latest(NULL), _touchIRQ(P2_25), _bios(bios), 00040 _biosData(biosData), _points(num), 00041 _listener(NULL), _lostData(0), 00042 _dbgAdded(0), _dbgRemoved(0) {} 00043 void handleTouchInterrupt(); 00044 void handleNewData(touch_coordinate_t* coord, int num); 00045 void changeTouchInterrupt(bool enable, touch_irq_trigger_t trigger); 00046 TouchPanel::TouchError read(touch_coordinate_t* coord, int num); 00047 void run(); 00048 FunctionPointer* setListener(FunctionPointer* listener); 00049 private: 00050 Mail<touch_mail_t, NUM_MAILS> _mailbox; 00051 Mutex _mutex; 00052 touch_coordinate_t* _latest; 00053 InterruptIn _touchIRQ; 00054 bios_header_t* _bios; 00055 void* _biosData; 00056 int _points; 00057 FunctionPointer* _listener; 00058 uint32_t _lostData; 00059 uint32_t _dbgAdded; 00060 uint32_t _dbgRemoved; 00061 }; 00062 00063 /****************************************************************************** 00064 * Local variables 00065 *****************************************************************************/ 00066 00067 /****************************************************************************** 00068 * Private Functions 00069 *****************************************************************************/ 00070 00071 BiosTouch::BiosTouch() : 00072 _initialized(false), 00073 _haveInfo(false), 00074 _poweredOn(false), 00075 //_touchIRQ(P2_25), 00076 _bios(NULL), 00077 _biosData(NULL), 00078 _handlerThread(NULL), 00079 _handler(NULL), 00080 _supportsTouch(false) 00081 { 00082 } 00083 00084 BiosTouch::~BiosTouch() 00085 { 00086 // _bios and _biosData are deallocated by BiosLoader 00087 00088 if (_handlerThread != NULL) { 00089 delete _handlerThread; 00090 _handlerThread = NULL; 00091 } 00092 if (_handler != NULL) { 00093 delete _handler; 00094 _handler = NULL; 00095 } 00096 } 00097 00098 // Function called from the BIOS 00099 static void touchIrqEnabler(uint32_t arg, bool enable, touch_irq_trigger_t trigger) 00100 { 00101 ((TouchHandler*)arg)->changeTouchInterrupt(enable, trigger); 00102 } 00103 00104 // Function called from the BIOS 00105 static void touchNewData(uint32_t arg, touch_coordinate_t* coords, int num) 00106 { 00107 ((TouchHandler*)arg)->handleNewData(coords, num); 00108 } 00109 00110 static void touchTask(void const* args) 00111 { 00112 ((TouchHandler*)args)->run(); 00113 } 00114 00115 00116 void TouchHandler::run() 00117 { 00118 RtosLog* log = DMBoard::instance().logger(); 00119 00120 _latest = (touch_coordinate_t*)malloc(_points*sizeof(touch_coordinate_t)); 00121 if (_latest == NULL) { 00122 log->printf("Failed to allocate memory for touch events\n"); 00123 mbed_die(); 00124 } 00125 memset(_latest, 0, _points*sizeof(touch_coordinate_t)); 00126 if (_points > 1) { 00127 // multitouch - inject end event if missing 00128 uint32_t maxDelay = osWaitForever; 00129 while(true) { 00130 osEvent evt = _mailbox.get(maxDelay); 00131 if (evt.status == osEventMail) { 00132 touch_mail_t* mail = (touch_mail_t*)evt.value.p; 00133 memcpy(_latest, mail->touch, mail->num * sizeof(touch_coordinate_t)); 00134 _mailbox.free(mail); 00135 _dbgRemoved++; 00136 maxDelay = 25; // wait up to 25ms for next event before injecting a "pen up" event 00137 } else if (evt.status == osEventTimeout) { 00138 int numNonZero = 0; 00139 for (int i = 0; i < _points; i++) { 00140 if (_latest[i].z > 0) { 00141 numNonZero++; 00142 } 00143 _latest[i].z = 0; 00144 } 00145 maxDelay = osWaitForever; 00146 if (numNonZero == 0) { 00147 // last event was a pen-up event so no need to inject one 00148 //log->printf("skip penup\n"); 00149 continue; 00150 } 00151 //log->printf("inject penup\n"); 00152 } else { 00153 log->printf("got non-mail event: 0x%x\n", evt.status); 00154 continue; 00155 } 00156 _mutex.lock(); 00157 FunctionPointer* fp = _listener; 00158 _mutex.unlock(); 00159 00160 if (fp != NULL) { 00161 fp->call(); 00162 } 00163 } 00164 } else { 00165 // normal singe-touch 00166 while(true) { 00167 osEvent evt = _mailbox.get(osWaitForever); 00168 if (evt.status == osEventMail) { 00169 touch_mail_t* mail = (touch_mail_t*)evt.value.p; 00170 memcpy(_latest, mail->touch, mail->num * sizeof(touch_coordinate_t)); 00171 _mailbox.free(mail); 00172 _dbgRemoved++; 00173 } else { 00174 log->printf("got non-mail event: 0x%x\n", evt.status); 00175 continue; 00176 } 00177 _mutex.lock(); 00178 FunctionPointer* fp = _listener; 00179 _mutex.unlock(); 00180 00181 if (fp != NULL) { 00182 fp->call(); 00183 } 00184 } 00185 } 00186 } 00187 00188 TouchPanel::TouchError TouchHandler::read(touch_coordinate_t* coord, int num) 00189 { 00190 if (num > _points || num < 1) { 00191 return TouchPanel::TouchError_InvalidParam; 00192 } 00193 _mutex.lock(); 00194 memcpy(coord, _latest, num*sizeof(touch_coordinate_t)); 00195 _mutex.unlock(); 00196 00197 return TouchPanel::TouchError_Ok; 00198 } 00199 00200 void TouchHandler::handleTouchInterrupt() 00201 { 00202 _bios->touchIrqHandler(_biosData); 00203 } 00204 00205 void TouchHandler::handleNewData(touch_coordinate_t* coord, int num) 00206 { 00207 touch_mail_t* mail = _mailbox.alloc(0); 00208 if (mail == NULL) { 00209 //DMBoard::instance().logger()->printf("Lost touch event\n"); 00210 _lostData++; 00211 } else { 00212 _dbgAdded++; 00213 mail->num = (num < NUM_COORDS) ? num : NUM_COORDS; 00214 memcpy(&mail->touch, coord, mail->num*sizeof(touch_coordinate_t)); 00215 _mailbox.put(mail); 00216 } 00217 } 00218 00219 void TouchHandler::changeTouchInterrupt(bool enable, touch_irq_trigger_t trigger) 00220 { 00221 switch (trigger) { 00222 case TOUCH_IRQ_RISING_EDGE: 00223 if (enable) { 00224 _touchIRQ.rise(this, &TouchHandler::handleTouchInterrupt); 00225 } else { 00226 _touchIRQ.rise(NULL); 00227 } 00228 break; 00229 00230 case TOUCH_IRQ_FALLING_EDGE: 00231 if (enable) { 00232 _touchIRQ.fall(this, &TouchHandler::handleTouchInterrupt); 00233 } else { 00234 _touchIRQ.fall(NULL); 00235 } 00236 break; 00237 00238 case TOUCH_IRQ_HIGH_LEVEL: 00239 case TOUCH_IRQ_LOW_LEVEL: 00240 default: 00241 DMBoard::instance().logger()->printf("BIOS requests unknown trigger type %d\n", trigger); 00242 break; 00243 } 00244 } 00245 00246 FunctionPointer* TouchHandler::setListener(FunctionPointer* listener) 00247 { 00248 _mutex.lock(); 00249 FunctionPointer* old = _listener; 00250 _listener = listener; 00251 _mutex.unlock(); 00252 return old; 00253 } 00254 00255 00256 /****************************************************************************** 00257 * Public Functions 00258 *****************************************************************************/ 00259 00260 BiosTouch::TouchError BiosTouch::init() 00261 { 00262 TouchError result = TouchError_Ok; 00263 if (!_initialized) { 00264 do { 00265 if (BiosLoader::instance().params(&_bios, &_biosData) != DMBoard::Ok) { 00266 result = TouchError_ConfigError; 00267 break; 00268 } 00269 00270 result = (TouchError)_bios->touchInformation(_biosData, &_supportsTouch, &_supportsTouchCalibration, &_touchNumFingers); 00271 if (result != TouchError_Ok) { 00272 break; 00273 } 00274 _haveInfo = true; 00275 00276 // is it supported at all? 00277 if (!_supportsTouch) { 00278 result = TouchError_TouchNotSupported; 00279 break; 00280 } 00281 00282 _handler = new TouchHandler(_bios, _biosData, _touchNumFingers); 00283 00284 result = (TouchError)_bios->touchInit(_biosData, touchIrqEnabler, (uint32_t)_handler, touchNewData, (uint32_t)_handler); 00285 if (result != TouchError_Ok) { 00286 break; 00287 } 00288 00289 result = (TouchError)_bios->touchPowerUp(_biosData); 00290 if (result != TouchError_Ok) { 00291 break; 00292 } 00293 00294 _handlerThread = new Thread(touchTask, _handler); 00295 00296 _initialized = true; 00297 } while(0); 00298 00299 if (!_initialized) { 00300 if (_handler != NULL) { 00301 delete _handler; 00302 _handler = NULL; 00303 } 00304 } 00305 } 00306 return result; 00307 } 00308 00309 BiosTouch::TouchError BiosTouch::read(touch_coordinate_t &coord) 00310 { 00311 TouchError err = TouchError_Ok; 00312 if (!_initialized) { 00313 err = TouchError_NoInit; 00314 } else { 00315 err = _handler->read(&coord, 1); 00316 } 00317 return err; 00318 } 00319 00320 BiosTouch::TouchError BiosTouch::read(touch_coordinate_t* coord, int num) 00321 { 00322 TouchError err = TouchError_Ok; 00323 if (!_initialized) { 00324 err = TouchError_NoInit; 00325 } else { 00326 err = _handler->read(coord, num); 00327 } 00328 return err; 00329 } 00330 00331 BiosTouch::TouchError BiosTouch::info(bool* resistive, int* maxPoints, bool* calibrated) 00332 { 00333 TouchError err = TouchError_Ok; 00334 if (!_haveInfo) { 00335 err = TouchError_NoInit; 00336 } else { 00337 *maxPoints = _touchNumFingers; 00338 *calibrated = _supportsTouchCalibration; 00339 } 00340 return err; 00341 } 00342 00343 bool BiosTouch::isTouchSupported() 00344 { 00345 #if defined(DM_BOARD_USE_TOUCH) 00346 if (_haveInfo) { 00347 return _supportsTouch; 00348 } 00349 #endif 00350 return false; 00351 } 00352 00353 BiosTouch::TouchError BiosTouch::calibrateStart() 00354 { 00355 TouchError err = TouchError_Ok; 00356 if (!_initialized) { 00357 err = TouchError_NoInit; 00358 } else { 00359 err = (TouchError)_bios->touchCalibrateStart(_biosData); 00360 } 00361 return err; 00362 } 00363 00364 BiosTouch::TouchError BiosTouch::getNextCalibratePoint(uint16_t* x, uint16_t* y, bool* last) 00365 { 00366 TouchError err = TouchError_Ok; 00367 if (!_initialized) { 00368 err = TouchError_NoInit; 00369 } else { 00370 err = (TouchError)_bios->touchGetNextCalibPoint(_biosData, x, y, last); 00371 } 00372 return err; 00373 } 00374 00375 BiosTouch::TouchError BiosTouch::waitForCalibratePoint(bool* morePoints, uint32_t timeout) 00376 { 00377 TouchError err = TouchError_Ok; 00378 if (!_initialized) { 00379 err = TouchError_NoInit; 00380 } else { 00381 err = (TouchError)_bios->touchWaitForCalibratePoint(_biosData, morePoints, timeout); 00382 } 00383 return err; 00384 } 00385 00386 FunctionPointer* BiosTouch::setListener(FunctionPointer* listener) 00387 { 00388 if (_initialized) { 00389 return _handler->setListener(listener); 00390 } 00391 return NULL; 00392 }
Generated on Tue Jul 12 2022 21:29:01 by
1.7.2
