t

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

Fork of DMSupport by Embedded Artists

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