Conversion of DisplayModule's DmTouch to work with UniGraphics as display driver rather than their own DmTftLib.

Fork of DmTouch_UniGraphic by Whitworth-EN173-2016

Revision:
0:fd018d3e7dab
Child:
1:852bf4b0714f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DmTouch.cpp	Wed Jan 20 07:25:22 2016 +0000
@@ -0,0 +1,551 @@
+/**********************************************************************************************
+ Copyright (c) 2014 DisplayModule. All rights reserved.
+ 
+ Redistribution and use of this source code, part of this source code or any compiled binary
+ based on this source code is permitted as long as the above copyright notice and following
+ disclaimer is retained.
+ 
+ DISCLAIMER:
+ THIS SOFTWARE IS SUPPLIED "AS IS" WITHOUT ANY WARRANTIES AND SUPPORT. DISPLAYMODULE ASSUMES
+ NO RESPONSIBILITY OR LIABILITY FOR THE USE OF THE SOFTWARE.
+ ********************************************************************************************/
+// Tested with Xpt2046 and RA8875
+
+/* Modified by John M. Larkin, Whitworth University, to remove Arduino code */
+ 
+#include "DmTouch.h"
+//#include "DmTouchCalibration.h"
+ 
+#define MEASUREMENTS 10
+ 
+// disp        - which display is used
+// spiMode     - How to read SPI-data, Software, Hardware or Auto
+// (JML) Modify to include cs and irq as input parameters
+// (JML) Modify so doesn't assume Arduino shield
+// (JML) Using with mbed so assume hardware SPI available
+DmTouch::DmTouch(Display disp, PinName mosi, PinName miso, PinName clk, PinName cs, PinName irq)
+{
+    _disp = disp;
+    _cs = cs;
+    _irq = irq;
+    _clk = clk;
+    _mosi = mosi;
+    _miso = miso;
+    _hardwareSpi = true; 
+    switch (disp) {
+        // Display with 40-pin connector on top of adapter board
+        case DmTouch::DM_TFT28_103:
+        case DmTouch::DM_TFT24_104:  
+            _width = 240;
+            _height = 320;
+            _touch_id = IC_2046;
+            break;
+ 
+    case DmTouch::DM_TFT28_105:
+      _cs = D4;
+      _irq = D2;
+      _clk = D13;
+      _mosi = D11;
+      _miso = D12;
+      _width = 240;
+      _height = 320;
+      _hardwareSpi = true;
+      _touch_id = IC_2046;
+      break;
+ 
+    case DmTouch::DM_TFT35_107:
+      _cs = D4;
+      _irq = D2;
+      _clk = D13;
+      _mosi = D11;
+      _miso = D12;
+      _width = 320;
+      _height = 240;      
+      _hardwareSpi = true;
+      _touch_id = IC_2046;
+      break;
+ 
+    case DmTouch::DM_TFT43_108:  // or DM_TFT43_110
+      _cs = D10;
+      _irq = D2;
+      _clk = D13;
+      _mosi = D11;
+      _miso = D12;
+      _width = 480;
+      _height = 272;
+      _hardwareSpi = true;
+      _touch_id = IC_8875;
+      break;     
+      
+    case DmTouch::DM_TFT50_111:  // or  DM_TFT50_112
+      _cs = D10;
+      _irq = D2;
+      _clk = D13;
+      _mosi = D11;
+      _miso = D12;
+      _width = 800;
+      _height = 480;
+      _hardwareSpi = true;
+      _touch_id = IC_8875;
+      break;    
+      
+    default:
+      _cs = D4;
+      _irq = D2;
+      _clk = D13;
+      _mosi = D11;
+      _miso = D12;
+      _width = 320;
+      _height = 240;
+      _hardwareSpi = true;
+      _touch_id = IC_2046;
+      break;
+  }
+  
+  //setCalibrationMatrix(DmTouchCalibration::getDefaultCalibrationData(disp));
+  setCalibrationMatrix(DmTouch::getDefaultCalibrationData(disp));               // Use new local version
+ 
+  _samplesPerMeasurement = 3;
+}
+ 
+void DmTouch::init() {
+  _pinCS = new DigitalOut(_cs);
+  if (_hardwareSpi) {
+    sbi(_pinCS, _bitmaskCS);
+    _spi = new SPI((PinName)_mosi, (PinName)_miso, (PinName)_clk);
+    _spi->format(8,0);
+    _spi->frequency(2000000); // Max SPI speed    
+  } else {
+    _pinCLK = new DigitalOut(_clk);
+    _pinMISO = new DigitalIn(_miso);
+    _pinMOSI = new DigitalOut(_mosi);
+    sbi(_pinCLK, _bitmaskCLK);
+  }
+ 
+  if (_irq != NC) { // We will use Touch IRQ
+    enableIrq();
+  }
+}
+ 
+void DmTouch::enableIrq() {
+    _pinIrq = new DigitalIn((PinName)_irq);
+    _pinIrq->mode(PullUp);  
+    if(_touch_id == IC_8875) {
+        // enable touch panel
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x80);
+        spiWrite(0x70);
+        sbi(_pinCS, _bitmaskCS);
+ 
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x00);
+        spiWrite(0xB3);
+        sbi(_pinCS, _bitmaskCS);
+ 
+        // set auto mode
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x80);
+        spiWrite(0x71);
+        sbi(_pinCS, _bitmaskCS);
+ 
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x00);
+        spiWrite(0x04);
+        sbi(_pinCS, _bitmaskCS);
+ 
+        // enable touch panel interrupt
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x80);
+        spiWrite(0xF0);
+        sbi(_pinCS, _bitmaskCS);
+ 
+        cbi(_pinCS, _bitmaskCS);
+        uint8_t temp;
+        spiWrite(0x40);
+        temp = spiRead();
+        sbi(_pinCS, _bitmaskCS);
+ 
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x80);
+        spiWrite(0xF0);
+        sbi(_pinCS, _bitmaskCS);
+ 
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x00);
+        spiWrite(temp | 0x04);
+        sbi(_pinCS, _bitmaskCS);
+ 
+        // Clear TP INT Status
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x80);
+        spiWrite(0xF1);
+        sbi(_pinCS, _bitmaskCS);
+ 
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x00);
+        spiWrite(0x04);
+        sbi(_pinCS, _bitmaskCS);
+    } 
+    else{
+        cbi(_pinCS, _bitmaskCS);
+        spiWrite(0x80); // Enable PENIRQ
+        sbi(_pinCS, _bitmaskCS);
+    }      
+}
+ 
+void DmTouch::spiWrite(uint8_t data) {
+  if (_hardwareSpi) {
+    _spi->write(data);
+  }
+  else {
+    uint8_t count=0;
+    uint8_t temp = data;
+    delay(1);
+    cbi(_pinCLK, _bitmaskCLK);
+    for(count=0;count<8;count++) {
+      if(temp&0x80) {
+        sbi(_pinMOSI, _bitmaskMOSI);
+      }
+      else {
+        cbi(_pinMOSI, _bitmaskMOSI);
+      }
+ 
+      temp=temp<<1;
+ 
+      slow_pulse_low(_pinCLK, _bitmaskCLK);
+    }
+  }
+}
+ 
+uint8_t DmTouch::spiRead() {// Only used for Hardware SPI
+  if (_hardwareSpi) {
+    return _spi->write(0x00); // dummy byte to read
+  } else {
+    uint8_t count=0;
+    uint8_t temp=0;
+    cbi(_pinCLK, _bitmaskCLK);
+    cbi(_pinMOSI, _bitmaskMOSI); // same as using 0x00 as dummy byte
+    for(count=0;count<8;count++) {
+ 
+      pulse_low(_pinCLK, _bitmaskCLK);
+      temp = temp<<1;
+      temp |= _pinMISO->read();
+    }
+    return temp;
+  }
+}
+ 
+uint16_t DmTouch::readData12(uint8_t command) {
+  uint8_t temp = 0;
+  uint16_t value = 0;
+ 
+  spiWrite(command); // Send command
+  // We use 7-bits from the first byte and 5-bit from the second byte
+  temp = spiRead();
+  value = temp<<8;
+  temp = spiRead();
+  value |= temp;
+  value >>=3;
+  value &= 0xFFF;
+  return value;
+}
+ 
+void DmTouch::readRawData(uint16_t &x, uint16_t &y) {
+  if(_touch_id == IC_8875){
+    uint16_t tx, ty;
+    uint8_t temp;
+ 
+    cbi(_pinCS, _bitmaskCS);
+    spiWrite(0x80);
+    spiWrite(0x72);
+    sbi(_pinCS, _bitmaskCS);
+    
+    cbi(_pinCS, _bitmaskCS);
+    spiWrite(0x40);
+    tx = spiRead();     
+    sbi(_pinCS, _bitmaskCS);
+ 
+    cbi(_pinCS, _bitmaskCS);
+    spiWrite(0x80);
+    spiWrite(0x73);     
+    sbi(_pinCS, _bitmaskCS);
+ 
+    cbi(_pinCS, _bitmaskCS);
+    spiWrite(0x40);
+    ty = spiRead();     
+    sbi(_pinCS, _bitmaskCS);
+ 
+    cbi(_pinCS, _bitmaskCS);
+    spiWrite(0x80);
+    spiWrite(0x74); 
+    sbi(_pinCS, _bitmaskCS);
+ 
+    cbi(_pinCS, _bitmaskCS);
+    spiWrite(0x40);
+    temp = spiRead();       
+    sbi(_pinCS, _bitmaskCS);
+            
+    tx <<= 2;
+    ty <<= 2;
+    tx |= temp & 0x03;              // get the bottom x bits
+    ty |= (temp >> 2) & 0x03; // get the bottom y bits
+            
+    x = tx;
+    y = ty;
+            
+    // Clear TP INT Status 
+    cbi(_pinCS, _bitmaskCS);
+    spiWrite(0x80);
+    spiWrite(0xF1);     
+    sbi(_pinCS, _bitmaskCS);
+ 
+    cbi(_pinCS, _bitmaskCS);
+    spiWrite(0x00);
+    spiWrite(0x04); 
+    sbi(_pinCS, _bitmaskCS);            
+  }
+  else{  
+    cbi(_pinCS, _bitmaskCS);
+    x = readData12(0xD0);
+    y = readData12(0x90);
+    sbi(_pinCS, _bitmaskCS);
+  }
+}
+ 
+void DmTouch::readTouchData(uint16_t& posX, uint16_t& posY, bool& touching) {  
+  uint16_t touchX, touchY;
+  getMiddleXY(touchX,touchY);
+  uint16_t screenX, screenY;
+ 
+  posX = getDisplayCoordinateX(touchX, touchY);
+  posY = getDisplayCoordinateY(touchX, touchY);
+  if(_touch_id == IC_8875) {
+    touching = isTouched() && (posX < _width && posY < _height);
+  }
+  else{
+    touching = (posX < _width && posY < _height);
+  }
+  // Now account for screen orientation and return in "screen coordinates"
+  switch(_orient) {
+        case 0:
+            screenX = posX;
+            screenY = posY;
+            break;
+        case 1:
+            screenX = posY;
+            screenY = _width-posX;
+            break;
+        case 2:
+            screenX = _width - posX;
+            screenY = _height - posY;
+            break;
+        case 3:
+            screenX = _height - posY;
+            screenY = posX;
+            break;
+        default:
+            screenX = posX;
+            screenY = posY;
+        }
+    posX = screenX;
+    posY = screenY;    
+}
+ 
+bool DmTouch::isSampleValid() {
+  uint16_t sampleX,sampleY;
+  readRawData(sampleX,sampleY);
+  if (sampleX > 0 && sampleX < 4095 && sampleY > 0 && sampleY < 4095) {
+    return true;
+  } else {
+    return false;
+  }
+}
+ 
+bool DmTouch::isTouched() {
+    if(_touch_id == IC_8875) {
+        delay(1);
+        if (!_pinIrq->read()) {
+            // Clear TP INT Status
+            cbi(_pinCS, _bitmaskCS);
+            spiWrite(0x80);
+            spiWrite(0xF1);
+            sbi(_pinCS, _bitmaskCS);
+ 
+            cbi(_pinCS, _bitmaskCS);
+            spiWrite(0x00);
+            spiWrite(0x04);
+            sbi(_pinCS, _bitmaskCS);
+            return true;
+        } else {
+            return false;
+        }
+    }
+  return isSampleValid();
+}
+ 
+bool DmTouch::getMiddleXY(uint16_t &x, uint16_t &y) {
+  bool haveAllMeasurements  = true;
+  uint16_t valuesX[MEASUREMENTS];
+  uint16_t valuesY[MEASUREMENTS];
+  uint8_t nbrOfMeasurements = 0;
+ 
+  for (int i=0; i<MEASUREMENTS; i++) {
+    getAverageXY(valuesX[i], valuesY[i]);  
+    nbrOfMeasurements++;
+    if(_touch_id != IC_8875) {
+      if (!isTouched()) {
+        haveAllMeasurements = false;
+        break;
+      }
+    }
+  }
+  if (haveAllMeasurements) {
+    x = calculateMiddleValue(valuesX, nbrOfMeasurements);
+    y = calculateMiddleValue(valuesY, nbrOfMeasurements);
+  }
+ 
+  return haveAllMeasurements;
+}
+ 
+void DmTouch::getAverageXY(uint16_t &x, uint16_t &y) {
+  uint32_t sumX = 0;
+  uint32_t sumY = 0;
+  uint16_t sampleX,sampleY;
+  readRawData(sampleX,sampleY);
+ 
+  for (int i=0; i<_samplesPerMeasurement; i++) {
+    readRawData(sampleX,sampleY);
+    sumX += sampleX;
+    sumY += sampleY;
+  }
+ 
+  x = (uint32_t)sumX/_samplesPerMeasurement;
+  y = (uint32_t)sumY/_samplesPerMeasurement;
+}
+ 
+// Total number of samples = MEASUREMENTS * _samplesPerMeasurement
+void DmTouch::setPrecison(uint8_t samplesPerMeasurement) {
+  _samplesPerMeasurement = samplesPerMeasurement;
+}
+ 
+void DmTouch::setCalibrationMatrix(CalibrationMatrix calibrationMatrix) {
+  _calibrationMatrix = calibrationMatrix;
+}
+ 
+void DmTouch::waitForTouch() {
+  while(!isTouched()) {}
+}
+ 
+void DmTouch::waitForTouchRelease() {
+  while(isTouched()) {}
+}
+ 
+uint16_t DmTouch::getDisplayCoordinateX(uint16_t x_touch, uint16_t y_touch) {
+  uint16_t Xd;
+  float temp;
+  temp = (_calibrationMatrix.a * x_touch + _calibrationMatrix.b * y_touch + _calibrationMatrix.c) / rescaleFactor();
+  Xd = (uint16_t)(temp);
+  if (Xd > 60000) {
+    Xd = 0;
+  }
+  return Xd;
+}
+ 
+uint16_t DmTouch::getDisplayCoordinateY(uint16_t x_touch, uint16_t y_touch) {
+  uint16_t Yd;
+  float temp;
+  temp = (_calibrationMatrix.d * x_touch + _calibrationMatrix.e * y_touch + _calibrationMatrix.f) / rescaleFactor();
+  Yd = (uint16_t)(temp);
+  if (Yd > 60000) {
+    Yd = 0;
+  }
+  return Yd;
+}
+ 
+uint16_t DmTouch::calculateMiddleValue(uint16_t values[], uint8_t count) {
+  uint16_t temp;
+ 
+  for(uint8_t i=0; i<count-1; i++) {
+    for(uint8_t j=i+1; j<count; j++) {
+      if(values[j] < values[i]) {
+        temp = values[i];
+        values[i] = values[j];
+        values[j] = temp;
+      }
+    }
+  }
+ 
+  if(count%2==0) {
+    return((values[count/2] + values[count/2 - 1]) / 2.0);
+  } else {
+    return values[count/2];
+  }
+}
+
+// (JML) Add a function to set screen orientation to match UniGraphics display feature
+void DmTouch::setOrientation(char orient) {
+    _orient = orient%4;
+}   
+
+
+/* Moved the default function to DmTouch rather than DmTouchCalibration as interim measure
+*/
+CalibrationMatrix DmTouch::getDefaultCalibrationData(DmTouch::Display disp) {
+  CalibrationMatrix calibrationMatrix = {0};
+  switch (disp) {
+    case DmTouch::DM_TFT28_103:
+      calibrationMatrix.a = 67548;    //    63787;
+      calibrationMatrix.b = -625;     //     -138;
+      calibrationMatrix.c = -16854644;//-15921157;
+      calibrationMatrix.d = 362;      //     -244;
+      calibrationMatrix.e = 89504;    //    89313;
+      calibrationMatrix.f = -14380636;//-10726623;
+      break;
+ 
+    case DmTouch::DM_TFT24_104:
+      calibrationMatrix.a = -71855;
+      calibrationMatrix.b = 2147;
+      calibrationMatrix.c = 259719524;
+      calibrationMatrix.d = -1339;
+      calibrationMatrix.e = -91012;
+      calibrationMatrix.f = 354268832;
+      break;
+ 
+    case DmTouch::DM_TFT28_105:
+      calibrationMatrix.a = 65521;
+      calibrationMatrix.b = -253;
+      calibrationMatrix.c = -11813673;
+      calibrationMatrix.d = -439;
+      calibrationMatrix.e = 89201;
+      calibrationMatrix.f = -10450920;
+      break;
+ 
+    case DmTouch::DM_TFT35_107:
+      calibrationMatrix.a = 91302;    //    85984;
+      calibrationMatrix.b = 817;      //      451;
+      calibrationMatrix.c = -26296117;//-16494041;
+      calibrationMatrix.d = -1877;    //     2308;
+      calibrationMatrix.e = 73762;    //    65173;
+      calibrationMatrix.f = -26384255;//-19179080;
+      break;
+    case DmTouch::DM_TFT43_108:   // or DM_TFT43_110
+      calibrationMatrix.a = 541307;
+      calibrationMatrix.b = -4288;
+      calibrationMatrix.c = -36678732;
+      calibrationMatrix.d = 2730;
+      calibrationMatrix.e = 321714;
+      calibrationMatrix.f = -31439472;    
+      break;
+    case DmTouch::DM_TFT50_111:   // or  DM_TFT50_112
+      calibrationMatrix.a = 875894;
+      calibrationMatrix.b = 1655;
+      calibrationMatrix.c = -53695309;
+      calibrationMatrix.d = -993;
+      calibrationMatrix.e = 544421;
+      calibrationMatrix.f = -41496753;                    
+      break;   
+    default:
+      break;
+  }
+  return calibrationMatrix;
+}
\ No newline at end of file