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

Added a fixed delta time to improve animation; Replaced gpio_item header with internal code for handling gpio pins. Added display for digital pin values.

Lokno Ketchup Decker 2 лет назад
Родитель
Сommit
c2526525ac
6 измененных файлов с 196 добавлено и 122 удалено
  1. 196 24
      gpio_controller.c
  2. 0 69
      gpio_items.c
  3. 0 29
      gpio_items.h
  4. BIN
      images/analog_box.png
  5. BIN
      images/digi_one.png
  6. BIN
      images/digi_zero.png

+ 196 - 24
gpio_controller.c

@@ -8,12 +8,16 @@
  * Just set fap_icon_assets in application.fam and #include {APPID}_icons.h */
 #include "gpio_controller_icons.h"
 
-#include "gpio_items.h"
+#define GPIO_PIN_COUNT 8
+#define ANIMATE_FRAME_TIME_MS 133
+#define FRAME_TIME 66.666666 
 
 typedef struct {
     int selected;
-    GPIOItems* gpio_items;
+    //GPIOItems* gpio_items;
     int wiggle_frame;
+    size_t prev_frame_time;
+    size_t elapsed_time;
 } ViewerState;
 
 //  5V  A7  A6  A4  B3  B2  C3 GND SET
@@ -59,40 +63,200 @@ typedef struct {
     Icon* selected_icon;
 }ViewElement;
 
-static ViewerState vstate = {.selected = PIN_A7,.gpio_items = NULL,.wiggle_frame=-1};
+typedef struct {
+    uint8_t element_idx;
+    const GpioPin* pin;
+    GpioMode mode;
+    GpioPull pull;
+    GpioSpeed speed;
+    uint8_t value;
+    const char* name;
+    char* expression;
+    bool unset;
+    bool found;
+    bool input;
+}GPIOPin;
+
+static ViewerState vstate = {.selected = PIN_A7,.wiggle_frame=-1};
 
 static int wiggle[] = {-1,1,-1,1};
+static uint32_t wiggle_frame_count = 4;
 
 static ViewElement elements[] = {
-    {PIN_5V,     PIN_3V,  true, false,  true,  true, -1,   0,   0, "5V" ,                (Icon*)&I_5v_pin, NULL},
-    {PIN_A7,     PIN_SWC, true,  true,  true,  true,  0,  14,   0, "A7",                 (Icon*)&I_a7_pin, NULL},
-    {PIN_A6,     NONE,    true,  true,  true,  true,  1,  28,   0, "A6",                 (Icon*)&I_a6_pin, NULL},
-    {PIN_A4,     PIN_SIO, true,  true,  true,  true,  2,  42,   0, "A4",                 (Icon*)&I_a4_pin, NULL},
-    {PIN_B3,     PIN_TX,  true,  true,  true,  true,  3,  56,   0, "B3",                 (Icon*)&I_b3_pin, NULL},
-    {PIN_B2,     PIN_RX,  true,  true,  true,  true,  4,  70,   0, "B2",                 (Icon*)&I_b2_pin, NULL},
-    {PIN_C3,     PIN_C1,  true,  true,  true,  true,  5,  84,   0, "C3",                 (Icon*)&I_c3_pin, NULL}, 
-    {GEARIC,     PIN_1W,  true,  true,  true, false, -1, 112,   0, "Settings",               (Icon*)&I_gear_unhighlighted, (Icon*)&I_gear_highlighted},
-    {PIN_3V,     PIN_5V,  true, false, false,  true, -1,   0,  48, "3.3V",               (Icon*)&I_3v_pin, NULL},
+    {PIN_5V,     PIN_3V,  true, false,  true,  true, -1,   0,   0, "5V" ,               (Icon*)&I_5v_pin, NULL},
+    {PIN_A7,     PIN_SWC, true, false,  true,  true, -1,  14,   0, "PA7",               (Icon*)&I_a7_pin, NULL},
+    {PIN_A6,     NONE,    true, false,  true,  true, -1,  28,   0, "PA6",               (Icon*)&I_a6_pin, NULL},
+    {PIN_A4,     PIN_SIO, true, false,  true,  true, -1,  42,   0, "PA4",               (Icon*)&I_a4_pin, NULL},
+    {PIN_B3,     PIN_TX,  true, false,  true,  true, -1,  56,   0, "PB3",               (Icon*)&I_b3_pin, NULL},
+    {PIN_B2,     PIN_RX,  true, false,  true,  true, -1,  70,   0, "PB2",               (Icon*)&I_b2_pin, NULL},
+    {PIN_C3,     PIN_C1,  true, false,  true,  true, -1,  84,   0, "PC3",               (Icon*)&I_c3_pin, NULL}, 
+    {GEARIC,     PIN_1W,  true,  true,  true, false, -1, 112,   0, "Settings",          (Icon*)&I_gear_unhighlighted, (Icon*)&I_gear_highlighted},
+    {PIN_3V,     PIN_5V,  true, false, false,  true, -1,   0,  48, "3.3V",              (Icon*)&I_3v_pin, NULL},
     {PIN_SWC,    PIN_A7,  true, false, false,  true, -1,  14,  48, "Serial Wire Clock", (Icon*)&I_swc_pin, NULL},
     {PIN_SIO,    PIN_A4,  true, false, false,  true, -1,  42,  48, "Serial IO",         (Icon*)&I_sio_pin, NULL},
     {PIN_TX,     PIN_B3,  true, false, false,  true, -1,  56,  48, "UART - Transmit",   (Icon*)&I_tx_pin, NULL},
     {PIN_RX,     PIN_B2,  true, false, false,  true, -1,  70,  48, "UART - Receive",    (Icon*)&I_rx_pin, NULL},
-    {PIN_C1,     PIN_C3,  true,  true, false,  true,  6,  84,  48, "C1",                (Icon*)&I_c1_pin, NULL},
-    {PIN_C0,     NONE,    true,  true, false,  true,  7,  98,  48, "C0",                (Icon*)&I_c0_pin, NULL},
+    {PIN_C1,     PIN_C3,  true, false, false,  true, -1,  84,  48, "PC1",               (Icon*)&I_c1_pin, NULL},
+    {PIN_C0,     NONE,    true, false, false,  true, -1,  98,  48, "PC0",               (Icon*)&I_c0_pin, NULL},
     {PIN_1W,     GEARIC,  true,  true, false,  true, -1, 112,  48, "1-Wire",            (Icon*)&I_1w_pin, NULL},
-    {PIN_GND_08, NONE,   false, false,  true, false, -1,  98,  -1, "GND (Ground)",       (Icon*)&I_gnd_pin, NULL},
+    {PIN_GND_08, NONE,   false, false,  true, false, -1,  98,  -1, "GND (Ground)",      (Icon*)&I_gnd_pin, NULL},
     {PIN_GND_11, NONE,   false, false, false, false, -1,  28,  48, "GND (Ground)",      (Icon*)&I_gnd_pin, NULL},
     {PIN_GND_18, NONE,   false, false, false, false, -1, 126,  48, "GND (Ground)",      (Icon*)&I_gnd_pin, NULL},
 };
 
