![](/media/cache/group/logo.png.50x50_q85.jpg)
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
Diff: Display/BiosTouch.cpp
- Revision:
- 22:1a58a518435c
- Child:
- 23:6afd6a716e80
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Display/BiosTouch.cpp Fri Jan 16 11:13:39 2015 +0100 @@ -0,0 +1,337 @@ +/* + * Copyright 2014 Embedded Artists AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "BiosTouch.h" +#include "BiosLoader.h" +#include "DMBoard.h" +#include "bios.h" +#include "meas.h" + +/****************************************************************************** + * Defines and typedefs + *****************************************************************************/ + +#define SIG_NEW_DATA 0x1 +class TouchHandler { + public: + TouchHandler(bios_header_t* bios, void* biosData, int num) : + _latest(NULL), _touchIRQ(P2_25), _bios(bios), + _biosData(biosData), _haveData(false), _points(num), + _thread(NULL), _listener(NULL) {} + void handleTouchInterrupt(); + void changeTouchInterrupt(bool enable, bool rising); + TouchPanel::TouchError read(touch_coordinate_t* coord, int num); + void run(); + void setThread(Thread* t) { _thread = t; } + FunctionPointer* setListener(FunctionPointer* listener); + private: + Mutex _mutex; + touch_coordinate_t* _latest; + InterruptIn _touchIRQ; + bios_header_t* _bios; + void* _biosData; + bool _haveData; //TODO: improve + int _points; + Thread* _thread; + FunctionPointer* _listener; +}; + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +/****************************************************************************** + * Private Functions + *****************************************************************************/ + +BiosTouch::BiosTouch() : + _initialized(false), + _haveInfo(false), + _poweredOn(false), + //_touchIRQ(P2_25), + _bios(NULL), + _biosData(NULL), + _handlerThread(NULL), + _handler(NULL), + _supportsTouch(false) +{ +} + +BiosTouch::~BiosTouch() +{ + // _bios and _biosData are deallocated by BiosLoader + + if (_handlerThread != NULL) { + delete _handlerThread; + _handlerThread = NULL; + } + if (_handler != NULL) { + delete _handler; + _handler = NULL; + } +} + +// Function called from the BIOS +static void touchIrqEnabler(uint32_t arg, bool enable, bool rising) +{ + ((TouchHandler*)arg)->changeTouchInterrupt(enable, rising); +#if defined(DM_BOARD_ENABLE_MEASSURING_PINS) + if (enable) { + SET_MEAS_PIN_1(); + } else { + CLR_MEAS_PIN_1(); + } +#endif +} + +static void touchTask(void const* args) +{ + ((TouchHandler*)args)->run(); +} + + +void TouchHandler::run() +{ + RtosLog* log = DMBoard::instance().logger(); + BiosError_t err; + + _latest = (touch_coordinate_t*)malloc(_points*sizeof(touch_coordinate_t)); + if (_latest == NULL) { + log->printf("Failed to allocate memory for touch events\n"); + mbed_die(); + } + memset(_latest, 0, _points*sizeof(touch_coordinate_t)); + while(true) { + Thread::signal_wait(SIG_NEW_DATA); +// if (_haveData) { +// _haveData = false; + SET_MEAS_PIN_3(); + _bios->touchIrqHandler(_biosData); + CLR_MEAS_PIN_3(); + //read + _mutex.lock(); + err = _bios->touchRead(_biosData, _latest, _points); + FunctionPointer* fp = _listener; + _mutex.unlock(); + if (err == BiosError_Ok) { + //notify registered callbacks + if (fp != NULL) { + SET_MEAS_PIN_4(); + fp->call(); + SET_MEAS_PIN_4(); + } + } else { + log->printf("Failed to read touch event, err = %d\n", err); + } +// } + } + //if (_latest != NULL) { + // free(_latest); + // _latest = NULL; + //} +} + +TouchPanel::TouchError TouchHandler::read(touch_coordinate_t* coord, int num) +{ + if (num > _points || num < 1) { + return TouchPanel::TouchError_InvalidParam; + } + _mutex.lock(); + memcpy(coord, _latest, num*sizeof(touch_coordinate_t)); + _mutex.unlock(); + + return TouchPanel::TouchError_Ok; +} + +void TouchHandler::handleTouchInterrupt() +{ + SET_MEAS_PIN_2(); + //_haveData = true; + if (_thread != NULL) { + _thread->signal_set(SIG_NEW_DATA); + } + CLR_MEAS_PIN_2(); +} + +void TouchHandler::changeTouchInterrupt(bool enable, bool rising) +{ + if (enable) { + if (rising) { + _touchIRQ.rise(this, &TouchHandler::handleTouchInterrupt); + } else { + _touchIRQ.fall(this, &TouchHandler::handleTouchInterrupt); + } + } else { + if (rising) { + _touchIRQ.rise(NULL); + } else { + _touchIRQ.fall(NULL); + } + } +} + +FunctionPointer* TouchHandler::setListener(FunctionPointer* listener) +{ + _mutex.lock(); + FunctionPointer* old = _listener; + _listener = listener; + _mutex.unlock(); + return old; +} + + +/****************************************************************************** + * Public Functions + *****************************************************************************/ + +BiosTouch::TouchError BiosTouch::init() +{ + TouchError result = TouchError_Ok; + if (!_initialized) { + do { + if (BiosLoader::instance().params(&_bios, &_biosData) != DMBoard::Ok) { + result = TouchError_ConfigError; + break; + } + + result = (TouchError)_bios->touchInformation(_biosData, &_supportsTouch, &_supportsTouchCalibration, &_touchIsResistive, &_touchNumFingers); + if (result != TouchError_Ok) { + break; + } + _haveInfo = true; + + // is it supported at all? + if (!_supportsTouch) { + result = TouchError_TouchNotSupported; + break; + } + + _handler = new TouchHandler(_bios, _biosData, _touchNumFingers); + + result = (TouchError)_bios->touchInit(_biosData, touchIrqEnabler, (uint32_t)_handler); + if (result != TouchError_Ok) { + break; + } + + result = (TouchError)_bios->touchPowerUp(_biosData); + if (result != TouchError_Ok) { + break; + } + + _handlerThread = new Thread(touchTask, _handler); + _handler->setThread(_handlerThread); + + _initialized = true; + } while(0); + + if (!_initialized) { + if (_handler != NULL) { + delete _handler; + _handler = NULL; + } + } + } + return result; +} + +BiosTouch::TouchError BiosTouch::read(touch_coordinate_t &coord) +{ + TouchError err = TouchError_Ok; + if (!_initialized) { + err = TouchError_NoInit; + } else { + //err = (TouchError)_bios->touchRead(_biosData, &coord, 1); + err = _handler->read(&coord, 1); + } + return err; +} + +BiosTouch::TouchError BiosTouch::read(touch_coordinate_t* coord, int num) +{ + TouchError err = TouchError_Ok; + if (!_initialized) { + err = TouchError_NoInit; + } else { + //err = (TouchError)_bios->touchRead(_biosData, coord, num); + err = _handler->read(coord, num); + } + return err; +} + +BiosTouch::TouchError BiosTouch::info(bool* resistive, int* maxPoints, bool* calibrated) +{ + TouchError err = TouchError_Ok; + if (!_haveInfo) { + err = TouchError_NoInit; + } else { + *resistive = _touchIsResistive; + *maxPoints = _touchNumFingers; + *calibrated = _supportsTouchCalibration; + } + return err; +} + +bool BiosTouch::isTouchSupported() +{ +#if defined(DM_BOARD_USE_TOUCH) + if (_haveInfo) { + return _supportsTouch; + } +#endif + return false; +} + +BiosTouch::TouchError BiosTouch::calibrateStart() +{ + TouchError err = TouchError_Ok; + if (!_initialized) { + err = TouchError_NoInit; + } else { + err = (TouchError)_bios->touchCalibrateStart(_biosData); + } + return err; +} + +BiosTouch::TouchError BiosTouch::getNextCalibratePoint(uint16_t* x, uint16_t* y, bool* last) +{ + TouchError err = TouchError_Ok; + if (!_initialized) { + err = TouchError_NoInit; + } else { + err = (TouchError)_bios->touchGetNextCalibPoint(_biosData, x, y, last); + } + return err; +} + +BiosTouch::TouchError BiosTouch::waitForCalibratePoint(bool* morePoints, uint32_t timeout) +{ + TouchError err = TouchError_Ok; + if (!_initialized) { + err = TouchError_NoInit; + } else { + err = (TouchError)_bios->touchWaitForCalibratePoint(_biosData, morePoints, timeout); + } + return err; +} + +FunctionPointer* BiosTouch::setListener(FunctionPointer* listener) +{ + if (_initialized) { + return _handler->setListener(listener); + } + return NULL; +}