A library for ADS7843 touch-screens which is interrupt driven, allowing you to register callback handlers for touchStart, touchMove and touchEnd events.

Dependents:   TouchScreenCalibrate TouchScreenGUIDemo

Committer:
duncanFrance
Date:
Tue May 17 16:28:08 2016 +0000
Revision:
3:8b5fcf3857ac
Parent:
2:e5ea47fb1ede
Can now attach instance methods as callback handlers

Who changed what in which revision?

UserRevisionLine numberNew contents of line
duncanFrance 0:3f0160100cc9 1 #include "TouchScreen.h"
duncanFrance 0:3f0160100cc9 2
duncanFrance 0:3f0160100cc9 3 TouchScreen::TouchScreen(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq) :
duncanFrance 0:3f0160100cc9 4 _spi(mosi, miso, sclk), _cs(cs), _intPin(irq), _int(irq), _precision(TOUCHSCREEN_PRECISION_12)
duncanFrance 0:3f0160100cc9 5 {
duncanFrance 0:3f0160100cc9 6 setLCDGeometry(320,240,TOUCHSCREEN_ORIENTATION_LANDSCAPE);
duncanFrance 0:3f0160100cc9 7 setCalibration(540, 3700, 340, 3656);
duncanFrance 0:3f0160100cc9 8
duncanFrance 0:3f0160100cc9 9 _movementThresholdSquared = TOUCHSCREEN_MOVEMENT_THRESHOLD * TOUCHSCREEN_MOVEMENT_THRESHOLD;
duncanFrance 0:3f0160100cc9 10 _cs = 1;
duncanFrance 0:3f0160100cc9 11 _spi.frequency(TOUCHSCREEN_SPI_FREQUENCY) ;
duncanFrance 0:3f0160100cc9 12 _spi.format(8,0) ;
duncanFrance 0:3f0160100cc9 13 _state = TOUCHSCREEN_STATE_IDLE;
duncanFrance 0:3f0160100cc9 14 _int.fall(this, &TouchScreen::_fallInterruptHandler);
duncanFrance 0:3f0160100cc9 15 _handlerThread = new Thread(&TouchScreen::_monitor, this);
duncanFrance 0:3f0160100cc9 16 }
duncanFrance 0:3f0160100cc9 17
duncanFrance 0:3f0160100cc9 18 void TouchScreen::setLCDGeometry(int width, int height, uint8_t orientation) {
duncanFrance 0:3f0160100cc9 19 _lcdWidth = width;
duncanFrance 0:3f0160100cc9 20 _lcdHeight = height;
duncanFrance 0:3f0160100cc9 21 _lcdOrientation = orientation;
duncanFrance 0:3f0160100cc9 22 }
duncanFrance 0:3f0160100cc9 23
duncanFrance 0:3f0160100cc9 24 void TouchScreen::setCalibration(int xmin, int xmax, int ymin, int ymax) {
duncanFrance 0:3f0160100cc9 25 _xmin = xmin; _xmax = xmax;
duncanFrance 0:3f0160100cc9 26 _ymin = ymin; _ymax = ymax;
duncanFrance 0:3f0160100cc9 27 }
duncanFrance 0:3f0160100cc9 28
duncanFrance 0:3f0160100cc9 29 void TouchScreen::setTouchStartHandler(TouchCallbackHandler handler)
duncanFrance 0:3f0160100cc9 30 {
duncanFrance 3:8b5fcf3857ac 31 _touchStartHandler.attach(handler);
duncanFrance 0:3f0160100cc9 32 }
duncanFrance 0:3f0160100cc9 33
duncanFrance 0:3f0160100cc9 34 void TouchScreen::setTouchMoveHandler(TouchCallbackHandler handler)
duncanFrance 0:3f0160100cc9 35 {
duncanFrance 3:8b5fcf3857ac 36 _touchMoveHandler.attach(handler);
duncanFrance 0:3f0160100cc9 37 }
duncanFrance 0:3f0160100cc9 38
duncanFrance 0:3f0160100cc9 39 void TouchScreen::setTouchEndHandler(TouchCallbackHandler handler)
duncanFrance 0:3f0160100cc9 40 {
duncanFrance 3:8b5fcf3857ac 41 _touchEndHandler.attach(handler);
duncanFrance 0:3f0160100cc9 42 }
duncanFrance 0:3f0160100cc9 43
duncanFrance 0:3f0160100cc9 44 void TouchScreen::setMovementTheshold(int thresholdInPixels) {
duncanFrance 0:3f0160100cc9 45 _movementThresholdSquared = thresholdInPixels * thresholdInPixels;
duncanFrance 0:3f0160100cc9 46 }
duncanFrance 0:3f0160100cc9 47
duncanFrance 0:3f0160100cc9 48 TouchPosition TouchScreen::_getPosition()
duncanFrance 0:3f0160100cc9 49 {
duncanFrance 0:3f0160100cc9 50 int xf, yf, xt, yt;
duncanFrance 0:3f0160100cc9 51 int xmin = 65535, ymin = 65535;
duncanFrance 0:3f0160100cc9 52 int xmax = 0, ymax = 0;
duncanFrance 0:3f0160100cc9 53
duncanFrance 0:3f0160100cc9 54 unsigned int samples;
duncanFrance 0:3f0160100cc9 55
duncanFrance 0:3f0160100cc9 56 TouchPosition position;
duncanFrance 0:3f0160100cc9 57
duncanFrance 0:3f0160100cc9 58 xf=0;
duncanFrance 0:3f0160100cc9 59 yf=0;
duncanFrance 0:3f0160100cc9 60 samples=0;
duncanFrance 0:3f0160100cc9 61
duncanFrance 0:3f0160100cc9 62 for(int i=0; i<32; i++) {
duncanFrance 0:3f0160100cc9 63 xt = _read(TOUCHSCREEN_CMD_GETX + _precision);
duncanFrance 0:3f0160100cc9 64 yt = _read(TOUCHSCREEN_CMD_GETY + _precision);
duncanFrance 0:3f0160100cc9 65 if(xt>0 && yt>0) {
duncanFrance 0:3f0160100cc9 66 xf+=xt;
duncanFrance 0:3f0160100cc9 67 yf+=yt;
duncanFrance 0:3f0160100cc9 68 samples++;
duncanFrance 0:3f0160100cc9 69 if(xt < xmin) xmin = xt;
duncanFrance 0:3f0160100cc9 70 if(xmax < xt) xmax = xt;
duncanFrance 0:3f0160100cc9 71 if(yt < ymin) ymin = yt;
duncanFrance 0:3f0160100cc9 72 if(ymax < yt) ymax = yt;
duncanFrance 0:3f0160100cc9 73 }
duncanFrance 0:3f0160100cc9 74 }
duncanFrance 0:3f0160100cc9 75 // remove the outlier samples
duncanFrance 0:3f0160100cc9 76 xf = xf - xmin - xmax;
duncanFrance 0:3f0160100cc9 77 yf = yf - ymin - ymax;
duncanFrance 0:3f0160100cc9 78
duncanFrance 0:3f0160100cc9 79
duncanFrance 0:3f0160100cc9 80 if(samples > 2) {
duncanFrance 0:3f0160100cc9 81 samples -=2;
duncanFrance 0:3f0160100cc9 82 xf = xf / samples;
duncanFrance 0:3f0160100cc9 83 yf = yf / samples;
duncanFrance 0:3f0160100cc9 84
duncanFrance 0:3f0160100cc9 85 // Now adjust and scale to fit screen
duncanFrance 0:3f0160100cc9 86
duncanFrance 0:3f0160100cc9 87 if(_lcdOrientation & TOUCHSCREEN_ORIENTATION_PORTRAIT) {
duncanFrance 0:3f0160100cc9 88 // swap x and y
duncanFrance 0:3f0160100cc9 89 xt = xf;
duncanFrance 0:3f0160100cc9 90 xf = yf;
duncanFrance 0:3f0160100cc9 91 yf = xt;
duncanFrance 0:3f0160100cc9 92 }
duncanFrance 0:3f0160100cc9 93
duncanFrance 0:3f0160100cc9 94 position.x = xf;
duncanFrance 0:3f0160100cc9 95 position.y = yf;
duncanFrance 0:3f0160100cc9 96 position.screenX = ((xf - _xmin) * _lcdWidth) / (_xmax - _xmin);
duncanFrance 0:3f0160100cc9 97 position.screenY = ((yf - _ymin) * _lcdHeight) / (_ymax - _ymin);
duncanFrance 0:3f0160100cc9 98
duncanFrance 0:3f0160100cc9 99 if(_lcdOrientation & TOUCHSCREEN_ORIENTATION_ROTATED) {
duncanFrance 0:3f0160100cc9 100 position.screenX = _lcdWidth - position.screenX;
duncanFrance 0:3f0160100cc9 101 position.screenY = _lcdHeight - position.screenY;
duncanFrance 0:3f0160100cc9 102 }
duncanFrance 0:3f0160100cc9 103
duncanFrance 0:3f0160100cc9 104 position.valid = true;
duncanFrance 0:3f0160100cc9 105
duncanFrance 0:3f0160100cc9 106 } else {
duncanFrance 0:3f0160100cc9 107 position.valid = false;
duncanFrance 0:3f0160100cc9 108 }
duncanFrance 0:3f0160100cc9 109
duncanFrance 0:3f0160100cc9 110 return position;
duncanFrance 0:3f0160100cc9 111 }
duncanFrance 0:3f0160100cc9 112
duncanFrance 0:3f0160100cc9 113 void TouchScreen::_handleTouchStart()
duncanFrance 0:3f0160100cc9 114 {
duncanFrance 0:3f0160100cc9 115 _lastPosition.valid = false;
duncanFrance 0:3f0160100cc9 116 _currentPosition = _getPosition();
duncanFrance 0:3f0160100cc9 117 // Raise an event if we got a valid position
duncanFrance 0:3f0160100cc9 118 if(_currentPosition.valid && _touchStartHandler) {
duncanFrance 3:8b5fcf3857ac 119 _touchStartHandler.call(_currentPosition);
duncanFrance 0:3f0160100cc9 120 }
duncanFrance 0:3f0160100cc9 121 }
duncanFrance 0:3f0160100cc9 122
duncanFrance 0:3f0160100cc9 123 void TouchScreen::_handleTouchEnd()
duncanFrance 0:3f0160100cc9 124 {
duncanFrance 0:3f0160100cc9 125 // Raise an event if we got a valid position
duncanFrance 0:3f0160100cc9 126 if(_currentPosition.valid && _touchEndHandler) {
duncanFrance 3:8b5fcf3857ac 127 _touchEndHandler.call(_currentPosition);
duncanFrance 0:3f0160100cc9 128 }
duncanFrance 0:3f0160100cc9 129 }
duncanFrance 0:3f0160100cc9 130
duncanFrance 0:3f0160100cc9 131 void TouchScreen::_handleTouchMoved()
duncanFrance 0:3f0160100cc9 132 {
duncanFrance 0:3f0160100cc9 133 // Update the position
duncanFrance 0:3f0160100cc9 134 TouchPosition newPosition = _getPosition();
duncanFrance 0:3f0160100cc9 135 if(!_lastPosition.valid) {
duncanFrance 0:3f0160100cc9 136 _lastPosition = newPosition;
duncanFrance 0:3f0160100cc9 137 }
duncanFrance 0:3f0160100cc9 138
duncanFrance 0:3f0160100cc9 139 if(_touchMoveHandler && _moved(newPosition, _lastPosition)) {
duncanFrance 0:3f0160100cc9 140 _lastPosition = _currentPosition;
duncanFrance 0:3f0160100cc9 141 _currentPosition = newPosition;
duncanFrance 3:8b5fcf3857ac 142 _touchMoveHandler.call(_currentPosition);
duncanFrance 0:3f0160100cc9 143 }
duncanFrance 0:3f0160100cc9 144 }
duncanFrance 0:3f0160100cc9 145
duncanFrance 0:3f0160100cc9 146 bool TouchScreen::_moved(TouchPosition a, TouchPosition b)
duncanFrance 0:3f0160100cc9 147 {
duncanFrance 0:3f0160100cc9 148 bool moved = false;
duncanFrance 0:3f0160100cc9 149
duncanFrance 0:3f0160100cc9 150 if(a.valid && b.valid) {
duncanFrance 0:3f0160100cc9 151 int dx = a.screenX - b.screenX;
duncanFrance 0:3f0160100cc9 152 int dy = a.screenY - b.screenY;
duncanFrance 0:3f0160100cc9 153 if((dx*dx + dy*dy) > _movementThresholdSquared) {
duncanFrance 0:3f0160100cc9 154 moved = true;
duncanFrance 0:3f0160100cc9 155 }
duncanFrance 0:3f0160100cc9 156 }
duncanFrance 0:3f0160100cc9 157
duncanFrance 0:3f0160100cc9 158 return moved;
duncanFrance 0:3f0160100cc9 159 }
duncanFrance 0:3f0160100cc9 160
duncanFrance 0:3f0160100cc9 161 void TouchScreen::_fallInterruptHandler()
duncanFrance 0:3f0160100cc9 162 {
duncanFrance 0:3f0160100cc9 163 __disable_irq(); // is this needed in an ISR?
duncanFrance 0:3f0160100cc9 164
duncanFrance 0:3f0160100cc9 165 _int.fall(0);
duncanFrance 0:3f0160100cc9 166 _int.rise(this, &TouchScreen::_riseInterruptHandler);
duncanFrance 0:3f0160100cc9 167 _ticker.attach_us(this, &TouchScreen::_tickerInterruptHandler, TOUCHSCREEN_DEBOUNCE_MICROS);
duncanFrance 0:3f0160100cc9 168 _state = TOUCHSCREEN_STATE_DEBOUNCE;
duncanFrance 0:3f0160100cc9 169
duncanFrance 0:3f0160100cc9 170 __enable_irq();
duncanFrance 0:3f0160100cc9 171
duncanFrance 0:3f0160100cc9 172 }
duncanFrance 0:3f0160100cc9 173
duncanFrance 0:3f0160100cc9 174 void TouchScreen::_riseInterruptHandler()
duncanFrance 0:3f0160100cc9 175 {
duncanFrance 0:3f0160100cc9 176 __disable_irq();
duncanFrance 0:3f0160100cc9 177
duncanFrance 0:3f0160100cc9 178 _int.rise(0);
duncanFrance 0:3f0160100cc9 179 _int.fall(this, &TouchScreen::_fallInterruptHandler);
duncanFrance 0:3f0160100cc9 180 _ticker.attach_us(this, &TouchScreen::_tickerInterruptHandler, TOUCHSCREEN_DEBOUNCE_MICROS);
duncanFrance 0:3f0160100cc9 181 _state = TOUCHSCREEN_STATE_DEBOUNCE;
duncanFrance 0:3f0160100cc9 182
duncanFrance 0:3f0160100cc9 183 __enable_irq();
duncanFrance 0:3f0160100cc9 184 }
duncanFrance 0:3f0160100cc9 185
duncanFrance 0:3f0160100cc9 186 void TouchScreen::_tickerInterruptHandler()
duncanFrance 0:3f0160100cc9 187 {
duncanFrance 0:3f0160100cc9 188 __disable_irq();
duncanFrance 0:3f0160100cc9 189 switch(_state) {
duncanFrance 0:3f0160100cc9 190 /**
duncanFrance 0:3f0160100cc9 191 * This state should not be reachable in this ISR
duncanFrance 0:3f0160100cc9 192 **/
duncanFrance 0:3f0160100cc9 193 case TOUCHSCREEN_STATE_IDLE:
duncanFrance 0:3f0160100cc9 194 // fallthrough to set the pin interrupt handler
duncanFrance 0:3f0160100cc9 195
duncanFrance 0:3f0160100cc9 196 /**
duncanFrance 0:3f0160100cc9 197 * The debounce timer timed-out, so we have a valid level.
duncanFrance 0:3f0160100cc9 198 **/
duncanFrance 0:3f0160100cc9 199 case TOUCHSCREEN_STATE_DEBOUNCE:
duncanFrance 0:3f0160100cc9 200
duncanFrance 0:3f0160100cc9 201 _ticker.detach();
duncanFrance 0:3f0160100cc9 202
duncanFrance 0:3f0160100cc9 203 if(_intPin == 1) {
duncanFrance 0:3f0160100cc9 204 _int.rise(0);
duncanFrance 0:3f0160100cc9 205 _int.fall(this, &TouchScreen::_fallInterruptHandler);
duncanFrance 0:3f0160100cc9 206 _state = TOUCHSCREEN_STATE_IDLE;
duncanFrance 0:3f0160100cc9 207
duncanFrance 0:3f0160100cc9 208 if(_handlerThread != 0) {
duncanFrance 0:3f0160100cc9 209 _handlerThread->signal_set(TOUCHSCREEN_SIGNAL_END);
duncanFrance 0:3f0160100cc9 210 }
duncanFrance 0:3f0160100cc9 211 } else {
duncanFrance 0:3f0160100cc9 212 _int.fall(0);
duncanFrance 0:3f0160100cc9 213 _int.rise(this, &TouchScreen::_riseInterruptHandler);
duncanFrance 0:3f0160100cc9 214 _state = TOUCHSCREEN_STATE_POLL;
duncanFrance 0:3f0160100cc9 215 _ticker.attach_us(this, &TouchScreen::_tickerInterruptHandler, TOUCHSCREEN_POLL_MICROS);
duncanFrance 0:3f0160100cc9 216
duncanFrance 0:3f0160100cc9 217 if(_handlerThread != 0) {
duncanFrance 0:3f0160100cc9 218 _handlerThread->signal_set(TOUCHSCREEN_SIGNAL_START);
duncanFrance 0:3f0160100cc9 219 }
duncanFrance 0:3f0160100cc9 220 }
duncanFrance 0:3f0160100cc9 221
duncanFrance 0:3f0160100cc9 222 break;
duncanFrance 0:3f0160100cc9 223
duncanFrance 0:3f0160100cc9 224 case TOUCHSCREEN_STATE_POLL:
duncanFrance 0:3f0160100cc9 225 if(_handlerThread != 0) {
duncanFrance 0:3f0160100cc9 226 _handlerThread->signal_set(TOUCHSCREEN_SIGNAL_POLL);
duncanFrance 0:3f0160100cc9 227 }
duncanFrance 0:3f0160100cc9 228
duncanFrance 0:3f0160100cc9 229 }
duncanFrance 0:3f0160100cc9 230 __enable_irq();
duncanFrance 0:3f0160100cc9 231 }
duncanFrance 0:3f0160100cc9 232
duncanFrance 0:3f0160100cc9 233 unsigned int TouchScreen::_read(uint8_t cmd)
duncanFrance 0:3f0160100cc9 234 {
duncanFrance 0:3f0160100cc9 235 unsigned int tmp;
duncanFrance 0:3f0160100cc9 236
duncanFrance 2:e5ea47fb1ede 237 __disable_irq();
duncanFrance 0:3f0160100cc9 238 _cs = 0;
duncanFrance 0:3f0160100cc9 239 wait_us(1);
duncanFrance 0:3f0160100cc9 240 _spi.write(cmd);
duncanFrance 0:3f0160100cc9 241 wait_us(1);
duncanFrance 0:3f0160100cc9 242 // First clock start conversion, so we only get 7-bits on this read
duncanFrance 0:3f0160100cc9 243 tmp = _spi.write(0x00) << 5;
duncanFrance 0:3f0160100cc9 244 // Remaining 5 bits on this read
duncanFrance 0:3f0160100cc9 245 tmp |= _spi.write(0x00) >> 3;
duncanFrance 0:3f0160100cc9 246 _cs = 1;
duncanFrance 0:3f0160100cc9 247
duncanFrance 0:3f0160100cc9 248 if (_precision == TOUCHSCREEN_PRECISION_8) {
duncanFrance 0:3f0160100cc9 249 tmp = tmp & 0x0ff0; // mask off lowest 4 bits since they are meaningless
duncanFrance 0:3f0160100cc9 250 }
duncanFrance 0:3f0160100cc9 251 tmp &= 0xfff;
duncanFrance 2:e5ea47fb1ede 252
duncanFrance 2:e5ea47fb1ede 253 __enable_irq();
duncanFrance 0:3f0160100cc9 254 return tmp;
duncanFrance 0:3f0160100cc9 255 }