#include #include #include #include /* 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; }