code_switch.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. #include "system/includes.h"
  2. #include "code_switch.h"
  3. #include "app_config.h"
  4. #include "stdlib.h"
  5. #if TCFG_CODE_SWITCH_ENABLE
  6. #if 1
  7. #define log_debug printf
  8. #else
  9. #define log_debug(...)
  10. #endif
  11. #define INPUT_CHANNLE6_SRC_SEL(x) SFR(JL_IOMAP->CON4, 16, 6, x)
  12. #define INPUT_CHANNLE7_SRC_SEL(x) SFR(JL_IOMAP->CON4, 24, 6, x)
  13. static SW_PLATFORM_DATA *sw_pdata = NULL;
  14. static u8 code_switch_active = 0;
  15. static void code_switch_event_to_usr(u8 event, s8 sw_val);
  16. static void get_code_value_handler(void *priv);
  17. /* static void get_code_value_handler(void); */
  18. static u8 code_switch_idle_query(void);
  19. static void code_switch_event_to_usr(u8 event, s8 sw_val)
  20. {
  21. struct sys_event e;
  22. e.type = SYS_DEVICE_EVENT;
  23. e.arg = "code_switch";
  24. e.u.codesw.event = event;
  25. e.u.codesw.value = sw_val;
  26. sys_event_notify(&e);
  27. }
  28. /* ___interrupt */
  29. /* static void get_code_value_handler(void) */
  30. /* { */
  31. /* if (JL_RDEC->CON & 0x80) */
  32. /* { */
  33. /* mouse_code_switch_event_to_usr(0, JL_RDEC->DAT); */
  34. /* JL_RDEC->CON |= BIT(6); */
  35. /* } */
  36. /* } */
  37. /* */
  38. u8 code_postive_list[] = {
  39. ((0x00 << 4) | (0x02 << 2) | (0x03 << 0)), \
  40. ((0x00 << 4) | (0x02 << 2) | (0x01 << 0)), \
  41. ((0x00 << 4) | (0x03 << 2) | (0x01 << 0)), \
  42. ((0x02 << 4) | (0x03 << 2) | (0x01 << 0)), \
  43. ((0x02 << 4) | (0x03 << 2) | (0x00 << 0)), \
  44. ((0x02 << 4) | (0x01 << 2) | (0x00 << 0)), \
  45. ((0x03 << 4) | (0x01 << 2) | (0x00 << 0)), \
  46. ((0x03 << 4) | (0x01 << 2) | (0x02 << 0)), \
  47. ((0x03 << 4) | (0x00 << 2) | (0x02 << 0)), \
  48. ((0x01 << 4) | (0x00 << 2) | (0x02 << 0)), \
  49. ((0x01 << 4) | (0x00 << 2) | (0x03 << 0)), \
  50. ((0x01 << 4) | (0x02 << 2) | (0x03 << 0))
  51. };
  52. u8 code_negative_list[] = {
  53. ((0x00 << 4) | (0x01 << 2) | (0x03 << 0)), \
  54. ((0x00 << 4) | (0x01 << 2) | (0x02 << 0)), \
  55. ((0x00 << 4) | (0x03 << 2) | (0x02 << 0)), \
  56. ((0x01 << 4) | (0x03 << 2) | (0x02 << 0)), \
  57. ((0x01 << 4) | (0x03 << 2) | (0x00 << 0)), \
  58. ((0x01 << 4) | (0x02 << 2) | (0x00 << 0)), \
  59. ((0x03 << 4) | (0x02 << 2) | (0x00 << 0)), \
  60. ((0x03 << 4) | (0x02 << 2) | (0x01 << 0)), \
  61. ((0x03 << 4) | (0x00 << 2) | (0x01 << 0)), \
  62. ((0x02 << 4) | (0x00 << 2) | (0x01 << 0)), \
  63. ((0x02 << 4) | (0x00 << 2) | (0x03 << 0)), \
  64. ((0x02 << 4) | (0x01 << 2) | (0x03 << 0))
  65. };
  66. //功能:相位纠正
  67. static void correct_code(u8 *code_data, u8 *list_data, u8 idx)
  68. {
  69. code_data[2] = (list_data[(idx / 3) * 3] & (0x03 << 4)) >> 4;
  70. code_data[1] = (list_data[(idx / 3) * 3] & (0x03 << 2)) >> 2;
  71. code_data[0] = (list_data[(idx / 3) * 3] & (0x03 << 0)) >> 0;
  72. log_debug("lost_phase_recover: %d %d %d\n", code_data[2], code_data[1], code_data[0]);
  73. }
  74. //功能:相位遍历
  75. static u8 traverse_phase_list(u8 *code_data, u8 *list_data, u8 size)
  76. {
  77. u8 code_num = 0, idx = 0;
  78. code_num = code_data[2] << 4 | code_data[1] << 2 | code_data[0] << 0;
  79. for (idx = 0; idx < size; idx++) {
  80. if (code_num == list_data[idx]) {
  81. if (idx % 3) {
  82. /* correct_code(code_data, list_data, idx); */
  83. }
  84. break;
  85. }
  86. }
  87. return idx;
  88. }
  89. //功能:消抖
  90. static bool code_phase_debounce(u8 code_val)
  91. {
  92. static u8 filter_value = 0, filter_cnt = 0;
  93. const u8 filter_time = 2;
  94. //当前值与上一次值如果不相等, 重新消抖处理, 注意filter_time != 0;
  95. if (code_val != filter_value && filter_time) {
  96. filter_cnt = 0; //消抖次数清0, 重新开始消抖
  97. filter_value = code_val;//记录上一次的值
  98. return false; //第一次检测, 返回不做处理
  99. }
  100. //当前值与上一次值相等, filter_cnt开始累加;
  101. if (filter_cnt < filter_time) {
  102. filter_cnt++;
  103. return false;
  104. }
  105. return true;
  106. }
  107. //功能:获取相位
  108. static bool get_code_phase(u8 *code_data)
  109. {
  110. static u8 code_now = 0, code_last = 0;
  111. static u8 debug_count = 0;
  112. //获取相位值
  113. code_last = code_now;
  114. code_now = (gpio_read(sw_pdata->a_phase_io) ? 0x02 : 0x00) + (gpio_read(sw_pdata->b_phase_io) ? 0x01 : 0x00);
  115. //相位状态出现变化,将相位值存入队列
  116. if (code_last != code_now && code_now != code_data[0]) {
  117. code_data[2] = code_data[1];
  118. code_data[1] = code_data[0];
  119. code_data[0] = code_now;
  120. code_switch_active = 200;//编码开关工作状态标志位
  121. /* log_debug(">>>%d<<<%d %d %d\n", debug_count, code_data[2], code_data[1], code_data[0]); */
  122. debug_count++;
  123. return true;
  124. }
  125. //相位状态无变化,编码开关工作状态标志位递减
  126. else {
  127. if (code_switch_active) {
  128. code_switch_active--;
  129. }
  130. }
  131. return false;
  132. }
  133. //功能:获取编码值
  134. u8 get_code_value(u8 *code_data)
  135. {
  136. u8 idx = 0; //相位序列号
  137. static u8 code_val = 0;
  138. static u8 move_now = 0, move_last = 0;
  139. static u8 idx_pos_last = 0, idx_neg_last = 0;
  140. enum {
  141. MOVE_POS,
  142. MOVE_NEG,
  143. };
  144. //正相位遍历,获取相位序列号
  145. idx = traverse_phase_list(code_data, &code_postive_list[0], ARRAY_SIZE(code_postive_list));
  146. //相位序列号有效,则出现正向滚动动作
  147. if (idx < ARRAY_SIZE(code_postive_list)) {
  148. move_last = move_now;
  149. move_now = MOVE_POS;
  150. //相位区域限制,避免重复检测
  151. if ((idx >= 0 && idx <= 2) || (idx >= 6 && idx <= 8) || (move_now != move_last))
  152. /* if (abs(idx_pos_last/3-idx/3)>=2 || (move_now != move_last)) */
  153. {
  154. code_val++; //正向滚动,编码值+1
  155. idx_pos_last = idx;
  156. /* log_debug(">>>>>>>>>>>>>>>>>>>>>>>idx = %d R\n", idx); */
  157. /* log_debug("\n"); */
  158. return code_val;
  159. }
  160. }
  161. //负相位遍历,获取相位序列号
  162. idx = traverse_phase_list(code_data, &code_negative_list[0], ARRAY_SIZE(code_negative_list));
  163. //相位序列号有效,则出现负向滚动
  164. if (idx < ARRAY_SIZE(code_negative_list)) {
  165. move_last = move_now;
  166. move_now = MOVE_NEG;
  167. //相位区域限制,避免重复检测
  168. if ((idx >= 3 && idx <= 5) || (idx >= 9 && idx <= 11) || (move_now != move_last))
  169. /* if (abs(idx_neg_last/3-idx/3)>=2 || (move_now != move_last)) */
  170. {
  171. code_val--; //负向滚动,编码值-1
  172. idx_neg_last = idx;
  173. /* log_debug(">>>>>>>>>>>>>>>>>>>>>>>idx = %d L\n", idx); */
  174. /* log_debug("\n"); */
  175. return code_val;
  176. }
  177. }
  178. return code_val;
  179. }
  180. //功能:旋转编码开关检测
  181. static u8 code_switch_detector(void)
  182. {
  183. static u8 code_table[3] = {0}; //相位值存储队列
  184. static u8 code_val = 0;
  185. //相位有变化,进行相位遍历,获取编码值
  186. if (get_code_phase(&code_table[0])) {
  187. code_val = get_code_value(&code_table[0]);
  188. }
  189. //相位无变化,编码值保持不变
  190. else {
  191. code_val = code_val;
  192. }
  193. return code_val;
  194. }
  195. //功能:旋转编码开关数据采集
  196. static void code_switch_handler(void *priv)
  197. {
  198. static u8 code_val_last = 0;
  199. static u8 code_val_now = 0;
  200. code_val_last = code_val_now;
  201. code_val_now = code_switch_detector();
  202. if (code_val_last != code_val_now) {
  203. code_switch_event_to_usr(0, code_val_now - code_val_last);
  204. }
  205. /* if (JL_RDEC->DAT != code) */
  206. /* { */
  207. /* code_switch_event_to_usr(0, JL_RDEC->DAT - code); */
  208. /* code_switch_active = 10; */
  209. /* } */
  210. /* */
  211. /* else */
  212. /* { */
  213. /* code_switch_active--; */
  214. /* } */
  215. /* */
  216. /* code = JL_RDEC->DAT; */
  217. /* pnd = JL_RDEC->CON & 0x80; */
  218. /* if (pnd) */
  219. /* { */
  220. /* code_switch_event_to_usr(0, JL_RDEC->DAT); */
  221. /* JL_RDEC->CON |= BIT(6); */
  222. /* putchar('Y'); */
  223. /* CODE_IO_DEBUG_TOGGLE(A,2) */
  224. /* } */
  225. }
  226. void code_switch_init(SW_PLATFORM_DATA *priv)
  227. {
  228. sw_pdata = priv;
  229. /* JL_RDEC->CON |= BIT(0); //Enable RDEC */
  230. /* JL_RDEC->CON &= ~BIT(1);//pull up */
  231. /* JL_RDEC->CON |= 15<<2; */
  232. /* JL_IOMAP->CON1 &= ~BIT(12); //RDES_IOSO = PB4 */
  233. /* JL_IOMAP->CON1 &= ~BIT(13); //RDES_IOS1 = PB5 */
  234. /* JL_IOMAP->CON1 |= BIT(12); */
  235. /* JL_IOMAP->CON1 |= BIT(13); */
  236. /* INPUT_CHANNLE6_SRC_SEL(sw_pdata->a_phase_io); */
  237. /* INPUT_CHANNLE7_SRC_SEL(sw_pdata->b_phase_io); */
  238. gpio_set_die(sw_pdata->a_phase_io, 1);
  239. gpio_set_dieh(sw_pdata->a_phase_io, 1);
  240. gpio_set_direction(sw_pdata->a_phase_io, 1);
  241. gpio_set_pull_up(sw_pdata->a_phase_io, 0);
  242. gpio_set_pull_down(sw_pdata->a_phase_io, 0);
  243. gpio_set_die(sw_pdata->b_phase_io, 1);
  244. gpio_set_dieh(sw_pdata->b_phase_io, 1);
  245. gpio_set_direction(sw_pdata->b_phase_io, 1);
  246. gpio_set_pull_up(sw_pdata->b_phase_io, 0);
  247. gpio_set_pull_down(sw_pdata->b_phase_io, 0);
  248. /* request_irq(IRQ_RDEC_IDX, 3, code_switch_handler, 0); */
  249. sys_s_hi_timer_add(NULL, code_switch_handler, 2); //10ms
  250. }
  251. static u8 code_switch_idle_query(void)
  252. {
  253. /* return !(JL_RDEC->CON & 0x80); */
  254. return (!code_switch_active);
  255. }
  256. REGISTER_LP_TARGET(code_switch_lp_target) = {
  257. .name = "code_switch",
  258. .is_idle = code_switch_idle_query,
  259. };
  260. #endif /* CODE_SWITCH_ENABLE */