drv_mouse.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020/12/31 Bernard Add license info
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include "board.h"
  14. #include "interrupt.h"
  15. #include "drv_mouse.h"
  16. #include "drv_clcd.h"
  17. #define DBG_TAG "drv.mouse"
  18. #define DBG_LVL DBG_INFO
  19. #include "rtdbg.h"
  20. #ifdef BSP_DRV_MOUSE
  21. #define MOUSE_ADDRESS (0x10007000)
  22. #define MOUSE_IRQ_NUM (IRQ_VEXPRESS_A9_MOUSE)
  23. #define MOUSE_XMAX (BSP_LCD_WIDTH)
  24. #define MOUSE_YMAX (BSP_LCD_HEIGHT)
  25. #define MOUSE_BUTTON_LEFT (0x01)
  26. #define MOUSE_BUTTON_RIGHT (0x02)
  27. #define MOUSE_BUTTON_MIDDLE (0x04)
  28. #define MOUSE_BUTTON_DOWN (0x10)
  29. #define MOUSE_BUTTON_UP (0x20)
  30. #define MOUSE_BUTTON_MOVE (0x40)
  31. #define MOUSE_BUTTON_WHELL (0x80)
  32. #ifdef PKG_USING_GUIENGINE
  33. #include <rtgui/event.h>
  34. #include <rtgui/rtgui_server.h>
  35. static rt_uint32_t emouse_id;
  36. #elif defined(PKG_USING_LITTLEVGL2RTT)
  37. #include <littlevgl2rtt.h>
  38. #elif defined(PKG_USING_LVGL)
  39. #include <lvgl.h>
  40. extern void lv_port_indev_input(rt_int16_t x, rt_int16_t y, lv_indev_state_t state);
  41. static rt_bool_t touch_down = RT_FALSE;
  42. #endif /* PKG_USING_GUIENGINE */
  43. typedef rt_uint32_t virtual_addr_t;
  44. enum {
  45. MOUSE_CR = 0x00,
  46. MOUSE_STAT = 0x04,
  47. MOUSE_DATA = 0x08,
  48. MOUSE_CLKDIV = 0x0c,
  49. MOUSE_IIR = 0x10,
  50. };
  51. struct mouse_pl050_pdata_t {
  52. virtual_addr_t virt;
  53. int irq;
  54. int xmax, ymax;
  55. int xpos, ypos;
  56. unsigned char packet[4];
  57. int index;
  58. int obtn;
  59. int type;
  60. };
  61. rt_inline rt_uint8_t read8(uint32_t addr)
  62. {
  63. return (*((volatile rt_uint8_t *)(addr)));
  64. }
  65. rt_inline void write8(uint32_t addr, rt_uint8_t value)
  66. {
  67. *((volatile rt_uint8_t *)(addr)) = value;
  68. }
  69. rt_inline rt_uint32_t read32(uint32_t addr)
  70. {
  71. return (*((volatile rt_uint32_t *)(addr)));
  72. }
  73. rt_inline void write32(uint32_t addr, rt_uint32_t value)
  74. {
  75. *((volatile rt_uint32_t *)(addr)) = value;
  76. }
  77. rt_inline int kmi_write(struct mouse_pl050_pdata_t * pdat, rt_uint8_t value)
  78. {
  79. int timeout = 1000;
  80. while((read8(pdat->virt + MOUSE_STAT) & (1 << 6)) == 0 && timeout--);
  81. if(timeout)
  82. {
  83. write8(pdat->virt + MOUSE_DATA, value);
  84. while((read8(pdat->virt + MOUSE_STAT) & (1 << 4)) == 0);
  85. if(read8(pdat->virt + MOUSE_DATA) == 0xfa)
  86. return RT_TRUE;
  87. }
  88. return RT_FALSE;
  89. }
  90. rt_inline int kmi_read(struct mouse_pl050_pdata_t * pdat, rt_uint8_t * value)
  91. {
  92. if((read8(pdat->virt + MOUSE_STAT) & (1 << 4)))
  93. {
  94. *value = read8(pdat->virt + MOUSE_DATA);
  95. return RT_TRUE;
  96. }
  97. return RT_FALSE;
  98. }
  99. void push_event_touch_move(int x, int y)
  100. {
  101. #ifdef PKG_USING_GUIENGINE
  102. struct rtgui_event_mouse emouse;
  103. emouse.parent.sender = RT_NULL;
  104. emouse.wid = RT_NULL;
  105. emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
  106. emouse.parent.type = RTGUI_EVENT_MOUSE_MOTION;
  107. emouse.x = x;
  108. emouse.y = y;
  109. emouse.ts = rt_tick_get();
  110. emouse.id = emouse_id;
  111. LOG_D("[line]:%d motion event id:%d x:%d y:%d", __LINE__, emouse.id, x, y);
  112. rtgui_server_post_event(&emouse.parent, sizeof(emouse));
  113. #elif defined(PKG_USING_LITTLEVGL2RTT)
  114. littlevgl2rtt_send_input_event(x, y, LITTLEVGL2RTT_INPUT_MOVE);
  115. #elif defined(PKG_USING_LVGL)
  116. lv_port_indev_input(x, y, (touch_down == RT_TRUE) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
  117. #endif
  118. }
  119. void push_event_touch_begin(int x, int y)
  120. {
  121. #ifdef PKG_USING_GUIENGINE
  122. struct rtgui_event_mouse emouse;
  123. emouse_id = rt_tick_get();
  124. emouse.parent.sender = RT_NULL;
  125. emouse.wid = RT_NULL;
  126. emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
  127. emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
  128. emouse.x = x;
  129. emouse.y = y;
  130. emouse.ts = rt_tick_get();
  131. emouse.id = emouse_id;
  132. LOG_D("[line]:%d down event id:%d x:%d y:%d", __LINE__, emouse.id, x, y);
  133. rtgui_server_post_event(&emouse.parent, sizeof(emouse));
  134. #elif defined(PKG_USING_LITTLEVGL2RTT)
  135. littlevgl2rtt_send_input_event(x, y, LITTLEVGL2RTT_INPUT_DOWN);
  136. #elif defined(PKG_USING_LVGL)
  137. touch_down = RT_TRUE;
  138. lv_port_indev_input(x, y, (touch_down == RT_TRUE) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
  139. #endif
  140. }
  141. void push_event_touch_end(int x, int y)
  142. {
  143. #ifdef PKG_USING_GUIENGINE
  144. struct rtgui_event_mouse emouse;
  145. emouse.parent.sender = RT_NULL;
  146. emouse.wid = RT_NULL;
  147. emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
  148. emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP;
  149. emouse.x = x;
  150. emouse.y = y;
  151. emouse.ts = rt_tick_get();
  152. emouse.id = emouse_id;
  153. LOG_D("[line]:%d up event id:%d x:%d y:%d", __LINE__, emouse.id, x, y);
  154. rtgui_server_post_event(&emouse.parent, sizeof(emouse));
  155. #elif defined(PKG_USING_LITTLEVGL2RTT)
  156. littlevgl2rtt_send_input_event(x, y, LITTLEVGL2RTT_INPUT_MOVE);
  157. #elif defined(PKG_USING_LVGL)
  158. touch_down = RT_FALSE;
  159. lv_port_indev_input(x, y, (touch_down == RT_TRUE) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
  160. #endif
  161. }
  162. static void mouse_pl050_interrupt(int irq, void * data)
  163. {
  164. struct mouse_pl050_pdata_t * pdat = (struct mouse_pl050_pdata_t *)data;
  165. int x, y, relx, rely, delta;
  166. int btndown, btnup, btn;
  167. int status = 0;
  168. status = read8(pdat->virt + MOUSE_IIR);
  169. while(status & (1 << 0))
  170. {
  171. pdat->packet[pdat->index] = read8(pdat->virt + MOUSE_DATA);
  172. pdat->index = (pdat->index + 1) & 0x3;
  173. if(pdat->index == 0)
  174. {
  175. btn = pdat->packet[0] & 0x7;
  176. btndown = (btn ^ pdat->obtn) & btn;
  177. btnup = (btn ^ pdat->obtn) & pdat->obtn;
  178. pdat->obtn = btn;
  179. if(pdat->packet[0] & 0x10)
  180. relx = 0xffffff00 | pdat->packet[1];
  181. else
  182. relx = pdat->packet[1];
  183. if(pdat->packet[0] & 0x20)
  184. rely = 0xffffff00 | pdat->packet[2];
  185. else
  186. rely = pdat->packet[2];
  187. rely = -rely;
  188. delta = pdat->packet[3] & 0xf;
  189. if(delta == 0xf)
  190. delta = -1;
  191. if(relx != 0)
  192. {
  193. pdat->xpos = pdat->xpos + relx;
  194. if(pdat->xpos < 0)
  195. pdat->xpos = 0;
  196. if(pdat->xpos > pdat->xmax - 1)
  197. pdat->xpos = pdat->xmax - 1;
  198. }
  199. if(rely != 0)
  200. {
  201. pdat->ypos = pdat->ypos + rely;
  202. if(pdat->ypos < 0)
  203. pdat->ypos = 0;
  204. if(pdat->ypos > pdat->ymax - 1)
  205. pdat->ypos = pdat->ymax - 1;
  206. }
  207. x = pdat->xpos;
  208. y = pdat->ypos;
  209. if((btn & (0x01 << 0)) && ((relx != 0) || (rely != 0)))
  210. push_event_touch_move(x, y);
  211. if(btndown & (0x01 << 0))
  212. push_event_touch_begin(x, y);
  213. if(btnup & (0x01 << 0))
  214. push_event_touch_end(x, y);
  215. }
  216. status = read8(pdat->virt + MOUSE_IIR);
  217. }
  218. }
  219. int rt_hw_mouse_init(void)
  220. {
  221. rt_uint8_t value;
  222. rt_uint32_t id;
  223. struct mouse_pl050_pdata_t *pdat;
  224. virtual_addr_t virt = MOUSE_ADDRESS;
  225. int irq = MOUSE_IRQ_NUM;
  226. #ifdef RT_USING_SMART
  227. virt = (virtual_addr_t)rt_ioremap((void*)MOUSE_ADDRESS, 0x1000);
  228. #endif
  229. id = (((read32(virt + 0xfec) & 0xff) << 24) |
  230. ((read32(virt + 0xfe8) & 0xff) << 16) |
  231. ((read32(virt + 0xfe4) & 0xff) << 8) |
  232. ((read32(virt + 0xfe0) & 0xff) << 0));
  233. if(((id >> 12) & 0xff) != 0x41 || (id & 0xfff) != 0x050)
  234. {
  235. LOG_E("read id fail id:0x%08x", id);
  236. return -RT_ERROR;
  237. }
  238. pdat = rt_malloc(sizeof(struct mouse_pl050_pdata_t));
  239. if(!pdat)
  240. {
  241. LOG_E("malloc memory failed");
  242. return -RT_ERROR;
  243. }
  244. rt_memset(pdat, 0, sizeof(struct mouse_pl050_pdata_t));
  245. pdat->virt = virt;
  246. pdat->irq = irq;
  247. pdat->xmax = MOUSE_XMAX;
  248. pdat->ymax = MOUSE_YMAX;
  249. pdat->xpos = pdat->xmax / 2;
  250. pdat->ypos = pdat->ymax / 2;
  251. pdat->packet[0] = 0;
  252. pdat->packet[1] = 0;
  253. pdat->packet[2] = 0;
  254. pdat->packet[3] = 0;
  255. pdat->index = 0;
  256. pdat->obtn = 0;
  257. write8(pdat->virt + MOUSE_CLKDIV, 0);
  258. write8(pdat->virt + MOUSE_CR, (1 << 2));
  259. kmi_write(pdat, 0xff);
  260. kmi_read(pdat, &value);
  261. kmi_write(pdat, 0xf3);
  262. kmi_write(pdat, 200);
  263. kmi_write(pdat, 0xf3);
  264. kmi_write(pdat, 100);
  265. kmi_write(pdat, 0xf3);
  266. kmi_write(pdat, 80);
  267. kmi_write(pdat, 0xf2);
  268. kmi_read(pdat, &value);
  269. kmi_read(pdat, &value);
  270. kmi_write(pdat, 0xf3);
  271. kmi_write(pdat, 100);
  272. kmi_write(pdat, 0xe8);
  273. kmi_write(pdat, 0x02);
  274. kmi_write(pdat, 0xe6);
  275. kmi_write(pdat, 0xf4);
  276. kmi_read(pdat, &value);
  277. kmi_read(pdat, &value);
  278. kmi_read(pdat, &value);
  279. kmi_read(pdat, &value);
  280. write8(pdat->virt + MOUSE_CR, (1 << 2) | (1 << 4));
  281. rt_hw_interrupt_install(pdat->irq, mouse_pl050_interrupt, (void *)pdat, "mouse");
  282. rt_hw_interrupt_umask(pdat->irq);
  283. return RT_EOK;
  284. }
  285. INIT_DEVICE_EXPORT(rt_hw_mouse_init);
  286. #endif