input.c 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #include "input_i.h"
  2. #define GPIO_Read(input_pin) \
  3. (HAL_GPIO_ReadPin((GPIO_TypeDef*)input_pin.pin->port, input_pin.pin->pin) ^ \
  4. input_pin.pin->inverted)
  5. static Input* input = NULL;
  6. void input_press_timer_callback(void* arg) {
  7. InputPinState* input_pin = arg;
  8. InputEvent event;
  9. event.key = input_pin->pin->key;
  10. event.type = InputTypeLong;
  11. notify_pubsub(&input->event_pubsub, &event);
  12. }
  13. void input_isr(void* _pin, void* _ctx) {
  14. osThreadFlagsSet(input->thread, INPUT_THREAD_FLAG_ISR);
  15. }
  16. int32_t input_task() {
  17. input = furi_alloc(sizeof(Input));
  18. input->thread = osThreadGetId();
  19. init_pubsub(&input->event_pubsub);
  20. furi_record_create("input_events", &input->event_pubsub);
  21. const size_t pin_count = input_pins_count;
  22. input->pin_states = furi_alloc(pin_count * sizeof(InputPinState));
  23. api_interrupt_add(input_isr, InterruptTypeExternalInterrupt, NULL);
  24. for(size_t i = 0; i < pin_count; i++) {
  25. input->pin_states[i].pin = &input_pins[i];
  26. input->pin_states[i].state = GPIO_Read(input->pin_states[i]);
  27. input->pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF;
  28. input->pin_states[i].press_timer =
  29. osTimerNew(input_press_timer_callback, osTimerOnce, &input->pin_states[i], NULL);
  30. }
  31. while(1) {
  32. bool is_changing = false;
  33. for(size_t i = 0; i < pin_count; i++) {
  34. bool state = GPIO_Read(input->pin_states[i]);
  35. if(input->pin_states[i].debounce > 0 &&
  36. input->pin_states[i].debounce < INPUT_DEBOUNCE_TICKS) {
  37. is_changing = true;
  38. input->pin_states[i].debounce += (state ? 1 : -1);
  39. } else if(input->pin_states[i].state != state) {
  40. input->pin_states[i].state = state;
  41. // Common state info
  42. InputEvent event;
  43. event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease;
  44. event.key = input->pin_states[i].pin->key;
  45. // Send Press/Release event
  46. notify_pubsub(&input->event_pubsub, &event);
  47. // Short/Long press logic
  48. if(state) {
  49. osTimerStart(input->pin_states[i].press_timer, INPUT_LONG_PRESS_TICKS);
  50. } else if(osTimerStop(input->pin_states[i].press_timer) == osOK) {
  51. event.type = InputTypeShort;
  52. notify_pubsub(&input->event_pubsub, &event);
  53. }
  54. }
  55. }
  56. if(is_changing) {
  57. osDelay(1);
  58. } else {
  59. osThreadFlagsWait(INPUT_THREAD_FLAG_ISR, osFlagsWaitAny, osWaitForever);
  60. }
  61. }
  62. return 0;
  63. }