mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 01:18:28 +00:00
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.
This commit is contained in:
parent
72bc784f7f
commit
c3112fd83d
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user