Subdirectory provided by Embedded Artists

Dependencies:   DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos mbed-src

Dependents:   lpc4088_displaymodule_hello_world_Sept_2018

Fork of DMSupport by Embedded Artists

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;
       }
     }
   }