xbox_controller_view.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include "xbox_controller_view.h"
  2. struct XboxControllerView {
  3. View* view;
  4. NotificationApp* notifications;
  5. };
  6. typedef struct {
  7. bool left_pressed;
  8. bool up_pressed;
  9. bool right_pressed;
  10. bool down_pressed;
  11. bool ok_pressed;
  12. bool back_pressed;
  13. bool connected;
  14. } XboxControllerViewModel;
  15. static void
  16. xbox_controller_view_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) {
  17. if(dir == CanvasDirectionBottomToTop) {
  18. canvas_draw_triangle(canvas, x - 2, y - 2, 5, 3, dir);
  19. canvas_draw_line(canvas, x - 2, y - 3, x - 2, y + 4);
  20. } else if(dir == CanvasDirectionTopToBottom) {
  21. canvas_draw_triangle(canvas, x - 2, y + 2, 5, 3, dir);
  22. canvas_draw_line(canvas, x - 2, y - 4, x - 2, y + 3);
  23. } else if(dir == CanvasDirectionRightToLeft) {
  24. canvas_draw_triangle(canvas, x - 4, y, 5, 3, dir);
  25. canvas_draw_line(canvas, x + 2, y, x - 5, y);
  26. } else if(dir == CanvasDirectionLeftToRight) {
  27. canvas_draw_triangle(canvas, x, y, 5, 3, dir);
  28. canvas_draw_line(canvas, x - 6, y, x + 1, y);
  29. }
  30. }
  31. static void xbox_controller_view_draw_arrow_button(
  32. Canvas* canvas,
  33. bool pressed,
  34. uint8_t x,
  35. uint8_t y,
  36. CanvasDirection direction) {
  37. canvas_draw_icon(canvas, x, y, &I_Button_18x18);
  38. if(pressed) {
  39. elements_slightly_rounded_box(canvas, x + 3, y + 2, 13, 13);
  40. canvas_set_color(canvas, ColorWhite);
  41. }
  42. xbox_controller_view_draw_arrow(canvas, x + 11, y + 8, direction);
  43. canvas_set_color(canvas, ColorBlack);
  44. }
  45. static void xbox_controller_draw_wide_button(
  46. Canvas* canvas,
  47. bool pressed,
  48. uint8_t x,
  49. uint8_t y,
  50. char* text,
  51. const Icon* icon) {
  52. // canvas_draw_icon(canvas, 0, 25, &I_Space_65x18);
  53. elements_slightly_rounded_frame(canvas, x, y, 64, 17);
  54. if(pressed) {
  55. elements_slightly_rounded_box(canvas, x + 2, y + 2, 60, 13);
  56. canvas_set_color(canvas, ColorWhite);
  57. }
  58. canvas_draw_icon(canvas, x + 11, y + 4, icon);
  59. elements_multiline_text_aligned(canvas, x + 28, y + 12, AlignLeft, AlignBottom, text);
  60. canvas_set_color(canvas, ColorBlack);
  61. }
  62. static void xbox_controller_view_draw_callback(Canvas* canvas, void* context) {
  63. furi_assert(context);
  64. XboxControllerViewModel* model = context;
  65. canvas_set_font(canvas, FontPrimary);
  66. elements_multiline_text_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Xbox One");
  67. canvas_set_font(canvas, FontSecondary);
  68. canvas_draw_icon(canvas, 0, 12, &I_Pin_back_arrow_10x8);
  69. canvas_draw_str(canvas, 12, 20, "Hold");
  70. xbox_controller_view_draw_arrow_button(
  71. canvas, model->up_pressed, 23, 74, CanvasDirectionBottomToTop);
  72. xbox_controller_view_draw_arrow_button(
  73. canvas, model->down_pressed, 23, 110, CanvasDirectionTopToBottom);
  74. xbox_controller_view_draw_arrow_button(
  75. canvas, model->left_pressed, 0, 92, CanvasDirectionRightToLeft);
  76. xbox_controller_view_draw_arrow_button(
  77. canvas, model->right_pressed, 46, 92, CanvasDirectionLeftToRight);
  78. int buttons_post = 30;
  79. // Ok
  80. xbox_controller_draw_wide_button(
  81. canvas, model->ok_pressed, 0, buttons_post, "A", &I_Ok_btn_9x9);
  82. // Back
  83. xbox_controller_draw_wide_button(
  84. canvas, model->back_pressed, 0, buttons_post + 19, "B", &I_Pin_back_arrow_10x8);
  85. }
  86. const NotificationSequence sequence_blink_purple_50 = {
  87. &message_red_255,
  88. &message_blue_255,
  89. &message_delay_50,
  90. NULL,
  91. };
  92. void send_xbox_ir(uint32_t command, NotificationApp* notifications) {
  93. InfraredMessage* message = malloc(sizeof(InfraredMessage));
  94. message->protocol = InfraredProtocolNECext;
  95. message->address = 0xD880;
  96. message->command = command;
  97. message->repeat = false;
  98. notification_message(notifications, &sequence_blink_purple_50);
  99. infrared_send(message, 2);
  100. free(message);
  101. }
  102. static void
  103. xbox_controller_view_process(XboxControllerView* xbox_controller_view, InputEvent* event) {
  104. with_view_model(
  105. xbox_controller_view->view,
  106. XboxControllerViewModel * model,
  107. {
  108. if(event->type == InputTypePress) {
  109. if(event->key == InputKeyUp) {
  110. model->up_pressed = true;
  111. send_xbox_ir(0xE11E, xbox_controller_view->notifications);
  112. } else if(event->key == InputKeyDown) {
  113. model->down_pressed = true;
  114. send_xbox_ir(0xE01F, xbox_controller_view->notifications);
  115. } else if(event->key == InputKeyLeft) {
  116. model->left_pressed = true;
  117. send_xbox_ir(0xDF20, xbox_controller_view->notifications);
  118. } else if(event->key == InputKeyRight) {
  119. model->right_pressed = true;
  120. send_xbox_ir(0xDE21, xbox_controller_view->notifications);
  121. } else if(event->key == InputKeyOk) {
  122. model->ok_pressed = true;
  123. send_xbox_ir(0x9966, xbox_controller_view->notifications);
  124. } else if(event->key == InputKeyBack) {
  125. model->back_pressed = true;
  126. send_xbox_ir(0x9A65, xbox_controller_view->notifications);
  127. }
  128. } else if(event->type == InputTypeRelease) {
  129. if(event->key == InputKeyUp) {
  130. model->up_pressed = false;
  131. } else if(event->key == InputKeyDown) {
  132. model->down_pressed = false;
  133. } else if(event->key == InputKeyLeft) {
  134. model->left_pressed = false;
  135. } else if(event->key == InputKeyRight) {
  136. model->right_pressed = false;
  137. } else if(event->key == InputKeyOk) {
  138. model->ok_pressed = false;
  139. } else if(event->key == InputKeyBack) {
  140. model->back_pressed = false;
  141. }
  142. } else if(event->type == InputTypeShort) {
  143. if(event->key == InputKeyBack) {
  144. // furi_hal_hid_kb_press(HID_KEYBOARD_DELETE);
  145. // furi_hal_hid_kb_release(HID_KEYBOARD_DELETE);
  146. // furi_hal_hid_consumer_key_press(HID_CONSUMER_AC_BACK);
  147. // furi_hal_hid_consumer_key_release(HID_CONSUMER_AC_BACK);
  148. }
  149. }
  150. },
  151. true);
  152. }
  153. static bool xbox_controller_view_input_callback(InputEvent* event, void* context) {
  154. furi_assert(context);
  155. XboxControllerView* xbox_controller_view = context;
  156. bool consumed = false;
  157. if(event->type == InputTypeLong && event->key == InputKeyBack) {
  158. // LONG KEY BACK PRESS HANDLER
  159. } else {
  160. xbox_controller_view_process(xbox_controller_view, event);
  161. consumed = true;
  162. }
  163. return consumed;
  164. }
  165. XboxControllerView* xbox_controller_view_alloc(NotificationApp* notifications) {
  166. XboxControllerView* xbox_controller_view = malloc(sizeof(XboxControllerView));
  167. xbox_controller_view->view = view_alloc();
  168. xbox_controller_view->notifications = notifications;
  169. view_set_orientation(xbox_controller_view->view, ViewOrientationVertical);
  170. view_set_context(xbox_controller_view->view, xbox_controller_view);
  171. view_allocate_model(
  172. xbox_controller_view->view, ViewModelTypeLocking, sizeof(XboxControllerViewModel));
  173. view_set_draw_callback(xbox_controller_view->view, xbox_controller_view_draw_callback);
  174. view_set_input_callback(xbox_controller_view->view, xbox_controller_view_input_callback);
  175. return xbox_controller_view;
  176. }
  177. void xbox_controller_view_free(XboxControllerView* xbox_controller_view) {
  178. furi_assert(xbox_controller_view);
  179. view_free(xbox_controller_view->view);
  180. free(xbox_controller_view);
  181. }
  182. View* xbox_controller_view_get_view(XboxControllerView* xbox_controller_view) {
  183. furi_assert(xbox_controller_view);
  184. return xbox_controller_view->view;
  185. }
  186. void xbox_controller_view_set_connected_status(
  187. XboxControllerView* xbox_controller_view,
  188. bool connected) {
  189. furi_assert(xbox_controller_view);
  190. with_view_model(
  191. xbox_controller_view->view,
  192. XboxControllerViewModel * model,
  193. { model->connected = connected; },
  194. true);
  195. }