Caiou
Dependents: LCD_Proj LCD_imagetest LCD_Proj_rtc
Fork of DmTftLibrary by
Diff: DmTouch.cpp
- Revision:
- 7:6cd8c36cbdb3
- Parent:
- 6:fde03297017b
- Child:
- 8:b24f01d148c4
diff -r fde03297017b -r 6cd8c36cbdb3 DmTouch.cpp --- a/DmTouch.cpp Fri May 23 08:10:09 2014 +0000 +++ b/DmTouch.cpp Fri Jul 04 09:26:32 2014 +0000 @@ -12,32 +12,22 @@ // Tested with Xpt2046 #include "DmTouch.h" +#include "DmTouchCalibration.h" + +#define MEASUREMENTS 10 #if defined(DM_TOOLCHAIN_ARDUINO) // disp - which display is used -// cs - pin number CS (Chip Select, SS) -// irq - pin number IRQ (set to -1 if you don't want to use) -// hardwareSpi - set to 1 if you want to use hardware Spi, 0 otherwise -// (note, if you use hardware Spi on arduino, clk, mosi and miso will be disregarded) -// clk - pin number CLK (SLK) -// mosi - pin number MOSI -// miso - pin number MISO -// width - width of display (default 240) -// height - height of display (default 320) -DmTouch::DmTouch(Display disp, int8_t cs, int8_t irq, int8_t hardwareSpi, int8_t clk, int8_t mosi, int8_t miso, uint16_t width, uint16_t height) : _width(width), _height(height) -{ - _hardwareSpi = hardwareSpi; - _cs = cs; - _irq = irq; - _clk = clk; - _mosi = mosi; - _miso = miso; +// spiMode - How to read SPI-data, Software, Hardware or Auto +// useIrq - Enable IRQ or disable IRQ +DmTouch::DmTouch(Display disp, SpiMode spiMode, bool useIrq) #elif defined (DM_TOOLCHAIN_MBED) // disp - which display is used -DmTouch::DmTouch(Display disp, bool hardwareSPI) +// spiMode - How to read SPI-data, Software, Hardware or Auto +DmTouch::DmTouch(Display disp, SpiMode spiMode) +#endif { - _hardwareSpi = hardwareSPI; switch (disp) { // Display with 40-pin connector on top of adapter board case DmTouch::DM_TFT28_103: @@ -47,8 +37,7 @@ _clk = A1; _mosi = A0; _miso = D9; - _width = 240; - _height = 320; + _hardwareSpi = false; break; case DmTouch::DM_TFT28_105: @@ -57,8 +46,7 @@ _clk = D13; _mosi = D11; _miso = D12; - _width = 240; - _height = 320; + _hardwareSpi = true; break; case DmTouch::DM_TFT35_107: @@ -68,47 +56,25 @@ _clk = D13; _mosi = D11; _miso = D12; - _width = 320; - _height = 240; + _hardwareSpi = true; break; } + + if (spiMode == DmTouch::Hardware) { + _hardwareSpi = true; + } else if (spiMode == DmTouch::Software) { + _hardwareSpi = false; + } + +#if defined(DM_TOOLCHAIN_ARDUINO) + if (!useIrq) { + _irq = -1; + } #endif - - // Calibration data for the different displays - switch (disp) { - case DmTouch::DM_TFT28_103: - _calibLowX = 220; - _calibLowY = 220; - _calibModifierX = 15.25; - _calibModifierY = 11.16; - _calibInvertedTouch = false; - break; + + setCalibrationMatrix(DmTouchCalibration::getDefaultCalibrationData(disp)); - case DmTouch::DM_TFT24_104: - _calibLowX = 210; - _calibLowY = 280; - _calibModifierX = 15; - _calibModifierY = 11.24; - _calibInvertedTouch = true; - break; - - case DmTouch::DM_TFT35_107: - _calibLowX = 912; - _calibLowY = 422 ; - _calibModifierX = 3.25; - _calibModifierY = 1.175; - _calibInvertedTouch = false; - break; - - case DmTouch::DM_TFT28_105: - default: - _calibLowX = 260; - _calibLowY = 220; - _calibModifierX = 14.42; - _calibModifierY = 10.78; - _calibInvertedTouch = false; - break; - } + _samplesPerMeasurement = 3; } void DmTouch::init() { @@ -119,7 +85,7 @@ if (_hardwareSpi) { SPI.begin(); - SPI.setClockDivider(SPI_CLOCK_DIV2); + SPI.setClockDivider(SPI_CLOCK_DIV32); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); _spiSettings = SPCR; @@ -172,38 +138,20 @@ } void DmTouch::spiWrite(uint8_t data) { + if (_hardwareSpi) { #if defined (DM_TOOLCHAIN_ARDUINO) - if (_hardwareSpi) { SPCR = _spiSettings; // SPI Control Register SPDR = data; // SPI Data Register while(!(SPSR & _BV(SPIF))); // SPI Status Register Wait for transmission to finish - } - else { - uint8_t count=0; - uint8_t temp; - unsigned nop; - temp=data; // really needed? - cbi(_pinCLK, _bitmaskCLK); - for(count=0;count<8;count++) { - if(temp&0x80) { - sbi(_pinMOSI, _bitmaskMOSI); - } - else { - cbi(_pinMOSI, _bitmaskMOSI); - } - - temp=temp<<1; - - pulse_low(_pinCLK, _bitmaskCLK); - } - } #elif defined (DM_TOOLCHAIN_MBED) - if (_hardwareSpi) { _spi->write(data); +#endif } 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); @@ -217,7 +165,6 @@ slow_pulse_low(_pinCLK, _bitmaskCLK); } } -#endif } uint8_t DmTouch::spiRead() {// Only used for Hardware SPI @@ -234,6 +181,7 @@ } 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++) { @@ -251,18 +199,18 @@ uint16_t value = 0; spiWrite(command); // Send command -//-------------- + #if defined (DM_TOOLCHAIN_ARDUINO) if (_hardwareSpi) { // 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 |= temp; value >>=3; value &= 0xFFF; - } - else { + } else { pulse_high(_pinCLK, _bitmaskCLK); unsigned nop; uint8_t count=0; @@ -286,53 +234,43 @@ return value; } -void DmTouch::readTouchData(uint16_t& posX, uint16_t& posY, bool& touching) { +void DmTouch::readRawData(uint16_t &x, uint16_t &y) { + cbi(_pinCS, _bitmaskCS); + x = readData12(0xD0); + y = readData12(0x90); + sbi(_pinCS, _bitmaskCS); +} + +void DmTouch::readTouchData(uint16_t& posX, uint16_t& posY, bool& touching) { #if defined (DM_TOOLCHAIN_MBED) if (!isTouched()) { touching = false; return; } - //touching = true; #endif - unsigned int TP_X, TP_Y; - cbi(_pinCS, _bitmaskCS); - - TP_X = readData12(0xD0); - TP_Y = readData12(0x90); - - sbi(_pinCS, _bitmaskCS); - -// Serial.print("Raw X: "); -// Serial.println(TP_X); -// Serial.print("Raw Y: "); -// Serial.println(TP_Y); + uint16_t touchX, touchY; + getMiddleXY(touchX,touchY); - // Convert raw data to screen positions - if (_calibInvertedTouch) { - posX=_width-((TP_X-_calibLowX)/_calibModifierX); - posY=_height-((TP_Y-_calibLowY)/_calibModifierY); - } else { - posX=((TP_X-_calibLowX)/_calibModifierX); - posY=((TP_Y-_calibLowY)/_calibModifierY); - } - //printf("Raw: %5u, %5u, Calibrated: %3u, %u\n", TP_X, TP_Y, posX, posY); - -//#if defined (DM_TOOLCHAIN_ARDUINO) - if (posX >= 0 && posX <= _width && posY >= 0 && posY <= _height) { - touching = true; - } else { - touching = false; - } -//#endif + posX = getDisplayCoordinateX(touchX, touchY); + posY = getDisplayCoordinateY(touchX, touchY); + + touching = isTouched(); } -uint8_t DmTouch::isTouched() { +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 defined (DM_TOOLCHAIN_ARDUINO) if (_irq == -1) { - uint16_t posX, posY; - bool touched; - readTouchData(posX, posY, touched); - return touched; + return isSampleValid(); } if ( !gbi(_pinIrq, _bitmaskIrq) ) { @@ -344,3 +282,98 @@ return (*_pinIrq == 0); #endif } + +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 (!isTouched()) { + haveAllMeasurements = false; + break; + } + } + 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]; + } +}