mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-12 03:48:45 +00:00
feat(core): add event polling to touch driver
[no changelog]
This commit is contained in:
parent
8d7a25e5eb
commit
4815118a6d
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <io/i2c_bus.h>
|
#include <io/i2c_bus.h>
|
||||||
#include <io/touch.h>
|
#include <io/touch.h>
|
||||||
|
#include <sys/sysevent_source.h>
|
||||||
#include <sys/systick.h>
|
#include <sys/systick.h>
|
||||||
#include "ft6x36.h"
|
#include "ft6x36.h"
|
||||||
|
|
||||||
@ -33,6 +34,8 @@
|
|||||||
#include "panels/lhs200kb-if21.h"
|
#include "panels/lhs200kb-if21.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../touch_fsm.h"
|
||||||
|
|
||||||
// #define TOUCH_TRACE_REGS
|
// #define TOUCH_TRACE_REGS
|
||||||
// #define TOUCH_TRACE_EVENT
|
// #define TOUCH_TRACE_EVENT
|
||||||
|
|
||||||
@ -46,17 +49,12 @@ typedef struct {
|
|||||||
secbool ready;
|
secbool ready;
|
||||||
// Captured tick counter when `touch_init()` was called
|
// Captured tick counter when `touch_init()` was called
|
||||||
uint32_t init_ticks;
|
uint32_t init_ticks;
|
||||||
// Time (in ticks) when touch_get_event() was called last time
|
|
||||||
uint32_t poll_ticks;
|
|
||||||
// Time (in ticks) when the touch registers were read last time
|
// Time (in ticks) when the touch registers were read last time
|
||||||
uint32_t read_ticks;
|
uint32_t read_ticks;
|
||||||
// Set if the touch controller is currently touched
|
// Last reported touch state
|
||||||
// (respectively, that we detected a touch event)
|
uint32_t state;
|
||||||
bool pressed;
|
// Touch state machine for each task
|
||||||
// Previously reported x-coordinate
|
touch_fsm_t tls[SYSTASK_MAX_TASKS];
|
||||||
uint16_t last_x;
|
|
||||||
// Previously reported y-coordinate
|
|
||||||
uint16_t last_y;
|
|
||||||
|
|
||||||
} touch_driver_t;
|
} touch_driver_t;
|
||||||
|
|
||||||
@ -65,6 +63,9 @@ static touch_driver_t g_touch_driver = {
|
|||||||
.initialized = secfalse,
|
.initialized = secfalse,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
static const syshandle_vmt_t g_touch_handle_vmt;
|
||||||
|
|
||||||
// Reads a subsequent registers from the FT6X36.
|
// Reads a subsequent registers from the FT6X36.
|
||||||
//
|
//
|
||||||
// Returns: `sectrue` if the register was read
|
// Returns: `sectrue` if the register was read
|
||||||
@ -192,7 +193,7 @@ static void ft6x36_power_down(void) {
|
|||||||
|
|
||||||
if (state == GPIO_PIN_SET) {
|
if (state == GPIO_PIN_SET) {
|
||||||
// 90 ms for circuitry to stabilize (being conservative)
|
// 90 ms for circuitry to stabilize (being conservative)
|
||||||
hal_delay(90);
|
systick_delay_ms(90);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -214,7 +215,7 @@ static void ft6x36_power_up(void) {
|
|||||||
|
|
||||||
// Wait until the circuit fully kicks-in
|
// Wait until the circuit fully kicks-in
|
||||||
// (5ms is the minimum time required for the reset signal to be effective)
|
// (5ms is the minimum time required for the reset signal to be effective)
|
||||||
hal_delay(10);
|
systick_delay_ms(10);
|
||||||
|
|
||||||
// Enable intterrupt input
|
// Enable intterrupt input
|
||||||
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
||||||
@ -230,7 +231,7 @@ static void ft6x36_power_up(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Wait for the touch controller to boot up
|
// Wait for the touch controller to boot up
|
||||||
hal_delay(5);
|
systick_delay_ms(5);
|
||||||
|
|
||||||
// Clear the flag indicating rising edge on INT_PIN
|
// Clear the flag indicating rising edge on INT_PIN
|
||||||
__HAL_GPIO_EXTI_CLEAR_FLAG(TOUCH_INT_PIN);
|
__HAL_GPIO_EXTI_CLEAR_FLAG(TOUCH_INT_PIN);
|
||||||
@ -316,28 +317,29 @@ secbool touch_init(void) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver->init_ticks = hal_ticks_ms();
|
if (!syshandle_register(SYSHANDLE_TOUCH, &g_touch_handle_vmt, driver)) {
|
||||||
driver->poll_ticks = driver->init_ticks;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver->init_ticks = systick_ms();
|
||||||
driver->read_ticks = driver->init_ticks;
|
driver->read_ticks = driver->init_ticks;
|
||||||
driver->initialized = sectrue;
|
driver->initialized = sectrue;
|
||||||
|
|
||||||
return sectrue;
|
return sectrue;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
i2c_bus_close(driver->i2c_bus);
|
touch_deinit();
|
||||||
ft6x36_power_down();
|
|
||||||
memset(driver, 0, sizeof(touch_driver_t));
|
|
||||||
return secfalse;
|
return secfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
void touch_deinit(void) {
|
void touch_deinit(void) {
|
||||||
touch_driver_t* driver = &g_touch_driver;
|
touch_driver_t* driver = &g_touch_driver;
|
||||||
|
syshandle_unregister(SYSHANDLE_TOUCH);
|
||||||
if (sectrue == driver->initialized) {
|
|
||||||
i2c_bus_close(driver->i2c_bus);
|
i2c_bus_close(driver->i2c_bus);
|
||||||
|
if (sectrue == driver->initialized) {
|
||||||
ft6x36_power_down();
|
ft6x36_power_down();
|
||||||
memset(driver, 0, sizeof(touch_driver_t));
|
|
||||||
}
|
}
|
||||||
|
memset(driver, 0, sizeof(touch_driver_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void touch_power_set(bool on) {
|
void touch_power_set(bool on) {
|
||||||
@ -355,7 +357,7 @@ secbool touch_ready(void) {
|
|||||||
if (sectrue == driver->initialized && sectrue != driver->ready) {
|
if (sectrue == driver->initialized && sectrue != driver->ready) {
|
||||||
// FT6X36 does not report events for 300ms
|
// FT6X36 does not report events for 300ms
|
||||||
// after it is released from the reset state
|
// after it is released from the reset state
|
||||||
if ((int)(hal_ticks_ms() - driver->init_ticks) >= 310) {
|
if ((int)(systick_ms() - driver->init_ticks) >= 310) {
|
||||||
driver->ready = sectrue;
|
driver->ready = sectrue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,7 +388,7 @@ uint8_t touch_get_version(void) {
|
|||||||
// to read the firmware version. If we try to read too soon, we get 0x00
|
// to read the firmware version. If we try to read too soon, we get 0x00
|
||||||
// and the chip behaves unpredictably.
|
// and the chip behaves unpredictably.
|
||||||
while (sectrue != touch_ready()) {
|
while (sectrue != touch_ready()) {
|
||||||
hal_delay(1);
|
systick_delay_ms(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ft6x36_wake_up(driver->i2c_bus);
|
ft6x36_wake_up(driver->i2c_bus);
|
||||||
@ -442,7 +444,7 @@ void trace_regs(uint8_t* regs) {
|
|||||||
event = '-';
|
event = '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t time = hal_ticks_ms() % 10000;
|
uint32_t time = systicks_ms() % 10000;
|
||||||
|
|
||||||
printf("%04ld [gesture=%02X, nb_touches=%d, flags=%c, x=%3d, y=%3d]\r\n",
|
printf("%04ld [gesture=%02X, nb_touches=%d, flags=%c, x=%3d, y=%3d]\r\n",
|
||||||
time, gesture, nb_touches, event, x, y);
|
time, gesture, nb_touches, event, x, y);
|
||||||
@ -461,17 +463,16 @@ void trace_event(uint32_t event) {
|
|||||||
|
|
||||||
uint32_t time = hal_ticks_ms() % 10000;
|
uint32_t time = hal_ticks_ms() % 10000;
|
||||||
|
|
||||||
printf("%04ld [event=%c, x=%3d, y=%3d]\r\n", time, event_type, x, y);
|
systask_id_t task_id = systask_id(systask_active());
|
||||||
|
|
||||||
|
printf("%04ld [task=%d, event=%c, x=%3d, y=%3d]\r\n", time, task_id,
|
||||||
|
event_type, x, y);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t touch_get_event(void) {
|
// Reads touch registers and returns the last touch event
|
||||||
touch_driver_t* driver = &g_touch_driver;
|
// (state of touch registers) the controller is reporting.
|
||||||
|
static uint32_t touch_get_state(touch_driver_t* driver) {
|
||||||
if (sectrue != driver->initialized) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Content of registers 0x00 - 0x06 read from the touch controller
|
// Content of registers 0x00 - 0x06 read from the touch controller
|
||||||
uint8_t regs[7];
|
uint8_t regs[7];
|
||||||
|
|
||||||
@ -485,18 +486,16 @@ uint32_t touch_get_event(void) {
|
|||||||
|
|
||||||
uint32_t ticks = hal_ticks_ms();
|
uint32_t ticks = hal_ticks_ms();
|
||||||
|
|
||||||
// Test if the touch_get_event() is starving (not called frequently enough)
|
|
||||||
bool starving = (int32_t)(ticks - driver->poll_ticks) > 300 /* ms */;
|
|
||||||
driver->poll_ticks = ticks;
|
|
||||||
|
|
||||||
// Test if the touch controller is polled too frequently
|
// Test if the touch controller is polled too frequently
|
||||||
// (less than 20ms since the last read)
|
// (less than 20ms since the last read)
|
||||||
bool toofast = (int32_t)(ticks - driver->read_ticks) < 20 /* ms */;
|
bool toofast = (int32_t)(ticks - driver->read_ticks) < 20 /* ms */;
|
||||||
|
|
||||||
// Fast track: if there is no new event and the touch controller
|
// Fast track: if there is no new event and the touch controller
|
||||||
// is not touched, we do not need to read the registers
|
// is not touched, we do not need to read the registers
|
||||||
if (!ft6x36_test_and_clear_interrupt() && (!driver->pressed || toofast)) {
|
bool pressed = (driver->state & TOUCH_START) || (driver->state & TOUCH_MOVE);
|
||||||
return 0;
|
|
||||||
|
if (!ft6x36_test_and_clear_interrupt() && (!pressed || toofast)) {
|
||||||
|
return driver->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver->read_ticks = ticks;
|
driver->read_ticks = ticks;
|
||||||
@ -537,71 +536,35 @@ uint32_t touch_get_event(void) {
|
|||||||
|
|
||||||
ft6x36_panel_correction(x_raw, y_raw, &x, &y);
|
ft6x36_panel_correction(x_raw, y_raw, &x, &y);
|
||||||
|
|
||||||
uint32_t event = 0;
|
uint32_t state = 0;
|
||||||
|
|
||||||
uint32_t xy = touch_pack_xy(x, y);
|
uint32_t xy = touch_pack_xy(x, y);
|
||||||
|
|
||||||
if ((nb_touches == 1) && (flags == FT6X63_EVENT_PRESS_DOWN)) {
|
if ((nb_touches == 1) && (flags == FT6X63_EVENT_PRESS_DOWN)) {
|
||||||
if (!driver->pressed) {
|
state = TOUCH_START | xy;
|
||||||
// Finger was just pressed down
|
|
||||||
event = TOUCH_START | xy;
|
|
||||||
} else {
|
|
||||||
if ((x != driver->last_x) || (y != driver->last_y)) {
|
|
||||||
// It looks like we have missed the lift up event
|
|
||||||
// We should send the TOUCH_END event here with old coordinates
|
|
||||||
event = TOUCH_END | touch_pack_xy(driver->last_x, driver->last_y);
|
|
||||||
} else {
|
|
||||||
// We have received the same coordinates as before,
|
|
||||||
// probably this is the same start event, or a quick bounce,
|
|
||||||
// we should ignore it.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((nb_touches == 1) && (flags == FT6X63_EVENT_CONTACT)) {
|
} else if ((nb_touches == 1) && (flags == FT6X63_EVENT_CONTACT)) {
|
||||||
if (driver->pressed) {
|
state = TOUCH_MOVE | xy;
|
||||||
if ((x != driver->last_x) || (y != driver->last_y)) {
|
|
||||||
// Report the move event only if the coordinates
|
|
||||||
// have changed
|
|
||||||
event = TOUCH_MOVE | xy;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We have missed the press down event, we have to simulate it.
|
|
||||||
// But ensure we don't simulate TOUCH_START if touch_get_event() is not
|
|
||||||
// called frequently enough to not produce false events.
|
|
||||||
if (!starving) {
|
|
||||||
event = TOUCH_START | xy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((nb_touches == 0) && (flags == FT6X63_EVENT_LIFT_UP)) {
|
} else if ((nb_touches == 0) && (flags == FT6X63_EVENT_LIFT_UP)) {
|
||||||
if (driver->pressed) {
|
state = TOUCH_END | xy;
|
||||||
// Finger was just lifted up
|
|
||||||
event = TOUCH_END | xy;
|
|
||||||
} else {
|
|
||||||
if (!starving && ((x != driver->last_x) || (y != driver->last_y))) {
|
|
||||||
// We have missed the PRESS_DOWN event.
|
|
||||||
// Report the start event only if the coordinates
|
|
||||||
// have changed and driver is not starving.
|
|
||||||
// This suggests that the previous touch was very short,
|
|
||||||
// or/and the driver is not called very frequently.
|
|
||||||
event = TOUCH_START | xy;
|
|
||||||
} else {
|
|
||||||
// Either the driver is starving or the coordinates
|
|
||||||
// have not changed, which would suggest that the TOUCH_END
|
|
||||||
// is repeated, so no event is needed -this should not happen
|
|
||||||
// since two consecutive LIFT_UPs are not possible due to
|
|
||||||
// testing the interrupt line before reading the registers.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remember the last state
|
driver->state = state;
|
||||||
if ((event & TOUCH_START) || (event & TOUCH_MOVE)) {
|
|
||||||
driver->pressed = true;
|
return state;
|
||||||
} else if (event & TOUCH_END) {
|
}
|
||||||
driver->pressed = false;
|
|
||||||
|
uint32_t touch_get_event(void) {
|
||||||
|
touch_driver_t* driver = &g_touch_driver;
|
||||||
|
|
||||||
|
if (sectrue != driver->initialized) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver->last_x = x;
|
touch_fsm_t* fsm = &driver->tls[systask_id(systask_active())];
|
||||||
driver->last_y = y;
|
|
||||||
|
uint32_t touch_state = touch_get_state(driver);
|
||||||
|
|
||||||
|
uint32_t event = touch_fsm_get_event(fsm, touch_state);
|
||||||
|
|
||||||
#ifdef TOUCH_TRACE_EVENT
|
#ifdef TOUCH_TRACE_EVENT
|
||||||
trace_event(event);
|
trace_event(event);
|
||||||
@ -610,4 +573,41 @@ uint32_t touch_get_event(void) {
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_task_created(void* context, systask_id_t task_id) {
|
||||||
|
touch_driver_t* driver = (touch_driver_t*)context;
|
||||||
|
touch_fsm_t* fsm = &driver->tls[task_id];
|
||||||
|
touch_fsm_init(fsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_event_poll(void* context, bool read_awaited,
|
||||||
|
bool write_awaited) {
|
||||||
|
touch_driver_t* driver = (touch_driver_t*)context;
|
||||||
|
UNUSED(write_awaited);
|
||||||
|
|
||||||
|
if (read_awaited) {
|
||||||
|
uint32_t touch_state = touch_get_state(driver);
|
||||||
|
if (touch_state != 0) {
|
||||||
|
syshandle_signal_read_ready(SYSHANDLE_TOUCH, &touch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool on_check_read_ready(void* context, systask_id_t task_id,
|
||||||
|
void* param) {
|
||||||
|
touch_driver_t* driver = (touch_driver_t*)context;
|
||||||
|
touch_fsm_t* fsm = &driver->tls[task_id];
|
||||||
|
|
||||||
|
uint32_t touch_state = *(uint32_t*)param;
|
||||||
|
|
||||||
|
return touch_fsm_event_ready(fsm, touch_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const syshandle_vmt_t g_touch_handle_vmt = {
|
||||||
|
.task_created = on_task_created,
|
||||||
|
.task_killed = NULL,
|
||||||
|
.check_read_ready = on_check_read_ready,
|
||||||
|
.check_write_ready = NULL,
|
||||||
|
.poll = on_event_poll,
|
||||||
|
};
|
||||||
|
|
||||||
#endif // KERNEL_MODE
|
#endif // KERNEL_MODE
|
||||||
|
@ -17,8 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TOUCH_FT6X36_H
|
#pragma once
|
||||||
#define _TOUCH_FT6X36_H
|
|
||||||
|
|
||||||
// I2C address of the FT6X36 on the I2C bus.
|
// I2C address of the FT6X36 on the I2C bus.
|
||||||
#define FT6X36_I2C_ADDR 0x38
|
#define FT6X36_I2C_ADDR 0x38
|
||||||
@ -71,5 +70,3 @@
|
|||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
#define FT6X36_GESTURE_NONE 0x00
|
#define FT6X36_GESTURE_NONE 0x00
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -658,6 +658,9 @@ __attribute__((optimize("-O0"))) int32_t SITRONIX_DetectTouch(
|
|||||||
*
|
*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "sitronix.h"
|
||||||
|
|
||||||
/* TS instances */
|
/* TS instances */
|
||||||
#define TS_INSTANCES_NBR 1U
|
#define TS_INSTANCES_NBR 1U
|
||||||
#define TS_TOUCH_NBR 10U
|
#define TS_TOUCH_NBR 10U
|
||||||
@ -671,13 +674,6 @@ __attribute__((optimize("-O0"))) int32_t SITRONIX_DetectTouch(
|
|||||||
/** @defgroup STM32U5x9J_DISCOVERY_TS_Exported_Types TS Exported Types
|
/** @defgroup STM32U5x9J_DISCOVERY_TS_Exported_Types TS Exported Types
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
|
||||||
uint32_t Width; /* Screen width */
|
|
||||||
uint32_t Height; /* Screen height */
|
|
||||||
uint32_t Orientation; /* Touch screen orientation */
|
|
||||||
uint32_t Accuracy; /* Expressed in pixel and means the x or y difference vs
|
|
||||||
old position to consider the new values valid */
|
|
||||||
} TS_Init_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t MultiTouch;
|
uint8_t MultiTouch;
|
||||||
@ -687,12 +683,6 @@ typedef struct {
|
|||||||
uint32_t MaxYl;
|
uint32_t MaxYl;
|
||||||
} TS_Capabilities_t;
|
} TS_Capabilities_t;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t TouchDetected;
|
|
||||||
uint32_t TouchX;
|
|
||||||
uint32_t TouchY;
|
|
||||||
} TS_State_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t TouchDetected;
|
uint32_t TouchDetected;
|
||||||
uint32_t TouchX[2];
|
uint32_t TouchX[2];
|
||||||
@ -1206,119 +1196,4 @@ static int32_t SITRONIX_Probe(uint32_t Instance) {
|
|||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <trezor_rtl.h>
|
|
||||||
|
|
||||||
#include <io/touch.h>
|
|
||||||
|
|
||||||
// Touch driver
|
|
||||||
typedef struct {
|
|
||||||
// Set if driver is initialized
|
|
||||||
secbool initialized;
|
|
||||||
// Last lower-level driver state
|
|
||||||
TS_State_t prev_state;
|
|
||||||
|
|
||||||
} touch_driver_t;
|
|
||||||
|
|
||||||
// Touch driver instance
|
|
||||||
static touch_driver_t g_touch_driver = {
|
|
||||||
.initialized = secfalse,
|
|
||||||
};
|
|
||||||
|
|
||||||
secbool touch_init(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
|
|
||||||
if (sectrue != driver->initialized) {
|
|
||||||
TS_Init_t TsInit;
|
|
||||||
|
|
||||||
/* Initialize the TouchScreen */
|
|
||||||
TsInit.Width = 480;
|
|
||||||
TsInit.Height = 480;
|
|
||||||
TsInit.Orientation = 0;
|
|
||||||
TsInit.Accuracy = 10;
|
|
||||||
|
|
||||||
BSP_TS_Init(0, &TsInit);
|
|
||||||
|
|
||||||
driver->initialized = sectrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return driver->initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void touch_deinit(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
|
|
||||||
if (sectrue == driver->initialized) {
|
|
||||||
BSP_TS_DeInit(0);
|
|
||||||
memset(driver, 0, sizeof(touch_driver_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void touch_power_set(bool on) {
|
|
||||||
// Not implemented for the discovery kit
|
|
||||||
}
|
|
||||||
|
|
||||||
secbool touch_ready(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
return driver->initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
secbool touch_set_sensitivity(uint8_t value) {
|
|
||||||
// Not implemented for the discovery kit
|
|
||||||
return sectrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t touch_get_version(void) {
|
|
||||||
// Not implemented for the discovery kit
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
secbool touch_activity(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
|
|
||||||
if (sectrue != driver->initialized) {
|
|
||||||
return secfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
TS_State_t new_state = {0};
|
|
||||||
BSP_TS_GetState(0, &new_state);
|
|
||||||
|
|
||||||
return sitronix_touching ? sectrue : secfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t touch_get_event(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
|
|
||||||
if (sectrue != driver->initialized) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TS_State_t new_state = {0};
|
|
||||||
BSP_TS_GetState(0, &new_state);
|
|
||||||
|
|
||||||
new_state.TouchDetected = (sitronix_touching != 0);
|
|
||||||
new_state.TouchX = new_state.TouchX > 120 ? new_state.TouchX - 120 : 0;
|
|
||||||
new_state.TouchY = new_state.TouchY > 120 ? new_state.TouchY - 120 : 0;
|
|
||||||
|
|
||||||
uint32_t event = 0;
|
|
||||||
|
|
||||||
if (new_state.TouchDetected && !driver->prev_state.TouchDetected) {
|
|
||||||
uint32_t xy = touch_pack_xy(new_state.TouchX, new_state.TouchY);
|
|
||||||
event = TOUCH_START | xy;
|
|
||||||
} else if (!new_state.TouchDetected && driver->prev_state.TouchDetected) {
|
|
||||||
uint32_t xy =
|
|
||||||
touch_pack_xy(driver->prev_state.TouchX, driver->prev_state.TouchY);
|
|
||||||
event = TOUCH_END | xy;
|
|
||||||
} else if (new_state.TouchDetected) {
|
|
||||||
if ((new_state.TouchX != driver->prev_state.TouchX) ||
|
|
||||||
(new_state.TouchY != driver->prev_state.TouchY)) {
|
|
||||||
uint32_t xy = touch_pack_xy(new_state.TouchX, new_state.TouchY);
|
|
||||||
event = TOUCH_MOVE | xy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
driver->prev_state = new_state;
|
|
||||||
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
34
core/embed/io/touch/sitronix/sitronix.h
Normal file
34
core/embed/io/touch/sitronix/sitronix.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// TS orientations
|
||||||
|
#define TS_ORIENTATION_PORTRAIT 0U
|
||||||
|
#define TS_ORIENTATION_LANDSCAPE 1U
|
||||||
|
#define TS_ORIENTATION_PORTRAIT_ROT180 2U
|
||||||
|
#define TS_ORIENTATION_LANDSCAPE_ROT180 3U
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Screen width
|
||||||
|
uint32_t Width;
|
||||||
|
// Screen width
|
||||||
|
uint32_t Height;
|
||||||
|
// Touch screen orientation
|
||||||
|
uint32_t Orientation;
|
||||||
|
// Expressed in pixel and means the x or y difference vs
|
||||||
|
// old position to consider the new values valid
|
||||||
|
uint32_t Accuracy;
|
||||||
|
|
||||||
|
} TS_Init_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t TouchDetected;
|
||||||
|
uint32_t TouchX;
|
||||||
|
uint32_t TouchY;
|
||||||
|
} TS_State_t;
|
||||||
|
|
||||||
|
extern uint8_t sitronix_touching;
|
||||||
|
|
||||||
|
int32_t BSP_TS_Init(uint32_t Instance, TS_Init_t *TS_Init);
|
||||||
|
|
||||||
|
int32_t BSP_TS_DeInit(uint32_t Instance);
|
||||||
|
|
||||||
|
int32_t BSP_TS_GetState(uint32_t Instance, TS_State_t *TS_State);
|
210
core/embed/io/touch/sitronix/touch.c
Normal file
210
core/embed/io/touch/sitronix/touch.c
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef KERNEL_MODE
|
||||||
|
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#include <io/touch.h>
|
||||||
|
#include <sys/sysevent_source.h>
|
||||||
|
|
||||||
|
#include "../touch_fsm.h"
|
||||||
|
#include "sitronix.h"
|
||||||
|
|
||||||
|
// Touch driver
|
||||||
|
typedef struct {
|
||||||
|
// Set if driver is initialized
|
||||||
|
secbool initialized;
|
||||||
|
// Last reported touch state
|
||||||
|
uint32_t state;
|
||||||
|
// Touch state machine for each task
|
||||||
|
touch_fsm_t tls[SYSTASK_MAX_TASKS];
|
||||||
|
|
||||||
|
} touch_driver_t;
|
||||||
|
|
||||||
|
// Touch driver instance
|
||||||
|
static touch_driver_t g_touch_driver = {
|
||||||
|
.initialized = secfalse,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
static const syshandle_vmt_t g_touch_handle_vmt;
|
||||||
|
|
||||||
|
secbool touch_init(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
|
if (sectrue == drv->initialized) {
|
||||||
|
// The driver is already initialized
|
||||||
|
return sectrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TS_Init_t TsInit;
|
||||||
|
|
||||||
|
// Initialize the TouchScreen
|
||||||
|
TsInit.Width = 480;
|
||||||
|
TsInit.Height = 480;
|
||||||
|
TsInit.Orientation = 0;
|
||||||
|
TsInit.Accuracy = 2;
|
||||||
|
|
||||||
|
if (0 != BSP_TS_Init(0, &TsInit)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!syshandle_register(SYSHANDLE_TOUCH, &g_touch_handle_vmt, drv)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv->initialized = sectrue;
|
||||||
|
return sectrue;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
touch_deinit();
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_deinit(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
|
BSP_TS_DeInit(0);
|
||||||
|
syshandle_unregister(SYSHANDLE_TOUCH);
|
||||||
|
|
||||||
|
memset(drv, 0, sizeof(touch_driver_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_power_set(bool on) {
|
||||||
|
// Not implemented for the discovery kit
|
||||||
|
}
|
||||||
|
|
||||||
|
secbool touch_ready(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
return drv->initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
secbool touch_set_sensitivity(uint8_t value) {
|
||||||
|
// Not implemented for the discovery kit
|
||||||
|
return sectrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t touch_get_version(void) {
|
||||||
|
// Not implemented for the discovery kit
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
secbool touch_activity(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
|
if (sectrue != drv->initialized) {
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
TS_State_t new_state = {0};
|
||||||
|
BSP_TS_GetState(0, &new_state);
|
||||||
|
|
||||||
|
return sitronix_touching ? sectrue : secfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t touch_get_state(touch_driver_t* drv) {
|
||||||
|
TS_State_t ts = {0};
|
||||||
|
BSP_TS_GetState(0, &ts);
|
||||||
|
|
||||||
|
uint32_t state = drv->state;
|
||||||
|
|
||||||
|
ts.TouchDetected = sitronix_touching ? 1 : 0;
|
||||||
|
ts.TouchX = ts.TouchX > 120 ? ts.TouchX - 120 : 0;
|
||||||
|
ts.TouchY = ts.TouchY > 120 ? ts.TouchY - 120 : 0;
|
||||||
|
|
||||||
|
uint32_t xy = touch_pack_xy(ts.TouchX, ts.TouchY);
|
||||||
|
|
||||||
|
if (ts.TouchDetected) {
|
||||||
|
if ((drv->state & TOUCH_END) || (drv->state == 0)) {
|
||||||
|
state = TOUCH_START | xy;
|
||||||
|
} else if (drv->state & TOUCH_MOVE) {
|
||||||
|
state = TOUCH_MOVE | xy;
|
||||||
|
} else {
|
||||||
|
state = TOUCH_START | xy;
|
||||||
|
if (state != drv->state) {
|
||||||
|
state = TOUCH_MOVE | xy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (drv->state & (TOUCH_START | TOUCH_MOVE)) {
|
||||||
|
state = drv->state & ~(TOUCH_START | TOUCH_MOVE);
|
||||||
|
state |= TOUCH_END;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drv->state = state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t touch_get_event(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
|
if (sectrue != drv->initialized) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
touch_fsm_t* fsm = &drv->tls[systask_id(systask_active())];
|
||||||
|
|
||||||
|
uint32_t touch_state = touch_get_state(drv);
|
||||||
|
|
||||||
|
uint32_t event = touch_fsm_get_event(fsm, touch_state);
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_task_created(void* context, systask_id_t task_id) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
touch_fsm_t* fsm = &drv->tls[task_id];
|
||||||
|
touch_fsm_init(fsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_event_poll(void* context, bool read_awaited,
|
||||||
|
bool write_awaited) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
|
||||||
|
UNUSED(write_awaited);
|
||||||
|
|
||||||
|
if (read_awaited) {
|
||||||
|
uint32_t touch_state = touch_get_state(drv);
|
||||||
|
if (touch_state != 0) {
|
||||||
|
syshandle_signal_read_ready(SYSHANDLE_TOUCH, &touch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool on_check_read_ready(void* context, systask_id_t task_id,
|
||||||
|
void* param) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
touch_fsm_t* fsm = &drv->tls[task_id];
|
||||||
|
|
||||||
|
uint32_t touch_state = *(uint32_t*)param;
|
||||||
|
|
||||||
|
return touch_fsm_event_ready(fsm, touch_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const syshandle_vmt_t g_touch_handle_vmt = {
|
||||||
|
.task_created = on_task_created,
|
||||||
|
.task_killed = NULL,
|
||||||
|
.check_read_ready = on_check_read_ready,
|
||||||
|
.check_write_ready = NULL,
|
||||||
|
.poll = on_event_poll,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KERNEL_MODE
|
@ -17,13 +17,13 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <trezor_bsp.h>
|
|
||||||
#include <trezor_rtl.h>
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
#ifdef KERNEL_MODE
|
#ifdef KERNEL_MODE
|
||||||
|
|
||||||
#include <io/i2c_bus.h>
|
#include <io/i2c_bus.h>
|
||||||
#include <io/touch.h>
|
#include <sys/systick.h>
|
||||||
|
|
||||||
#include "stmpe811.h"
|
#include "stmpe811.h"
|
||||||
|
|
||||||
/* Chip IDs */
|
/* Chip IDs */
|
||||||
@ -175,7 +175,7 @@
|
|||||||
uint32_t I2cxTimeout =
|
uint32_t I2cxTimeout =
|
||||||
I2Cx_TIMEOUT_MAX; /*<! Value of Timeout when I2C communication fails */
|
I2Cx_TIMEOUT_MAX; /*<! Value of Timeout when I2C communication fails */
|
||||||
|
|
||||||
static i2c_bus_t *i2c_bus = NULL;
|
static i2c_bus_t *g_i2c_bus = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes a value in a register of the device through BUS.
|
* @brief Writes a value in a register of the device through BUS.
|
||||||
@ -199,7 +199,7 @@ static void I2Cx_WriteData(uint8_t Addr, uint8_t Reg, uint8_t Value) {
|
|||||||
.ops = ops,
|
.ops = ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c_status_t status = i2c_bus_submit_and_wait(i2c_bus, &pkt);
|
i2c_status_t status = i2c_bus_submit_and_wait(g_i2c_bus, &pkt);
|
||||||
|
|
||||||
(void)status;
|
(void)status;
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ static void I2Cx_WriteBuffer(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer,
|
|||||||
.ops = ops,
|
.ops = ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c_status_t status = i2c_bus_submit_and_wait(i2c_bus, &pkt);
|
i2c_status_t status = i2c_bus_submit_and_wait(g_i2c_bus, &pkt);
|
||||||
|
|
||||||
(void)status;
|
(void)status;
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ static uint8_t I2Cx_ReadData(uint8_t Addr, uint8_t Reg) {
|
|||||||
.ops = ops,
|
.ops = ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c_status_t status = i2c_bus_submit_and_wait(i2c_bus, &pkt);
|
i2c_status_t status = i2c_bus_submit_and_wait(g_i2c_bus, &pkt);
|
||||||
|
|
||||||
(void)status;
|
(void)status;
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ static uint8_t I2Cx_ReadBuffer(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer,
|
|||||||
.ops = ops,
|
.ops = ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c_status_t status = i2c_bus_submit_and_wait(i2c_bus, &pkt);
|
i2c_status_t status = i2c_bus_submit_and_wait(g_i2c_bus, &pkt);
|
||||||
|
|
||||||
return status == I2C_STATUS_OK ? 0 : 1;
|
return status == I2C_STATUS_OK ? 0 : 1;
|
||||||
}
|
}
|
||||||
@ -356,7 +356,7 @@ uint16_t IOE_ReadMultiple(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer,
|
|||||||
* @brief IOE Delay.
|
* @brief IOE Delay.
|
||||||
* @param Delay in ms
|
* @param Delay in ms
|
||||||
*/
|
*/
|
||||||
void IOE_Delay(uint32_t Delay) { HAL_Delay(Delay); }
|
void IOE_Delay(uint32_t Delay) { systick_delay_ms(Delay); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable the AF for the selected IO pin(s).
|
* @brief Enable the AF for the selected IO pin(s).
|
||||||
@ -462,7 +462,9 @@ void touch_set_mode(void) {
|
|||||||
* @param DeviceAddr: Device address on communication Bus.
|
* @param DeviceAddr: Device address on communication Bus.
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void stmpe811_Reset() {
|
void stmpe811_Reset(i2c_bus_t *i2c_bus) {
|
||||||
|
g_i2c_bus = i2c_bus;
|
||||||
|
|
||||||
/* Power Down the stmpe811 */
|
/* Power Down the stmpe811 */
|
||||||
IOE_Write(TS_I2C_ADDRESS, STMPE811_REG_SYS_CTRL1, 2);
|
IOE_Write(TS_I2C_ADDRESS, STMPE811_REG_SYS_CTRL1, 2);
|
||||||
|
|
||||||
@ -477,7 +479,7 @@ void stmpe811_Reset() {
|
|||||||
IOE_Delay(2);
|
IOE_Delay(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t touch_active(void) {
|
uint32_t touch_active(void) {
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
uint8_t ret = 0;
|
uint8_t ret = 0;
|
||||||
|
|
||||||
@ -523,25 +525,27 @@ void stmpe811_TS_GetXY(uint16_t *X, uint16_t *Y) {
|
|||||||
/* Enable the FIFO again */
|
/* Enable the FIFO again */
|
||||||
IOE_Write(TS_I2C_ADDRESS, STMPE811_REG_FIFO_STA, 0x00);
|
IOE_Write(TS_I2C_ADDRESS, STMPE811_REG_FIFO_STA, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t TouchDetected;
|
|
||||||
uint16_t X;
|
|
||||||
uint16_t Y;
|
|
||||||
uint16_t Z;
|
|
||||||
} TS_StateTypeDef;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns status and positions of the touch screen.
|
* @brief Returns status and positions of the touch screen.
|
||||||
* @param TsState: Pointer to touch screen current state structure
|
* @param TsState: Pointer to touch screen current state structure
|
||||||
*/
|
*/
|
||||||
void BSP_TS_GetState(TS_StateTypeDef *TsState) {
|
void BSP_TS_GetState(TS_StateTypeDef *TsState) {
|
||||||
|
static bool _detected = false;
|
||||||
static uint32_t _x = 0, _y = 0;
|
static uint32_t _x = 0, _y = 0;
|
||||||
uint16_t xDiff, yDiff, x, y, xr, yr;
|
uint16_t xDiff, yDiff, x, y, xr, yr;
|
||||||
|
|
||||||
TsState->TouchDetected = touch_active();
|
TsState->TouchDetected = _detected;
|
||||||
|
TsState->X = _x;
|
||||||
|
TsState->Y = _y;
|
||||||
|
|
||||||
if (TsState->TouchDetected) {
|
bool detected = (IOE_Read(TS_I2C_ADDRESS, STMPE811_REG_TSC_CTRL) &
|
||||||
|
STMPE811_TS_CTRL_STATUS) != 0;
|
||||||
|
|
||||||
|
if (!detected) {
|
||||||
|
TsState->TouchDetected = _detected = false;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (IOE_Read(TS_I2C_ADDRESS, STMPE811_REG_FIFO_SIZE) > 0) {
|
||||||
stmpe811_TS_GetXY(&x, &y);
|
stmpe811_TS_GetXY(&x, &y);
|
||||||
|
|
||||||
/* Y value first correction */
|
/* Y value first correction */
|
||||||
@ -587,110 +591,15 @@ void BSP_TS_GetState(TS_StateTypeDef *TsState) {
|
|||||||
_y = y;
|
_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_detected = true;
|
||||||
|
|
||||||
/* Update the X position */
|
/* Update the X position */
|
||||||
TsState->X = _x;
|
TsState->X = _x;
|
||||||
|
|
||||||
/* Update the Y position */
|
/* Update the Y position */
|
||||||
TsState->Y = _y;
|
TsState->Y = _y;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
// Set if driver is initialized
|
|
||||||
secbool initialized;
|
|
||||||
// Last lower-level driver state
|
|
||||||
TS_StateTypeDef prev_state;
|
|
||||||
|
|
||||||
} touch_driver_t;
|
|
||||||
|
|
||||||
// Touch driver instance
|
|
||||||
static touch_driver_t g_touch_driver = {
|
|
||||||
.initialized = secfalse,
|
|
||||||
};
|
|
||||||
|
|
||||||
secbool touch_init(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
|
|
||||||
if (driver->initialized != sectrue) {
|
|
||||||
i2c_bus = i2c_bus_open(TOUCH_I2C_INSTANCE);
|
|
||||||
if (i2c_bus == NULL) {
|
|
||||||
return secfalse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmpe811_Reset();
|
|
||||||
touch_set_mode();
|
|
||||||
|
|
||||||
driver->initialized = sectrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return driver->initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void touch_deinit(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
|
|
||||||
if (driver->initialized == sectrue) {
|
|
||||||
// Not implemented properly
|
|
||||||
|
|
||||||
i2c_bus_close(i2c_bus);
|
|
||||||
memset(driver, 0, sizeof(touch_driver_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void touch_power_set(bool on) {
|
|
||||||
// Not implemented for the discovery kit
|
|
||||||
}
|
|
||||||
|
|
||||||
secbool touch_ready(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
return driver->initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
secbool touch_set_sensitivity(uint8_t value) {
|
|
||||||
// Not implemented for the discovery kit
|
|
||||||
return sectrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t touch_get_version(void) {
|
|
||||||
// Not implemented for the discovery kit
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
secbool touch_activity(void) {
|
|
||||||
uint8_t state = ((IOE_Read(TS_I2C_ADDRESS, STMPE811_REG_TSC_CTRL) &
|
|
||||||
(uint8_t)STMPE811_TS_CTRL_STATUS) == (uint8_t)0x80);
|
|
||||||
return state > 0 ? sectrue : secfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t touch_get_event(void) {
|
|
||||||
touch_driver_t *driver = &g_touch_driver;
|
|
||||||
|
|
||||||
if (driver->initialized != sectrue) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TS_StateTypeDef new_state = {0};
|
|
||||||
BSP_TS_GetState(&new_state);
|
|
||||||
|
|
||||||
uint32_t event = 0;
|
|
||||||
|
|
||||||
if (new_state.TouchDetected && !driver->prev_state.TouchDetected) {
|
|
||||||
uint32_t xy = touch_pack_xy(new_state.X, new_state.Y);
|
|
||||||
event = TOUCH_START | xy;
|
|
||||||
} else if (!new_state.TouchDetected && driver->prev_state.TouchDetected) {
|
|
||||||
uint32_t xy = touch_pack_xy(driver->prev_state.X, driver->prev_state.Y);
|
|
||||||
event = TOUCH_END | xy;
|
|
||||||
} else if (new_state.TouchDetected) {
|
|
||||||
if ((new_state.X != driver->prev_state.X) ||
|
|
||||||
(new_state.Y != driver->prev_state.Y)) {
|
|
||||||
uint32_t xy = touch_pack_xy(new_state.X, new_state.Y);
|
|
||||||
event = TOUCH_MOVE | xy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
driver->prev_state = new_state;
|
|
||||||
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,6 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#ifndef _STMPE811_H
|
#include <trezor_types.h>
|
||||||
#define _STMPE811_H
|
|
||||||
|
|
||||||
#endif //_STMPE811_H
|
#include <io/i2c_bus.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t TouchDetected;
|
||||||
|
uint16_t X;
|
||||||
|
uint16_t Y;
|
||||||
|
uint16_t Z;
|
||||||
|
} TS_StateTypeDef;
|
||||||
|
|
||||||
|
void BSP_TS_GetState(TS_StateTypeDef *TsState);
|
||||||
|
|
||||||
|
void stmpe811_Reset(i2c_bus_t *i2c_bus);
|
||||||
|
|
||||||
|
void touch_set_mode(void);
|
||||||
|
|
||||||
|
uint32_t touch_active(void);
|
||||||
|
199
core/embed/io/touch/stmpe811/touch.c
Normal file
199
core/embed/io/touch/stmpe811/touch.c
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <trezor_bsp.h>
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#ifdef KERNEL_MODE
|
||||||
|
|
||||||
|
#include <io/touch.h>
|
||||||
|
#include <sys/sysevent_source.h>
|
||||||
|
|
||||||
|
#include "../touch_fsm.h"
|
||||||
|
#include "stmpe811.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Set if driver is initialized
|
||||||
|
secbool initialized;
|
||||||
|
// I2C Bus driver
|
||||||
|
i2c_bus_t* i2c_bus;
|
||||||
|
// Last reported touch state
|
||||||
|
uint32_t state;
|
||||||
|
// Touch state machine for each task
|
||||||
|
touch_fsm_t tls[SYSTASK_MAX_TASKS];
|
||||||
|
|
||||||
|
} touch_driver_t;
|
||||||
|
|
||||||
|
// Touch driver instance
|
||||||
|
static touch_driver_t g_touch_driver = {
|
||||||
|
.initialized = secfalse,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
static const syshandle_vmt_t g_touch_handle_vmt;
|
||||||
|
|
||||||
|
secbool touch_init(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
|
if (drv->initialized == sectrue) {
|
||||||
|
return sectrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(drv, 0, sizeof(drv));
|
||||||
|
|
||||||
|
drv->i2c_bus = i2c_bus_open(TOUCH_I2C_INSTANCE);
|
||||||
|
|
||||||
|
if (drv->i2c_bus == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!syshandle_register(SYSHANDLE_TOUCH, &g_touch_handle_vmt, drv)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
stmpe811_Reset(drv->i2c_bus);
|
||||||
|
touch_set_mode();
|
||||||
|
|
||||||
|
drv->initialized = sectrue;
|
||||||
|
return sectrue;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
touch_deinit();
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_deinit(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
|
syshandle_unregister(SYSHANDLE_TOUCH);
|
||||||
|
i2c_bus_close(drv->i2c_bus);
|
||||||
|
memset(drv, 0, sizeof(touch_driver_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_power_set(bool on) {
|
||||||
|
// Not implemented for the discovery kit
|
||||||
|
}
|
||||||
|
|
||||||
|
secbool touch_ready(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
return drv->initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
secbool touch_set_sensitivity(uint8_t value) {
|
||||||
|
// Not implemented for the discovery kit
|
||||||
|
return sectrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t touch_get_version(void) {
|
||||||
|
// Not implemented for the discovery kit
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
secbool touch_activity(void) {
|
||||||
|
return touch_active() ? sectrue : secfalse;
|
||||||
|
/* uint8_t state = ((IOE_Read(TS_I2C_ADDRESS, STMPE811_REG_TSC_CTRL) &
|
||||||
|
(uint8_t)STMPE811_TS_CTRL_STATUS) == (uint8_t)0x80);
|
||||||
|
return state > 0 ? sectrue : secfalse;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t touch_get_state(touch_driver_t* drv) {
|
||||||
|
TS_StateTypeDef ts = {0};
|
||||||
|
BSP_TS_GetState(&ts);
|
||||||
|
|
||||||
|
uint32_t state = drv->state;
|
||||||
|
|
||||||
|
uint32_t xy = touch_pack_xy(ts.X, ts.Y);
|
||||||
|
|
||||||
|
if (ts.TouchDetected) {
|
||||||
|
if ((drv->state & TOUCH_END) || (drv->state == 0)) {
|
||||||
|
state = TOUCH_START | xy;
|
||||||
|
} else if (drv->state & TOUCH_MOVE) {
|
||||||
|
state = TOUCH_MOVE | xy;
|
||||||
|
} else {
|
||||||
|
state = TOUCH_START | xy;
|
||||||
|
if (state != drv->state) {
|
||||||
|
state = TOUCH_MOVE | xy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (drv->state & (TOUCH_START | TOUCH_MOVE)) {
|
||||||
|
state = drv->state & ~(TOUCH_START | TOUCH_MOVE);
|
||||||
|
state |= TOUCH_END;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drv->state = state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t touch_get_event(void) {
|
||||||
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
|
if (sectrue != drv->initialized) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
touch_fsm_t* fsm = &drv->tls[systask_id(systask_active())];
|
||||||
|
|
||||||
|
uint32_t touch_state = touch_get_state(drv);
|
||||||
|
|
||||||
|
uint32_t event = touch_fsm_get_event(fsm, touch_state);
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_task_created(void* context, systask_id_t task_id) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
touch_fsm_t* fsm = &drv->tls[task_id];
|
||||||
|
touch_fsm_init(fsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_event_poll(void* context, bool read_awaited,
|
||||||
|
bool write_awaited) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
|
||||||
|
UNUSED(write_awaited);
|
||||||
|
|
||||||
|
if (read_awaited) {
|
||||||
|
uint32_t touch_state = touch_get_state(drv);
|
||||||
|
if (touch_state != 0) {
|
||||||
|
syshandle_signal_read_ready(SYSHANDLE_TOUCH, &touch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool on_check_read_ready(void* context, systask_id_t task_id,
|
||||||
|
void* param) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
touch_fsm_t* fsm = &drv->tls[task_id];
|
||||||
|
|
||||||
|
uint32_t touch_state = *(uint32_t*)param;
|
||||||
|
|
||||||
|
return touch_fsm_event_ready(fsm, touch_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const syshandle_vmt_t g_touch_handle_vmt = {
|
||||||
|
.task_created = on_task_created,
|
||||||
|
.task_killed = NULL,
|
||||||
|
.check_read_ready = on_check_read_ready,
|
||||||
|
.check_write_ready = NULL,
|
||||||
|
.poll = on_event_poll,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KERNEL_MODE
|
118
core/embed/io/touch/touch_fsm.c
Normal file
118
core/embed/io/touch/touch_fsm.c
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef KERNEL_MODE
|
||||||
|
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#include <io/touch.h>
|
||||||
|
#include <sys/systick.h>
|
||||||
|
|
||||||
|
#include "touch_fsm.h"
|
||||||
|
|
||||||
|
void touch_fsm_init(touch_fsm_t* fsm) {
|
||||||
|
memset(fsm, 0, sizeof(touch_fsm_t));
|
||||||
|
fsm->update_ticks = systick_ms();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool touch_fsm_event_ready(touch_fsm_t* fsm, uint32_t touch_state) {
|
||||||
|
return fsm->state != touch_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t touch_fsm_get_event(touch_fsm_t* fsm, uint32_t touch_state) {
|
||||||
|
fsm->state = touch_state;
|
||||||
|
|
||||||
|
uint32_t ticks = hal_ticks_ms();
|
||||||
|
|
||||||
|
// Test if the touch_get_event() is starving (not called frequently enough)
|
||||||
|
bool starving = (int32_t)(ticks - fsm->update_ticks) > 300 /* ms */;
|
||||||
|
fsm->update_ticks = ticks;
|
||||||
|
|
||||||
|
uint16_t x = touch_unpack_x(touch_state);
|
||||||
|
uint16_t y = touch_unpack_y(touch_state);
|
||||||
|
|
||||||
|
uint32_t event = 0;
|
||||||
|
uint32_t xy = touch_pack_xy(x, y);
|
||||||
|
|
||||||
|
if (touch_state & TOUCH_START) {
|
||||||
|
if (!fsm->pressed) {
|
||||||
|
// Finger was just pressed down
|
||||||
|
event = TOUCH_START | xy;
|
||||||
|
} else {
|
||||||
|
if ((x != fsm->last_x) || (y != fsm->last_y)) {
|
||||||
|
// It looks like we have missed the lift up event
|
||||||
|
// We should send the TOUCH_END event here with old coordinates
|
||||||
|
event = TOUCH_END | touch_pack_xy(fsm->last_x, fsm->last_y);
|
||||||
|
} else {
|
||||||
|
// We have received the same coordinates as before,
|
||||||
|
// probably this is the same start event, or a quick bounce,
|
||||||
|
// we should ignore it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (touch_state & TOUCH_MOVE) {
|
||||||
|
if (fsm->pressed) {
|
||||||
|
if ((x != fsm->last_x) || (y != fsm->last_y)) {
|
||||||
|
// Report the move event only if the coordinates
|
||||||
|
// have changed
|
||||||
|
event = TOUCH_MOVE | xy;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We have missed the press down event, we have to simulate it.
|
||||||
|
// But ensure we don't simulate TOUCH_START if touch_get_event() is not
|
||||||
|
// called frequently enough to not produce false events.
|
||||||
|
if (!starving) {
|
||||||
|
event = TOUCH_START | xy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (touch_state & TOUCH_END) {
|
||||||
|
if (fsm->pressed) {
|
||||||
|
// Finger was just lifted up
|
||||||
|
event = TOUCH_END | xy;
|
||||||
|
} else {
|
||||||
|
if (!starving && ((x != fsm->last_x) || (y != fsm->last_y))) {
|
||||||
|
// We have missed the PRESS_DOWN event.
|
||||||
|
// Report the start event only if the coordinates
|
||||||
|
// have changed and driver is not starving.
|
||||||
|
// This suggests that the previous touch was very short,
|
||||||
|
// or/and the driver is not called very frequently.
|
||||||
|
event = TOUCH_START | xy;
|
||||||
|
} else {
|
||||||
|
// Either the driver is starving or the coordinates
|
||||||
|
// have not changed, which would suggest that the TOUCH_END
|
||||||
|
// is repeated, so no event is needed -this should not happen
|
||||||
|
// since two consecutive LIFT_UPs are not possible due to
|
||||||
|
// testing the interrupt line before reading the registers.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember the last state
|
||||||
|
if ((event & TOUCH_START) || (event & TOUCH_MOVE)) {
|
||||||
|
fsm->pressed = true;
|
||||||
|
} else if (event & TOUCH_END) {
|
||||||
|
fsm->pressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fsm->last_x = x;
|
||||||
|
fsm->last_y = y;
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // KERNEL_MODE
|
63
core/embed/io/touch/touch_fsm.h
Normal file
63
core/embed/io/touch/touch_fsm.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// This module is a simple finite state machine for touch events.
|
||||||
|
//
|
||||||
|
// It is designed to be used in a polling loop, where the state of the touch
|
||||||
|
// is read periodically. The module keeps track of the state changes and
|
||||||
|
// provides a simple interface to get the events that happened since the last
|
||||||
|
// call to touch_fsm_get_event().
|
||||||
|
//
|
||||||
|
// The benefit of using this module is that it can properly handle situations
|
||||||
|
// when the touch panel is not read frequently enough or when some
|
||||||
|
// touch events are missed.
|
||||||
|
//
|
||||||
|
// The structure is designed to be used in a multi-threaded environment, where
|
||||||
|
// each thread has its own state machine. The state machines are stored in an
|
||||||
|
// array indexed by the task ID.
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Time (in ticks) when the tls was last updated
|
||||||
|
uint32_t update_ticks;
|
||||||
|
// Last reported touch state
|
||||||
|
uint32_t state;
|
||||||
|
// Set if the touch controller is currently touched
|
||||||
|
// (respectively, that we detected a touch event)
|
||||||
|
bool pressed;
|
||||||
|
// Previously reported x-coordinate
|
||||||
|
uint16_t last_x;
|
||||||
|
// Previously reported y-coordinate
|
||||||
|
uint16_t last_y;
|
||||||
|
} touch_fsm_t;
|
||||||
|
|
||||||
|
// Initializes button finite state machine
|
||||||
|
void touch_fsm_init(touch_fsm_t* fsm);
|
||||||
|
|
||||||
|
// Checks if touch_fsm_get_event() would return `true` on the next call
|
||||||
|
bool touch_fsm_event_ready(touch_fsm_t* fsm, uint32_t touch_state);
|
||||||
|
|
||||||
|
// Processes the new state of thetouch panel and fills the event structure.
|
||||||
|
//
|
||||||
|
// `touch_state` is the current state of the touch panel. The state has
|
||||||
|
// the same format as the return value of `touch_get_state()`.
|
||||||
|
//
|
||||||
|
// Returns `true` if the event structure was filled.
|
||||||
|
uint32_t touch_fsm_get_event(touch_fsm_t* fsm, uint32_t touch_state);
|
@ -20,9 +20,12 @@
|
|||||||
#include <trezor_bsp.h>
|
#include <trezor_bsp.h>
|
||||||
#include <trezor_rtl.h>
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
|
|
||||||
#include <io/touch.h>
|
#include <io/touch.h>
|
||||||
|
#include <sys/sysevent_source.h>
|
||||||
|
#include <sys/systick.h>
|
||||||
|
#include <sys/unix/sdl_event.h>
|
||||||
|
|
||||||
|
#include "../touch_fsm.h"
|
||||||
|
|
||||||
extern int sdl_display_res_x, sdl_display_res_y;
|
extern int sdl_display_res_x, sdl_display_res_y;
|
||||||
extern int sdl_touch_offset_x, sdl_touch_offset_y;
|
extern int sdl_touch_offset_x, sdl_touch_offset_y;
|
||||||
@ -41,11 +44,7 @@ typedef enum {
|
|||||||
IDLE,
|
IDLE,
|
||||||
MOUSE_DOWN_INSIDE,
|
MOUSE_DOWN_INSIDE,
|
||||||
MOUSE_DOWN_OUTSIDE,
|
MOUSE_DOWN_OUTSIDE,
|
||||||
BUTTON_SWIPE_LEFT_INITIATED,
|
BUTTON_SWIPE_INITIATED,
|
||||||
BUTTON_SWIPE_RIGHT_INITIATED,
|
|
||||||
BUTTON_SWIPE_UP_INITIATED,
|
|
||||||
BUTTON_SWIPE_DOWN_INITIATED,
|
|
||||||
BUTTON_SWIPE_COMPLETED
|
|
||||||
} touch_state_t;
|
} touch_state_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -53,9 +52,18 @@ typedef struct {
|
|||||||
secbool initialized;
|
secbool initialized;
|
||||||
// Current state of the touch driver
|
// Current state of the touch driver
|
||||||
touch_state_t state;
|
touch_state_t state;
|
||||||
// Last valid coordinates
|
|
||||||
int last_x;
|
uint32_t swipe_time;
|
||||||
int last_y;
|
int swipe_start_x;
|
||||||
|
int swipe_start_y;
|
||||||
|
int swipe_end_x;
|
||||||
|
int swipe_end_y;
|
||||||
|
int swipe_key;
|
||||||
|
|
||||||
|
// Last event not yet read
|
||||||
|
uint32_t last_event;
|
||||||
|
// Touch state machine for each task
|
||||||
|
touch_fsm_t tls[SYSTASK_MAX_TASKS];
|
||||||
|
|
||||||
} touch_driver_t;
|
} touch_driver_t;
|
||||||
|
|
||||||
@ -64,153 +72,164 @@ static touch_driver_t g_touch_driver = {
|
|||||||
.initialized = secfalse,
|
.initialized = secfalse,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
static const syshandle_vmt_t g_touch_handle_vmt;
|
||||||
|
|
||||||
static bool is_inside_display(int x, int y) {
|
static bool is_inside_display(int x, int y) {
|
||||||
return x >= sdl_touch_offset_x && y >= sdl_touch_offset_y &&
|
return x >= sdl_touch_offset_x && y >= sdl_touch_offset_y &&
|
||||||
x - sdl_touch_offset_x < sdl_display_res_x &&
|
x - sdl_touch_offset_x < sdl_display_res_x &&
|
||||||
y - sdl_touch_offset_y < sdl_display_res_y;
|
y - sdl_touch_offset_y < sdl_display_res_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_button_swipe_initiated(const touch_driver_t* driver) {
|
static void handle_mouse_events(touch_driver_t* drv, SDL_Event* event) {
|
||||||
return driver->state == BUTTON_SWIPE_LEFT_INITIATED ||
|
bool inside_display = is_inside_display(event->button.x, event->button.y);
|
||||||
driver->state == BUTTON_SWIPE_RIGHT_INITIATED ||
|
|
||||||
driver->state == BUTTON_SWIPE_UP_INITIATED ||
|
|
||||||
driver->state == BUTTON_SWIPE_DOWN_INITIATED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_mouse_events(touch_driver_t* driver, SDL_Event event,
|
switch (event->type) {
|
||||||
int* ev_type, int* ev_x, int* ev_y) {
|
|
||||||
bool inside_display = is_inside_display(event.button.x, event.button.y);
|
|
||||||
switch (event.type) {
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
if (inside_display) {
|
if (inside_display) {
|
||||||
*ev_x = event.button.x - sdl_touch_offset_x;
|
int x = event->button.x - sdl_touch_offset_x;
|
||||||
*ev_y = event.button.y - sdl_touch_offset_y;
|
int y = event->button.y - sdl_touch_offset_y;
|
||||||
*ev_type = TOUCH_START;
|
drv->last_event = TOUCH_START | touch_pack_xy(x, y);
|
||||||
driver->state = MOUSE_DOWN_INSIDE;
|
drv->state = MOUSE_DOWN_INSIDE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_MOUSEBUTTONUP:
|
case SDL_MOUSEBUTTONUP:
|
||||||
if (driver->state != IDLE) {
|
if (drv->state != IDLE) {
|
||||||
*ev_x = inside_display ? event.button.x - sdl_touch_offset_x
|
int x = inside_display ? event->button.x - sdl_touch_offset_x
|
||||||
: driver->last_x;
|
: touch_unpack_x(drv->last_event);
|
||||||
*ev_y = inside_display ? event.button.y - sdl_touch_offset_y
|
int y = inside_display ? event->button.y - sdl_touch_offset_y
|
||||||
: driver->last_y;
|
: touch_unpack_y(drv->last_event);
|
||||||
*ev_type = TOUCH_END;
|
;
|
||||||
driver->state = IDLE;
|
drv->last_event = TOUCH_END | touch_pack_xy(x, y);
|
||||||
|
drv->state = IDLE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
if (driver->state != IDLE) {
|
if (drv->state != IDLE) {
|
||||||
if (inside_display) {
|
if (inside_display) {
|
||||||
*ev_x = event.motion.x - sdl_touch_offset_x;
|
int x = event->motion.x - sdl_touch_offset_x;
|
||||||
*ev_y = event.motion.y - sdl_touch_offset_y;
|
int y = event->motion.y - sdl_touch_offset_y;
|
||||||
// simulate TOUCH_START if pressed in mouse returned on visible area
|
// simulate TOUCH_START if pressed in mouse returned on visible area
|
||||||
*ev_type =
|
if (drv->state == MOUSE_DOWN_OUTSIDE) {
|
||||||
(driver->state == MOUSE_DOWN_OUTSIDE) ? TOUCH_START : TOUCH_MOVE;
|
drv->last_event = TOUCH_START | touch_pack_xy(x, y);
|
||||||
driver->state = MOUSE_DOWN_INSIDE;
|
|
||||||
} else {
|
} else {
|
||||||
if (driver->state == MOUSE_DOWN_INSIDE) {
|
drv->last_event = TOUCH_MOVE | touch_pack_xy(x, y);
|
||||||
// use last valid coordinates and simulate TOUCH_END
|
|
||||||
*ev_x = driver->last_x;
|
|
||||||
*ev_y = driver->last_y;
|
|
||||||
*ev_type = TOUCH_END;
|
|
||||||
}
|
}
|
||||||
driver->state = MOUSE_DOWN_OUTSIDE;
|
drv->state = MOUSE_DOWN_INSIDE;
|
||||||
|
} else {
|
||||||
|
if (drv->state == MOUSE_DOWN_INSIDE) {
|
||||||
|
// use last valid coordinates and simulate TOUCH_END
|
||||||
|
int x = touch_unpack_x(drv->last_event);
|
||||||
|
int y = touch_unpack_y(drv->last_event);
|
||||||
|
drv->last_event = TOUCH_END | touch_pack_xy(x, y);
|
||||||
|
}
|
||||||
|
drv->state = MOUSE_DOWN_OUTSIDE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_button_events(touch_driver_t* driver, SDL_Event event,
|
static void handle_button_events(touch_driver_t* drv, SDL_Event* event) {
|
||||||
int* ev_type, int* ev_x, int* ev_y) {
|
|
||||||
// Handle arrow buttons to trigger a scroll movement by set length in the
|
// Handle arrow buttons to trigger a scroll movement by set length in the
|
||||||
// direction of the button
|
// direction of the button
|
||||||
if (event.type == SDL_KEYDOWN && !event.key.repeat &&
|
if (event->type == SDL_KEYDOWN && !event->key.repeat) {
|
||||||
!is_button_swipe_initiated(driver)) {
|
if (drv->state != BUTTON_SWIPE_INITIATED) {
|
||||||
switch (event.key.keysym.sym) {
|
switch (event->key.keysym.sym) {
|
||||||
case SDLK_LEFT:
|
case SDLK_LEFT:
|
||||||
*ev_x = _btn_swipe_begin;
|
drv->swipe_start_x = _btn_swipe_begin;
|
||||||
*ev_y = sdl_display_res_y / 2;
|
drv->swipe_start_y = sdl_display_res_y / 2;
|
||||||
*ev_type = TOUCH_START;
|
drv->swipe_end_x = drv->swipe_start_x + _btn_swipe_length;
|
||||||
driver->state = BUTTON_SWIPE_LEFT_INITIATED;
|
drv->swipe_end_y = drv->swipe_start_y;
|
||||||
|
drv->state = BUTTON_SWIPE_INITIATED;
|
||||||
break;
|
break;
|
||||||
case SDLK_RIGHT:
|
case SDLK_RIGHT:
|
||||||
*ev_x = sdl_display_res_x - _btn_swipe_begin;
|
drv->swipe_start_x = sdl_display_res_x - _btn_swipe_begin;
|
||||||
*ev_y = sdl_display_res_y / 2;
|
drv->swipe_start_y = sdl_display_res_y / 2;
|
||||||
*ev_type = TOUCH_START;
|
drv->swipe_end_x = drv->swipe_start_x - _btn_swipe_length;
|
||||||
driver->state = BUTTON_SWIPE_RIGHT_INITIATED;
|
drv->swipe_end_y = drv->swipe_start_y;
|
||||||
|
drv->state = BUTTON_SWIPE_INITIATED;
|
||||||
break;
|
break;
|
||||||
case SDLK_UP:
|
case SDLK_UP:
|
||||||
*ev_x = sdl_display_res_x / 2;
|
drv->swipe_start_x = sdl_display_res_x / 2;
|
||||||
*ev_y = _btn_swipe_begin;
|
drv->swipe_start_y = _btn_swipe_begin;
|
||||||
*ev_type = TOUCH_START;
|
drv->swipe_end_x = drv->swipe_start_x;
|
||||||
driver->state = BUTTON_SWIPE_UP_INITIATED;
|
drv->swipe_end_y = drv->swipe_start_y + _btn_swipe_length;
|
||||||
|
drv->state = BUTTON_SWIPE_INITIATED;
|
||||||
break;
|
break;
|
||||||
case SDLK_DOWN:
|
case SDLK_DOWN:
|
||||||
*ev_x = sdl_display_res_x / 2;
|
drv->swipe_start_x = sdl_display_res_x / 2;
|
||||||
*ev_y = sdl_display_res_y - _btn_swipe_begin;
|
drv->swipe_start_y = sdl_display_res_y - _btn_swipe_begin;
|
||||||
*ev_type = TOUCH_START;
|
drv->swipe_end_x = drv->swipe_start_x;
|
||||||
driver->state = BUTTON_SWIPE_DOWN_INITIATED;
|
drv->swipe_end_y = drv->swipe_start_y - _btn_swipe_length;
|
||||||
|
drv->state = BUTTON_SWIPE_INITIATED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (event.type == SDL_KEYUP && driver->state != IDLE) {
|
|
||||||
switch (event.key.keysym.sym) {
|
if (drv->state == BUTTON_SWIPE_INITIATED) {
|
||||||
case SDLK_LEFT:
|
drv->swipe_key = event->key.keysym.sym;
|
||||||
if (driver->state == BUTTON_SWIPE_LEFT_INITIATED) {
|
drv->swipe_time = systick_ms();
|
||||||
*ev_x = _btn_swipe_begin + _btn_swipe_length;
|
drv->last_event =
|
||||||
*ev_y = sdl_display_res_y / 2;
|
TOUCH_START | touch_pack_xy(drv->swipe_start_x, drv->swipe_start_y);
|
||||||
*ev_type = TOUCH_MOVE;
|
|
||||||
driver->state = BUTTON_SWIPE_COMPLETED;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case SDLK_RIGHT:
|
|
||||||
if (driver->state == BUTTON_SWIPE_RIGHT_INITIATED) {
|
|
||||||
*ev_x = sdl_display_res_x - _btn_swipe_begin - _btn_swipe_length;
|
|
||||||
*ev_y = sdl_display_res_y / 2;
|
|
||||||
*ev_type = TOUCH_MOVE;
|
|
||||||
driver->state = BUTTON_SWIPE_COMPLETED;
|
|
||||||
}
|
}
|
||||||
break;
|
} else if (event->type == SDL_KEYUP &&
|
||||||
case SDLK_UP:
|
event->key.keysym.sym == drv->swipe_key) {
|
||||||
if (driver->state == BUTTON_SWIPE_UP_INITIATED) {
|
if (drv->state == BUTTON_SWIPE_INITIATED) {
|
||||||
*ev_x = sdl_display_res_x / 2;
|
drv->last_event =
|
||||||
*ev_y = _btn_swipe_begin + _btn_swipe_length;
|
TOUCH_END | touch_pack_xy(drv->swipe_end_x, drv->swipe_end_y);
|
||||||
*ev_type = TOUCH_MOVE;
|
drv->state = IDLE;
|
||||||
driver->state = BUTTON_SWIPE_COMPLETED;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case SDLK_DOWN:
|
|
||||||
if (driver->state == BUTTON_SWIPE_DOWN_INITIATED) {
|
|
||||||
*ev_x = sdl_display_res_x / 2;
|
|
||||||
*ev_y = sdl_display_res_y - _btn_swipe_begin - _btn_swipe_length;
|
|
||||||
*ev_type = TOUCH_MOVE;
|
|
||||||
driver->state = BUTTON_SWIPE_COMPLETED;
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
// Called from global event loop to filter and process SDL events
|
||||||
|
static void touch_sdl_event_filter(void* context, SDL_Event* sdl_event) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
|
||||||
|
if (drv->state == IDLE || drv->state == MOUSE_DOWN_INSIDE ||
|
||||||
|
drv->state == MOUSE_DOWN_OUTSIDE) {
|
||||||
|
handle_mouse_events(drv, sdl_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drv->state == IDLE || drv->state == BUTTON_SWIPE_INITIATED) {
|
||||||
|
handle_button_events(drv, sdl_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool touch_init(void) {
|
secbool touch_init(void) {
|
||||||
touch_driver_t* driver = &g_touch_driver;
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
if (driver->initialized != sectrue) {
|
if (drv->initialized) {
|
||||||
memset(driver, 0, sizeof(touch_driver_t));
|
return sectrue;
|
||||||
driver->state = IDLE;
|
|
||||||
driver->initialized = sectrue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return driver->initialized;
|
memset(drv, 0, sizeof(touch_driver_t));
|
||||||
|
drv->state = IDLE;
|
||||||
|
|
||||||
|
if (!syshandle_register(SYSHANDLE_TOUCH, &g_touch_handle_vmt, drv)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sdl_events_register(touch_sdl_event_filter, drv)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv->initialized = sectrue;
|
||||||
|
return drv->initialized;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return secfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
void touch_deinit(void) {
|
void touch_deinit(void) {
|
||||||
touch_driver_t* driver = &g_touch_driver;
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
|
|
||||||
if (driver->initialized == sectrue) {
|
if (drv->initialized == sectrue) {
|
||||||
memset(driver, 0, sizeof(touch_driver_t));
|
syshandle_unregister(SYSHANDLE_TOUCH);
|
||||||
|
memset(drv, 0, sizeof(touch_driver_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,8 +238,8 @@ void touch_power_set(bool on) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
secbool touch_ready(void) {
|
secbool touch_ready(void) {
|
||||||
touch_driver_t* driver = &g_touch_driver;
|
touch_driver_t* drv = &g_touch_driver;
|
||||||
return driver->initialized;
|
return drv->initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
secbool touch_set_sensitivity(uint8_t value) {
|
secbool touch_set_sensitivity(uint8_t value) {
|
||||||
@ -241,37 +260,74 @@ secbool touch_activity(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t touch_get_state(touch_driver_t* drv) {
|
||||||
|
sdl_events_poll();
|
||||||
|
|
||||||
|
if (drv->state == BUTTON_SWIPE_INITIATED) {
|
||||||
|
if (drv->last_event & TOUCH_START) {
|
||||||
|
// Emulate swipe by sending MOVE event after 100ms
|
||||||
|
uint32_t time_delta = systick_ms() - drv->swipe_time;
|
||||||
|
if (time_delta > 100) {
|
||||||
|
int x = (drv->swipe_start_x + drv->swipe_end_x) / 2;
|
||||||
|
int y = (drv->swipe_start_y + drv->swipe_end_y) / 2;
|
||||||
|
drv->last_event = TOUCH_MOVE | touch_pack_xy(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return drv->last_event;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t touch_get_event(void) {
|
uint32_t touch_get_event(void) {
|
||||||
touch_driver_t* driver = &g_touch_driver;
|
touch_driver_t* driver = &g_touch_driver;
|
||||||
|
|
||||||
if (driver->initialized != sectrue) {
|
if (sectrue != driver->initialized) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (driver->state == BUTTON_SWIPE_COMPLETED) {
|
touch_fsm_t* fsm = &driver->tls[systask_id(systask_active())];
|
||||||
driver->state = IDLE;
|
|
||||||
return TOUCH_END | touch_pack_xy(driver->last_x, driver->last_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Event event;
|
uint32_t touch_state = touch_get_state(driver);
|
||||||
|
|
||||||
int ev_x = 0;
|
uint32_t event = touch_fsm_get_event(fsm, touch_state);
|
||||||
int ev_y = 0;
|
|
||||||
int ev_type = 0;
|
|
||||||
|
|
||||||
while (SDL_PollEvent(&event) > 0) {
|
return event;
|
||||||
if (driver->state == IDLE || driver->state == MOUSE_DOWN_INSIDE ||
|
|
||||||
driver->state == MOUSE_DOWN_OUTSIDE) {
|
|
||||||
handle_mouse_events(driver, event, &ev_type, &ev_x, &ev_y);
|
|
||||||
}
|
|
||||||
if (driver->state == IDLE || is_button_swipe_initiated(driver)) {
|
|
||||||
handle_button_events(driver, event, &ev_type, &ev_x, &ev_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev_type != 0) {
|
|
||||||
driver->last_x = ev_x;
|
|
||||||
driver->last_y = ev_y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ev_type | touch_pack_xy(ev_x, ev_y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_task_created(void* context, systask_id_t task_id) {
|
||||||
|
touch_driver_t* dr = (touch_driver_t*)context;
|
||||||
|
touch_fsm_t* fsm = &dr->tls[task_id];
|
||||||
|
touch_fsm_init(fsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_event_poll(void* context, bool read_awaited,
|
||||||
|
bool write_awaited) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
|
||||||
|
UNUSED(write_awaited);
|
||||||
|
|
||||||
|
if (read_awaited) {
|
||||||
|
uint32_t touch_state = touch_get_state(drv);
|
||||||
|
if (touch_state != 0) {
|
||||||
|
syshandle_signal_read_ready(SYSHANDLE_TOUCH, &touch_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool on_check_read_ready(void* context, systask_id_t task_id,
|
||||||
|
void* param) {
|
||||||
|
touch_driver_t* drv = (touch_driver_t*)context;
|
||||||
|
touch_fsm_t* fsm = &drv->tls[task_id];
|
||||||
|
|
||||||
|
uint32_t touch_state = *(uint32_t*)param;
|
||||||
|
|
||||||
|
return touch_fsm_event_ready(fsm, touch_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const syshandle_vmt_t g_touch_handle_vmt = {
|
||||||
|
.task_created = on_task_created,
|
||||||
|
.task_killed = NULL,
|
||||||
|
.check_read_ready = on_check_read_ready,
|
||||||
|
.check_write_ready = NULL,
|
||||||
|
.poll = on_event_poll,
|
||||||
|
};
|
||||||
|
@ -72,6 +72,8 @@ def configure(
|
|||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/i2c_bus/stm32f4/i2c_bus.c"]
|
sources += ["embed/io/i2c_bus/stm32f4/i2c_bus.c"]
|
||||||
sources += ["embed/io/touch/stmpe811/stmpe811.c"]
|
sources += ["embed/io/touch/stmpe811/stmpe811.c"]
|
||||||
|
sources += ["embed/io/touch/stmpe811/touch.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/i2c_bus/inc"]
|
paths += ["embed/io/i2c_bus/inc"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
|
@ -55,7 +55,9 @@ def configure(
|
|||||||
|
|
||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/i2c_bus/stm32u5/i2c_bus.c"]
|
sources += ["embed/io/i2c_bus/stm32u5/i2c_bus.c"]
|
||||||
|
sources += ["embed/io/touch/sitronix/touch.c"]
|
||||||
sources += ["embed/io/touch/sitronix/sitronix.c"]
|
sources += ["embed/io/touch/sitronix/sitronix.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/i2c_bus/inc"]
|
paths += ["embed/io/i2c_bus/inc"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
|
@ -52,6 +52,7 @@ def configure(
|
|||||||
|
|
||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/touch/unix/touch.c"]
|
sources += ["embed/io/touch/unix/touch.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
defines += [("USE_TOUCH", "1")]
|
defines += [("USE_TOUCH", "1")]
|
||||||
|
@ -63,6 +63,7 @@ def configure(
|
|||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/i2c_bus/stm32f4/i2c_bus.c"]
|
sources += ["embed/io/i2c_bus/stm32f4/i2c_bus.c"]
|
||||||
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/i2c_bus/inc"]
|
paths += ["embed/io/i2c_bus/inc"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
|
@ -62,6 +62,7 @@ def configure(
|
|||||||
|
|
||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/touch/unix/touch.c"]
|
sources += ["embed/io/touch/unix/touch.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
defines += [("USE_TOUCH", "1")]
|
defines += [("USE_TOUCH", "1")]
|
||||||
|
@ -66,6 +66,7 @@ def configure(
|
|||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/i2c_bus/stm32u5/i2c_bus.c"]
|
sources += ["embed/io/i2c_bus/stm32u5/i2c_bus.c"]
|
||||||
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
sources += ["embed/io/touch/ft6x36/panels/lx154a2422cpt23.c"]
|
sources += ["embed/io/touch/ft6x36/panels/lx154a2422cpt23.c"]
|
||||||
paths += ["embed/io/i2c_bus/inc"]
|
paths += ["embed/io/i2c_bus/inc"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
|
@ -81,6 +81,7 @@ def configure(
|
|||||||
|
|
||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/touch/unix/touch.c"]
|
sources += ["embed/io/touch/unix/touch.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
defines += [("USE_TOUCH", "1")]
|
defines += [("USE_TOUCH", "1")]
|
||||||
|
@ -60,6 +60,7 @@ def configure(
|
|||||||
|
|
||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
sources += ["embed/io/button/stm32/button.c"]
|
sources += ["embed/io/button/stm32/button.c"]
|
||||||
|
@ -60,6 +60,7 @@ def configure(
|
|||||||
|
|
||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
sources += ["embed/io/button/stm32/button.c"]
|
sources += ["embed/io/button/stm32/button.c"]
|
||||||
|
@ -60,6 +60,7 @@ def configure(
|
|||||||
|
|
||||||
if "input" in features_wanted:
|
if "input" in features_wanted:
|
||||||
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
sources += ["embed/io/touch/ft6x36/ft6x36.c"]
|
||||||
|
sources += ["embed/io/touch/touch_fsm.c"]
|
||||||
paths += ["embed/io/touch/inc"]
|
paths += ["embed/io/touch/inc"]
|
||||||
features_available.append("touch")
|
features_available.append("touch")
|
||||||
sources += ["embed/io/button/stm32/button.c"]
|
sources += ["embed/io/button/stm32/button.c"]
|
||||||
|
Loading…
Reference in New Issue
Block a user