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

Committer:
duncanFrance
Date:
2016-03-19
Revision:
0:3f0160100cc9
Child:
1:9bd85d0331a8

File content as of revision 0:3f0160100cc9:

#ifndef TOUCHSCREEN_H
#define TOUCHSCREEN_H

/**
* An interrupt-driven library to interface with touch-screens using the ADS7843 chip.
*
*
**/
#include "mbed.h"
#include "rtos.h"

#define TOUCHSCREEN_SPI_FREQUENCY 500000

#define TOUCHSCREEN_CMD_GETX 0x90
#define TOUCHSCREEN_CMD_GETY 0xD0
#define TOUCHSCREEN_PRECISION_8 0x08
#define TOUCHSCREEN_PRECISION_12 0x00

#define TOUCHSCREEN_SIGNAL_START 0x01
#define TOUCHSCREEN_SIGNAL_END 0x02
#define TOUCHSCREEN_SIGNAL_POLL 0x04

#define TOUCHSCREEN_POLL_MICROS 50000

/**
* Default value for how far the touch position must have moved before a new TouchMove event is raised
**/
#define TOUCHSCREEN_MOVEMENT_THRESHOLD 4
#define TOUCHSCREEN_DEBOUNCE_MICROS 50000

#define TOUCHSCREEN_STATE_IDLE 0
#define TOUCHSCREEN_STATE_DEBOUNCE 1
#define TOUCHSCREEN_STATE_POLL 2

#define TOUCHSCREEN_ORIENTATION_LANDSCAPE 0
#define TOUCHSCREEN_ORIENTATION_PORTRAIT 1
#define TOUCHSCREEN_ORIENTATION_ROTATED 2

typedef struct TouchPosition {
    // Raw touch position 0 - 4095
    int x;
    int y;
    
    // Touch position in screen pixels
    int screenX;
    int screenY;
    
    bool valid;
} TouchPosition;

typedef void (* TouchCallbackHandler)(TouchPosition p);

class TouchScreen
{

public:

    /**
    * Basic setup uses hard-coded defaults so the screen can do something.
    * you'll want to setLCDGeometry() and setCalibration() for your screen
    * Use the TouchScreenCalibrate program to get calibration data for your screen
    **/
    TouchScreen(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq);
    
    /**
    * Register a handler which will be called every time a touch is detected on the screen
    **/
    void setTouchStartHandler(TouchCallbackHandler handler);
    
    /**
    * Register a handler which will be called every time a movement greater than a given threshold is detected.
    * You can set the threshold with the setMovementThreshold() method
    **/
    void setTouchMoveHandler(TouchCallbackHandler handler);
    
    /**
    * Register a handler which will be called when a touch stops being detected
    **/
    void setTouchEndHandler(TouchCallbackHandler handler);
    
    /**
    * Set the dimensions and orientation of the LCD screen
    **/
    void setLCDGeometry(int width, int height, uint8_t orientation);
    
    /**
    * Set the calibration data used to calculate the screen position in pixels of a touch
    **/
    void setCalibration(int xmin, int xmax, int ymin, int ymax);
    
    /**
    * Set the amount of movement which must occur before a TouchMove event is raised
    **/
    void setMovementTheshold(int thresholdInPixels);
    
private:

    /**
    * SPI control
    **/
    SPI  _spi ;
    DigitalOut _cs ;
    
    /**
    * The interrupt pin and its handler
    **/
    DigitalIn _intPin;
    InterruptIn _int;
    
    uint8_t _precision;
    
    int _lcdWidth;
    int _lcdHeight;
    uint8_t _lcdOrientation;
    
    int _xmin, _xmax, _ymin, _ymax;
    int _movementThresholdSquared;
    
    TouchPosition _currentPosition;
    TouchPosition _lastPosition;

    unsigned int _read(uint8_t cmd);
    
    volatile uint8_t _state;
    
    void _fallInterruptHandler();
    void _riseInterruptHandler();
    void _tickerInterruptHandler();
    
    
    void _handleTouchStart();
    void _handleTouchMoved();
    void _handleTouchEnd();
    
    bool _moved(TouchPosition a, TouchPosition b);
    
    TouchPosition _getPosition();

    TouchCallbackHandler _touchStartHandler;
    TouchCallbackHandler _touchMoveHandler;
    TouchCallbackHandler _touchEndHandler;
    
    Thread* _handlerThread;
    
    // Used to poll the screen while it is being touched to track movement and to debounce edge changes
    Ticker _ticker;
   
    /**
    * Needs to be static because a Thread can't be started on an instance method.
    **/
    static void _monitor(void const *touchScreen) {
        
        TouchScreen* screen = (TouchScreen*)touchScreen;

        while(true) {
            osEvent evt = Thread::signal_wait(0);
            if(evt.status == osEventSignal) {
                if(evt.value.signals & TOUCHSCREEN_SIGNAL_START) {
                    screen->_handlerThread->signal_clr(TOUCHSCREEN_SIGNAL_START);
                    screen->_handleTouchStart();
                }
                if(evt.value.signals & TOUCHSCREEN_SIGNAL_END) {
                    screen->_handlerThread->signal_clr(TOUCHSCREEN_SIGNAL_END);
                    screen->_handleTouchEnd();
                }
                if(evt.value.signals & TOUCHSCREEN_SIGNAL_POLL) {
                    screen->_handlerThread->signal_clr(TOUCHSCREEN_SIGNAL_POLL);
                    screen->_handleTouchMoved();
                }
            }
        }
    }

};

#endif