t
Dependencies: DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos
Fork of DMSupport by
Diff: Display/BiosTouch.cpp
- Revision:
- 26:a65fbb4bde5c
- Parent:
- 24:9a677afc86f1
- Child:
- 28:8ae20cb0b943
diff -r ca399b043d30 -r a65fbb4bde5c Display/BiosTouch.cpp --- a/Display/BiosTouch.cpp Tue Jan 20 09:11:28 2015 +0100 +++ b/Display/BiosTouch.cpp Thu Jan 22 16:04:54 2015 +0100 @@ -25,39 +25,59 @@ * Defines and typedefs *****************************************************************************/ +#define NUM_COORDS 5 +#define NUM_MAILS 10 +typedef struct { + touch_coordinate_t touch[NUM_COORDS]; + int num; +} touch_mail_t; + #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) {} + _biosData(biosData), _points(num), + _listener(NULL), _lostData(0), + _dbgAdded(0), _dbgRemoved(0) {} void handleTouchInterrupt(); + void handleI2CInterrupt(); + void handleNewData(touch_coordinate_t* coord, int num); 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: + Mail<touch_mail_t, NUM_MAILS> _mailbox; Mutex _mutex; touch_coordinate_t* _latest; InterruptIn _touchIRQ; bios_header_t* _bios; void* _biosData; - bool _haveData; //TODO: improve int _points; - Thread* _thread; FunctionPointer* _listener; + uint32_t _lostData; + uint32_t _dbgAdded; + uint32_t _dbgRemoved; }; /****************************************************************************** * Local variables *****************************************************************************/ +static TouchHandler* theTouchHandler = NULL; // ugly but needed for IRQ + /****************************************************************************** * Private Functions *****************************************************************************/ +static void touch_i2c0_irq_handler() +{ + if (theTouchHandler != NULL) { + theTouchHandler->handleI2CInterrupt(); + } +} + BiosTouch::BiosTouch() : _initialized(false), _haveInfo(false), @@ -89,13 +109,12 @@ 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 +} + +// Function called from the BIOS +static void touchNewData(uint32_t arg, touch_coordinate_t* coords, int num) +{ + ((TouchHandler*)arg)->handleNewData(coords, num); } static void touchTask(void const* args) @@ -107,82 +126,51 @@ 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)); - uint32_t maxDelay = osWaitForever; -SET_MEAS_PIN_1(); while(true) { -#if 1 - osEvent evt = Thread::signal_wait(SIG_NEW_DATA, maxDelay); - if (evt.status == osEventTimeout) { - // got a timeout after the last touch event, now go back to - // waiting forever for the next one - maxDelay = osWaitForever; -SET_MEAS_PIN_1(); - } else { - // normal event, start a timeout to make sure that we get an - // event when the user stops fiddling with the display - //maxDelay = 10; -CLR_MEAS_PIN_1(); - } -SET_MEAS_PIN_3(); - _bios->touchIrqHandler(_biosData); -CLR_MEAS_PIN_3(); - - _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(); -CLR_MEAS_PIN_4(); - } + SET_MEAS_PIN_1(); + osEvent evt = _mailbox.get(osWaitForever); + CLR_MEAS_PIN_1(); + if (evt.status == osEventMail) { + touch_mail_t* mail = (touch_mail_t*)evt.value.p; + memcpy(_latest, mail->touch, mail->num * sizeof(touch_coordinate_t)); + _mailbox.free(mail); + _dbgRemoved++; + if (_points == 1) { + log->printf("{%3d,%3d,%d} at %u/%u, with %u lost\n", + _latest[0].x, + _latest[0].y, + _latest[0].z, + _dbgRemoved, _dbgAdded, + _lostData); } else { - log->printf("Failed to read touch event, err = %d\n", err); + log->printf("{%d,%d,%d,%d,%d} at %u/%u, with %u lost\n", + _latest[0].z, + _latest[1].z, + _latest[2].z, + _latest[3].z, + _latest[4].z, + _dbgRemoved, _dbgAdded, + _lostData); } - - // mode 2 - wait max 10ms for touch event and simulate - // one if there isn't anyone (for the "touch up" - // event) -#else - 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(); - CLR_MEAS_PIN_4(); - } - } else { - log->printf("Failed to read touch event, err = %d\n", err); - } -// } -#endif + } else { + log->printf("got non-mail event: 0x%x\n", evt.status); + continue; + } + _mutex.lock(); + FunctionPointer* fp = _listener; + _mutex.unlock(); + + if (fp != NULL) { + fp->call(); + } } - //if (_latest != NULL) { - // free(_latest); - // _latest = NULL; - //} } TouchPanel::TouchError TouchHandler::read(touch_coordinate_t* coord, int num) @@ -200,11 +188,31 @@ void TouchHandler::handleTouchInterrupt() { SET_MEAS_PIN_2(); - //_haveData = true; - if (_thread != NULL) { - _thread->signal_set(SIG_NEW_DATA); + _bios->touchIrqHandler(_biosData); + CLR_MEAS_PIN_2(); +} + +void TouchHandler::handleI2CInterrupt() +{ + SET_MEAS_PIN_3(); + _bios->touchI2CIRQHandler(_biosData); + CLR_MEAS_PIN_3(); +} + +void TouchHandler::handleNewData(touch_coordinate_t* coord, int num) +{ + SET_MEAS_PIN_4(); + touch_mail_t* mail = _mailbox.alloc(0); + if (mail == NULL) { + //DMBoard::instance().logger()->printf("Lost touch event\n"); + _lostData++; + } else { + _dbgAdded++; + mail->num = (num < NUM_COORDS) ? num : NUM_COORDS; + memcpy(&mail->touch, coord, mail->num*sizeof(touch_coordinate_t)); + _mailbox.put(mail); } - CLR_MEAS_PIN_2(); + CLR_MEAS_PIN_4(); } void TouchHandler::changeTouchInterrupt(bool enable, bool rising) @@ -260,9 +268,12 @@ break; } - _handler = new TouchHandler(_bios, _biosData, _touchNumFingers); + NVIC_DisableIRQ(I2C0_IRQn); + NVIC_SetVector(I2C0_IRQn, (uint32_t)touch_i2c0_irq_handler); + _handler = theTouchHandler = new TouchHandler(_bios, _biosData, _touchNumFingers); + NVIC_EnableIRQ(I2C0_IRQn); - result = (TouchError)_bios->touchInit(_biosData, touchIrqEnabler, (uint32_t)_handler); + result = (TouchError)_bios->touchInit(_biosData, touchIrqEnabler, (uint32_t)_handler, touchNewData, (uint32_t)_handler); if (result != TouchError_Ok) { break; } @@ -273,7 +284,6 @@ } _handlerThread = new Thread(touchTask, _handler); - _handler->setThread(_handlerThread); _initialized = true; } while(0); @@ -282,6 +292,7 @@ if (_handler != NULL) { delete _handler; _handler = NULL; + theTouchHandler = NULL; } } }