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 EthernetInterface HTTPClient mbed-rtos mbed-src
Fork of DMSupport by
Diff: Display/BiosTouch.cpp
- Revision:
- 26:a65fbb4bde5c
- Parent:
- 24:9a677afc86f1
- Child:
- 28:8ae20cb0b943
--- 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;
}
}
}
