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
Diff: DmTouch.cpp
- Revision:
- 0:d6ff5fa503e8
- Child:
- 3:02c19cbc707c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DmTouch.cpp Tue May 13 09:31:24 2014 +0000 @@ -0,0 +1,349 @@ +/********************************************************************************************** + 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 + +#include "DmTouch.h" + +#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; + +#elif defined (DM_TOOLCHAIN_MBED) +// disp - which display is used +DmTouch::DmTouch(Display disp, bool hardwareSPI) +{ + _hardwareSpi = hardwareSPI; + switch (disp) { + // Display with 40-pin connector on top of adapter board + case DmTouch::DM_TFT28_103: + case DmTouch::DM_TFT24_104: + _cs = D8; + _irq = D10; + _clk = A1; + _mosi = A0; + _miso = D9; + _width = 240; + _height = 320; + break; + + case DmTouch::DM_TFT28_105: + _cs = D4; + _irq = D2; + _clk = D13; + _mosi = D11; + _miso = D12; + _width = 240; + _height = 320; + break; + + case DmTouch::DM_TFT35_107: + default: + _cs = D4; + _irq = D2; + _clk = D13; + _mosi = D11; + _miso = D12; + _width = 320; + _height = 240; + break; + } +#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; + + 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; + } +} + +void DmTouch::init() { +#if defined (DM_TOOLCHAIN_ARDUINO) + pinMode(_cs, OUTPUT); + _pinCS = portOutputRegister(digitalPinToPort(_cs)); + _bitmaskCS = digitalPinToBitMask(_cs); + + if (_hardwareSpi) { + SPI.begin(); + SPI.setClockDivider(SPI_CLOCK_DIV2); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + _spiSettings = SPCR; + } + else { + pinMode(_clk, OUTPUT); + pinMode(_mosi, OUTPUT); + pinMode(_miso, INPUT); + _pinCLK = portOutputRegister(digitalPinToPort(_clk)); + _bitmaskCLK = digitalPinToBitMask(_clk); + _pinMOSI = portOutputRegister(digitalPinToPort(_mosi)); + _bitmaskMOSI = digitalPinToBitMask(_mosi); + _pinMISO = portInputRegister(digitalPinToPort(_miso)); + _bitmaskMISO = digitalPinToBitMask(_miso); + } +#elif defined (DM_TOOLCHAIN_MBED) + _pinCS = new DigitalOut((PinName)_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 + //cbi(_pinCS, _bitmaskCS); + } else { + _pinCLK = new DigitalOut((PinName)_clk); + _pinMISO = new DigitalOut((PinName)_miso); + _pinMOSI = new DigitalOut((PinName)_mosi); + } +#endif + + if (_irq != -1) { // We will use Touch IRQ + enableIrq(); + } +} + +void DmTouch::enableIrq() { +#if defined (DM_TOOLCHAIN_ARDUINO) + pinMode(_irq, INPUT); + _pinIrq = portInputRegister(digitalPinToPort(_irq)); + _bitmaskIrq = digitalPinToBitMask(_irq); +#elif defined (DM_TOOLCHAIN_MBED) + _pinIrq = new DigitalIn((PinName)_irq); + _pinIrq->mode(PullUp); +#endif + + cbi(_pinCS, _bitmaskCS); + spiWrite(0x80); // Enable PENIRQ + sbi(_pinCS, _bitmaskCS); +} + +void DmTouch::spiWrite(uint8_t data) { +#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); + } + else { + uint8_t count=0; + uint8_t temp = data; + 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); + } + } +#endif +} + +uint8_t DmTouch::spiRead() {// Only used for Hardware SPI +#if defined (DM_TOOLCHAIN_ARDUINO) + uint8_t data; + SPCR = _spiSettings; + spiWrite(0x00); + data = SPDR; + + return data; +#elif defined (DM_TOOLCHAIN_MBED) + 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); + for(count=0;count<8;count++) { + + pulse_low(_pinCLK, _bitmaskCLK); + temp = temp<<1; + temp |= _pinMISO->read(); + } + return temp; + } +#endif +} + +uint16_t DmTouch::readData12(uint8_t command) { + uint8_t temp = 0; + 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 >>=3; + value &= 0xFFF; + } + else { + pulse_high(_pinCLK, _bitmaskCLK); + unsigned nop; + uint8_t count=0; + for(count=0;count<12;count++) { + value<<=1; + pulse_high(_pinCLK, _bitmaskCLK); + if ( gbi(_pinMISO, _bitmaskMISO) ) { + value++; + } + } + } +#elif defined (DM_TOOLCHAIN_MBED) + // 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; +#endif + return value; +} + +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); + + // 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); + } + +//#if defined (DM_TOOLCHAIN_ARDUINO) + if (posX >= 0 && posX <= _width && posY >= 0 && posY <= _height) { + touching = true; + } else { + touching = false; + } +//#endif +} + +uint8_t DmTouch::isTouched() { +#if defined (DM_TOOLCHAIN_ARDUINO) + if (_irq == -1) { + uint16_t posX, posY; + bool touched; + readTouchData(posX, posY, touched); + return touched; + } + + if ( !gbi(_pinIrq, _bitmaskIrq) ) { + return true; + } + + return false; +#elif defined (DM_TOOLCHAIN_MBED) + return (*_pinIrq == 0); +#endif +} + + +