gpio_controller.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include <gui/gui.h>
  4. #include <input/input.h>
  5. /* Magic happens here -- this file is generated by fbt.
  6. * Just set fap_icon_assets in application.fam and #include {APPID}_icons.h */
  7. #include "gpio_controller_icons.h"
  8. #include "gpio_items.h"
  9. typedef struct {
  10. int selected;
  11. GPIOItems* gpio_items;
  12. int wiggle_frame;
  13. } ViewerState;
  14. // 5V A7 A6 A4 B3 B2 C3 GND SET
  15. //
  16. //
  17. // 3V SWC GND SIO TX RX C1 C0 1W GND
  18. typedef enum {
  19. PIN_5V = 0,
  20. PIN_A7,
  21. PIN_A6,
  22. PIN_A4,
  23. PIN_B3,
  24. PIN_B2,
  25. PIN_C3,
  26. GEARIC,
  27. PIN_3V,
  28. PIN_SWC,
  29. PIN_SIO,
  30. PIN_TX,
  31. PIN_RX,
  32. PIN_C1,
  33. PIN_C0,
  34. PIN_1W,
  35. PIN_GND_08,
  36. PIN_GND_11,
  37. PIN_GND_18,
  38. NONE
  39. }enum_view_element;
  40. typedef struct {
  41. enum_view_element element;
  42. enum_view_element opposite;
  43. bool selectable;
  44. bool editable;
  45. bool top_row;
  46. bool pull_out;
  47. int gp_idx;
  48. uint8_t x_pos;
  49. uint8_t y_pos;
  50. const char* name;
  51. Icon* icon;
  52. Icon* selected_icon;
  53. }ViewElement;
  54. static ViewerState vstate = {.selected = PIN_A7,.gpio_items = NULL,.wiggle_frame=-1};
  55. static int wiggle[] = {-1,1,-1,1};
  56. static ViewElement elements[] = {
  57. {PIN_5V, PIN_3V, true, false, true, true, -1, 0, 0, "5V" , (Icon*)&I_5v_pin, NULL},
  58. {PIN_A7, PIN_SWC, true, true, true, true, 0, 14, 0, "A7", (Icon*)&I_a7_pin, NULL},
  59. {PIN_A6, NONE, true, true, true, true, 1, 28, 0, "A6", (Icon*)&I_a6_pin, NULL},
  60. {PIN_A4, PIN_SIO, true, true, true, true, 2, 42, 0, "A4", (Icon*)&I_a4_pin, NULL},
  61. {PIN_B3, PIN_TX, true, true, true, true, 3, 56, 0, "B3", (Icon*)&I_b3_pin, NULL},
  62. {PIN_B2, PIN_RX, true, true, true, true, 4, 70, 0, "B2", (Icon*)&I_b2_pin, NULL},
  63. {PIN_C3, PIN_C1, true, true, true, true, 5, 84, 0, "C3", (Icon*)&I_c3_pin, NULL},
  64. {GEARIC, PIN_1W, true, true, true, false, -1, 112, 0, "Settings", (Icon*)&I_gear_unhighlighted, (Icon*)&I_gear_highlighted},
  65. {PIN_3V, PIN_5V, true, false, false, true, -1, 0, 48, "3.3V", (Icon*)&I_3v_pin, NULL},
  66. {PIN_SWC, PIN_A7, true, false, false, true, -1, 14, 48, "Serial Wire Clock", (Icon*)&I_swc_pin, NULL},
  67. {PIN_SIO, PIN_A4, true, false, false, true, -1, 42, 48, "Serial IO", (Icon*)&I_sio_pin, NULL},
  68. {PIN_TX, PIN_B3, true, false, false, true, -1, 56, 48, "UART - Transmit", (Icon*)&I_tx_pin, NULL},
  69. {PIN_RX, PIN_B2, true, false, false, true, -1, 70, 48, "UART - Receive", (Icon*)&I_rx_pin, NULL},
  70. {PIN_C1, PIN_C3, true, true, false, true, 6, 84, 48, "C1", (Icon*)&I_c1_pin, NULL},
  71. {PIN_C0, NONE, true, true, false, true, 7, 98, 48, "C0", (Icon*)&I_c0_pin, NULL},
  72. {PIN_1W, GEARIC, true, true, false, true, -1, 112, 48, "1-Wire", (Icon*)&I_1w_pin, NULL},
  73. {PIN_GND_08, NONE, false, false, true, false, -1, 98, -1, "GND (Ground)", (Icon*)&I_gnd_pin, NULL},
  74. {PIN_GND_11, NONE, false, false, false, false, -1, 28, 48, "GND (Ground)", (Icon*)&I_gnd_pin, NULL},
  75. {PIN_GND_18, NONE, false, false, false, false, -1, 126, 48, "GND (Ground)", (Icon*)&I_gnd_pin, NULL},
  76. };
  77. static int element_count = NONE;
  78. // Screen is 128x64 px
  79. static void app_draw_callback(Canvas* canvas, void* ctx) {
  80. UNUSED(ctx);
  81. canvas_clear(canvas);
  82. for(int i = 0; i < element_count; i++)
  83. {
  84. ViewElement e = elements[i];
  85. int x = e.x_pos;
  86. int y = e.y_pos + (e.top_row && e.pull_out ? -3 : 0);
  87. Icon* icon = e.icon;
  88. if( vstate.selected == i )
  89. {
  90. if( e.pull_out )
  91. {
  92. y += e.top_row ? 3 : -3;
  93. }
  94. if( e.selected_icon != NULL )
  95. {
  96. icon = e.selected_icon;
  97. }
  98. if(vstate.wiggle_frame >= 0)
  99. {
  100. x += wiggle[vstate.wiggle_frame/2];
  101. vstate.wiggle_frame++;
  102. if ((unsigned int)(vstate.wiggle_frame/2) >= (sizeof(wiggle)/sizeof(int)))
  103. {
  104. vstate.wiggle_frame = -1;
  105. }
  106. }
  107. }
  108. canvas_draw_icon(canvas, x, y, icon);
  109. }
  110. canvas_set_font(canvas, FontSecondary);
  111. canvas_draw_str(canvas, 0, 40, elements[vstate.selected].name);
  112. }
  113. static void app_input_callback(InputEvent* input_event, void* ctx) {
  114. furi_assert(ctx);
  115. FuriMessageQueue* event_queue = ctx;
  116. furi_message_queue_put(event_queue, input_event, FuriWaitForever);
  117. }
  118. int32_t gpio_controller_main(void* p) {
  119. UNUSED(p);
  120. FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
  121. // Configure view port
  122. ViewPort* view_port = view_port_alloc();
  123. view_port_draw_callback_set(view_port, app_draw_callback, view_port);
  124. view_port_input_callback_set(view_port, app_input_callback, event_queue);
  125. // Register view port in GUI
  126. Gui* gui = furi_record_open(RECORD_GUI);
  127. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  128. InputEvent event;
  129. vstate.gpio_items = gpio_items_alloc();
  130. gpio_items_configure_all_pins(vstate.gpio_items, GpioModeOutputPushPull);
  131. bool running = true;
  132. while(running) {
  133. if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
  134. if( vstate.wiggle_frame < 0 )
  135. {
  136. if( (event.type == InputTypePress || event.type == InputTypeRelease) && event.key == InputKeyOk )
  137. {
  138. if( event.type == InputTypePress && elements[vstate.selected].gp_idx < 0 )
  139. {
  140. vstate.wiggle_frame = 0;
  141. }
  142. else if( elements[vstate.selected].gp_idx >= 0 && (event.type == InputTypePress || event.type == InputTypeRelease) )
  143. {
  144. gpio_items_set_pin(vstate.gpio_items, elements[vstate.selected].gp_idx, event.type == InputTypePress);
  145. }
  146. }
  147. else if(event.type == InputTypePress || event.type == InputTypeRepeat) {
  148. switch(event.key) {
  149. case InputKeyLeft:
  150. vstate.selected--;
  151. if(vstate.selected == GEARIC) vstate.selected = PIN_1W;
  152. else if(vstate.selected < 0) vstate.selected = GEARIC;
  153. break;
  154. case InputKeyRight:
  155. if(vstate.selected <= GEARIC)
  156. {
  157. vstate.selected++;
  158. vstate.selected = vstate.selected > GEARIC ? PIN_5V : vstate.selected;
  159. }
  160. else
  161. {
  162. vstate.selected++;
  163. vstate.selected = vstate.selected > PIN_1W ? PIN_3V : vstate.selected;
  164. }
  165. break;
  166. case InputKeyUp:
  167. case InputKeyDown:
  168. if (elements[vstate.selected].opposite != NONE) vstate.selected = elements[vstate.selected].opposite;
  169. break;
  170. case InputKeyBack:
  171. running = false;
  172. break;
  173. default:
  174. break;
  175. }
  176. }
  177. }
  178. }
  179. view_port_update(view_port);
  180. }
  181. gpio_items_free(vstate.gpio_items);
  182. view_port_enabled_set(view_port, false);
  183. gui_remove_view_port(gui, view_port);
  184. view_port_free(view_port);
  185. furi_message_queue_free(event_queue);
  186. furi_record_close(RECORD_GUI);
  187. return 0;
  188. }