+static GPIOPin gpio_pin_config[GPIO_PIN_COUNT];
+
 static int element_count = NONE;
 
+// GPIO enums from firmware/targets/f7/furi_hal/furi_hal_gpio.h
+
+// /**
+//  * Gpio modes
+//  */
+// typedef enum {
+//     *GpioModeInput,
+//     *GpioModeOutputPushPull,
+//     GpioModeOutputOpenDrain,
+//     GpioModeAltFunctionPushPull,
+//     GpioModeAltFunctionOpenDrain,
+//     *GpioModeAnalog,
+//     GpioModeInterruptRise,
+//     GpioModeInterruptFall,
+//     GpioModeInterruptRiseFall,
+//     GpioModeEventRise,
+//     GpioModeEventFall,
+//     GpioModeEventRiseFall,
+// } GpioMode;
+
+// /**
+//  * Gpio pull modes
+//  */
+// typedef enum {
+//     GpioPullNo,
+//     GpioPullUp,
+//     GpioPullDown,
+// } GpioPull;
+
+// /**
+//  * Gpio speed modes
+//  */
+// typedef enum {
+//     GpioSpeedLow,
+//     GpioSpeedMedium,
+//     GpioSpeedHigh,
+//     GpioSpeedVeryHigh,
+// } GpioSpeed;
+
+static void init_gpio()
+{
+    int count = 0;
+    for(size_t i = 0; i < gpio_pins_count; i++) {
+        if(!gpio_pins[i].debug) {
+            for(int j = 0; j < element_count; j++) {
+                if( strcmp(elements[j].name,gpio_pins[i].name) == 0 )
+                {
+                        gpio_pin_config[count].element_idx = j;
+                        gpio_pin_config[count].pin         = gpio_pins[i].pin;
+                        gpio_pin_config[count].mode        = GpioModeOutputPushPull;
+                        gpio_pin_config[count].pull        = GpioPullNo;
+                        gpio_pin_config[count].speed       = GpioSpeedVeryHigh;
+                        gpio_pin_config[count].value       = 0;
+                        gpio_pin_config[count].name        = gpio_pins[i].name;
+                        gpio_pin_config[count].expression  = NULL;
+                        gpio_pin_config[count].unset       = true;
+                        gpio_pin_config[count].found       = true;
+                        gpio_pin_config[count].input       = false;
+
+                        elements[j].gp_idx   = i;
+                        elements[j].editable = true;
+
+                        count++;
+                }
+            }
+        }
+    }
+
+    // naively set all as digitial output
+    for(int i = 0; i < count; i++) {
+        GPIOPin* gpc = &gpio_pin_config[i];
+        gpc->input = true;
+        gpc->unset = false;
+        furi_hal_gpio_write(gpc->pin, false);
+        furi_hal_gpio_init(gpc->pin, gpc->mode, gpc->pull, gpc->speed);
+    }
+}
+
+//static void update_gpio()
+//{
+//    // write to gpio pins
+//
+//    // read frm gpio pins
+//}
+
+// TODO: Determine the lowest frame delta we can get away with. 
+// TODO: Redraw only what changes.
+//       - clear previous (drawn) selected pin
+//       - clear newly selected pin
+
 // Screen is 128x64 px
 static void app_draw_callback(Canvas* canvas, void* ctx) {
     UNUSED(ctx);
 
     canvas_clear(canvas);
 
+    size_t current_frame_time = furi_get_tick();
+    size_t delta_cycles = (current_frame_time > vstate.prev_frame_time ? current_frame_time - vstate.prev_frame_time : 0);
+    size_t delta_time_ms = delta_cycles * 1000 / furi_kernel_get_tick_frequency();
+
+    // delay until desired delta time and recalculate
+    if( delta_time_ms < FRAME_TIME )
+    {
+        furi_delay_ms(FRAME_TIME-delta_time_ms);
+        current_frame_time = furi_get_tick();
+        delta_cycles = (current_frame_time > vstate.prev_frame_time ? current_frame_time - vstate.prev_frame_time : 0);
+        delta_time_ms = delta_cycles * 1000 / furi_kernel_get_tick_frequency();
+    }
+    
+    vstate.elapsed_time += delta_time_ms;
+    vstate.prev_frame_time = current_frame_time;
+
+    // draw values
+    for(int i = 0; i < GPIO_PIN_COUNT; i++) {
+        if( !gpio_pin_config[i].unset )
+        {
+            ViewElement e = elements[gpio_pin_config[i].element_idx];
+
+            // draw wire
+            if(e.top_row)
+            {
+                canvas_draw_line(canvas, e.x_pos + 6, e.y_pos + 16, e.x_pos + 6, e.y_pos + 16 + 8);
+            }
+            else
+            {
+                canvas_draw_line(canvas, e.x_pos + 6, e.y_pos, e.x_pos + 6, e.y_pos - 8);
+            }
+            
+
+            if(gpio_pin_config[i].mode == GpioModeAnalog)
+            {
+
+            }
+            else
+            {
+                const Icon* icon = gpio_pin_config[i].value ? &I_digi_one : &I_digi_zero;
+                if(e.top_row)
+                {
+                    canvas_draw_icon(canvas, e.x_pos + 2, e.y_pos + 20, icon);
+                }   
+                else
+                {
+                    canvas_draw_icon(canvas, e.x_pos + 2, e.y_pos - 13, icon);
+                }
+                
+            }
+        }
+    }
+
     for(int i = 0; i < element_count; i++)
     {
         ViewElement e = elements[i];
@@ -113,11 +277,16 @@ static void app_draw_callback(Canvas* canvas, void* ctx) {
 
             if(vstate.wiggle_frame >= 0)
             {
-                x += wiggle[vstate.wiggle_frame/2];
-                vstate.wiggle_frame++;
-                if ((unsigned int)(vstate.wiggle_frame/2) >= (sizeof(wiggle)/sizeof(int)))
+                x += wiggle[vstate.wiggle_frame];
+
+                if(vstate.elapsed_time >= ANIMATE_FRAME_TIME_MS)
                 {
-                    vstate.wiggle_frame = -1;
+                    vstate.wiggle_frame++;
+                    if ((unsigned int)(vstate.wiggle_frame) >= wiggle_frame_count) //(sizeof(wiggle)/sizeof(int)))
+                    {
+                        vstate.wiggle_frame = -1;
+                    }
+                    vstate.elapsed_time = 0;
                 }
             }
         }
@@ -151,8 +320,10 @@ int32_t gpio_controller_main(void* p) {
 
     InputEvent event;
 
-    vstate.gpio_items = gpio_items_alloc();
-    gpio_items_configure_all_pins(vstate.gpio_items, GpioModeOutputPushPull);
+    init_gpio();
+
+    vstate.prev_frame_time = furi_get_tick();
+    vstate.elapsed_time = 0;
 
     bool running = true;
     while(running) {
@@ -164,10 +335,13 @@ int32_t gpio_controller_main(void* p) {
                     if( event.type == InputTypePress && elements[vstate.selected].gp_idx < 0 )
                     {
                         vstate.wiggle_frame = 0;
+                        vstate.elapsed_time = 0;
                     }
                     else if( elements[vstate.selected].gp_idx >= 0 && (event.type == InputTypePress || event.type == InputTypeRelease) )
                     {
-                        gpio_items_set_pin(vstate.gpio_items, elements[vstate.selected].gp_idx, event.type == InputTypePress);
+                        int gp_idx = elements[vstate.selected].gp_idx;
+                        furi_hal_gpio_write(gpio_pin_config[gp_idx].pin, event.type == InputTypePress);
+                        gpio_pin_config[gp_idx].value = event.type == InputTypePress ? 1 : 0;
                     }
                 }
                 else if(event.type == InputTypePress || event.type == InputTypeRepeat) {
@@ -205,8 +379,6 @@ int32_t gpio_controller_main(void* p) {
         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);

+ 0 - 69
gpio_items.c

@@ -1,69 +0,0 @@
-#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;
-    }
-}

+ 0 - 29
gpio_items.h

@@ -1,29 +0,0 @@
-#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/analog_box.png


BIN
images/digi_one.png


BIN
images/digi_zero.png