ps2.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * Copyright (c) 2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-08-26 sogwms The first version
  9. */
  10. #include "ps2.h"
  11. #include "ps2_table.h"
  12. #define DBG_SECTION_NAME "ps2"
  13. #define DBG_LEVEL DBG_LOG
  14. #include <rtdbg.h>
  15. #define THREAD_DELAY_TIME 30
  16. #define THREAD_PRIORITY ((RT_THREAD_PRIORITY_MAX / 3) + 3)
  17. #define THREAD_STACK_SIZE 1024
  18. #define THREAD_TIMESLICE 10
  19. #define KEEP_TIME() _delay_us(16);
  20. static uint8_t light_mode = PS2_NO_MODE;
  21. static rt_thread_t tid_ps2 = RT_NULL;
  22. static struct ps2_table table[PS2_TABLE_SIZE] = PS2_DEFAULT_TABLE;
  23. static rt_base_t ps2_cs_pin;
  24. static rt_base_t ps2_clk_pin;
  25. static rt_base_t ps2_do_pin;
  26. static rt_base_t ps2_di_pin;
  27. static void hal_cs_high(void)
  28. {
  29. rt_pin_write(ps2_cs_pin, PIN_HIGH);
  30. }
  31. static void hal_cs_low(void)
  32. {
  33. rt_pin_write(ps2_cs_pin, PIN_LOW);
  34. }
  35. static void hal_clk_high(void)
  36. {
  37. rt_pin_write(ps2_clk_pin, PIN_HIGH);
  38. }
  39. static void hal_clk_low(void)
  40. {
  41. rt_pin_write(ps2_clk_pin, PIN_LOW);
  42. }
  43. static void hal_do_high(void)
  44. {
  45. rt_pin_write(ps2_do_pin, PIN_HIGH);
  46. }
  47. static void hal_do_low(void)
  48. {
  49. rt_pin_write(ps2_do_pin, PIN_LOW);
  50. }
  51. static int hal_read_di(void)
  52. {
  53. return rt_pin_read(ps2_di_pin);
  54. }
  55. static void _delay_us(uint16_t us)
  56. {
  57. for (int i = 0; i < us; i++)
  58. {
  59. for (int j = 0; j < 0x1F;)
  60. j++;
  61. }
  62. }
  63. static uint8_t _transfer(uint8_t data)
  64. {
  65. uint8_t temp = 0;
  66. for (uint16_t i = 0x01; i < 0x0100; i <<= 1)
  67. {
  68. if (i & data)
  69. hal_do_high();
  70. else
  71. hal_do_low();
  72. hal_clk_high();
  73. KEEP_TIME();
  74. hal_clk_low();
  75. if (hal_read_di())
  76. temp = i | temp;
  77. KEEP_TIME();
  78. hal_clk_high();
  79. }
  80. return temp;
  81. }
  82. static void transfer(const uint8_t *pb_send, uint8_t *pb_recv, uint8_t len)
  83. {
  84. hal_cs_low();
  85. _delay_us(16);
  86. for (uint8_t i = 0; i < len; i++)
  87. {
  88. pb_recv[i] = _transfer(pb_send[i]);
  89. }
  90. hal_cs_high();
  91. _delay_us(16);
  92. }
  93. int ps2_scan(ps2_ctrl_data_t pt)
  94. {
  95. uint8_t temp[9] = {0};
  96. temp[0] = 0x01;
  97. temp[1] = 0x42;
  98. temp[3] = 0;
  99. temp[4] = 0;
  100. transfer(temp, temp, 9);
  101. pt->button = temp[3] | (temp[4] << 8);
  102. pt->right_stick_x = temp[5];
  103. pt->right_stick_y = temp[6];
  104. pt->left_stick_x = temp[7];
  105. pt->left_stick_y = temp[8];
  106. if (temp[2] == 0x5A)
  107. {
  108. light_mode = temp[1];
  109. return 1;
  110. }
  111. else
  112. {
  113. light_mode = PS2_NO_MODE;
  114. }
  115. return 0;
  116. }
  117. /**
  118. * @return PS2_GREEN_MDOE or PS2_RED_MDOE or other(no connect)
  119. */
  120. int ps2_read_light(void)
  121. {
  122. return light_mode;
  123. }
  124. static rt_err_t ps2_sender_send(rt_uint16_t cmd, void *param, rt_uint16_t size)
  125. {
  126. // TODO
  127. if (cmd == COMMAND_RC_VIBRATE)
  128. {
  129. }
  130. else
  131. {
  132. return RT_ERROR;
  133. }
  134. return RT_EOK;
  135. }
  136. static struct command_sender ps2_sender = {
  137. .name = "ano",
  138. .send = ps2_sender_send
  139. };
  140. command_sender_t ps2_get_sender(void)
  141. {
  142. return &ps2_sender;
  143. }
  144. static void ps2_thread_entry(void *param)
  145. {
  146. struct ps2_ctrl_data ctrl_data;
  147. struct cmd_velocity target_velocity;
  148. while (1)
  149. {
  150. rt_thread_mdelay(THREAD_DELAY_TIME);
  151. ps2_scan(&ctrl_data);
  152. // look-up table and send standard command
  153. for (int i = 0; i < PS2_TABLE_SIZE; i++)
  154. {
  155. if (!(ctrl_data.button & table[i].ps2_cmd))
  156. {
  157. if (table[i].standard_cmd != COMMAND_NONE)
  158. {
  159. command_handle(table[i].standard_cmd, RT_NULL, 0);
  160. }
  161. }
  162. }
  163. // rocker
  164. if (ps2_read_light() == PS2_RED_MODE)
  165. {
  166. uint8_t value[4] = {
  167. ctrl_data.left_stick_x,
  168. ctrl_data.right_stick_x,
  169. ctrl_data.left_stick_y,
  170. ctrl_data.right_stick_y};
  171. rt_int16_t cmd[4] = {
  172. table[PS2_ROCKER_LX].standard_cmd,
  173. table[PS2_ROCKER_LY].standard_cmd,
  174. table[PS2_ROCKER_RX].standard_cmd,
  175. table[PS2_ROCKER_RY].standard_cmd};
  176. for (int i = 0; i < 4; i++)
  177. {
  178. if (cmd[i] != COMMAND_NONE)
  179. {
  180. float tmp = CHASSIS_VELOCITY_LINEAR_MAXIMUM;
  181. if (cmd[i] == COMMAND_SET_CHASSIS_VELOCITY_ANGULAR_Z)
  182. {
  183. tmp = CHASSIS_VELOCITY_ANGULAR_MAXIMUM;
  184. }
  185. target_velocity.data.common = tmp * ((0x80 - (int)(i/2)) - value[i]) / 128;
  186. command_handle(cmd[i], &target_velocity, sizeof(struct cmd_velocity));
  187. }
  188. }
  189. }
  190. }
  191. }
  192. void ps2_init(rt_base_t cs_pin, rt_base_t clk_pin, rt_base_t do_pin, rt_base_t di_pin)
  193. {
  194. ps2_cs_pin = cs_pin;
  195. ps2_clk_pin = clk_pin;
  196. ps2_do_pin = do_pin;
  197. ps2_di_pin = di_pin;
  198. rt_pin_mode(ps2_cs_pin, PIN_MODE_OUTPUT);
  199. rt_pin_mode(ps2_clk_pin, PIN_MODE_OUTPUT);
  200. rt_pin_mode(ps2_do_pin, PIN_MODE_OUTPUT);
  201. rt_pin_mode(ps2_di_pin, PIN_MODE_INPUT);
  202. hal_cs_high();
  203. hal_clk_high();
  204. // cmd_info.target = target;
  205. tid_ps2 = rt_thread_create("ps2",
  206. ps2_thread_entry, RT_NULL,
  207. THREAD_STACK_SIZE,
  208. THREAD_PRIORITY, THREAD_TIMESLICE);
  209. if (tid_ps2 != RT_NULL)
  210. {
  211. rt_thread_startup(tid_ps2);
  212. }
  213. else
  214. {
  215. LOG_E("Can't create thread for ps2");
  216. }
  217. }