A board support package for the LPC4088 Display Module.
Dependencies: DM_HttpServer DM_USBHost
Dependents: lpc4088_displaymodule_emwin lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI ... more
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 void setListener(Callback<void()> 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 Callback<void()> _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 00157 if (_listener) { 00158 _listener(); 00159 } 00160 } 00161 } else { 00162 // normal singe-touch 00163 while(true) { 00164 osEvent evt = _mailbox.get(osWaitForever); 00165 if (evt.status == osEventMail) { 00166 touch_mail_t* mail = (touch_mail_t*)evt.value.p; 00167 memcpy(_latest, mail->touch, mail->num * sizeof(touch_coordinate_t)); 00168 _mailbox.free(mail); 00169 _dbgRemoved++; 00170 } else { 00171 log->printf("got non-mail event: 0x%x\n", evt.status); 00172 continue; 00173 } 00174 00175 if (_listener) { 00176 _listener(); 00177 } 00178 } 00179 } 00180 } 00181 00182 TouchPanel::TouchError TouchHandler::read(touch_coordinate_t* coord, int num) 00183 { 00184 if (num > _points || num < 1) { 00185 return TouchPanel::TouchError_InvalidParam; 00186 } 00187 _mutex.lock(); 00188 memcpy(coord, _latest, num*sizeof(touch_coordinate_t)); 00189 _mutex.unlock(); 00190 00191 return TouchPanel::TouchError_Ok; 00192 } 00193 00194 void TouchHandler::handleTouchInterrupt() 00195 { 00196 _bios->touchIrqHandler(_biosData); 00197 } 00198 00199 void TouchHandler::handleNewData(touch_coordinate_t* coord, int num) 00200 { 00201 touch_mail_t* mail = _mailbox.alloc(0); 00202 if (mail == NULL) { 00203 //DMBoard::instance().logger()->printf("Lost touch event\n"); 00204 _lostData++; 00205 } else { 00206 _dbgAdded++; 00207 mail->num = (num < NUM_COORDS) ? num : NUM_COORDS; 00208 memcpy(&mail->touch, coord, mail->num*sizeof(touch_coordinate_t)); 00209 _mailbox.put(mail); 00210 } 00211 } 00212 00213 void TouchHandler::changeTouchInterrupt(bool enable, touch_irq_trigger_t trigger) 00214 { 00215 switch (trigger) { 00216 case TOUCH_IRQ_RISING_EDGE: 00217 if (enable) { 00218 _touchIRQ.rise(callback(this, &TouchHandler::handleTouchInterrupt)); 00219 } else { 00220 _touchIRQ.rise(NULL); 00221 } 00222 break; 00223 00224 case TOUCH_IRQ_FALLING_EDGE: 00225 if (enable) { 00226 _touchIRQ.fall(callback(this, &TouchHandler::handleTouchInterrupt)); 00227 } else { 00228 _touchIRQ.fall(NULL); 00229 } 00230 break; 00231 00232 case TOUCH_IRQ_HIGH_LEVEL: 00233 case TOUCH_IRQ_LOW_LEVEL: 00234 default: 00235 DMBoard::instance().logger()->printf("BIOS requests unknown trigger type %d\n", trigger); 00236 break; 00237 } 00238 } 00239 00240 void TouchHandler::setListener(Callback<void()> listener) 00241 { 00242 _mutex.lock(); 00243 _listener = listener; 00244 _mutex.unlock(); 00245 } 00246 00247 00248 /****************************************************************************** 00249 * Public Functions 00250 *****************************************************************************/ 00251 00252 BiosTouch::TouchError BiosTouch::init() 00253 { 00254 TouchError result = TouchError_Ok; 00255 if (!_initialized) { 00256 do { 00257 if (BiosLoader::instance().params(&_bios, &_biosData) != DMBoard::Ok) { 00258 result = TouchError_ConfigError; 00259 break; 00260 } 00261 00262 result = (TouchError)_bios->touchInformation(_biosData, &_supportsTouch, &_supportsTouchCalibration, &_touchNumFingers); 00263 if (result != TouchError_Ok) { 00264 break; 00265 } 00266 _haveInfo = true; 00267 00268 // is it supported at all? 00269 if (!_supportsTouch) { 00270 result = TouchError_TouchNotSupported; 00271 break; 00272 } 00273 00274 _handler = new TouchHandler(_bios, _biosData, _touchNumFingers); 00275 00276 result = (TouchError)_bios->touchInit(_biosData, touchIrqEnabler, (uint32_t)_handler, touchNewData, (uint32_t)_handler); 00277 if (result != TouchError_Ok) { 00278 break; 00279 } 00280 00281 result = (TouchError)_bios->touchPowerUp(_biosData); 00282 if (result != TouchError_Ok) { 00283 break; 00284 } 00285 00286 _handlerThread = new Thread(); 00287 _handlerThread->start(callback(touchTask, _handler)); 00288 00289 _initialized = true; 00290 } while(0); 00291 00292 if (!_initialized) { 00293 if (_handler != NULL) { 00294 delete _handler; 00295 _handler = NULL; 00296 } 00297 } 00298 } 00299 return result; 00300 } 00301 00302 BiosTouch::TouchError BiosTouch::read(touch_coordinate_t &coord) 00303 { 00304 TouchError err = TouchError_Ok; 00305 if (!_initialized) { 00306 err = TouchError_NoInit; 00307 } else { 00308 err = _handler->read(&coord, 1); 00309 } 00310 return err; 00311 } 00312 00313 BiosTouch::TouchError BiosTouch::read(touch_coordinate_t* coord, int num) 00314 { 00315 TouchError err = TouchError_Ok; 00316 if (!_initialized) { 00317 err = TouchError_NoInit; 00318 } else { 00319 err = _handler->read(coord, num); 00320 } 00321 return err; 00322 } 00323 00324 BiosTouch::TouchError BiosTouch::info(bool* resistive, int* maxPoints, bool* calibrated) 00325 { 00326 TouchError err = TouchError_Ok; 00327 if (!_haveInfo) { 00328 err = TouchError_NoInit; 00329 } else { 00330 *maxPoints = _touchNumFingers; 00331 *calibrated = _supportsTouchCalibration; 00332 } 00333 return err; 00334 } 00335 00336 bool BiosTouch::isTouchSupported() 00337 { 00338 #if defined(DM_BOARD_USE_TOUCH) 00339 if (_haveInfo) { 00340 return _supportsTouch; 00341 } 00342 #endif 00343 return false; 00344 } 00345 00346 BiosTouch::TouchError BiosTouch::calibrateStart() 00347 { 00348 TouchError err = TouchError_Ok; 00349 if (!_initialized) { 00350 err = TouchError_NoInit; 00351 } else { 00352 err = (TouchError)_bios->touchCalibrateStart(_biosData); 00353 } 00354 return err; 00355 } 00356 00357 BiosTouch::TouchError BiosTouch::getNextCalibratePoint(uint16_t* x, uint16_t* y, bool* last) 00358 { 00359 TouchError err = TouchError_Ok; 00360 if (!_initialized) { 00361 err = TouchError_NoInit; 00362 } else { 00363 err = (TouchError)_bios->touchGetNextCalibPoint(_biosData, x, y, last); 00364 } 00365 return err; 00366 } 00367 00368 BiosTouch::TouchError BiosTouch::waitForCalibratePoint(bool* morePoints, uint32_t timeout) 00369 { 00370 TouchError err = TouchError_Ok; 00371 if (!_initialized) { 00372 err = TouchError_NoInit; 00373 } else { 00374 err = (TouchError)_bios->touchWaitForCalibratePoint(_biosData, morePoints, timeout); 00375 } 00376 return err; 00377 } 00378 00379 void BiosTouch::setListener(Callback<void()> listener) 00380 { 00381 if (_initialized) { 00382 _handler->setListener(listener); 00383 } 00384 }
Generated on Tue Jul 12 2022 14:18:31 by 1.7.2