Просмотр исходного кода

initial commit of application; WIP - select pins and press ok to send a high value.

Lokno Ketchup Decker 2 лет назад
Родитель
Сommit
fa73d23f75

+ 2 - 1
README.md

@@ -1,2 +1,3 @@
 # gpio_controller
-A visual tool to control the general purpose pins of the Flipper Zero
+
+A visual tool to control the general purpose pins of the Flipper Zero

+ 11 - 0
application.fam

@@ -0,0 +1,11 @@
+App(
+    appid="gpio_controller",
+    name="GPIO Controller",
+    apptype=FlipperAppType.EXTERNAL,
+    entry_point="gpio_controller_main",
+    requires=["gui"],
+    stack_size=1 * 1024,
+    fap_category="GPIO",
+    fap_icon="icon10px.png",
+    fap_icon_assets="images",
+)

+ 239 - 0
gpio_controller.c

@@ -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;
+}

+ 69 - 0
gpio_items.c

@@ -0,0 +1,69 @@
+#include "gpio_items.h"
+
+#include <furi_hal_resources.h>
+
+struct GPIOItems {
+    GpioPinRecord* pins;
+    size_t count;
+};
+
+GPIOItems* gpio_items_alloc() {
+    GPIOItems* items = malloc(sizeof(GPIOItems));
+
+    items->count = 0;
+    for(size_t i = 0; i < gpio_pins_count; i++) {
+        if(!gpio_pins[i].debug) {
+            items->count++;
+        }
+    }
+
+    items->pins = malloc(sizeof(GpioPinRecord) * items->count);
+    for(size_t i = 0; i < items->count; i++) {
+        if(!gpio_pins[i].debug) {
+            items->pins[i].pin = gpio_pins[i].pin;
+            items->pins[i].name = gpio_pins[i].name;
+        }
+    }
+    return items;
+}
+
+void gpio_items_free(GPIOItems* items) {
+    free(items->pins);
+    free(items);
+}
+
+uint8_t gpio_items_get_count(GPIOItems* items) {
+    return items->count;
+}
+
+void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode) {
+    furi_assert(index < items->count);
+    furi_hal_gpio_write(items->pins[index].pin, false);
+    furi_hal_gpio_init(items->pins[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh);
+}
+
+void gpio_items_configure_all_pins(GPIOItems* items, GpioMode mode) {
+    for(uint8_t i = 0; i < items->count; i++) {
+        gpio_items_configure_pin(items, i, mode);
+    }
+}
+
+void gpio_items_set_pin(GPIOItems* items, uint8_t index, bool level) {
+    furi_assert(index < items->count);
+    furi_hal_gpio_write(items->pins[index].pin, level);
+}
+
+void gpio_items_set_all_pins(GPIOItems* items, bool level) {
+    for(uint8_t i = 0; i < items->count; i++) {
+        gpio_items_set_pin(items, i, level);
+    }
+}
+
+const char* gpio_items_get_pin_name(GPIOItems* items, uint8_t index) {
+    furi_assert(index < items->count + 1);
+    if(index == items->count) {
+        return "ALL";
+    } else {
+        return items->pins[index].name;
+    }
+}

+ 29 - 0
gpio_items.h

@@ -0,0 +1,29 @@
+#pragma once
+
+#include <furi_hal_gpio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct GPIOItems GPIOItems;
+
+GPIOItems* gpio_items_alloc();
+
+void gpio_items_free(GPIOItems* items);
+
+uint8_t gpio_items_get_count(GPIOItems* items);
+
+void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode);
+
+void gpio_items_configure_all_pins(GPIOItems* items, GpioMode mode);
+
+void gpio_items_set_pin(GPIOItems* items, uint8_t index, bool level);
+
+void gpio_items_set_all_pins(GPIOItems* items, bool level);
+
+const char* gpio_items_get_pin_name(GPIOItems* items, uint8_t index);
+
+#ifdef __cplusplus
+}
+#endif


BIN
images/1w_pin.png


BIN
images/3v_pin.png


BIN
images/5v_pin.png


BIN
images/a4_pin.png


BIN
images/a6_pin.png


BIN
images/a7_pin.png


BIN
images/arrow_down.png


BIN
images/arrow_up.png


BIN
images/b2_pin.png


BIN
images/b3_pin.png


BIN
images/c0_pin.png


BIN
images/c1_pin.png


BIN
images/c3_pin.png


BIN
images/gear_highlighted.png


BIN
images/gear_unhighlighted.png


BIN
images/gnd_pin.png


BIN
images/rx_pin.png


BIN
images/sio_pin.png


BIN
images/swc_pin.png


BIN
images/tx_pin.png