Modified version of the DmTftLibrary, optimized for the LPC4088 Experiment Base Board
Dependents: lpc4088_ebb_dm_calc lpc4088_ebb_dm_bubbles
Fork of DmTftLibrary by
DmTouch.cpp
00001 /********************************************************************************************** 00002 Copyright (c) 2014 DisplayModule. All rights reserved. 00003 00004 Redistribution and use of this source code, part of this source code or any compiled binary 00005 based on this source code is permitted as long as the above copyright notice and following 00006 disclaimer is retained. 00007 00008 DISCLAIMER: 00009 THIS SOFTWARE IS SUPPLIED "AS IS" WITHOUT ANY WARRANTIES AND SUPPORT. DISPLAYMODULE ASSUMES 00010 NO RESPONSIBILITY OR LIABILITY FOR THE USE OF THE SOFTWARE. 00011 ********************************************************************************************/ 00012 // Tested with Xpt2046 00013 00014 #include "DmTouch.h" 00015 #include "DmTouchCalibration.h" 00016 00017 #define MEASUREMENTS 10 00018 00019 #if defined(DM_TOOLCHAIN_ARDUINO) 00020 // disp - which display is used 00021 // spiMode - How to read SPI-data, Software, Hardware or Auto 00022 // useIrq - Enable IRQ or disable IRQ 00023 DmTouch::DmTouch(Display disp, SpiMode spiMode, bool useIrq) 00024 00025 #elif defined (DM_TOOLCHAIN_MBED) 00026 // disp - which display is used 00027 // spiMode - How to read SPI-data, Software, Hardware or Auto 00028 DmTouch::DmTouch(Display disp, SpiMode spiMode) 00029 #endif 00030 { 00031 _disp = disp; 00032 switch (disp) { 00033 // Display with 40-pin connector on top of adapter board 00034 case DmTouch::DM_TFT28_103: 00035 case DmTouch::DM_TFT24_104: 00036 _cs = D8; 00037 _irq = D10; 00038 _clk = A1; 00039 _mosi = A0; 00040 _miso = D9; 00041 _width = 240; 00042 _height = 320; 00043 _hardwareSpi = false; 00044 break; 00045 00046 case DmTouch::DM_TFT28_105: 00047 _cs = D4; 00048 _irq = D2; 00049 _clk = D13; 00050 _mosi = D11; 00051 _miso = D12; 00052 _width = 240; 00053 _height = 320; 00054 _hardwareSpi = true; 00055 break; 00056 00057 case DmTouch::DM_TFT35_107: 00058 default: 00059 _cs = D4; 00060 _irq = D2; 00061 _clk = D13; 00062 _mosi = D11; 00063 _miso = D12; 00064 _width = 320; 00065 _height = 240; 00066 _hardwareSpi = true; 00067 break; 00068 } 00069 00070 if (spiMode == DmTouch::Hardware) { 00071 _hardwareSpi = true; 00072 } else if (spiMode == DmTouch::Software) { 00073 _hardwareSpi = false; 00074 } 00075 00076 #if defined(DM_TOOLCHAIN_ARDUINO) 00077 if (!useIrq) { 00078 _irq = -1; 00079 } 00080 #elif defined (DM_TOOLCHAIN_MBED) 00081 _irq = -1; 00082 #endif 00083 00084 setCalibrationMatrix(DmTouchCalibration::getDefaultCalibrationData(disp)); 00085 00086 _samplesPerMeasurement = 3; 00087 } 00088 00089 void DmTouch::init() { 00090 #if defined (DM_TOOLCHAIN_ARDUINO) 00091 pinMode(_cs, OUTPUT); 00092 _pinCS = portOutputRegister(digitalPinToPort(_cs)); 00093 _bitmaskCS = digitalPinToBitMask(_cs); 00094 00095 if (_hardwareSpi) { 00096 SPI.begin(); 00097 SPI.setClockDivider(SPI_CLOCK_DIV32); 00098 SPI.setBitOrder(MSBFIRST); 00099 SPI.setDataMode(SPI_MODE0); 00100 _spiSettings = SPCR; 00101 } 00102 else { 00103 pinMode(_clk, OUTPUT); 00104 pinMode(_mosi, OUTPUT); 00105 pinMode(_miso, INPUT); 00106 _pinCLK = portOutputRegister(digitalPinToPort(_clk)); 00107 _bitmaskCLK = digitalPinToBitMask(_clk); 00108 _pinMOSI = portOutputRegister(digitalPinToPort(_mosi)); 00109 _bitmaskMOSI = digitalPinToBitMask(_mosi); 00110 _pinMISO = portInputRegister(digitalPinToPort(_miso)); 00111 _bitmaskMISO = digitalPinToBitMask(_miso); 00112 } 00113 #elif defined (DM_TOOLCHAIN_MBED) 00114 _pinCS = new DigitalOut((PinName)_cs); 00115 if (_hardwareSpi) { 00116 sbi(_pinCS, _bitmaskCS); 00117 _spi = new SPI((PinName)_mosi, (PinName)_miso, (PinName)_clk); 00118 _spi->format(8,0); 00119 _spi->frequency(2000000); // Max SPI speed 00120 //cbi(_pinCS, _bitmaskCS); 00121 } else { 00122 _pinCLK = new DigitalOut((PinName)_clk); 00123 _pinMISO = new DigitalIn((PinName)_miso); 00124 _pinMOSI = new DigitalOut((PinName)_mosi); 00125 sbi(_pinCS, _bitmaskCS); 00126 sbi(_pinCLK, _bitmaskCLK); 00127 } 00128 #endif 00129 00130 if (_irq != -1) { // We will use Touch IRQ 00131 enableIrq(); 00132 } 00133 } 00134 00135 void DmTouch::enableIrq() { 00136 #if defined (DM_TOOLCHAIN_ARDUINO) 00137 pinMode(_irq, INPUT); 00138 _pinIrq = portInputRegister(digitalPinToPort(_irq)); 00139 _bitmaskIrq = digitalPinToBitMask(_irq); 00140 00141 cbi(_pinCS, _bitmaskCS); 00142 spiWrite(0x80); // Enable PENIRQ 00143 sbi(_pinCS, _bitmaskCS); 00144 #endif 00145 } 00146 00147 void DmTouch::spiWrite(uint8_t data) { 00148 if (_hardwareSpi) { 00149 #if defined (DM_TOOLCHAIN_ARDUINO) 00150 SPCR = _spiSettings; // SPI Control Register 00151 SPDR = data; // SPI Data Register 00152 while(!(SPSR & _BV(SPIF))); // SPI Status Register Wait for transmission to finish 00153 #elif defined (DM_TOOLCHAIN_MBED) 00154 _spi->write(data); 00155 #endif 00156 } 00157 else { 00158 uint8_t count=0; 00159 uint8_t temp = data; 00160 //delay(1); 00161 cbi(_pinCLK, _bitmaskCLK); 00162 for(count=0;count<8;count++) { 00163 if(temp&0x80) { 00164 sbi(_pinMOSI, _bitmaskMOSI); 00165 } 00166 else { 00167 cbi(_pinMOSI, _bitmaskMOSI); 00168 } 00169 00170 temp=temp<<1; 00171 00172 pulse_low(_pinCLK, _bitmaskCLK); 00173 } 00174 } 00175 } 00176 00177 uint8_t DmTouch::spiRead() {// Only used for Hardware SPI 00178 #if defined (DM_TOOLCHAIN_ARDUINO) 00179 uint8_t data; 00180 SPCR = _spiSettings; 00181 spiWrite(0x00); 00182 data = SPDR; 00183 00184 return data; 00185 #elif defined (DM_TOOLCHAIN_MBED) 00186 if (_hardwareSpi) { 00187 return _spi->write(0x00); // dummy byte to read 00188 } else { 00189 uint8_t count=0; 00190 uint8_t temp=0; 00191 cbi(_pinCLK, _bitmaskCLK); 00192 cbi(_pinMOSI, _bitmaskMOSI); // same as using 0x00 as dummy byte 00193 for(count=0;count<8;count++) { 00194 00195 pulse_low(_pinCLK, _bitmaskCLK); 00196 temp = temp<<1; 00197 temp |= _pinMISO->read(); 00198 } 00199 return temp; 00200 } 00201 #endif 00202 } 00203 00204 uint16_t DmTouch::readData12(uint8_t command) { 00205 uint8_t temp = 0; 00206 uint16_t value = 0; 00207 00208 spiWrite(command); // Send command 00209 00210 #if defined (DM_TOOLCHAIN_ARDUINO) 00211 if (_hardwareSpi) { 00212 // We use 7-bits from the first byte and 5-bit from the second byte 00213 temp = spiRead(); 00214 value = temp<<8; 00215 temp = spiRead(); 00216 00217 value |= temp; 00218 value >>=3; 00219 value &= 0xFFF; 00220 } else { 00221 pulse_high(_pinCLK, _bitmaskCLK); 00222 unsigned nop; 00223 uint8_t count=0; 00224 for(count=0;count<12;count++) { 00225 value<<=1; 00226 pulse_high(_pinCLK, _bitmaskCLK); 00227 if ( gbi(_pinMISO, _bitmaskMISO) ) { 00228 value++; 00229 } 00230 } 00231 } 00232 #elif defined (DM_TOOLCHAIN_MBED) 00233 // We use 7-bits from the first byte and 5-bit from the second byte 00234 temp = spiRead(); 00235 value = temp<<8; 00236 temp = spiRead(); 00237 value |= temp; 00238 value >>=3; 00239 value &= 0xFFF; 00240 #endif 00241 return value; 00242 } 00243 00244 void DmTouch::readRawData(uint16_t &x, uint16_t &y) { 00245 cbi(_pinCS, _bitmaskCS); 00246 x = readData12(0xD0); 00247 y = readData12(0x90); 00248 sbi(_pinCS, _bitmaskCS); 00249 } 00250 00251 void DmTouch::readTouchData(uint16_t& posX, uint16_t& posY, bool& touching) { 00252 uint16_t touchX, touchY; 00253 if (!getMiddleXY(touchX,touchY)) { 00254 touching = false; 00255 } 00256 00257 posX = getDisplayCoordinateX(touchX, touchY); 00258 posY = getDisplayCoordinateY(touchX, touchY); 00259 00260 #if defined (DM_TOOLCHAIN_ARDUINO) 00261 touching = isTouched(); 00262 #elif defined (DM_TOOLCHAIN_MBED) 00263 touching = (posX < _width && posY < _height); 00264 #endif 00265 } 00266 00267 bool DmTouch::isSampleValid() { 00268 uint16_t sampleX,sampleY; 00269 readRawData(sampleX,sampleY); 00270 if (sampleX > 0 && sampleX < 4095 && sampleY > 0 && sampleY < 4095) { 00271 return true; 00272 } else { 00273 return false; 00274 } 00275 } 00276 00277 bool DmTouch::isTouched() { 00278 #if defined (DM_TOOLCHAIN_ARDUINO) 00279 if (_irq == -1) { 00280 return isSampleValid(); 00281 } 00282 00283 if ( !gbi(_pinIrq, _bitmaskIrq) ) { 00284 return true; 00285 } 00286 00287 return false; 00288 #elif defined (DM_TOOLCHAIN_MBED) 00289 return isSampleValid(); 00290 #endif 00291 } 00292 00293 bool DmTouch::getMiddleXY(uint16_t &x, uint16_t &y) { 00294 bool haveAllMeasurements = true; 00295 uint16_t valuesX[MEASUREMENTS]; 00296 uint16_t valuesY[MEASUREMENTS]; 00297 uint8_t nbrOfMeasurements = 0; 00298 00299 for (int i=0; i<MEASUREMENTS; i++) { 00300 getAverageXY(valuesX[i], valuesY[i]); 00301 nbrOfMeasurements++; 00302 #if defined (DM_TOOLCHAIN_ARDUINO) 00303 if (!isTouched()) { 00304 haveAllMeasurements = false; 00305 break; 00306 } 00307 #elif defined (DM_TOOLCHAIN_MBED) 00308 if (valuesX[i] >= 4095 || valuesY[i] >= 4095) { 00309 haveAllMeasurements = false; 00310 break; 00311 } 00312 #endif 00313 } 00314 if (haveAllMeasurements) { 00315 x = calculateMiddleValue(valuesX, nbrOfMeasurements); 00316 y = calculateMiddleValue(valuesY, nbrOfMeasurements); 00317 } 00318 00319 return haveAllMeasurements; 00320 } 00321 00322 void DmTouch::getAverageXY(uint16_t &x, uint16_t &y) { 00323 uint32_t sumX = 0; 00324 uint32_t sumY = 0; 00325 uint16_t sampleX,sampleY; 00326 readRawData(sampleX,sampleY); 00327 00328 for (int i=0; i<_samplesPerMeasurement; i++) { 00329 readRawData(sampleX,sampleY); 00330 sumX += sampleX; 00331 sumY += sampleY; 00332 } 00333 00334 x = (uint32_t)sumX/_samplesPerMeasurement; 00335 y = (uint32_t)sumY/_samplesPerMeasurement; 00336 } 00337 00338 // Total number of samples = MEASUREMENTS * _samplesPerMeasurement 00339 void DmTouch::setPrecison(uint8_t samplesPerMeasurement) { 00340 _samplesPerMeasurement = samplesPerMeasurement; 00341 } 00342 00343 void DmTouch::setCalibrationMatrix(CalibrationMatrix calibrationMatrix) { 00344 _calibrationMatrix = calibrationMatrix; 00345 } 00346 00347 void DmTouch::waitForTouch() { 00348 while(!isTouched()) {} 00349 } 00350 00351 void DmTouch::waitForTouchRelease() { 00352 while(isTouched()) {} 00353 } 00354 00355 uint16_t DmTouch::getDisplayCoordinateX(uint16_t x_touch, uint16_t y_touch) { 00356 uint16_t Xd; 00357 float temp; 00358 temp = (_calibrationMatrix.a * x_touch + _calibrationMatrix.b * y_touch + _calibrationMatrix.c) / rescaleFactor(); 00359 Xd = (uint16_t)(temp); 00360 if (Xd > 60000) { 00361 Xd = 0; 00362 } 00363 return Xd; 00364 } 00365 00366 uint16_t DmTouch::getDisplayCoordinateY(uint16_t x_touch, uint16_t y_touch) { 00367 uint16_t Yd; 00368 float temp; 00369 temp = (_calibrationMatrix.d * x_touch + _calibrationMatrix.e * y_touch + _calibrationMatrix.f) / rescaleFactor(); 00370 Yd = (uint16_t)(temp); 00371 if (Yd > 60000) { 00372 Yd = 0; 00373 } 00374 return Yd; 00375 } 00376 00377 uint16_t DmTouch::calculateMiddleValue(uint16_t values[], uint8_t count) { 00378 uint16_t temp; 00379 00380 for(uint8_t i=0; i<count-1; i++) { 00381 for(uint8_t j=i+1; j<count; j++) { 00382 if(values[j] < values[i]) { 00383 temp = values[i]; 00384 values[i] = values[j]; 00385 values[j] = temp; 00386 } 00387 } 00388 } 00389 00390 if(count%2==0) { 00391 return((values[count/2] + values[count/2 - 1]) / 2.0); 00392 } else { 00393 return values[count/2]; 00394 } 00395 }
Generated on Tue Jul 12 2022 19:30:31 by 1.7.2