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
TouchScreen.h@0:3f0160100cc9, 2016-03-19 (annotated)
- Committer:
- duncanFrance
- Date:
- Sat Mar 19 15:39:36 2016 +0000
- Revision:
- 0:3f0160100cc9
- Child:
- 1:9bd85d0331a8
Initial import
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
duncanFrance | 0:3f0160100cc9 | 1 | #ifndef TOUCHSCREEN_H |
duncanFrance | 0:3f0160100cc9 | 2 | #define TOUCHSCREEN_H |
duncanFrance | 0:3f0160100cc9 | 3 | |
duncanFrance | 0:3f0160100cc9 | 4 | /** |
duncanFrance | 0:3f0160100cc9 | 5 | * An interrupt-driven library to interface with touch-screens using the ADS7843 chip. |
duncanFrance | 0:3f0160100cc9 | 6 | * |
duncanFrance | 0:3f0160100cc9 | 7 | * |
duncanFrance | 0:3f0160100cc9 | 8 | **/ |
duncanFrance | 0:3f0160100cc9 | 9 | #include "mbed.h" |
duncanFrance | 0:3f0160100cc9 | 10 | #include "rtos.h" |
duncanFrance | 0:3f0160100cc9 | 11 | |
duncanFrance | 0:3f0160100cc9 | 12 | #define TOUCHSCREEN_SPI_FREQUENCY 500000 |
duncanFrance | 0:3f0160100cc9 | 13 | |
duncanFrance | 0:3f0160100cc9 | 14 | #define TOUCHSCREEN_CMD_GETX 0x90 |
duncanFrance | 0:3f0160100cc9 | 15 | #define TOUCHSCREEN_CMD_GETY 0xD0 |
duncanFrance | 0:3f0160100cc9 | 16 | #define TOUCHSCREEN_PRECISION_8 0x08 |
duncanFrance | 0:3f0160100cc9 | 17 | #define TOUCHSCREEN_PRECISION_12 0x00 |
duncanFrance | 0:3f0160100cc9 | 18 | |
duncanFrance | 0:3f0160100cc9 | 19 | #define TOUCHSCREEN_SIGNAL_START 0x01 |
duncanFrance | 0:3f0160100cc9 | 20 | #define TOUCHSCREEN_SIGNAL_END 0x02 |
duncanFrance | 0:3f0160100cc9 | 21 | #define TOUCHSCREEN_SIGNAL_POLL 0x04 |
duncanFrance | 0:3f0160100cc9 | 22 | |
duncanFrance | 0:3f0160100cc9 | 23 | #define TOUCHSCREEN_POLL_MICROS 50000 |
duncanFrance | 0:3f0160100cc9 | 24 | |
duncanFrance | 0:3f0160100cc9 | 25 | /** |
duncanFrance | 0:3f0160100cc9 | 26 | * Default value for how far the touch position must have moved before a new TouchMove event is raised |
duncanFrance | 0:3f0160100cc9 | 27 | **/ |
duncanFrance | 0:3f0160100cc9 | 28 | #define TOUCHSCREEN_MOVEMENT_THRESHOLD 4 |
duncanFrance | 0:3f0160100cc9 | 29 | #define TOUCHSCREEN_DEBOUNCE_MICROS 50000 |
duncanFrance | 0:3f0160100cc9 | 30 | |
duncanFrance | 0:3f0160100cc9 | 31 | #define TOUCHSCREEN_STATE_IDLE 0 |
duncanFrance | 0:3f0160100cc9 | 32 | #define TOUCHSCREEN_STATE_DEBOUNCE 1 |
duncanFrance | 0:3f0160100cc9 | 33 | #define TOUCHSCREEN_STATE_POLL 2 |
duncanFrance | 0:3f0160100cc9 | 34 | |
duncanFrance | 0:3f0160100cc9 | 35 | #define TOUCHSCREEN_ORIENTATION_LANDSCAPE 0 |
duncanFrance | 0:3f0160100cc9 | 36 | #define TOUCHSCREEN_ORIENTATION_PORTRAIT 1 |
duncanFrance | 0:3f0160100cc9 | 37 | #define TOUCHSCREEN_ORIENTATION_ROTATED 2 |
duncanFrance | 0:3f0160100cc9 | 38 | |
duncanFrance | 0:3f0160100cc9 | 39 | typedef struct TouchPosition { |
duncanFrance | 0:3f0160100cc9 | 40 | // Raw touch position 0 - 4095 |
duncanFrance | 0:3f0160100cc9 | 41 | int x; |
duncanFrance | 0:3f0160100cc9 | 42 | int y; |
duncanFrance | 0:3f0160100cc9 | 43 | |
duncanFrance | 0:3f0160100cc9 | 44 | // Touch position in screen pixels |
duncanFrance | 0:3f0160100cc9 | 45 | int screenX; |
duncanFrance | 0:3f0160100cc9 | 46 | int screenY; |
duncanFrance | 0:3f0160100cc9 | 47 | |
duncanFrance | 0:3f0160100cc9 | 48 | bool valid; |
duncanFrance | 0:3f0160100cc9 | 49 | } TouchPosition; |
duncanFrance | 0:3f0160100cc9 | 50 | |
duncanFrance | 0:3f0160100cc9 | 51 | typedef void (* TouchCallbackHandler)(TouchPosition p); |
duncanFrance | 0:3f0160100cc9 | 52 | |
duncanFrance | 0:3f0160100cc9 | 53 | class TouchScreen |
duncanFrance | 0:3f0160100cc9 | 54 | { |
duncanFrance | 0:3f0160100cc9 | 55 | |
duncanFrance | 0:3f0160100cc9 | 56 | public: |
duncanFrance | 0:3f0160100cc9 | 57 | |
duncanFrance | 0:3f0160100cc9 | 58 | /** |
duncanFrance | 0:3f0160100cc9 | 59 | * Basic setup uses hard-coded defaults so the screen can do something. |
duncanFrance | 0:3f0160100cc9 | 60 | * you'll want to setLCDGeometry() and setCalibration() for your screen |
duncanFrance | 0:3f0160100cc9 | 61 | * Use the TouchScreenCalibrate program to get calibration data for your screen |
duncanFrance | 0:3f0160100cc9 | 62 | **/ |
duncanFrance | 0:3f0160100cc9 | 63 | TouchScreen(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq); |
duncanFrance | 0:3f0160100cc9 | 64 | |
duncanFrance | 0:3f0160100cc9 | 65 | /** |
duncanFrance | 0:3f0160100cc9 | 66 | * Register a handler which will be called every time a touch is detected on the screen |
duncanFrance | 0:3f0160100cc9 | 67 | **/ |
duncanFrance | 0:3f0160100cc9 | 68 | void setTouchStartHandler(TouchCallbackHandler handler); |
duncanFrance | 0:3f0160100cc9 | 69 | |
duncanFrance | 0:3f0160100cc9 | 70 | /** |
duncanFrance | 0:3f0160100cc9 | 71 | * Register a handler which will be called every time a movement greater than a given threshold is detected. |
duncanFrance | 0:3f0160100cc9 | 72 | * You can set the threshold with the setMovementThreshold() method |
duncanFrance | 0:3f0160100cc9 | 73 | **/ |
duncanFrance | 0:3f0160100cc9 | 74 | void setTouchMoveHandler(TouchCallbackHandler handler); |
duncanFrance | 0:3f0160100cc9 | 75 | |
duncanFrance | 0:3f0160100cc9 | 76 | /** |
duncanFrance | 0:3f0160100cc9 | 77 | * Register a handler which will be called when a touch stops being detected |
duncanFrance | 0:3f0160100cc9 | 78 | **/ |
duncanFrance | 0:3f0160100cc9 | 79 | void setTouchEndHandler(TouchCallbackHandler handler); |
duncanFrance | 0:3f0160100cc9 | 80 | |
duncanFrance | 0:3f0160100cc9 | 81 | /** |
duncanFrance | 0:3f0160100cc9 | 82 | * Set the dimensions and orientation of the LCD screen |
duncanFrance | 0:3f0160100cc9 | 83 | **/ |
duncanFrance | 0:3f0160100cc9 | 84 | void setLCDGeometry(int width, int height, uint8_t orientation); |
duncanFrance | 0:3f0160100cc9 | 85 | |
duncanFrance | 0:3f0160100cc9 | 86 | /** |
duncanFrance | 0:3f0160100cc9 | 87 | * Set the calibration data used to calculate the screen position in pixels of a touch |
duncanFrance | 0:3f0160100cc9 | 88 | **/ |
duncanFrance | 0:3f0160100cc9 | 89 | void setCalibration(int xmin, int xmax, int ymin, int ymax); |
duncanFrance | 0:3f0160100cc9 | 90 | |
duncanFrance | 0:3f0160100cc9 | 91 | /** |
duncanFrance | 0:3f0160100cc9 | 92 | * Set the amount of movement which must occur before a TouchMove event is raised |
duncanFrance | 0:3f0160100cc9 | 93 | **/ |
duncanFrance | 0:3f0160100cc9 | 94 | void setMovementTheshold(int thresholdInPixels); |
duncanFrance | 0:3f0160100cc9 | 95 | |
duncanFrance | 0:3f0160100cc9 | 96 | private: |
duncanFrance | 0:3f0160100cc9 | 97 | |
duncanFrance | 0:3f0160100cc9 | 98 | /** |
duncanFrance | 0:3f0160100cc9 | 99 | * SPI control |
duncanFrance | 0:3f0160100cc9 | 100 | **/ |
duncanFrance | 0:3f0160100cc9 | 101 | SPI _spi ; |
duncanFrance | 0:3f0160100cc9 | 102 | DigitalOut _cs ; |
duncanFrance | 0:3f0160100cc9 | 103 | |
duncanFrance | 0:3f0160100cc9 | 104 | /** |
duncanFrance | 0:3f0160100cc9 | 105 | * The interrupt pin and its handler |
duncanFrance | 0:3f0160100cc9 | 106 | **/ |
duncanFrance | 0:3f0160100cc9 | 107 | DigitalIn _intPin; |
duncanFrance | 0:3f0160100cc9 | 108 | InterruptIn _int; |
duncanFrance | 0:3f0160100cc9 | 109 | |
duncanFrance | 0:3f0160100cc9 | 110 | uint8_t _precision; |
duncanFrance | 0:3f0160100cc9 | 111 | |
duncanFrance | 0:3f0160100cc9 | 112 | int _lcdWidth; |
duncanFrance | 0:3f0160100cc9 | 113 | int _lcdHeight; |
duncanFrance | 0:3f0160100cc9 | 114 | uint8_t _lcdOrientation; |
duncanFrance | 0:3f0160100cc9 | 115 | |
duncanFrance | 0:3f0160100cc9 | 116 | int _xmin, _xmax, _ymin, _ymax; |
duncanFrance | 0:3f0160100cc9 | 117 | int _movementThresholdSquared; |
duncanFrance | 0:3f0160100cc9 | 118 | |
duncanFrance | 0:3f0160100cc9 | 119 | TouchPosition _currentPosition; |
duncanFrance | 0:3f0160100cc9 | 120 | TouchPosition _lastPosition; |
duncanFrance | 0:3f0160100cc9 | 121 | |
duncanFrance | 0:3f0160100cc9 | 122 | unsigned int _read(uint8_t cmd); |
duncanFrance | 0:3f0160100cc9 | 123 | |
duncanFrance | 0:3f0160100cc9 | 124 | volatile uint8_t _state; |
duncanFrance | 0:3f0160100cc9 | 125 | |
duncanFrance | 0:3f0160100cc9 | 126 | void _fallInterruptHandler(); |
duncanFrance | 0:3f0160100cc9 | 127 | void _riseInterruptHandler(); |
duncanFrance | 0:3f0160100cc9 | 128 | void _tickerInterruptHandler(); |
duncanFrance | 0:3f0160100cc9 | 129 | |
duncanFrance | 0:3f0160100cc9 | 130 | |
duncanFrance | 0:3f0160100cc9 | 131 | void _handleTouchStart(); |
duncanFrance | 0:3f0160100cc9 | 132 | void _handleTouchMoved(); |
duncanFrance | 0:3f0160100cc9 | 133 | void _handleTouchEnd(); |
duncanFrance | 0:3f0160100cc9 | 134 | |
duncanFrance | 0:3f0160100cc9 | 135 | bool _moved(TouchPosition a, TouchPosition b); |
duncanFrance | 0:3f0160100cc9 | 136 | |
duncanFrance | 0:3f0160100cc9 | 137 | TouchPosition _getPosition(); |
duncanFrance | 0:3f0160100cc9 | 138 | |
duncanFrance | 0:3f0160100cc9 | 139 | TouchCallbackHandler _touchStartHandler; |
duncanFrance | 0:3f0160100cc9 | 140 | TouchCallbackHandler _touchMoveHandler; |
duncanFrance | 0:3f0160100cc9 | 141 | TouchCallbackHandler _touchEndHandler; |
duncanFrance | 0:3f0160100cc9 | 142 | |
duncanFrance | 0:3f0160100cc9 | 143 | Thread* _handlerThread; |
duncanFrance | 0:3f0160100cc9 | 144 | |
duncanFrance | 0:3f0160100cc9 | 145 | // Used to poll the screen while it is being touched to track movement and to debounce edge changes |
duncanFrance | 0:3f0160100cc9 | 146 | Ticker _ticker; |
duncanFrance | 0:3f0160100cc9 | 147 | |
duncanFrance | 0:3f0160100cc9 | 148 | /** |
duncanFrance | 0:3f0160100cc9 | 149 | * Needs to be static because a Thread can't be started on an instance method. |
duncanFrance | 0:3f0160100cc9 | 150 | **/ |
duncanFrance | 0:3f0160100cc9 | 151 | static void _monitor(void const *touchScreen) { |
duncanFrance | 0:3f0160100cc9 | 152 | |
duncanFrance | 0:3f0160100cc9 | 153 | TouchScreen* screen = (TouchScreen*)touchScreen; |
duncanFrance | 0:3f0160100cc9 | 154 | |
duncanFrance | 0:3f0160100cc9 | 155 | while(true) { |
duncanFrance | 0:3f0160100cc9 | 156 | osEvent evt = Thread::signal_wait(0); |
duncanFrance | 0:3f0160100cc9 | 157 | if(evt.status == osEventSignal) { |
duncanFrance | 0:3f0160100cc9 | 158 | if(evt.value.signals & TOUCHSCREEN_SIGNAL_START) { |
duncanFrance | 0:3f0160100cc9 | 159 | screen->_handlerThread->signal_clr(TOUCHSCREEN_SIGNAL_START); |
duncanFrance | 0:3f0160100cc9 | 160 | screen->_handleTouchStart(); |
duncanFrance | 0:3f0160100cc9 | 161 | } |
duncanFrance | 0:3f0160100cc9 | 162 | if(evt.value.signals & TOUCHSCREEN_SIGNAL_END) { |
duncanFrance | 0:3f0160100cc9 | 163 | screen->_handlerThread->signal_clr(TOUCHSCREEN_SIGNAL_END); |
duncanFrance | 0:3f0160100cc9 | 164 | screen->_handleTouchEnd(); |
duncanFrance | 0:3f0160100cc9 | 165 | } |
duncanFrance | 0:3f0160100cc9 | 166 | if(evt.value.signals & TOUCHSCREEN_SIGNAL_POLL) { |
duncanFrance | 0:3f0160100cc9 | 167 | screen->_handlerThread->signal_clr(TOUCHSCREEN_SIGNAL_POLL); |
duncanFrance | 0:3f0160100cc9 | 168 | screen->_handleTouchMoved(); |
duncanFrance | 0:3f0160100cc9 | 169 | } |
duncanFrance | 0:3f0160100cc9 | 170 | } |
duncanFrance | 0:3f0160100cc9 | 171 | } |
duncanFrance | 0:3f0160100cc9 | 172 | } |
duncanFrance | 0:3f0160100cc9 | 173 | |
duncanFrance | 0:3f0160100cc9 | 174 | }; |
duncanFrance | 0:3f0160100cc9 | 175 | |
duncanFrance | 0:3f0160100cc9 | 176 | #endif |