EVGUI 触控简单处理笔记
这是我的硕士论文笔记系列第四篇,原文写于 2016 年六月。
Touchscreen driver
- STM32F429 Discovery 板載 STMPE811 觸屏控制器
- ST 官方提供了驅動程式
stm32f429i_discovery_ioe
1 | typedef struct { |
在 uGUI 的範例中,使用方法如下:
定義一個結構體:
static TP_STATE* TP_State
;初始化觸控晶片:
IOE_Config()
;在 SysTick 的 ISR 程式中:
1
2
3
4
5
6
7
8
9
10
11
12TP_State = IOE_TP_GetState();
if (TP_State->TouchDetected) {
if ((TP_State->X > 0) && (TP_State->X < 239 ))
{
if ((TP_State->Y > 0) && (TP_State->Y < 319 ))
{
UG_TouchUpdate(TP_State->X,TP_State->Y,TOUCH_STATE_PRESSED);
}
}
} else {
UG_TouchUpdate(-1,-1,TOUCH_STATE_RELEASED);
}
TWIN
在 EVGUI 中去掉了 TWIN 中的 cursor.c 和 file.c 兩個文件,第一個是因爲觸控屏不再需要指標,第二個則是我們需要實作的部分,把 X11 的滑鼠換成觸控屏的輸入
TWIN 中事件類型的定義:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef enum _twin_event_kind {
/* Mouse */
TwinEventButtonDown = 0x0001,
TwinEventButtonUp = 0x0002,
TwinEventMotion = 0x0003,
TwinEventEnter = 0x0004,
TwinEventLeave = 0x0005,
/* keyboard */
TwinEventKeyDown = 0x0101,
TwinEventKeyUp = 0x0102,
TwinEventUcs4 = 0x0103,
/* Focus */
TwinEventActivate = 0x0201,
TwinEventDeactivate = 0x0202,
/* Joystick */
TwinEventJoyButton = 0x0401,
TwinEventJoyAxis = 0x0402,
/* Widgets */
TwinEventPaint = 0x1001,
TwinEventQueryGeometry = 0x1002,
TwinEventConfigure = 0x1003,
TwinEventDestroy = 0x1004,
} twin_event_kind_t;TWIN 中事件的定義:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
typedef struct _twin_event {
twin_event_kind_t kind;
union {
struct {
twin_coord_t x, y;
twin_coord_t screen_x, screen_y;
twin_count_t button;
} pointer;
struct {
twin_keysym_t key;
} key;
struct {
twin_js_number_t control;
twin_js_value_t value;
} js;
struct {
twin_ucs4_t ucs4;
} ucs4;
struct {
twin_rect_t extents;
} configure;
} u;
} twin_event_t;
添加觸控功能
開啓事件處理的函式注冊
- 要在 fbdev 的 twin_fbdev_create_ext() 加入 handle_events 這個標志(值爲 1)
1 | if (handle_events) { |
實作事件讀取函式
- File:
backend/system.c
- 關於輸入來源:
- X11 通過 Xlib 的 XNextEvent() 獲取
- Framebuffer 實作了一個 linux_mouse 模塊,讀取 “/dev/input/mice” 的資料
- 關於 mice 設備的讀取可以參考這裡
- 下一節有說明,我們實作一個單向鏈表作爲輸入
處理 Raw Data
File:
backend/system.c
回顧,在
SysTick_Handler
中:TP_State = IOE_TP_GetState();
TP_State
中有TouchDetected
X
Y
Z
四個成員- 判斷
TouchDetected
是否爲真且X
Y
在合法範圍內
構建
twin_event_t
參照 X11,因爲原生 TWIN 的 framebuffer 模式下 input 本身就有問題,且實作了一個fb
的事件讀取和一個滑鼠的事件讀取,這兩個放在一起更合理由於存在
screen->clicklock
(在twin_screen.c
中,會判斷screen->clicklock
和event→kind != TwinEventButtonUp
同時爲真才進行追蹤),暫時先不實作TwinEventMotion
這個類別- 因爲手指移動時一定是
ButtonDown
的類別也滿足上述判斷式 - 這樣可能導致的後果是:採用相對坐標,手指下次從其他地方滑動時,坐標還是之前的位置,出現很大的便宜
- 因爲手指移動時一定是
實作
TwinEventMotion
類別- 設定一個是否按住的標志(初始值爲 1)爲
FirstTouch
- 每次
TouchDetected
爲真時判斷FirstTouch
的值- 若
FirstTouch
爲真則把這次動作的類別記爲TwinEventMotion
,然後再補一個TwinEventButtonDown
的節點,最後將FirstTouch
置爲 0 - 若
FirstTouch
爲假則只單純添加TwinEventButtonDown
的節點
- 若
- 若
TouchDetected
爲假時則把FirstTouch
置爲 1
- 設定一個是否按住的標志(初始值爲 1)爲
輸入節點爲一個單向鏈表,有兩個 global 節點爲
TP_Head
和TP_Latest
:1
2
3
4typedef struct _FB_event {
struct _FBEvent *Next;
twin_event_t event;
} FB_event;
問題
-
藍屏 → 無法正常載入圖形- GDB 調試發現在 SysTick Hadnler 重復呼叫幾次,就直接會跳到通用異常處理的 ISR 裏
- 這樣很容易猜測是 SySTick 中斷頻率太高,一次裏面的事情還沒做完,下一次就發生了,所以掛掉
- 通過
SysTick_Config()
把中斷頻率由原來的 1000Hz 改爲 100Hz,果然就好了
-
時鍾不走,觸屏沒反應timeout_delay()
函式有問題
- 自己寫一個簡單的時間調度處理