|
|
@@ -0,0 +1,239 @@
|
|
|
+#include <furi.h>
|
|
|
+#include <furi_hal.h>
|
|
|
+
|
|
|
+#include <gui/gui.h>
|
|
|
+#include <input/input.h>
|
|
|
+
|
|
|
+/* Magic happens here -- this file is generated by fbt.
|
|
|
+ * Just set fap_icon_assets in application.fam and #include {APPID}_icons.h */
|
|
|
+#include "gpio_controller_icons.h"
|
|
|
+
|
|
|
+#include "gpio_items.h"
|
|
|
+
|
|
|
+typedef struct {
|
|
|
+ int selected;
|
|
|
+ GPIOItems* gpio_items;
|
|
|
+} ViewerState;
|
|
|
+
|
|
|
+static ViewerState vstate = {.selected = 0};
|
|
|
+
|
|
|
+typedef enum {
|
|
|
+ PIN_5V = 0,
|
|
|
+ PIN_A7,
|
|
|
+ PIN_A6,
|
|
|
+ PIN_A4,
|
|
|
+ PIN_B3,
|
|
|
+ PIN_B2,
|
|
|
+ PIN_C3,
|
|
|
+ GEARIC,
|
|
|
+ PIN_3V,
|
|
|
+ PIN_SWC,
|
|
|
+ PIN_SIO,
|
|
|
+ PIN_TX,
|
|
|
+ PIN_RX,
|
|
|
+ PIN_C1,
|
|
|
+ PIN_C0,
|
|
|
+ PIN_1W,
|
|
|
+ PIN_GND_08,
|
|
|
+ PIN_GND_11,
|
|
|
+ PIN_GND_18,
|
|
|
+ NONE
|
|
|
+}ViewElement;
|
|
|
+
|
|
|
+ // 5V A7 A6 A4 B3 B2 C3 GND SET
|
|
|
+ //
|
|
|
+ //
|
|
|
+ // 3V SWC GND SIO TX RX C1 C0 1W GND
|
|
|
+
|
|
|
+// next element when pressing up or down from a given element
|
|
|
+// ground pins cannot be selected
|
|
|
+static uint8_t y_mapping[] = {
|
|
|
+ PIN_3V, // <- PIN_5V
|
|
|
+ PIN_SWC, // <- PIN_A7
|
|
|
+ NONE, // <- PIN_A6
|
|
|
+ PIN_SIO, // <- PIN_A4
|
|
|
+ PIN_TX, // <- PIN_B3
|
|
|
+ PIN_RX, // <- PIN_B2
|
|
|
+ PIN_C1, // <- PIN_C3
|
|
|
+ PIN_1W, // <- GEARIC
|
|
|
+ PIN_5V, // <- PIN_3V
|
|
|
+ PIN_A7, // <- PIN_SWC
|
|
|
+ PIN_A4, // <- PIN_SIO
|
|
|
+ PIN_B3, // <- PIN_TX
|
|
|
+ PIN_B2, // <- PIN_RX
|
|
|
+ PIN_C3, // <- PIN_C1
|
|
|
+ NONE, // <- PIN_C0
|
|
|
+ GEARIC // <- PIN_1W
|
|
|
+};
|
|
|
+
|
|
|
+static uint8_t x_pos[] = {
|
|
|
+ 0, // PIN_5V
|
|
|
+ 14, // PIN_A7
|
|
|
+ 28, // PIN_A6
|
|
|
+ 42, // PIN_A4
|
|
|
+ 56, // PIN_B3
|
|
|
+ 70, // PIN_B2
|
|
|
+ 84, // PIN_C3
|
|
|
+ 112, // GEARIC
|
|
|
+ 0, // PIN_3V
|
|
|
+ 14, // PIN_SWC
|
|
|
+ 42, // PIN_SIO
|
|
|
+ 56, // PIN_TX
|
|
|
+ 70, // PIN_RX
|
|
|
+ 84, // PIN_C1
|
|
|
+ 98, // PIN_C0
|
|
|
+ 112, // PIN_1W
|
|
|
+ 98, // PIN_GND_08
|
|
|
+ 28, // PIN_GND_11
|
|
|
+ 126 // PIN_GND_18
|
|
|
+};
|
|
|
+
|
|
|
+static int gp_pins[] = {
|
|
|
+ -1, // PIN_5V
|
|
|
+ 0, // PIN_A7
|
|
|
+ 1, // PIN_A6
|
|
|
+ 2, // PIN_A4
|
|
|
+ 3, // PIN_B3
|
|
|
+ 4, // PIN_B2
|
|
|
+ 5, // PIN_C3
|
|
|
+ -1, // GEARIC
|
|
|
+ -1, // PIN_3V
|
|
|
+ -1, // PIN_SWC
|
|
|
+ -1, // PIN_SIO
|
|
|
+ -1, // PIN_TX
|
|
|
+ -1, // PIN_RX
|
|
|
+ 6, // PIN_C1
|
|
|
+ 7, // PIN_C0
|
|
|
+ -1, // PIN_1W
|
|
|
+};
|
|
|
+
|
|
|
+static Icon * icons[] = {
|
|
|
+ (Icon*)&I_5v_pin, // PIN_5V
|
|
|
+ (Icon*)&I_a7_pin, // PIN_A7
|
|
|
+ (Icon*)&I_a6_pin, // PIN_A6
|
|
|
+ (Icon*)&I_a4_pin, // PIN_A4
|
|
|
+ (Icon*)&I_b3_pin, // PIN_B3
|
|
|
+ (Icon*)&I_b2_pin, // PIN_B2
|
|
|
+ (Icon*)&I_c3_pin, // PIN_C3
|
|
|
+ (Icon*)&I_gear_unhighlighted, // GEARIC
|
|
|
+ (Icon*)&I_3v_pin, // PIN_3V
|
|
|
+ (Icon*)&I_swc_pin, // PIN_SWC
|
|
|
+ (Icon*)&I_sio_pin, // PIN_SIO
|
|
|
+ (Icon*)&I_tx_pin, // PIN_TX
|
|
|
+ (Icon*)&I_rx_pin, // PIN_RX
|
|
|
+ (Icon*)&I_c1_pin, // PIN_C1
|
|
|
+ (Icon*)&I_c0_pin, // PIN_C0
|
|
|
+ (Icon*)&I_1w_pin // PIN_1W
|
|
|
+};
|
|
|
+
|
|
|
+static uint8_t bot_row_y = 48;
|
|
|
+
|
|
|
+// Screen is 128x64 px
|
|
|
+static void app_draw_callback(Canvas* canvas, void* ctx) {
|
|
|
+ UNUSED(ctx);
|
|
|
+
|
|
|
+ canvas_clear(canvas);
|
|
|
+
|
|
|
+ // draw ground pins
|
|
|
+ canvas_draw_icon(canvas, x_pos[PIN_GND_08], -1, &I_gnd_pin);
|
|
|
+ canvas_draw_icon(canvas, x_pos[PIN_GND_11], bot_row_y, &I_gnd_pin);
|
|
|
+ canvas_draw_icon(canvas, x_pos[PIN_GND_18], bot_row_y, &I_gnd_pin);
|
|
|
+
|
|
|
+ // draw gear
|
|
|
+ canvas_draw_icon(canvas, x_pos[GEARIC], 0, (vstate.selected == GEARIC ? &I_gear_highlighted : &I_gear_unhighlighted));
|
|
|
+
|
|
|
+ // draw top row of pins
|
|
|
+ for( int i = 0; i < GEARIC; i++ )
|
|
|
+ {
|
|
|
+ int y = vstate.selected == i ? 0 : -3;
|
|
|
+ canvas_draw_icon(canvas, x_pos[i], y, icons[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // draw bottom row of pins
|
|
|
+ for( int i = PIN_3V; i <= PIN_1W; i++ )
|
|
|
+ {
|
|
|
+ int y = bot_row_y - (vstate.selected == i ? 3 : 0);
|
|
|
+ canvas_draw_icon(canvas, x_pos[i], y, icons[i]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void app_input_callback(InputEvent* input_event, void* ctx) {
|
|
|
+ furi_assert(ctx);
|
|
|
+
|
|
|
+ FuriMessageQueue* event_queue = ctx;
|
|
|
+ furi_message_queue_put(event_queue, input_event, FuriWaitForever);
|
|
|
+}
|
|
|
+
|
|
|
+int32_t gpio_controller_main(void* p) {
|
|
|
+ UNUSED(p);
|
|
|
+ FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
|
|
+
|
|
|
+ // Configure view port
|
|
|
+ ViewPort* view_port = view_port_alloc();
|
|
|
+ view_port_draw_callback_set(view_port, app_draw_callback, view_port);
|
|
|
+ view_port_input_callback_set(view_port, app_input_callback, event_queue);
|
|
|
+
|
|
|
+ // Register view port in GUI
|
|
|
+ Gui* gui = furi_record_open(RECORD_GUI);
|
|
|
+ gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
|
|
+
|
|
|
+ InputEvent event;
|
|
|
+
|
|
|
+ vstate.gpio_items = gpio_items_alloc();
|
|
|
+ gpio_items_configure_all_pins(vstate.gpio_items, GpioModeOutputPushPull);
|
|
|
+
|
|
|
+ bool running = true;
|
|
|
+ while(running) {
|
|
|
+ if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
|
|
|
+ if((event.type == InputTypePress) || (event.type == InputTypeRepeat)) {
|
|
|
+ switch(event.key) {
|
|
|
+ case InputKeyLeft:
|
|
|
+ vstate.selected--;
|
|
|
+ if(vstate.selected == GEARIC) vstate.selected = PIN_1W;
|
|
|
+ else if(vstate.selected < 0) vstate.selected = GEARIC;
|
|
|
+ break;
|
|
|
+ case InputKeyRight:
|
|
|
+ if(vstate.selected <= GEARIC)
|
|
|
+ {
|
|
|
+ vstate.selected++;
|
|
|
+ vstate.selected = vstate.selected > GEARIC ? PIN_5V : vstate.selected;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ vstate.selected++;
|
|
|
+ vstate.selected = vstate.selected > PIN_1W ? PIN_3V : vstate.selected;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case InputKeyUp:
|
|
|
+ case InputKeyDown:
|
|
|
+ if (y_mapping[vstate.selected] != NONE) vstate.selected = y_mapping[vstate.selected];
|
|
|
+ break;
|
|
|
+ case InputKeyBack:
|
|
|
+ running = false;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(event.key == InputKeyOk)
|
|
|
+ {
|
|
|
+ if( gp_pins[vstate.selected] >= 0 && (event.type == InputTypePress || event.type == InputTypeRelease) )
|
|
|
+ {
|
|
|
+ gpio_items_set_pin(vstate.gpio_items, gp_pins[vstate.selected], event.type == InputTypePress);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ view_port_update(view_port);
|
|
|
+ }
|
|
|
+
|
|
|
+ gpio_items_free(vstate.gpio_items);
|
|
|
+
|
|
|
+ view_port_enabled_set(view_port, false);
|
|
|
+ gui_remove_view_port(gui, view_port);
|
|
|
+ view_port_free(view_port);
|
|
|
+ furi_message_queue_free(event_queue);
|
|
|
+
|
|
|
+ furi_record_close(RECORD_GUI);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|