Conversion of DisplayModule's DmTouch to work with UniGraphics as display driver rather than their own DmTftLib.
Fork of DmTouch_UniGraphic by
Diff: DmTouch.cpp
- Revision:
- 0:fd018d3e7dab
- Child:
- 1:852bf4b0714f
diff -r 000000000000 -r fd018d3e7dab DmTouch.cpp --- /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