LCD LIB
Fork of RA8875 by
Diff: RA8875_Touch.cpp
- Revision:
- 124:1690a7ae871c
- Parent:
- 123:2f45e80fec5f
- Child:
- 127:db7f2c704693
--- a/RA8875_Touch.cpp Mon Jul 25 10:55:58 2016 +0000 +++ b/RA8875_Touch.cpp Sun Jul 31 20:59:01 2016 +0000 @@ -1,69 +1,107 @@ /// This file contains the RA8875 Touch panel methods. /// - +/// It combines both resistive and capacitive touch methods, and tries +/// to make them nearly transparent alternates for each other. +/// #include "RA8875.h" #define NOTOUCH_TIMEOUT_uS 100000 #define TOUCH_TICKER_uS 1000 + +// Translate from FT5206 Event Flag to Touch Code to API-match the +// alternate resistive touch screen driver common in the RA8875 +// displays. +static const TouchCode_t EventFlagToTouchCode[4] = { + touch, // 00b Put Down + release, // 01b Put Up + held, // 10b Contact + no_touch // 11b Reserved +}; + + RetCode_t RA8875::TouchPanelInit(void) { - //TPCR0: Set enable bit, default sample time, wakeup, and ADC clock - WriteCommand(TPCR0, TP_ENABLE | TP_ADC_SAMPLE_DEFAULT_CLKS | TP_ADC_CLKDIV_DEFAULT); - // TPCR1: Set auto/manual, Ref voltage, debounce, manual mode params - WriteCommand(TPCR1, TP_MODE_DEFAULT | TP_DEBOUNCE_DEFAULT); - WriteCommand(INTC1, ReadCommand(INTC1) | RA8875_INT_TP); // reg INTC1: Enable Touch Panel Interrupts (D2 = 1) - WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear any TP interrupt flag - touchSample = 0; - touchState = no_cal; - touchTicker.attach_us(this, &RA8875::_TouchTicker, TOUCH_TICKER_uS); - touchTimer.start(); - touchTimer.reset(); - return noerror; -} - -RetCode_t RA8875::TouchPanelInit(uint8_t bTpEnable, uint8_t bTpAutoManual, uint8_t bTpDebounce, uint8_t bTpManualMode, uint8_t bTpAdcClkDiv, uint8_t bTpAdcSampleTime) -{ - // Parameter bounds check - if( \ - !(bTpEnable == TP_ENABLE || bTpEnable == TP_ENABLE) || \ - !(bTpAutoManual == TP_MODE_AUTO || bTpAutoManual == TP_MODE_MANUAL) || \ - !(bTpDebounce == TP_DEBOUNCE_OFF || bTpDebounce == TP_DEBOUNCE_ON) || \ - !(bTpManualMode <= TP_MANUAL_LATCH_Y) || \ - !(bTpAdcClkDiv <= TP_ADC_CLKDIV_128) || \ - !(bTpAdcSampleTime <= TP_ADC_SAMPLE_65536_CLKS) \ - ) return bad_parameter; - // Construct the config byte for TPCR0 and write them - WriteCommand(TPCR0, bTpEnable | bTpAdcClkDiv | bTpAdcSampleTime); // Note: Wakeup is never enabled - // Construct the config byte for TPCR1 and write them - WriteCommand(TPCR1, bTpManualMode | bTpDebounce | bTpManualMode); // Note: Always uses internal Vref. - // Set up the interrupt flag and enable bits - WriteCommand(INTC1, ReadCommand(INTC1) | RA8875_INT_TP); // reg INTC1: Enable Touch Panel Interrupts (D2 = 1) - WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear any TP interrupt flag - touchSample = 0; - touchState = no_cal; - if (bTpEnable == TP_ENABLE) { + panelTouched = false; + if (useTouchPanel == TP_CAP) { + // Set to normal mode + writeRegister8(FT5206_DEVICE_MODE, 0); + } else { + //TPCR0: Set enable bit, default sample time, wakeup, and ADC clock + WriteCommand(TPCR0, TP_ENABLE | TP_ADC_SAMPLE_DEFAULT_CLKS | TP_ADC_CLKDIV_DEFAULT); + // TPCR1: Set auto/manual, Ref voltage, debounce, manual mode params + WriteCommand(TPCR1, TP_MODE_DEFAULT | TP_DEBOUNCE_DEFAULT); + WriteCommand(INTC1, ReadCommand(INTC1) | RA8875_INT_TP); // reg INTC1: Enable Touch Panel Interrupts (D2 = 1) + WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear any TP interrupt flag + touchSample = 0; + touchState = no_cal; touchTicker.attach_us(this, &RA8875::_TouchTicker, TOUCH_TICKER_uS); touchTimer.start(); touchTimer.reset(); - } else { - touchTicker.detach(); - touchTimer.stop(); } return noerror; } - // +----------------------------------------------------+ - // | | - // | 1 | - // | | - // | | - // | 2 | - // | | - // | | - // | 3 | - // | | - // +----------------------------------------------------+ + +RetCode_t RA8875::TouchPanelInit(uint8_t bTpEnable, uint8_t bTpAutoManual, uint8_t bTpDebounce, uint8_t bTpManualMode, uint8_t bTpAdcClkDiv, uint8_t bTpAdcSampleTime) +{ + if (useTouchPanel == TP_CAP) { + TouchPanelInit(); + } else { + // Parameter bounds check + if( \ + !(bTpEnable == TP_ENABLE || bTpEnable == TP_ENABLE) || \ + !(bTpAutoManual == TP_MODE_AUTO || bTpAutoManual == TP_MODE_MANUAL) || \ + !(bTpDebounce == TP_DEBOUNCE_OFF || bTpDebounce == TP_DEBOUNCE_ON) || \ + !(bTpManualMode <= TP_MANUAL_LATCH_Y) || \ + !(bTpAdcClkDiv <= TP_ADC_CLKDIV_128) || \ + !(bTpAdcSampleTime <= TP_ADC_SAMPLE_65536_CLKS) \ + ) return bad_parameter; + // Construct the config byte for TPCR0 and write them + WriteCommand(TPCR0, bTpEnable | bTpAdcClkDiv | bTpAdcSampleTime); // Note: Wakeup is never enabled + // Construct the config byte for TPCR1 and write them + WriteCommand(TPCR1, bTpManualMode | bTpDebounce | bTpManualMode); // Note: Always uses internal Vref. + // Set up the interrupt flag and enable bits + WriteCommand(INTC1, ReadCommand(INTC1) | RA8875_INT_TP); // reg INTC1: Enable Touch Panel Interrupts (D2 = 1) + WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear any TP interrupt flag + touchSample = 0; + touchState = no_cal; + if (bTpEnable == TP_ENABLE) { + touchTicker.attach_us(this, &RA8875::_TouchTicker, TOUCH_TICKER_uS); + touchTimer.start(); + touchTimer.reset(); + } else { + touchTicker.detach(); + touchTimer.stop(); + } + } + return noerror; +} + + +int RA8875::TouchChannels(void) +{ + if (useTouchPanel == TP_CAP) { + return 5; // based on the FT5206 hardware + } else if (useTouchPanel == TP_RES) { + return 1; // based on the RA8875 resistive touch driver + } else { + return 0; // it isn't enabled, so there are none. + } +} + + +// +----------------------------------------------------+ +// | | +// | 1 | +// | | +// | | +// | 2 | +// | | +// | | +// | 3 | +// | | +// +----------------------------------------------------+ RetCode_t RA8875::TouchPanelCalibrate(tpMatrix_t * matrix) { @@ -76,7 +114,7 @@ point_t pSample[3]; int x,y; Timer timeout; // timeout guards for not-installed, stuck, user not present... - + timeout.start(); while (TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s) { wait_ms(20); @@ -90,9 +128,12 @@ if (msg) puts(msg); SetTextCursor(0,height()/2); - pTest[0].x = 50; pTest[0].y = 50; - pTest[1].x = width() - 50; pTest[1].y = height()/2; - pTest[2].x = width()/2; pTest[2].y = height() - 50; + pTest[0].x = 50; + pTest[0].y = 50; + pTest[1].x = width() - 50; + pTest[1].y = height()/2; + pTest[2].x = width()/2; + pTest[2].y = height() - 50; for (int i=0; i<3; i++) { foreground(Blue); @@ -144,24 +185,24 @@ * Description: Given a valid set of calibration factors and a point * value reported by the touch screen, this function * calculates and returns the true (or closest to true) - * display point below the spot where the touch screen + * display point below the spot where the touch screen * was touched. - * + * * - * + * * Argument(s): displayPtr (output) - Pointer to the calculated * (true) display point. * screenPtr (input) - Pointer to the reported touch * screen point. * matrixPtr (input) - Pointer to calibration factors * matrix previously calculated - * from a call to + * from a call to * setCalibrationMatrix() - * + * * - * The function simply solves for Xd and Yd by implementing the - * computations required by the translation matrix. - * + * The function simply solves for Xd and Yd by implementing the + * computations required by the translation matrix. + * * /- -\ * /- -\ /- -\ | | * | | | | | Xs | @@ -171,10 +212,10 @@ * | | | | | 1 | * \- -/ \- -/ | | * \- -/ - * + * * It must be kept brief to avoid consuming CPU cycles. * - * Return: OK - the display point was correctly calculated + * Return: OK - the display point was correctly calculated * and its value is in the output argument. * NOT_OK - an error was detected and the function * failed to return a valid point. @@ -182,42 +223,60 @@ * NOTE! NOTE! NOTE! * * setCalibrationMatrix() and getDisplayPoint() will do fine - * for you as they are, provided that your digitizer + * for you as they are, provided that your digitizer * resolution does not exceed 10 bits (1024 values). Higher * resolutions may cause the integer operations to overflow - * and return incorrect values. If you wish to use these - * functions with digitizer resolutions of 12 bits (4096 - * values) you will either have to a) use 64-bit signed - * integer variables and math, or b) judiciously modify the - * operations to scale results by a factor of 2 or even 4. + * and return incorrect values. If you wish to use these + * functions with digitizer resolutions of 12 bits (4096 + * values) you will either have to a) use 64-bit signed + * integer variables and math, or b) judiciously modify the + * operations to scale results by a factor of 2 or even 4. * */ TouchCode_t RA8875::TouchPanelReadable(point_t * TouchPoint) { - int a2dX = 0; - int a2dY = 0; - - TouchCode_t ts = TouchPanelA2DFiltered(&a2dX, &a2dY); - if (ts != no_touch) { - if (tpMatrix.Divider != 0) { - if (TouchPoint) { + TouchCode_t ts = no_touch; + + if (useTouchPanel == TP_RES) { + int a2dX = 0; + int a2dY = 0; + + touchInfo[0].touchID = 0; + ts = TouchPanelA2DFiltered(&a2dX, &a2dY); + if (ts != no_touch) { + panelTouched = true; + numberOfTouchPoints = 1; + + if (tpMatrix.Divider != 0) { + /* Operation order is important since we are doing integer */ /* math. Make sure you add all terms together before */ /* dividing, so that the remainder is not rounded off */ /* prematurely. */ - TouchPoint->x = ( (tpMatrix.An * a2dX) + + touchInfo[0].coordinates.x = ( (tpMatrix.An * a2dX) + (tpMatrix.Bn * a2dY) + tpMatrix.Cn ) / tpMatrix.Divider ; - TouchPoint->y = ( (tpMatrix.Dn * a2dX) + + touchInfo[0].coordinates.y = ( (tpMatrix.Dn * a2dX) + (tpMatrix.En * a2dY) + tpMatrix.Fn ) / tpMatrix.Divider ; + } else { + ts = no_cal; } } else { - ts = no_cal; + numberOfTouchPoints = 0; } + touchInfo[0].touchCode = ts; + } + if (panelTouched == true) { + panelTouched = false; + if (TouchPoint) { + *TouchPoint = touchInfo[0].coordinates; + ts = touchInfo[0].touchCode; + } + ts = touch; } return ts; } @@ -226,7 +285,7 @@ TouchCode_t RA8875::TouchPanelGet(point_t * TouchPoint) { TouchCode_t t = no_touch; - + while (true) { t = TouchPanelReadable(TouchPoint); if (t != no_touch) @@ -256,7 +315,7 @@ { int i, j; int temp; - + for(i = 1; i < bufsize; i++) { temp = buf[i]; j = i; @@ -386,28 +445,28 @@ * * Copyright (c) 2001, Carlos E. Vidales. All rights reserved. * - * This sample program was written and put in the public domain - * by Carlos E. Vidales. The program is provided "as is" + * This sample program was written and put in the public domain + * by Carlos E. Vidales. The program is provided "as is" * without warranty of any kind, either expressed or implied. * If you choose to use the program within your own products * you do so at your own risk, and assume the responsibility * for servicing, repairing or correcting the program should * it prove defective in any manner. - * You may copy and distribute the program's source code in any + * You may copy and distribute the program's source code in any * medium, provided that you also include in each copy an * appropriate copyright notice and disclaimer of warranty. * You may also modify this program and distribute copies of - * it provided that you include prominent notices stating + * it provided that you include prominent notices stating * that you changed the file(s) and the date of any change, - * and that you do not charge any royalties or licenses for + * and that you do not charge any royalties or licenses for * its use. - * - * This file contains functions that implement calculations + * + * This file contains functions that implement calculations * necessary to obtain calibration factors for a touch screen - * that suffers from multiple distortion effects: namely, + * that suffers from multiple distortion effects: namely, * translation, scaling and rotation. * - * The following set of equations represent a valid display + * The following set of equations represent a valid display * point given a corresponding set of touch screen points: * * /- -\ @@ -420,7 +479,7 @@ * \- -/ \- -/ | | * \- -/ * where: - * (Xd,Yd) represents the desired display point + * (Xd,Yd) represents the desired display point * coordinates, * (Xs,Ys) represents the available touch screen * coordinates, and the matrix @@ -428,18 +487,18 @@ * |A,B,C| * |D,E,F| represents the factors used to translate * \- -/ the available touch screen point values - * into the corresponding display + * into the corresponding display * coordinates. - * Note that for practical considerations, the utilities + * Note that for practical considerations, the utilities * within this file do not use the matrix coefficients as - * defined above, but instead use the following + * defined above, but instead use the following * equivalents, since floating point math is not used: - * A = An/Divider - * B = Bn/Divider - * C = Cn/Divider - * D = Dn/Divider - * E = En/Divider - * F = Fn/Divider + * A = An/Divider + * B = Bn/Divider + * C = Cn/Divider + * D = Dn/Divider + * E = En/Divider + * F = Fn/Divider * The functions provided within this file are: * setCalibrationMatrix() - calculates the set of factors * in the above equation, given @@ -458,23 +517,23 @@ * Function: setCalibrationMatrix() * * Description: Calling this function with valid input data - * in the display and screen input arguments + * in the display and screen input arguments * causes the calibration factors between the * screen and display points to be calculated, - * and the output argument - matrixPtr - to be + * and the output argument - matrixPtr - to be * populated. * * This function needs to be called only when new * calibration factors are desired. - * - * - * Argument(s): displayPtr (input) - Pointer to an array of three + * + * + * Argument(s): displayPtr (input) - Pointer to an array of three * sample, reference points. - * screenPtr (input) - Pointer to the array of touch - * screen points corresponding + * screenPtr (input) - Pointer to the array of touch + * screen points corresponding * to the reference display points. - * matrixPtr (output) - Pointer to the calibration - * matrix computed for the set + * matrixPtr (output) - Pointer to the calibration + * matrix computed for the set * of points being provided. * * @@ -496,8 +555,8 @@ * Divider * * - * Ys0*(Xs2*Xd1 - Xs1*Xd2) + - * Ys1*(Xs0*Xd2 - Xs2*Xd0) + + * Ys0*(Xs2*Xd1 - Xs1*Xd2) + + * Ys1*(Xs0*Xd2 - Xs2*Xd0) + * Ys2*(Xs1*Xd0 - Xs0*Xd1) * C = --------------------------------------------------- * Divider @@ -513,17 +572,17 @@ * Divider * * - * Ys0*(Xs2*Yd1 - Xs1*Yd2) + - * Ys1*(Xs0*Yd2 - Xs2*Yd0) + + * Ys0*(Xs2*Yd1 - Xs1*Yd2) + + * Ys1*(Xs0*Yd2 - Xs2*Yd0) + * Ys2*(Xs1*Yd0 - Xs0*Yd1) * F = --------------------------------------------------- * Divider * * - * Return: OK - the calibration matrix was correctly - * calculated and its value is in the + * Return: OK - the calibration matrix was correctly + * calculated and its value is in the * output argument. - * NOT_OK - an error was detected and the + * NOT_OK - an error was detected and the * function failed to return a valid * set of matrix values. * The only time this sample code returns @@ -534,14 +593,14 @@ * NOTE! NOTE! NOTE! * * setCalibrationMatrix() and getDisplayPoint() will do fine - * for you as they are, provided that your digitizer + * for you as they are, provided that your digitizer * resolution does not exceed 10 bits (1024 values). Higher * resolutions may cause the integer operations to overflow - * and return incorrect values. If you wish to use these - * functions with digitizer resolutions of 12 bits (4096 - * values) you will either have to a) use 64-bit signed - * integer variables and math, or b) judiciously modify the - * operations to scale results by a factor of 2 or even 4. + * and return incorrect values. If you wish to use these + * functions with digitizer resolutions of 12 bits (4096 + * values) you will either have to a) use 64-bit signed + * integer variables and math, or b) judiciously modify the + * operations to scale results by a factor of 2 or even 4. * */ RetCode_t RA8875::TouchPanelComputeCalibration(point_t * displayPtr, point_t * screenPtr, tpMatrix_t * matrixPtr) @@ -580,4 +639,83 @@ return( retValue ) ; } +////////////////// Capacitive Touch Panel + +uint8_t RA8875::readRegister8(uint8_t reg) { + char val; + + m_i2c->write(m_addr, (const char *)®, 1); + m_i2c->read(m_addr, &val, 1); + return (uint8_t)val; +} + +void RA8875::writeRegister8(uint8_t reg, uint8_t val) { + char data[2]; + + data[0] = (char)reg; + data[1] = (char)val; + m_i2c->write((int)FT5206_I2C_ADDRESS, data, 2); +} + + +// Interrupt for touch detection +void RA8875::TouchPanelISR(void) +{ + getTouchPositions(); + panelTouched = true; +} + +uint8_t RA8875::getTouchPositions(void) { + uint8_t valXH; + uint8_t valYH; + + numberOfTouchPoints = readRegister8(FT5206_TD_STATUS) & 0xF; + gesture = readRegister8(FT5206_GEST_ID); + + // If the switch statement was based only on numberOfTouchPoints, it would not + // be able to generate notification for 'release' events (as it is no longer touched). + // Therefore, forcing a 5, and it intentially falls through each lower case. + switch (5) { // numberOfTouchPoints + case 5: + valXH = readRegister8(FT5206_TOUCH5_XH); + valYH = readRegister8(FT5206_TOUCH5_YH); + touchInfo[4].touchCode = EventFlagToTouchCode[valXH >> 6]; + touchInfo[4].touchID = (valYH >> 4); + touchInfo[4].coordinates.x = (valXH & 0x0f)*256 + readRegister8(FT5206_TOUCH5_XL); + touchInfo[4].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH5_YL); + case 4: + valXH = readRegister8(FT5206_TOUCH4_XH); + valYH = readRegister8(FT5206_TOUCH4_YH); + touchInfo[3].touchCode = EventFlagToTouchCode[valXH >> 6]; + touchInfo[3].touchID = (valYH >> 4); + touchInfo[3].coordinates.x = (readRegister8(FT5206_TOUCH4_XH) & 0x0f)*256 + readRegister8(FT5206_TOUCH4_XL); + touchInfo[3].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH4_YL); + case 3: + valXH = readRegister8(FT5206_TOUCH3_XH); + valYH = readRegister8(FT5206_TOUCH3_YH); + touchInfo[2].touchCode = EventFlagToTouchCode[valXH >> 6]; + touchInfo[2].touchID = (valYH >> 4); + touchInfo[2].coordinates.x = (readRegister8(FT5206_TOUCH3_XH) & 0x0f)*256 + readRegister8(FT5206_TOUCH3_XL); + touchInfo[2].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH3_YL); + case 2: + valXH = readRegister8(FT5206_TOUCH2_XH); + valYH = readRegister8(FT5206_TOUCH2_YH); + touchInfo[1].touchCode = EventFlagToTouchCode[valXH >> 6]; + touchInfo[1].touchID = (valYH >> 4); + touchInfo[1].coordinates.x = (readRegister8(FT5206_TOUCH2_XH) & 0x0f)*256 + readRegister8(FT5206_TOUCH2_XL); + touchInfo[1].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH2_YL); + case 1: + valXH = readRegister8(FT5206_TOUCH1_XH); + valYH = readRegister8(FT5206_TOUCH1_YH); + touchInfo[0].touchCode = EventFlagToTouchCode[valXH >> 6]; + touchInfo[0].touchID = (valYH >> 4); + touchInfo[0].coordinates.x = (readRegister8(FT5206_TOUCH1_XH) & 0x0f)*256 + readRegister8(FT5206_TOUCH1_XL); + touchInfo[0].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH1_YL); + break; + default: + break; + } + return numberOfTouchPoints; +} + // #### end of touch panel code additions