aanper 5 лет назад
Родитель
Сommit
e684869970

+ 73 - 43
applications/gui/canvas.c

@@ -6,74 +6,104 @@
 #include <u8g2.h>
 
 struct Canvas {
-    FuriRecordSubscriber* fb_record;
-    u8g2_t* fb;
+    u8g2_t fb;
     uint8_t offset_x;
     uint8_t offset_y;
     uint8_t width;
     uint8_t height;
 };
 
-Canvas* canvas_alloc() {
-    Canvas* canvas = furi_alloc(sizeof(Canvas));
-    canvas->fb_record = furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
-    assert(canvas->fb_record);
-    return canvas;
+uint8_t canvas_width(CanvasApi* api);
+uint8_t canvas_height(CanvasApi* api);
+void canvas_clear(CanvasApi* api);
+void canvas_color_set(CanvasApi* api, uint8_t color);
+void canvas_font_set(CanvasApi* api, Font font);
+void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str);
+
+CanvasApi* canvas_api_init() {
+    CanvasApi* api = furi_alloc(sizeof(CanvasApi));
+
+    u8g2_t _u8g2;
+    u8g2_Setup_st7565_erc12864_alt_f(
+        &api->canvas.fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
+    u8g2_InitDisplay(
+        &canvas->fb); // send init sequence to the display, display is in sleep mode after this
+    u8g2_SetContrast(&api->canvas.fb, 36);
+
+    u8g2_SetPowerSave(&api->canvas.fb, 0); // wake up display
+    u8g2_SendBuffer(&api->canvas.fb);
+
+    api->width = canvas_width;
+    api->height = canvas_height;
+    api->clear = canvas_clear;
+    api->canvas_color_set = canvas_color_set;
+    api->canvas_font_set = canvas_font_set;
+    api->draw_str = canvas_str_draw;
+
+    api->fonts = {
+        .primary = u8g2_font_Born2bSportyV2_tr,
+        .secondary = u8g2_font_HelvetiPixel_tr,
+    };
+
+    return api;
 }
 
-void canvas_free(Canvas* canvas) {
-    assert(canvas);
-    free(canvas);
+void canvas_api_free(CanvasApi* api) {
+    assert(api);
+    free(api);
 }
 
-void canvas_commit(Canvas* canvas) {
-    assert(canvas);
-    if(canvas->fb) {
-        furi_commit(canvas->fb_record);
-        canvas->fb = NULL;
-    }
+void canvas_commit(CanvasApi* api) {
+    assert(api);
+
+    u8g2_SetPowerSave(&api->canvas.fb, 0); // wake up display
+    u8g2_SendBuffer(&api->canvas.fb);
 }
 
 void canvas_frame_set(
-    Canvas* canvas,
+    CanvasApi* api,
     uint8_t offset_x,
     uint8_t offset_y,
     uint8_t width,
     uint8_t height) {
-    assert(canvas);
-    canvas->offset_x = offset_x;
-    canvas->offset_y = offset_y;
-    canvas->width = width;
-    canvas->height = height;
+    assert(api);
+    api->canvas.offset_x = offset_x;
+    api->canvas.offset_y = offset_y;
+    api->canvas.width = width;
+    api->canvas.height = height;
 }
 
-u8g2_t* canvas_fb(Canvas* canvas) {
-    if(!canvas->fb) {
-        canvas->fb = furi_take(canvas->fb_record);
-        assert(canvas->fb);
-    }
-    return canvas->fb;
+uint8_t canvas_width(CanvasApi* api) {
+    assert(api);
+
+    return api->canvas.width;
+}
+
+uint8_t canvas_height(CanvasApi* api) {
+    assert(api);
+
+    return api->canvas.height;
 }
 
-void canvas_clear(Canvas* canvas) {
-    u8g2_t* fb = canvas_fb(canvas);
-    u8g2_ClearBuffer(fb);
+void canvas_clear(CanvasApi* api) {
+    assert(api);
+    u8g2_ClearBuffer(&api->canvas.fb);
 }
 
-void canvas_color_set(Canvas* canvas, uint8_t color) {
-    u8g2_t* fb = canvas_fb(canvas);
-    u8g2_SetDrawColor(fb, 1);
+void canvas_color_set(CanvasApi* api, Color color) {
+    assert(api);
+    u8g2_SetDrawColor(&api->canvas.fb, color);
 }
 
-void canvas_font_set(Canvas* canvas, font_t font) {
-    u8g2_t* fb = canvas_fb(canvas);
-    u8g2_SetFontMode(fb, 1);
-    u8g2_SetFont(fb, font);
+void canvas_font_set(CanvasApi* api, Font font) {
+    assert(api);
+    u8g2_SetFontMode(&api->canvas.fb, 1);
+    u8g2_SetFont(&api->canvas.fb, font);
 }
 
-void canvas_str_draw(Canvas* canvas, uint8_t x, uint8_t y, const char* str) {
-    x += canvas->offset_x;
-    y += canvas->offset_y;
-    u8g2_t* fb = canvas_fb(canvas);
-    u8g2_DrawStr(fb, x, y, str);
+void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str) {
+    assert(api);
+    x += api->canvas.offset_x;
+    y += api->canvas.offset_y;
+    u8g2_DrawStr(&api->canvas.fb, x, y, str);
 }

+ 24 - 13
applications/gui/canvas.h

@@ -1,24 +1,35 @@
 #pragma once
 
 #include <stdint.h>
-#include <u8g2.h>
 
-#define COLOR_WHITE 0x00
-#define COLOR_BLACK 0x01
-
-#define CANVAS_FONT_PRIMARY u8g2_font_Born2bSportyV2_tr
-#define CANVAS_FONT_SECONDARY u8g2_font_HelvetiPixel_tr
+typedef enum {
+	ColorWhite = 0x00,
+	ColorBlack = 0x01,
+} Color;
 
 typedef struct Canvas Canvas;
-typedef const uint8_t* font_t;
+typedef const uint8_t* Font;
+
+struct _CanvasApi;
+
+typedef struct _CanvasApi CanvasApi;
 
-uint8_t canvas_width(Canvas* canvas);
-uint8_t canvas_height(Canvas* canvas);
+typedef struct {
+	Font primary;
+	Font secondary;
+} Fonts;
 
-void canvas_clear(Canvas* canvas);
+struct {
+    Canvas canvas;
+    Fonts* fonts;
+    
+    uint8_t (*width)(CanvasApi* canvas);
+    uint8_t (*height)(CanvasApi* canvas);
 
-void canvas_color_set(Canvas* canvas, uint8_t color);
+    void (*clear)(CanvasApi* canvas);
 
-void canvas_font_set(Canvas* canvas, font_t font);
+    void (*canvas_color_set)(CanvasApi* canvas, Color color);
+    void (*canvas_font_set)(CanvasApi* canvas, Font font);
 
-void canvas_str_draw(Canvas* canvas, uint8_t x, uint8_t y, const char* str);
+    void (*draw_str)(CanvasApi* canvas, uint8_t x, uint8_t y, const char* str);
+} _CanvasApi;

+ 2 - 2
applications/gui/canvas_i.h

@@ -1,8 +1,8 @@
 #pragma once
 
-Canvas* canvas_alloc();
+CanvasApi* canvas_api_init();
 
-void canvas_free(Canvas* canvas);
+void canvas_api_free(CanvasApi* api);
 
 void canvas_commit(Canvas* canvas);
 

+ 26 - 23
applications/gui/gui.c

@@ -13,16 +13,16 @@
 
 ARRAY_DEF(WidgetArray, Widget*, M_PTR_OPLIST);
 
-struct GUI {
-    GUIEvent* event;
-    Canvas* canvas;
+struct Gui {
+    GuiEvent* event;
+    CanvasApi* canvas_api;
     WidgetArray_t widgets_status_bar;
     WidgetArray_t widgets;
     WidgetArray_t widgets_fs;
     WidgetArray_t widgets_dialog;
 };
 
-void gui_add_widget(GUI* gui, Widget* widget, WidgetLayer layer) {
+void gui_add_widget(Gui* gui, Widget* widget, WidgetLayer layer) {
     WidgetArray_t* widget_array = NULL;
 
     switch(layer) {
@@ -54,10 +54,10 @@ void gui_add_widget(GUI* gui, Widget* widget, WidgetLayer layer) {
     gui_update(gui);
 }
 
-void gui_update(GUI* gui) {
+void gui_update(Gui* gui) {
     assert(gui);
-    GUIMessage message;
-    message.type = GUIMessageTypeRedraw;
+    GuiMessage message;
+    message.type = GuiMessageTypeRedraw;
     gui_event_messsage_send(gui->event, &message);
 }
 
@@ -72,7 +72,7 @@ Widget* gui_widget_find_enabled(WidgetArray_t array) {
     return NULL;
 }
 
-bool gui_redraw_fs(GUI* gui) {
+bool gui_redraw_fs(Gui* gui) {
     canvas_frame_set(gui->canvas, 0, 0, 128, 64);
     Widget* widget = gui_widget_find_enabled(gui->widgets_fs);
     if(widget) {
@@ -83,25 +83,25 @@ bool gui_redraw_fs(GUI* gui) {
     }
 }
 
-void gui_redraw_status_bar(GUI* gui) {
+void gui_redraw_status_bar(Gui* gui) {
     canvas_frame_set(gui->canvas, 0, 0, 128, 64);
     Widget* widget = gui_widget_find_enabled(gui->widgets_status_bar);
     if(widget) widget_draw(widget, gui->canvas);
 }
 
-void gui_redraw_normal(GUI* gui) {
+void gui_redraw_normal(Gui* gui) {
     canvas_frame_set(gui->canvas, 0, 9, 128, 55);
     Widget* widget = gui_widget_find_enabled(gui->widgets);
     if(widget) widget_draw(widget, gui->canvas);
 }
 
-void gui_redraw_dialogs(GUI* gui) {
+void gui_redraw_dialogs(Gui* gui) {
     canvas_frame_set(gui->canvas, 10, 20, 118, 44);
     Widget* widget = gui_widget_find_enabled(gui->widgets_dialog);
     if(widget) widget_draw(widget, gui->canvas);
 }
 
-void gui_redraw(GUI* gui) {
+void gui_redraw(Gui* gui) {
     assert(gui);
 
     if(!gui_redraw_fs(gui)) {
@@ -110,10 +110,11 @@ void gui_redraw(GUI* gui) {
     }
     gui_redraw_dialogs(gui);
 
-    canvas_commit(gui->canvas);
+    // canvas_commit(gui->canvas);
+    // redraw u8g2
 }
 
-void gui_input(GUI* gui, InputEvent* input_event) {
+void gui_input(Gui* gui, InputEvent* input_event) {
     assert(gui);
 
     Widget* widget = gui_widget_find_enabled(gui->widgets_dialog);
@@ -125,8 +126,8 @@ void gui_input(GUI* gui, InputEvent* input_event) {
     }
 }
 
-GUI* gui_alloc() {
-    GUI* gui = furi_alloc(sizeof(GUI));
+Gui* gui_alloc() {
+    Gui* gui = furi_alloc(sizeof(Gui));
     // Initialize widget arrays
     WidgetArray_init(gui->widgets_status_bar);
     WidgetArray_init(gui->widgets);
@@ -135,15 +136,17 @@ GUI* gui_alloc() {
 
     // Event dispatcher
     gui->event = gui_event_alloc();
-    
-    // Drawing canvas
-    gui->canvas = canvas_alloc();
+
+    // Drawing canvas api
+
+    gui->canvas_api = 
+    canvas_api_init();
 
     return gui;
 }
 
 void gui_task(void* p) {
-    GUI* gui = gui_alloc();
+    Gui* gui = gui_alloc();
 
     GuiApi gui_api = {
         .add_widget = gui_add_widget,
@@ -160,10 +163,10 @@ void gui_task(void* p) {
 
     // Forever dispatch
     while(1) {
-        GUIMessage message = gui_event_message_next(gui->event);
-        if(message.type == GUIMessageTypeRedraw) {
+        GuiMessage message = gui_event_message_next(gui->event);
+        if(message.type == GuiMessageTypeRedraw) {
             gui_redraw(gui);
-        } else if(message.type == GUIMessageTypeInput) {
+        } else if(message.type == GuiMessageTypeInput) {
             gui_input(gui, &message.input);
         }
     }

+ 4 - 3
applications/gui/gui.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "widget.h"
+#include "canvas.h"
 
 typedef enum {
     WidgetLayerStatusBar,
@@ -10,9 +11,9 @@ typedef enum {
 } WidgetLayer;
 
 typedef struct Widget Widget;
-typedef struct GUI GUI;
+typedef struct Gui Gui;
 
 typedef struct {
-    void (*add_widget)(GUI* gui, Widget* widget, WidgetLayer layer);
-    GUI* gui;
+    void (*add_widget)(Gui* gui, Widget* widget, WidgetLayer layer);
+    Gui* gui;
 } GuiApi;

+ 9 - 9
applications/gui/gui_event.c

@@ -5,7 +5,7 @@
 
 #define GUI_EVENT_MQUEUE_SIZE 8
 
-struct GUIEvent {
+struct GuiEvent {
     FuriRecordSubscriber* input_event_record;
     osMessageQueueId_t mqueue;
     osMutexId_t lock_mutex;
@@ -13,7 +13,7 @@ struct GUIEvent {
 
 void gui_event_input_events_callback(const void* value, size_t size, void* ctx) {
     assert(ctx);
-    GUIEvent* gui_event = ctx;
+    GuiEvent* gui_event = ctx;
 
     GUIMessage message;
     message.type = GUIMessageTypeInput;
@@ -22,8 +22,8 @@ void gui_event_input_events_callback(const void* value, size_t size, void* ctx)
     osMessageQueuePut(gui_event->mqueue, &message, 0, 0);
 }
 
-GUIEvent* gui_event_alloc() {
-    GUIEvent* gui_event = furi_alloc(sizeof(GUIEvent));
+GuiEvent* gui_event_alloc() {
+    GuiEvent* gui_event = furi_alloc(sizeof(GuiEvent));
     // Allocate message que
     gui_event->mqueue = osMessageQueueNew(GUI_EVENT_MQUEUE_SIZE, sizeof(GUIMessage), NULL);
     assert(gui_event->mqueue);
@@ -40,30 +40,30 @@ GUIEvent* gui_event_alloc() {
     return gui_event;
 }
 
-void gui_event_free(GUIEvent* gui_event) {
+void gui_event_free(GuiEvent* gui_event) {
     assert(gui_event);
     gui_event_unlock(gui_event);
     assert(osMessageQueueDelete(gui_event->mqueue) == osOK);
     free(gui_event);
 }
 
-void gui_event_lock(GUIEvent* gui_event) {
+void gui_event_lock(GuiEvent* gui_event) {
     assert(gui_event);
     assert(osMutexAcquire(gui_event->lock_mutex, osWaitForever) == osOK);
 }
 
-void gui_event_unlock(GUIEvent* gui_event) {
+void gui_event_unlock(GuiEvent* gui_event) {
     assert(gui_event);
     assert(osMutexRelease(gui_event->lock_mutex) == osOK);
 }
 
-void gui_event_messsage_send(GUIEvent* gui_event, GUIMessage* message) {
+void gui_event_messsage_send(GuiEvent* gui_event, GUIMessage* message) {
     assert(gui_event);
     assert(message);
     osMessageQueuePut(gui_event->mqueue, message, 0, 0);
 }
 
-GUIMessage gui_event_message_next(GUIEvent* gui_event) {
+GUIMessage gui_event_message_next(GuiEvent* gui_event) {
     assert(gui_event);
     GUIMessage message;
     gui_event_unlock(gui_event);

+ 7 - 7
applications/gui/gui_event.h

@@ -14,16 +14,16 @@ typedef struct {
     void* data;
 } GUIMessage;
 
-typedef struct GUIEvent GUIEvent;
+typedef struct GuiEvent GuiEvent;
 
-GUIEvent* gui_event_alloc();
+GuiEvent* gui_event_alloc();
 
-void gui_event_free(GUIEvent* gui_event);
+void gui_event_free(GuiEvent* gui_event);
 
-void gui_event_lock(GUIEvent* gui_event);
+void gui_event_lock(GuiEvent* gui_event);
 
-void gui_event_unlock(GUIEvent* gui_event);
+void gui_event_unlock(GuiEvent* gui_event);
 
-void gui_event_messsage_send(GUIEvent* gui_event, GUIMessage* message);
+void gui_event_messsage_send(GuiEvent* gui_event, GUIMessage* message);
 
-GUIMessage gui_event_message_next(GUIEvent* gui_event);
+GUIMessage gui_event_message_next(GuiEvent* gui_event);

+ 1 - 1
applications/gui/gui_i.h

@@ -1,3 +1,3 @@
 #pragma once
 
-void gui_update(GUI* gui);
+void gui_update(Gui* gui);

+ 18 - 3
applications/gui/widget.c

@@ -7,6 +7,15 @@
 #include "gui.h"
 #include "gui_i.h"
 
+struct Widget {
+    void* gui;
+    bool is_enabled;
+    WidgetDrawCallback draw_callback;
+    void* draw_callback_context;
+    WidgetInputCallback input_callback;
+    void* input_callback_context;
+}
+
 Widget* widget_alloc(WidgetDrawCallback callback, void* callback_context) {
     Widget* widget = furi_alloc(sizeof(Widget));
     widget->is_enabled = true;
@@ -53,12 +62,18 @@ void widget_gui_set(Widget* widget, GUI* gui) {
     widget->gui = gui;
 }
 
-void widget_draw(Widget* widget, Canvas* canvas) {
+void widget_draw(Widget* widget, ValueMutex* canvas_api_mutex) {
     assert(widget);
-    assert(canvas);
+    assert(canvas_api_mutex);
     assert(widget->gui);
 
-    if(widget->draw_callback) widget->draw_callback(canvas, widget->draw_callback_context);
+    if(widget->draw_callback) {
+        CanvasApi* api = acquire_mutex_block(canvas_api_mutex); // TODO: timeout?
+        if(api != NULL) {
+            widget->draw_callback(api, widget->draw_callback_context);
+        }
+        release_mutex(canvas_api_mutex, api);
+    }
 }
 
 void widget_input(Widget* widget, InputEvent* event) {

+ 3 - 12
applications/gui/widget.h

@@ -1,20 +1,11 @@
 #pragma once
 
 #include <input/input.h>
+#include "canvas.h"
 
-typedef struct GUI GUI;
-typedef struct Canvas Canvas;
+typedef struct Widget Widget;
 
-typedef struct {
-    void* gui;
-    bool is_enabled;
-    WidgetDrawCallback draw_callback;
-    void* draw_callback_context;
-    WidgetInputCallback input_callback;
-    void* input_callback_context;
-} Widget;
-
-typedef void (*WidgetDrawCallback)(Canvas* canvas, void* context);
+typedef void (*WidgetDrawCallback)(CanvasApi* api, void* context);
 typedef void (*WidgetInputCallback)(InputEvent* event, void* context);
 
 Widget* widget_alloc();

+ 1 - 1
applications/gui/widget_i.h

@@ -1,6 +1,6 @@
 #pragma once
 
-void widget_gui_set(Widget* widget, GUI* gui);
+void widget_gui_set(Widget* widget, Gui* gui);
 
 void widget_draw(Widget* widget, Canvas* canvas);
 

+ 1 - 2
applications/menu/menu.c

@@ -6,7 +6,6 @@
 #include <flipper.h>
 #include <gui/gui.h>
 #include <gui/canvas.h>
-#include <gui/widget.h>
 
 #include "menu_event.h"
 #include "menu_item.h"
@@ -37,7 +36,7 @@ Menu* menu_alloc() {
     widget_input_callback_set(menu->widget, menu_event_input_callback, menu->event);
 
     // Open GUI and register fullscreen widget
-    menu->gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL);
+    menu->gui_record = furi_open("gui");
     assert(menu->gui_record);
 
     return menu;