button.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Copyright (C) 2023 Daniele Lacamera <root@danielinux.net>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdint.h>
  18. #include <stdlib.h>
  19. #include "system.h"
  20. #include "button.h"
  21. #include "unicore-mx/stm32/gpio.h"
  22. #include "unicore-mx/stm32/exti.h"
  23. #include "unicore-mx/stm32/rcc.h"
  24. #include "unicore-mx/stm32/adc.h"
  25. #include "unicore-mx/stm32/f7/nvic.h"
  26. #include "unicore-mx/stm32/f4/adc.h"
  27. #include "systick.h"
  28. #include "task.h"
  29. #include "adc.h"
  30. #define BUTTON_DEBOUNCE_TIME 100
  31. #define TS_DEBOUNCE_TIME 0
  32. #define PSEL_0 (1 << 0)
  33. #define PSEL_1 (1 << 1)
  34. #define PSEL_2 (1 << 2)
  35. /* Input lines: PH6, PA8, PB15, PB14 */
  36. #define PLINE_0 (1 << 6)
  37. #define PLINE_1 (1 << 8)
  38. #define PLINE_2 (1 << 15)
  39. #define PLINE_3 (1 << 14)
  40. #define TS_PIN (1 << 13) /* GPIO I13 */
  41. static volatile int button_current_latch = 0;
  42. static uint32_t button_latch_switchtime;
  43. static volatile int button_press_pending = 0;
  44. static void input_run(uint32_t ev, void *arg);
  45. static void input_init(void);
  46. const char button_task_name[] = "Input";
  47. struct task input_task = {
  48. .init = input_init,
  49. .run = input_run,
  50. .events = EV_SYSTICK,
  51. .name = button_task_name
  52. };
  53. static void button_setup(void)
  54. {
  55. int i;
  56. uint32_t exti_irq;
  57. rcc_periph_clock_enable(RCC_SYSCFG);
  58. rcc_periph_clock_enable(RCC_GPIOA);
  59. rcc_periph_clock_enable(RCC_GPIOB);
  60. rcc_periph_clock_enable(RCC_GPIOH);
  61. rcc_periph_clock_enable(RCC_GPIOI);
  62. gpio_mode_setup(GPIOI, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, PSEL_0 | PSEL_1 | PSEL_2);
  63. gpio_clear(GPIOI, PSEL_0 | PSEL_1 | PSEL_2);
  64. nvic_enable_irq(NVIC_EXTI15_10_IRQ);
  65. nvic_enable_irq(NVIC_EXTI9_5_IRQ);
  66. nvic_set_priority(NVIC_EXTI15_10_IRQ, 1);
  67. nvic_set_priority(NVIC_EXTI9_5_IRQ, 1);
  68. gpio_mode_setup(GPIOH, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, PLINE_0);
  69. gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, PLINE_1);
  70. gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, PLINE_2 | PLINE_3);
  71. /* Set touch screen interrupt line */
  72. gpio_mode_setup(GPIOI, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TS_PIN);
  73. exti_select_source(PLINE_0, GPIOH);
  74. exti_select_source(PLINE_1, GPIOA);
  75. exti_select_source(PLINE_2, GPIOB);
  76. exti_select_source(PLINE_3, GPIOB);
  77. exti_select_source(TS_PIN, GPIOI);
  78. }
  79. static void button_start_read(void)
  80. {
  81. exti_set_trigger(PLINE_0 | PLINE_1 | PLINE_2 | PLINE_3 | TS_PIN, EXTI_TRIGGER_RISING);
  82. exti_enable_request(PLINE_0 | PLINE_1 | PLINE_2 | PLINE_3|TS_PIN);
  83. }
  84. void isr_exti15_10(void)
  85. {
  86. exti_reset_request(PLINE_2);
  87. exti_reset_request(PLINE_3);
  88. if (exti_get_flag_status(TS_PIN))
  89. exti_reset_request(TS_PIN);
  90. button_press_pending++;
  91. }
  92. void isr_exti9_5(void)
  93. {
  94. exti_reset_request(PLINE_1);
  95. exti_reset_request(PLINE_0);
  96. button_press_pending++;
  97. }
  98. /*** Event generation interface ***/
  99. struct input_status Input_status = {};
  100. #define TS_TOUCH_NONE 0
  101. #define TS_TOUCH_DETECTED 1
  102. int input_detect_touch(void)
  103. {
  104. uint8_t n_touch = 0;
  105. n_touch = ft5336_TS_DetectTouch(TS_I2C_ADDR);
  106. if (n_touch > 0) {
  107. uint16_t x, y;
  108. ft5336_TS_GetXY(TS_I2C_ADDR, &y, &x);
  109. Input_status.ts.Y = y;
  110. Input_status.ts.X = x;
  111. Input_status.start_touch = jiffies;
  112. return TS_TOUCH_DETECTED;
  113. } else
  114. return TS_TOUCH_NONE;
  115. }
  116. static int input_process_buttons(void)
  117. {
  118. int b_pressed = -1;
  119. struct user_button *b;
  120. uint8_t n_touch = 0;
  121. if (button_press_pending) {
  122. n_touch = input_detect_touch();
  123. if (n_touch != TS_TOUCH_NONE) {
  124. b = &Input_status.b[TOUCHSCREEN];
  125. b->pressed = 1;
  126. return 1;
  127. } else if (gpio_get(GPIOH, PLINE_0))
  128. b_pressed = 0;
  129. else if (gpio_get(GPIOA, PLINE_1))
  130. b_pressed = 1;
  131. else if (gpio_get(GPIOB, PLINE_2))
  132. b_pressed = 2;
  133. else if (gpio_get(GPIOB, PLINE_3))
  134. b_pressed = 3;
  135. else {
  136. button_press_pending = 0;
  137. return 0;
  138. }
  139. b_pressed += 4 * button_current_latch;
  140. if (b_pressed >= N_BUTTONS)
  141. return 0;
  142. b = &Input_status.b[b_pressed];
  143. if (b->transition_start_timestamp == 0U) {
  144. b->transition_start_timestamp = jiffies;
  145. return 0;
  146. }
  147. if ((jiffies - b->transition_start_timestamp) > BUTTON_DEBOUNCE_TIME) {
  148. button_press_pending = 0;
  149. b->pressed = 1;
  150. return 1;
  151. }
  152. } else if (jiffies >= button_latch_switchtime) {
  153. int i, start = 4 *button_current_latch,
  154. end = start + 4;
  155. button_latch_switchtime = jiffies + 5;
  156. for (i = start; i < end; i++)
  157. Input_status.b[i].transition_start_timestamp = 0;
  158. switch (button_current_latch) {
  159. case 0:
  160. gpio_clear(GPIOI, PSEL_0 | PSEL_2);
  161. gpio_set(GPIOI, PSEL_1);
  162. button_current_latch = 1;
  163. break;
  164. case 1:
  165. gpio_clear(GPIOI, PSEL_0 | PSEL_1);
  166. gpio_set(GPIOI, PSEL_2);
  167. button_current_latch = 2;
  168. break;
  169. case 2:
  170. default:
  171. gpio_clear(GPIOI, PSEL_1 | PSEL_2);
  172. gpio_set(GPIOI, PSEL_0);
  173. button_current_latch = 0;
  174. break;
  175. }
  176. }
  177. return 0;
  178. }
  179. int input_get_swl(void)
  180. {
  181. return gpio_get(GPIOF, (1 << 10) );
  182. }
  183. int input_get_swr(void)
  184. {
  185. return gpio_get(GPIOF, (1 << 7) );
  186. }
  187. static void adc_setup(void)
  188. {
  189. int i;
  190. rcc_periph_clock_enable(RCC_ADC3);
  191. rcc_periph_clock_enable(RCC_GPIOA);
  192. rcc_periph_clock_enable(RCC_GPIOF);
  193. gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, 0, GPIO0);
  194. gpio_mode_setup(GPIOF, GPIO_MODE_ANALOG, 0, GPIO6 | GPIO8 | GPIO9);
  195. adc_init();
  196. }
  197. void input_init(void)
  198. {
  199. button_setup();
  200. adc_setup();
  201. button_start_read();
  202. }
  203. void input_run(uint32_t ev, void *arg)
  204. {
  205. int p = input_process_buttons();
  206. if (p > 0) {
  207. trigger_event(EV_BUTTON);
  208. }
  209. }
  210. void input_setup(void)
  211. {
  212. register_task(&input_task);
  213. }