From c3112fd83db23fa78ed8418ef862aa5108cd20d5 Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 22 Nov 2018 16:08:57 +0100 Subject: [PATCH] embed/trezorhal: only poll CTPM when touch is detected Because CTPM dislikes being polled when no touches are seen, keeps resetting, and maybe freezes once in a while. This is very likely a fix for #334. Before, we would simply read the touch registers on every loop. Now we first check whether the interrupt line is down, which indicates that the CTPM has data to tell us. Tracking the `touching` flag is necessary, as sometimes we don't poll frequently enough to catch the TOUCH_END event before interrupt line goes up again. The `last_packet` handling miiight not be necessary - AFAICT, the CTPM has some sort of buffer and always returns TOUCH_START at first and TOUCH_END at last. Still, better safe than sorry. --- embed/trezorhal/touch_t.h | 43 ++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/embed/trezorhal/touch_t.h b/embed/trezorhal/touch_t.h index b2d602af53..13ff904ff3 100644 --- a/embed/trezorhal/touch_t.h +++ b/embed/trezorhal/touch_t.h @@ -121,9 +121,32 @@ void touch_power_off(void) { touch_default_pin_state(); } +uint32_t touch_is_detected(void) +{ + // check the interrupt line coming in from the CTPM. + // the line goes low when a touch event is actively detected. + // reference section 1.2 of "Application Note for FT6x06 CTPM". + // we configure the touch controller to use "interrupt polling mode". + return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4); +} + uint32_t touch_read(void) { static uint8_t touch_data[TOUCH_PACKET_SIZE], previous_touch_data[TOUCH_PACKET_SIZE]; + static uint32_t xy; + static int touching; + + int last_packet = 0; + if (!touch_is_detected()) { + // only poll when the touch interrupt is active. + // when it's inactive, we might need to read one last data packet to get to + // the TOUCH_END event, which clears the `touching` flag. + if (touching) { + last_packet = 1; + } else { + return 0; + } + } uint8_t outgoing[] = {0x00}; // start reading from address 0x00 if (HAL_OK != HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, outgoing, sizeof(outgoing), 1)) { @@ -143,24 +166,24 @@ uint32_t touch_read(void) const uint32_t number_of_touch_points = touch_data[2] & 0x0F; // valid values are 0, 1, 2 (invalid 0xF before first touch) (tested with FT6206) const uint32_t event_flag = touch_data[3] & 0xC0; if (touch_data[1] == GESTURE_NO_GESTURE) { - uint32_t xy = touch_pack_xy((X_POS_MSB << 8) | X_POS_LSB, (Y_POS_MSB << 8) | Y_POS_LSB); + xy = touch_pack_xy((X_POS_MSB << 8) | X_POS_LSB, (Y_POS_MSB << 8) | Y_POS_LSB); if ((number_of_touch_points == 1) && (event_flag == EVENT_PRESS_DOWN)) { + touching = 1; return TOUCH_START | xy; } else if ((number_of_touch_points == 1) && (event_flag == EVENT_CONTACT)) { return TOUCH_MOVE | xy; } else if ((number_of_touch_points == 0) && (event_flag == EVENT_LIFT_UP)) { + touching = 0; return TOUCH_END | xy; } } + if (last_packet) { + // interrupt line is inactive, we didn't read valid touch data, and as far as + // we know, we never sent a TOUCH_END event. + touching = 0; + return TOUCH_END | xy; + } + return 0; } - -uint32_t touch_is_detected(void) -{ - // check the interrupt line coming in from the CTPM. - // the line goes low when a touch event is actively detected. - // reference section 1.2 of "Application Note for FT6x06 CTPM". - // we configure the touch controller to use "interrupt polling mode". - return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4); -}