input_converter.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include "input_converter.h"
  2. #include <furi/core/message_queue.h>
  3. #include "../game.h"
  4. // #define FRAME_IN_MS (1000 / 30)
  5. // #define CHECK_PERIOD_IN_MS 150
  6. #define CHECK_PERIOD_IN_FRAMES 5 // (int)(CHECK_PERIOD_IN_MS / FRAME_IN_MS)
  7. #define LONG_PRESS_IN_FRAMES 10 // (int)(CHECK_PERIOD_IN_MS * 2 / FRAME_IN_MS)
  8. const InputKey input_keys[InputKeyMAX] = { InputKeyUp, InputKeyDown,
  9. InputKeyRight, InputKeyLeft,
  10. InputKeyOk, InputKeyBack };
  11. const GameKey game_keys[InputKeyMAX] = {
  12. GameKeyUp, GameKeyDown, GameKeyRight, GameKeyLeft, GameKeyOk, GameKeyBack
  13. };
  14. struct InputConverter
  15. {
  16. size_t holded_frames_for_key[InputKeyMAX];
  17. FuriMessageQueue* queue;
  18. bool skip_next_input;
  19. };
  20. static void
  21. put_input_event(InputConverter* input_converter, InputEvent* event)
  22. {
  23. FURI_LOG_D(GAME_NAME,
  24. "Input event: %s %s",
  25. input_get_key_name(event->key),
  26. input_get_type_name(event->type));
  27. FuriStatus status =
  28. furi_message_queue_put(input_converter->queue, event, 0);
  29. furi_check(status == FuriStatusOk);
  30. }
  31. static void
  32. process_pressed(InputConverter* input_converter,
  33. InputState* input_state,
  34. GameKey game_key,
  35. InputKey input_key)
  36. {
  37. if (!(input_state->pressed & game_key)) {
  38. return;
  39. }
  40. ++(input_converter->holded_frames_for_key[input_key]);
  41. InputEvent event = { .key = input_key, .type = InputTypePress };
  42. put_input_event(input_converter, &event);
  43. }
  44. static void
  45. process_holded(InputConverter* input_converter,
  46. InputState* input_state,
  47. GameKey game_key,
  48. InputKey input_key)
  49. {
  50. size_t* holded_frames_for_key =
  51. &input_converter->holded_frames_for_key[input_key];
  52. if (!(input_state->held & game_key) || *holded_frames_for_key == 0) {
  53. return;
  54. }
  55. // Add current frame
  56. ++(*holded_frames_for_key);
  57. InputEvent event = { .key = input_key };
  58. if (*holded_frames_for_key == LONG_PRESS_IN_FRAMES) {
  59. // Long press
  60. event.type = InputTypeLong;
  61. put_input_event(input_converter, &event);
  62. } else if (*holded_frames_for_key ==
  63. LONG_PRESS_IN_FRAMES + CHECK_PERIOD_IN_FRAMES) {
  64. // Pause between events
  65. input_converter->holded_frames_for_key[input_key] =
  66. LONG_PRESS_IN_FRAMES;
  67. // Repeat
  68. event.type = InputTypeRepeat;
  69. put_input_event(input_converter, &event);
  70. }
  71. }
  72. static void
  73. process_released(InputConverter* input_converter,
  74. InputState* input_state,
  75. GameKey game_key,
  76. InputKey input_key)
  77. {
  78. size_t* holded_frames_for_key =
  79. &input_converter->holded_frames_for_key[input_key];
  80. if (!(input_state->released & game_key) || 0 == *holded_frames_for_key) {
  81. return;
  82. }
  83. InputEvent event = { .key = input_key };
  84. // Process short press
  85. if (*holded_frames_for_key < LONG_PRESS_IN_FRAMES) {
  86. event.type = InputTypeShort;
  87. put_input_event(input_converter, &event);
  88. }
  89. // Reset state
  90. input_converter->holded_frames_for_key[input_key] = 0;
  91. // Put release event
  92. event.type = InputTypeRelease;
  93. put_input_event(input_converter, &event);
  94. }
  95. InputConverter*
  96. input_converter_alloc(void)
  97. {
  98. InputConverter* input_converter = malloc(sizeof(InputConverter));
  99. // Init queue
  100. input_converter->queue =
  101. furi_message_queue_alloc(2 * InputKeyMAX, sizeof(InputEvent));
  102. // Init counter
  103. for (size_t i = 0; i < InputKeyMAX; ++i) {
  104. input_converter->holded_frames_for_key[i] = 0;
  105. }
  106. return input_converter;
  107. }
  108. void
  109. input_converter_free(InputConverter* input_converter)
  110. {
  111. furi_check(input_converter);
  112. furi_message_queue_free(input_converter->queue);
  113. free(input_converter);
  114. }
  115. void
  116. input_converter_reset(InputConverter* input_converter)
  117. {
  118. for (InputKey i = 0; i < InputKeyMAX; ++i) {
  119. input_converter->holded_frames_for_key[i] = 0;
  120. }
  121. furi_message_queue_reset(input_converter->queue);
  122. input_converter->skip_next_input = true;
  123. }
  124. void
  125. input_converter_process_state(InputConverter* input_converter,
  126. InputState* input_state)
  127. {
  128. furi_check(input_converter);
  129. furi_check(input_state);
  130. if (input_converter->skip_next_input) {
  131. input_converter->skip_next_input = false;
  132. return;
  133. }
  134. // Process new state
  135. for (size_t key_index = 0; key_index < sizeof(game_keys); ++key_index) {
  136. GameKey game_key = game_keys[key_index];
  137. InputKey input_key = input_keys[key_index];
  138. process_pressed(input_converter, input_state, game_key, input_key);
  139. process_holded(input_converter, input_state, game_key, input_key);
  140. process_released(input_converter, input_state, game_key, input_key);
  141. }
  142. }
  143. FuriStatus
  144. input_converter_get_event(InputConverter* input_converter, InputEvent* event)
  145. {
  146. furi_check(input_converter);
  147. return furi_message_queue_get(input_converter->queue, event, 0);
  148. }