tsTouchError_t tsRead(tsTouchData_t* data) { uint32_t x1, y1; // Assign pressure levels regardless of touch state tsReadZ(&data->z1, &data->z2); data->xraw = 0; data->yraw = 0; data->xlcd = 0; data->ylcd = 0; // Abort if the screen is not being touched (0 levels reported) if (data->z1 < _tsThreshhold) { data->valid = false; return TS_ERROR_NONE; } nopDelay(CFG_TFTLCD_TS_DELAYBETWEENSAMPLES); // Get two X/Y readings and compare results x1 = tsReadX(); y1 = tsReadY(); // X/Y seems to be valid and reading has been confirmed twice data->xraw = x1; data->yraw = y1; // Convert x/y values to pixel location with matrix multiply tsPoint_t location, touch; touch.x = x1; touch.y = y1; getDisplayPoint(&location, &touch, &_tsMatrix); data->xlcd = location.x; data->ylcd = location.y; data->valid = true; return TS_ERROR_NONE; }
void tsCalibrate(void) { lcdOrientation_t orientation; uint16_t right2, top2, left2, bottom2; bool passed = false; // Determine screen orientation before starting calibration orientation = lcdGetOrientation(); /* -------------- Welcome Screen --------------- */ tsRenderCalibrationScreen(lcdGetWidth() / 2, lcdGetHeight() / 2, 5); // Delay to avoid multiple touch events systickDelay(250); /* -------------- CALIBRATE TOP-LEFT --------------- */ passed = false; while (!passed) { // Read X/Y depending on screen orientation tsRenderCalibrationScreen(3, 3, 5); _calibration.offsetLeft = orientation == LCD_ORIENTATION_LANDSCAPE ? tsReadY() : tsReadX(); _calibration.offsetTop = orientation == LCD_ORIENTATION_LANDSCAPE ? tsReadX() : tsReadY(); // Make sure values are in range if (_calibration.offsetLeft < TS_CALIBRATION_OUTOFRANGE && _calibration.offsetTop < TS_CALIBRATION_OUTOFRANGE) passed = true; } // Delay to avoid multiple touch events systickDelay(250); /* -------------- CALIBRATE BOTTOM-RIGHT --------------- */ passed = false; while (!passed) { tsRenderCalibrationScreen(lcdGetWidth() - 4, lcdGetHeight() - 4, 5); // Read X/Y depending on screen orientation _calibration.offsetRight = orientation == LCD_ORIENTATION_LANDSCAPE ? TS_ADC_LIMIT - tsReadY() : TS_ADC_LIMIT - tsReadX(); _calibration.offsetBottom = orientation == LCD_ORIENTATION_LANDSCAPE ? TS_ADC_LIMIT - tsReadX() : TS_ADC_LIMIT - tsReadY(); // Redo test if value is out of range if (_calibration.offsetRight < TS_CALIBRATION_OUTOFRANGE && _calibration.offsetBottom < TS_CALIBRATION_OUTOFRANGE) passed = true; } // Delay to avoid multiple touch events systickDelay(250); /* -------------- CALIBRATE TOP-RIGHT --------------- */ passed = false; while (!passed) { tsRenderCalibrationScreen(lcdGetWidth() - 4, 3, 5); if (orientation == LCD_ORIENTATION_LANDSCAPE) { right2 = TS_ADC_LIMIT - tsReadY(); top2 = tsReadX(); } else { right2 = tsReadX(); top2 = TS_ADC_LIMIT - tsReadY(); } // Redo test if value is out of range if (right2 < TS_CALIBRATION_OUTOFRANGE && top2 < TS_CALIBRATION_OUTOFRANGE) passed = true; } // Average readings _calibration.offsetRight = (_calibration.offsetRight + right2) / 2; _calibration.offsetTop = (_calibration.offsetTop + top2) / 2; // Delay to avoid multiple touch events systickDelay(250); /* -------------- CALIBRATE BOTTOM-LEFT --------------- */ passed = false; while (!passed) { tsRenderCalibrationScreen(3, lcdGetHeight() - 4, 5); if (orientation == LCD_ORIENTATION_LANDSCAPE) { left2 = tsReadY(); bottom2 = TS_ADC_LIMIT - tsReadX(); } else { left2 = TS_ADC_LIMIT - tsReadX(); bottom2 = tsReadY(); } // Redo test if value is out of range if (left2 < TS_CALIBRATION_OUTOFRANGE && bottom2 < TS_CALIBRATION_OUTOFRANGE) passed = true; } // Average readings _calibration.offsetLeft = (_calibration.offsetLeft + left2) / 2; _calibration.offsetBottom = (_calibration.offsetBottom + bottom2) / 2; // Delay to avoid multiple touch events systickDelay(250); _calibration.divisorX = ((TS_ADC_LIMIT - (_calibration.offsetLeft + _calibration.offsetRight)) * 100) / lcdGetWidth(); _calibration.divisorY = ((TS_ADC_LIMIT - (_calibration.offsetTop + _calibration.offsetBottom)) * 100) / lcdGetHeight(); /* -------------- Persist Data --------------- */ // Persist data to EEPROM eepromWriteU16(CFG_EEPROM_TOUCHSCREEN_OFFSET_LEFT, _calibration.offsetLeft); eepromWriteU16(CFG_EEPROM_TOUCHSCREEN_OFFSET_RIGHT, _calibration.offsetRight); eepromWriteU16(CFG_EEPROM_TOUCHSCREEN_OFFSET_TOP, _calibration.offsetTop); eepromWriteU16(CFG_EEPROM_TOUCHSCREEN_OFFSET_BOT, _calibration.offsetBottom); eepromWriteU16(CFG_EEPROM_TOUCHSCREEN_OFFSET_DIVX, _calibration.divisorX); eepromWriteU16(CFG_EEPROM_TOUCHSCREEN_OFFSET_DIVY, _calibration.divisorY); eepromWriteU8(CFG_EEPROM_TOUCHSCREEN_CALIBRATED, 1); // Clear the screen drawFill(COLOR_BLACK); }
tsTouchError_t tsWaitForEvent(tsTouchData_t* data, uint32_t timeoutMS) { if (!_tsInitialised) tsInit(); uint32_t z1, z2; uint32_t xRaw1, xRaw2, yRaw1, yRaw2; z1 = z2 = 0; // Handle timeout if delay > 0 milliseconds if (timeoutMS) { uint32_t startTick = systickGetTicks(); // Systick rollover may occur while waiting for timeout if (startTick > 0xFFFFFFFF - timeoutMS) { // Wait for timeout or touch event while (z2 < CFG_TFTLCD_TS_THRESHOLD) { // Throw alert if timeout delay has been passed if ((systickGetTicks() < startTick) && (systickGetTicks() >= (timeoutMS - (0xFFFFFFFF - startTick)))) { return TS_ERROR_TIMEOUT; } tsReadZ(&z1, &z2); } } // No systick rollover will occur ... calculate timeout the simple way else { // Wait in infinite loop while (z2 < CFG_TFTLCD_TS_THRESHOLD) { // Throw timeout if delay has been passed if ((systickGetTicks() - startTick) > timeoutMS) { return TS_ERROR_TIMEOUT; } tsReadZ(&z1, &z2); } } } // No timeout requested ... wait forever else { while (z2 < CFG_TFTLCD_TS_THRESHOLD) { tsReadZ(&z1, &z2); } } // Get raw conversion results // Each value is read twice and compared to avoid erroneous readings xRaw1 = tsReadY(); // X and Y are reversed xRaw2 = tsReadY(); // X and Y are reversed yRaw1 = tsReadX(); // X and Y are reverse yRaw2 = tsReadX(); // X and Y are reverse // If both read attempts aren't identical, return mismatch error if ((xRaw1 != xRaw2) || (yRaw1 != yRaw2)) { return TS_ERROR_XYMISMATCH; } // Normalise X data->x = ((xRaw1 - _calibration.offsetLeft > TS_ADC_LIMIT ? 0 : xRaw1 - _calibration.offsetLeft) * 100) / _calibration.divisorX; if (data->x > lcdGetWidth() - 1) data->x = lcdGetWidth() - 1; // Normalise Y data->y = ((yRaw1 - _calibration.offsetTop > TS_ADC_LIMIT ? 0 : yRaw1 - _calibration.offsetTop) * 100) / _calibration.divisorY; if (data->y > lcdGetHeight() - 1) data->y = lcdGetHeight() - 1; // Indicate correct reading return TS_ERROR_NONE; }
tsTouchError_t tsRead(tsTouchData_t* data, uint8_t calibrating) { uint32_t x1, x2, y1, y2, z1, z2; // Assign pressure levels regardless of touch state tsReadZ(&z1, &z2); data->z1 = z1; data->z2 = z2; data->xraw = 0; data->yraw = 0; data->xlcd = 0; data->ylcd = 0; // Abort if the screen is not being touched (0 levels reported) if (z1 < _tsThreshhold) { data->valid = false; return TS_ERROR_NONE; } // Get two X/Y readings and compare results x1 = tsReadX(); x2 = tsReadX(); y1 = tsReadY(); y2 = tsReadY(); // Throw an error if both readings aren't identical if (x1 != x2 || y1 != y2) { data->valid = false; data->xraw = x1; data->yraw = y1; return TS_ERROR_XYMISMATCH; } // X/Y seems to be valid and reading has been confirmed twice data->xraw = x1; data->yraw = y1; // Convert x/y values to pixel location with matrix multiply tsPoint_t location, touch; touch.x = x1; touch.y = y1; // Only calculate the relative LCD value if this isn't for calibration if (!calibrating) { getDisplayPoint( &location, &touch, &_tsMatrix) ; data->xlcd = location.x; data->ylcd = location.y; } else { // Assign some false values, but only xraw and yraw are // used for calibration data->xlcd = 0; data->ylcd = 0; } data->valid = true; return TS_ERROR_NONE; }