From f2a38cf1740e1f0605a11af5588f72025119333c Mon Sep 17 00:00:00 2001 From: aanper Date: Thu, 15 Oct 2020 10:38:20 +0300 Subject: [PATCH 01/14] fix syntax --- applications/examples/fatfs_list.c | 3 ++- applications/examples/u8g2_example.c | 3 ++- applications/examples/u8g2_qrcode.c | 3 ++- applications/gui/gui_event.c | 7 ++++--- applications/menu/menu.c | 2 +- applications/tests/furi_valuemutex_test.c | 1 - applications/tests/minunit_test.c | 1 - core/api-basic/value-expanders.h | 12 +++--------- core/api-hal/api-spi.h | 17 ++++++++++------- 9 files changed, 24 insertions(+), 25 deletions(-) diff --git a/applications/examples/fatfs_list.c b/applications/examples/fatfs_list.c index b15db514..58e6730c 100644 --- a/applications/examples/fatfs_list.c +++ b/applications/examples/fatfs_list.c @@ -49,7 +49,8 @@ void fatfs_list(void* p) { furi_log = get_default_log(); - FuriRecordSubscriber* fb_record = furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL); + FuriRecordSubscriber* fb_record = + furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL); if(fb_record == NULL) { fuprintf(furi_log, "[widget][fatfs_list] cannot create fb record\n"); furiac_exit(NULL); diff --git a/applications/examples/u8g2_example.c b/applications/examples/u8g2_example.c index 02f35ecb..e77012d4 100644 --- a/applications/examples/u8g2_example.c +++ b/applications/examples/u8g2_example.c @@ -5,7 +5,8 @@ void u8g2_example(void* p) { FuriRecordSubscriber* log = get_default_log(); // open record - FuriRecordSubscriber* fb_record = furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL); + FuriRecordSubscriber* fb_record = + furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL); if(fb_record == NULL) { fuprintf(log, "[widget] cannot create fb record\n"); diff --git a/applications/examples/u8g2_qrcode.c b/applications/examples/u8g2_qrcode.c index 630199c1..2799df33 100644 --- a/applications/examples/u8g2_qrcode.c +++ b/applications/examples/u8g2_qrcode.c @@ -14,7 +14,8 @@ void u8g2_qrcode(void* p) { FuriRecordSubscriber* log = get_default_log(); // open record - FuriRecordSubscriber* fb_record = furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL); + FuriRecordSubscriber* fb_record = + furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL); // Allocate a chunk of memory to store the QR code // https://github.com/ricmoo/QRCode diff --git a/applications/gui/gui_event.c b/applications/gui/gui_event.c index 1d7caf64..a2ee801b 100644 --- a/applications/gui/gui_event.c +++ b/applications/gui/gui_event.c @@ -29,8 +29,8 @@ GUIEvent* gui_event_alloc() { assert(gui_event->mqueue); // Input - gui_event->input_event_record = - furi_open_deprecated("input_events", false, false, gui_event_input_events_callback, NULL, gui_event); + gui_event->input_event_record = furi_open_deprecated( + "input_events", false, false, gui_event_input_events_callback, NULL, gui_event); assert(gui_event->input_event_record != NULL); // Lock mutex gui_event->lock_mutex = osMutexNew(NULL); @@ -58,7 +58,8 @@ void gui_event_unlock(GUIEvent* gui_event) { } void gui_event_messsage_send(GUIEvent* gui_event, GUIMessage* message) { - assert(gui_event); assert(message); + assert(gui_event); + assert(message); osMessageQueuePut(gui_event->mqueue, message, 0, 0); } diff --git a/applications/menu/menu.c b/applications/menu/menu.c index f551c6af..8cafe6a4 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -187,7 +187,7 @@ void menu_task(void* p) { furiac_exit(NULL); } furiac_ready(); - + while(1) { MenuMessage m = menu_event_next(menu->event); diff --git a/applications/tests/furi_valuemutex_test.c b/applications/tests/furi_valuemutex_test.c index 960d1543..6279d188 100644 --- a/applications/tests/furi_valuemutex_test.c +++ b/applications/tests/furi_valuemutex_test.c @@ -39,7 +39,6 @@ void test_furi_valuemutex() { //read mutex blocking case } - /* TEST: concurrent access diff --git a/applications/tests/minunit_test.c b/applications/tests/minunit_test.c index f99b6204..37cc6b77 100644 --- a/applications/tests/minunit_test.c +++ b/applications/tests/minunit_test.c @@ -67,7 +67,6 @@ MU_TEST_SUITE(test_suite) { MU_RUN_TEST(mu_test_furi_create_open); MU_RUN_TEST(mu_test_furi_valuemutex); MU_RUN_TEST(mu_test_furi_concurrent_access); - } int run_minunit() { diff --git a/core/api-basic/value-expanders.h b/core/api-basic/value-expanders.h index cec0e75c..70adf856 100644 --- a/core/api-basic/value-expanders.h +++ b/core/api-basic/value-expanders.h @@ -12,15 +12,10 @@ void COPY_COMPOSE(void* ctx, void* state) { read_mutex((ValueMutex*)ctx, state, 0); } -typedef enum { - UiLayerBelowNotify - UiLayerNotify, - UiLayerAboveNotify -} UiLayer; +typedef enum { UiLayerBelowNotify UiLayerNotify, UiLayerAboveNotify } UiLayer; -ValueComposerHandle* add_compose_layer( - ValueComposer* composer, ValueComposerCallback cb, void* ctx, uint32_t layer -); +ValueComposerHandle* +add_compose_layer(ValueComposer* composer, ValueComposerCallback cb, void* ctx, uint32_t layer); bool remove_compose_layer(ValueComposerHandle* handle); @@ -44,7 +39,6 @@ typedef struct { PubSub pubsub; } ValueManager; - /* acquire value, changes it and send notify with current value. */ diff --git a/core/api-hal/api-spi.h b/core/api-hal/api-spi.h index b3bfe674..74559c54 100644 --- a/core/api-hal/api-spi.h +++ b/core/api-hal/api-spi.h @@ -17,13 +17,17 @@ For transmit/receive data use `spi_xfer` function. */ bool spi_xfer( SPI_HandleTypeDef* spi, - uint8_t* tx_data, uint8_t* rx_data, size_t len, - PubSubCallback cb, void* ctx); + uint8_t* tx_data, + uint8_t* rx_data, + size_t len, + PubSubCallback cb, + void* ctx); /* Blocking verison: */ -static inline bool spi_xfer_block(SPI_HandleTypeDef* spi, uint8_t* tx_data, uint8_t* rx_data, size_t len) { +static inline bool +spi_xfer_block(SPI_HandleTypeDef* spi, uint8_t* tx_data, uint8_t* rx_data, size_t len) { semaphoreInfo s; osSemaphore block = createSemaphoreStatic(s); if(!spi_xfer(spi, tx_data, rx_data, len, RELEASE_SEMAPHORE, (void*)block)) { @@ -52,15 +56,15 @@ typedef struct { ValueMutex* bus; ///< } SpiDevice; -## SPI IRQ device +##SPI IRQ device -/* + /* Many devices (like CC1101 and NFC) present as SPI bus and IRQ line. For work with it there is special entity `SpiIrqDevice`. Use `subscribe_pubsub` for subscribinq to irq events. */ -typedef struct { + typedef struct { ValueMutex* bus; ///< PubSub* irq; } SpiIrqDevice; @@ -75,7 +79,6 @@ typedef struct { ValueMutex* spi; ///< } DisplayBus; - typedef struct { ValueMutex* bus; ///< } DisplayDevice; From 19ef348c80e027f4c9ea304bc96349c195e97fbb Mon Sep 17 00:00:00 2001 From: aanper Date: Thu, 15 Oct 2020 11:32:48 +0300 Subject: [PATCH 02/14] [wip] change gui/widget api --- applications/gui/gui.c | 72 ++++++++++++++++++--------------------- applications/gui/gui.h | 20 +++++++---- applications/gui/widget.c | 9 ----- applications/gui/widget.h | 10 +++++- 4 files changed, 55 insertions(+), 56 deletions(-) diff --git a/applications/gui/gui.c b/applications/gui/gui.c index ecc314d7..6724b97d 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -22,48 +22,32 @@ struct GUI { WidgetArray_t widgets_dialog; }; -void gui_widget_status_bar_add(GUI* gui, Widget* widget) { +void gui_add_widget(GUI* gui, Widget* widget, WidgetLayer layer) { + WidgetArray_t* widget_array = NULL; + + switch(layer) { + case WidgetLayerStatusBar: + widget_array = &gui->widgets_status_bar; + break; + case WidgetLayerMain: + widget_array = &gui->widgets; + break; + case WidgetLayerFullscreen: + widget_array = &gui->widgets_fs; + break; + case WidgetLayerDialog: + widget_array = &gui->widgets_dialog; + break; + + default: + } + assert(gui); assert(widget); + assert(widget_array); gui_event_lock(gui->event); - WidgetArray_push_back(gui->widgets_status_bar, widget); - widget_gui_set(widget, gui); - gui_event_unlock(gui->event); - - gui_update(gui); -} - -void gui_widget_add(GUI* gui, Widget* widget) { - assert(gui); - assert(widget); - - gui_event_lock(gui->event); - WidgetArray_push_back(gui->widgets, widget); - widget_gui_set(widget, gui); - gui_event_unlock(gui->event); - - gui_update(gui); -} - -void gui_widget_fs_add(GUI* gui, Widget* widget) { - assert(gui); - assert(widget); - - gui_event_lock(gui->event); - WidgetArray_push_back(gui->widgets_fs, widget); - widget_gui_set(widget, gui); - gui_event_unlock(gui->event); - - gui_update(gui); -} - -void gui_widget_dialog_add(GUI* gui, Widget* widget) { - assert(gui); - assert(widget); - - gui_event_lock(gui->event); - WidgetArray_push_back(gui->widgets_dialog, widget); + WidgetArray_push_back(widget_array, widget); widget_gui_set(widget, gui); gui_event_unlock(gui->event); @@ -148,8 +132,10 @@ GUI* gui_alloc() { WidgetArray_init(gui->widgets); WidgetArray_init(gui->widgets_fs); WidgetArray_init(gui->widgets_dialog); + // Event dispatcher gui->event = gui_event_alloc(); + // Drawing canvas gui->canvas = canvas_alloc(); @@ -158,12 +144,20 @@ GUI* gui_alloc() { void gui_task(void* p) { GUI* gui = gui_alloc(); + + GuiApi gui_api = { + .add_widget = gui_add_widget, + .gui = gui, + }; + // Create FURI record - if(!furi_create_deprecated("gui", gui, sizeof(gui))) { + if(!furi_create("gui", &gui_api)) { printf("[gui_task] cannot create the gui record\n"); furiac_exit(NULL); } + furiac_ready(); + // Forever dispatch while(1) { GUIMessage message = gui_event_message_next(gui->event); diff --git a/applications/gui/gui.h b/applications/gui/gui.h index a95b802c..b09e3bff 100644 --- a/applications/gui/gui.h +++ b/applications/gui/gui.h @@ -1,12 +1,18 @@ #pragma once +#include "widget.h" + +typedef enum { + WidgetLayerStatusBar, + WidgetLayerMain, + WidgetLayerFullscreen, + WidgetLayerDialog +} WidgetLayer; + typedef struct Widget Widget; typedef struct GUI GUI; -void gui_widget_status_bar_add(GUI* gui, Widget* widget); - -void gui_widget_add(GUI* gui, Widget* widget); - -void gui_widget_fs_add(GUI* gui, Widget* widget); - -void gui_widget_dialog_add(GUI* gui, Widget* widget); +typedef struct { + void (*add_widget)(GUI* gui, Widget* widget, WidgetLayer layer); + GUI* gui; +} GuiApi; diff --git a/applications/gui/widget.c b/applications/gui/widget.c index bff2a4b9..1b6b6345 100644 --- a/applications/gui/widget.c +++ b/applications/gui/widget.c @@ -7,15 +7,6 @@ #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; diff --git a/applications/gui/widget.h b/applications/gui/widget.h index b29ade45..340e5310 100644 --- a/applications/gui/widget.h +++ b/applications/gui/widget.h @@ -4,7 +4,15 @@ 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 (*WidgetInputCallback)(InputEvent* event, void* context); From e684869970ce5e4b9d785dd25ccd6620c82f441a Mon Sep 17 00:00:00 2001 From: aanper Date: Thu, 15 Oct 2020 18:05:28 +0300 Subject: [PATCH 03/14] refactor canvas --- applications/gui/canvas.c | 116 ++++++++++++++++++++++------------- applications/gui/canvas.h | 37 +++++++---- applications/gui/canvas_i.h | 4 +- applications/gui/gui.c | 49 ++++++++------- applications/gui/gui.h | 7 ++- applications/gui/gui_event.c | 18 +++--- applications/gui/gui_event.h | 14 ++--- applications/gui/gui_i.h | 2 +- applications/gui/widget.c | 21 ++++++- applications/gui/widget.h | 15 +---- applications/gui/widget_i.h | 2 +- applications/menu/menu.c | 3 +- 12 files changed, 169 insertions(+), 119 deletions(-) diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index 6f137284..2572bd23 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -6,74 +6,104 @@ #include 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; } -void canvas_clear(Canvas* canvas) { - u8g2_t* fb = canvas_fb(canvas); - u8g2_ClearBuffer(fb); +uint8_t canvas_height(CanvasApi* api) { + assert(api); + + return api->canvas.height; } -void canvas_color_set(Canvas* canvas, uint8_t color) { - u8g2_t* fb = canvas_fb(canvas); - u8g2_SetDrawColor(fb, 1); +void canvas_clear(CanvasApi* api) { + assert(api); + u8g2_ClearBuffer(&api->canvas.fb); } -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_color_set(CanvasApi* api, Color color) { + assert(api); + u8g2_SetDrawColor(&api->canvas.fb, color); } -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_font_set(CanvasApi* api, Font font) { + assert(api); + u8g2_SetFontMode(&api->canvas.fb, 1); + u8g2_SetFont(&api->canvas.fb, font); +} + +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); } diff --git a/applications/gui/canvas.h b/applications/gui/canvas.h index 3b0f547e..d5692bf7 100644 --- a/applications/gui/canvas.h +++ b/applications/gui/canvas.h @@ -1,24 +1,35 @@ #pragma once #include -#include -#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; -uint8_t canvas_width(Canvas* canvas); -uint8_t canvas_height(Canvas* canvas); +struct _CanvasApi; -void canvas_clear(Canvas* canvas); +typedef struct _CanvasApi CanvasApi; -void canvas_color_set(Canvas* canvas, uint8_t color); +typedef struct { + Font primary; + Font secondary; +} Fonts; -void canvas_font_set(Canvas* canvas, font_t font); +struct { + Canvas canvas; + Fonts* fonts; + + uint8_t (*width)(CanvasApi* canvas); + uint8_t (*height)(CanvasApi* canvas); -void canvas_str_draw(Canvas* canvas, uint8_t x, uint8_t y, const char* str); + void (*clear)(CanvasApi* canvas); + + void (*canvas_color_set)(CanvasApi* canvas, Color color); + void (*canvas_font_set)(CanvasApi* canvas, Font font); + + void (*draw_str)(CanvasApi* canvas, uint8_t x, uint8_t y, const char* str); +} _CanvasApi; diff --git a/applications/gui/canvas_i.h b/applications/gui/canvas_i.h index c24b2102..b32eb049 100644 --- a/applications/gui/canvas_i.h +++ b/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); diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 6724b97d..75b9611d 100644 --- a/applications/gui/gui.c +++ b/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); } } diff --git a/applications/gui/gui.h b/applications/gui/gui.h index b09e3bff..a65ea53d 100644 --- a/applications/gui/gui.h +++ b/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; diff --git a/applications/gui/gui_event.c b/applications/gui/gui_event.c index a2ee801b..5c04d9a3 100644 --- a/applications/gui/gui_event.c +++ b/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); diff --git a/applications/gui/gui_event.h b/applications/gui/gui_event.h index c3a47e45..730eb8c6 100644 --- a/applications/gui/gui_event.h +++ b/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); diff --git a/applications/gui/gui_i.h b/applications/gui/gui_i.h index e12970fc..6a9bf2a0 100644 --- a/applications/gui/gui_i.h +++ b/applications/gui/gui_i.h @@ -1,3 +1,3 @@ #pragma once -void gui_update(GUI* gui); +void gui_update(Gui* gui); diff --git a/applications/gui/widget.c b/applications/gui/widget.c index 1b6b6345..16981262 100644 --- a/applications/gui/widget.c +++ b/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) { diff --git a/applications/gui/widget.h b/applications/gui/widget.h index 340e5310..83f7d497 100644 --- a/applications/gui/widget.h +++ b/applications/gui/widget.h @@ -1,20 +1,11 @@ #pragma once #include +#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(); diff --git a/applications/gui/widget_i.h b/applications/gui/widget_i.h index 5c1af22d..b0fefa44 100644 --- a/applications/gui/widget_i.h +++ b/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); diff --git a/applications/menu/menu.c b/applications/menu/menu.c index 8cafe6a4..fdef8cad 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -6,7 +6,6 @@ #include #include #include -#include #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; From 78e016412e5cda6bc25932c1fbae25d19662737c Mon Sep 17 00:00:00 2001 From: aanper Date: Thu, 15 Oct 2020 18:13:18 +0300 Subject: [PATCH 04/14] gui draw refactor --- applications/gui/gui.c | 22 ++++++++++------------ applications/gui/gui_event.c | 12 ++++++------ applications/gui/gui_event.h | 14 +++++++------- applications/gui/widget.c | 12 ++++-------- 4 files changed, 27 insertions(+), 33 deletions(-) diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 75b9611d..c49ced53 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -73,10 +73,10 @@ Widget* gui_widget_find_enabled(WidgetArray_t array) { } bool gui_redraw_fs(Gui* gui) { - canvas_frame_set(gui->canvas, 0, 0, 128, 64); + canvas_frame_set(gui->canvas_api, 0, 0, 128, 64); Widget* widget = gui_widget_find_enabled(gui->widgets_fs); if(widget) { - widget_draw(widget, gui->canvas); + widget_draw(widget, gui->canvas_api); return true; } else { return false; @@ -84,21 +84,21 @@ bool gui_redraw_fs(Gui* gui) { } void gui_redraw_status_bar(Gui* gui) { - canvas_frame_set(gui->canvas, 0, 0, 128, 64); + canvas_frame_set(gui->canvas_api, 0, 0, 128, 64); Widget* widget = gui_widget_find_enabled(gui->widgets_status_bar); - if(widget) widget_draw(widget, gui->canvas); + if(widget) widget_draw(widget, gui->canvas_api); } void gui_redraw_normal(Gui* gui) { - canvas_frame_set(gui->canvas, 0, 9, 128, 55); + canvas_frame_set(gui->canvas_api, 0, 9, 128, 55); Widget* widget = gui_widget_find_enabled(gui->widgets); - if(widget) widget_draw(widget, gui->canvas); + if(widget) widget_draw(widget, gui->canvas_api); } void gui_redraw_dialogs(Gui* gui) { - canvas_frame_set(gui->canvas, 10, 20, 118, 44); + canvas_frame_set(gui->canvas_api, 10, 20, 118, 44); Widget* widget = gui_widget_find_enabled(gui->widgets_dialog); - if(widget) widget_draw(widget, gui->canvas); + if(widget) widget_draw(widget, gui->canvas_api); } void gui_redraw(Gui* gui) { @@ -110,8 +110,7 @@ void gui_redraw(Gui* gui) { } gui_redraw_dialogs(gui); - // canvas_commit(gui->canvas); - // redraw u8g2 + canvas_commit(gui->canvas); } void gui_input(Gui* gui, InputEvent* input_event) { @@ -139,8 +138,7 @@ Gui* gui_alloc() { // Drawing canvas api - gui->canvas_api = - canvas_api_init(); + gui->canvas_api = canvas_api_init(); return gui; } diff --git a/applications/gui/gui_event.c b/applications/gui/gui_event.c index 5c04d9a3..8d0914c2 100644 --- a/applications/gui/gui_event.c +++ b/applications/gui/gui_event.c @@ -15,8 +15,8 @@ void gui_event_input_events_callback(const void* value, size_t size, void* ctx) assert(ctx); GuiEvent* gui_event = ctx; - GUIMessage message; - message.type = GUIMessageTypeInput; + GuiMessage message; + message.type = GuiMessageTypeInput; message.input = *(InputEvent*)value; osMessageQueuePut(gui_event->mqueue, &message, 0, 0); @@ -25,7 +25,7 @@ void gui_event_input_events_callback(const void* value, size_t size, void* ctx) 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); + gui_event->mqueue = osMessageQueueNew(GUI_EVENT_MQUEUE_SIZE, sizeof(GuiMessage), NULL); assert(gui_event->mqueue); // Input @@ -57,15 +57,15 @@ void gui_event_unlock(GuiEvent* 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; + GuiMessage message; gui_event_unlock(gui_event); while(osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever) != osOK) { }; diff --git a/applications/gui/gui_event.h b/applications/gui/gui_event.h index 730eb8c6..89ba4ee2 100644 --- a/applications/gui/gui_event.h +++ b/applications/gui/gui_event.h @@ -4,15 +4,15 @@ #include typedef enum { - GUIMessageTypeRedraw = 0x00, - GUIMessageTypeInput = 0x01, -} GUIMessageType; + GuiMessageTypeRedraw = 0x00, + GuiMessageTypeInput = 0x01, +} GuiMessageType; typedef struct { - GUIMessageType type; + GuiMessageType type; InputEvent input; void* data; -} GUIMessage; +} GuiMessage; typedef struct GuiEvent GuiEvent; @@ -24,6 +24,6 @@ void gui_event_lock(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); diff --git a/applications/gui/widget.c b/applications/gui/widget.c index 16981262..106ac7f1 100644 --- a/applications/gui/widget.c +++ b/applications/gui/widget.c @@ -56,23 +56,19 @@ void widget_update(Widget* widget) { if(widget->gui) gui_update(widget->gui); } -void widget_gui_set(Widget* widget, GUI* gui) { +void widget_gui_set(Widget* widget, Gui* gui) { assert(widget); assert(gui); widget->gui = gui; } -void widget_draw(Widget* widget, ValueMutex* canvas_api_mutex) { +void widget_draw(Widget* widget, CanvasApi* canvas_api) { assert(widget); - assert(canvas_api_mutex); + assert(canvas_api); assert(widget->gui); 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); + widget->draw_callback(canvas_api, widget->draw_callback_context); } } From f0f3615c550b55fcb55a5881c901ae7118e7ccc1 Mon Sep 17 00:00:00 2001 From: aanper Date: Thu, 15 Oct 2020 18:56:47 +0300 Subject: [PATCH 05/14] compile/run ok, issue with backlight --- applications/applications.mk | 3 +-- applications/gui/canvas.c | 34 +++++++++++++--------------- applications/gui/canvas.h | 27 ++++++++++++++-------- applications/gui/canvas_i.h | 4 ++-- applications/gui/gui.c | 31 +++++++++++++++----------- applications/gui/gui.h | 9 +++++--- applications/gui/widget.c | 4 +++- applications/gui/widget_i.h | 4 +++- applications/menu/menu.c | 43 +++++++++++++++++------------------- applications/startup.h | 2 +- 10 files changed, 87 insertions(+), 74 deletions(-) diff --git a/applications/applications.mk b/applications/applications.mk index 906f6690..d60ed2d5 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -5,7 +5,7 @@ CFLAGS += -I$(APP_DIR) APP_RELEASE ?= 0 ifeq ($(APP_RELEASE), 1) -APP_DISPLAY = 1 +APP_GUI = 1 APP_INPUT = 1 APP_MENU = 1 endif @@ -79,7 +79,6 @@ endif # device drivers APP_GUI ?= 0 ifeq ($(APP_GUI), 1) -APP_DISPLAY = 1 CFLAGS += -DAPP_GUI C_SOURCES += $(wildcard $(APP_DIR)/gui/*.c) endif diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index 2572bd23..5a8d7307 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -3,15 +3,6 @@ #include #include -#include - -struct Canvas { - u8g2_t fb; - uint8_t offset_x; - uint8_t offset_y; - uint8_t width; - uint8_t height; -}; uint8_t canvas_width(CanvasApi* api); uint8_t canvas_height(CanvasApi* api); @@ -20,14 +11,20 @@ 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); +uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); +uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); + 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 + &api->canvas.fb, + U8G2_R0, + u8x8_hw_spi_stm32, + u8g2_gpio_and_delay_stm32); + + // send init sequence to the display, display is in sleep mode after this + u8g2_InitDisplay(&api->canvas.fb); u8g2_SetContrast(&api->canvas.fb, 36); u8g2_SetPowerSave(&api->canvas.fb, 0); // wake up display @@ -36,14 +33,13 @@ CanvasApi* canvas_api_init() { 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->set_color = canvas_color_set; + api->set_font = canvas_font_set; api->draw_str = canvas_str_draw; - api->fonts = { - .primary = u8g2_font_Born2bSportyV2_tr, - .secondary = u8g2_font_HelvetiPixel_tr, - }; + api->fonts = furi_alloc(sizeof(Fonts)); + api->fonts->primary = u8g2_font_Born2bSportyV2_tr; + api->fonts->secondary = u8g2_font_HelvetiPixel_tr; return api; } diff --git a/applications/gui/canvas.h b/applications/gui/canvas.h index d5692bf7..3d77e8fe 100644 --- a/applications/gui/canvas.h +++ b/applications/gui/canvas.h @@ -1,25 +1,34 @@ #pragma once #include +#include typedef enum { ColorWhite = 0x00, ColorBlack = 0x01, } Color; -typedef struct Canvas Canvas; typedef const uint8_t* Font; -struct _CanvasApi; - -typedef struct _CanvasApi CanvasApi; - typedef struct { Font primary; Font secondary; } Fonts; -struct { +struct _CanvasApi; + +typedef struct _CanvasApi CanvasApi; + +// Canvas is private but we need its declaration here +typedef struct { + u8g2_t fb; + uint8_t offset_x; + uint8_t offset_y; + uint8_t width; + uint8_t height; +} Canvas; + +struct _CanvasApi { Canvas canvas; Fonts* fonts; @@ -28,8 +37,8 @@ struct { void (*clear)(CanvasApi* canvas); - void (*canvas_color_set)(CanvasApi* canvas, Color color); - void (*canvas_font_set)(CanvasApi* canvas, Font font); + void (*set_color)(CanvasApi* canvas, Color color); + void (*set_font)(CanvasApi* canvas, Font font); void (*draw_str)(CanvasApi* canvas, uint8_t x, uint8_t y, const char* str); -} _CanvasApi; +}; diff --git a/applications/gui/canvas_i.h b/applications/gui/canvas_i.h index b32eb049..7337db00 100644 --- a/applications/gui/canvas_i.h +++ b/applications/gui/canvas_i.h @@ -4,10 +4,10 @@ CanvasApi* canvas_api_init(); void canvas_api_free(CanvasApi* api); -void canvas_commit(Canvas* canvas); +void canvas_commit(CanvasApi* api); void canvas_frame_set( - Canvas* canvas, + CanvasApi* api, uint8_t offset_x, uint8_t offset_y, uint8_t width, diff --git a/applications/gui/gui.c b/applications/gui/gui.c index c49ced53..e03971eb 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -2,6 +2,7 @@ #include "gui_i.h" #include +#include #include #include @@ -22,36 +23,40 @@ struct Gui { WidgetArray_t widgets_dialog; }; -void gui_add_widget(Gui* gui, Widget* widget, WidgetLayer layer) { +void gui_add_widget(GuiApi* gui_api, Widget* widget, WidgetLayer layer) { + assert(gui_api); + assert(gui_api->gui); + + // TODO add mutex on widget array + WidgetArray_t* widget_array = NULL; switch(layer) { case WidgetLayerStatusBar: - widget_array = &gui->widgets_status_bar; + widget_array = &gui_api->gui->widgets_status_bar; break; case WidgetLayerMain: - widget_array = &gui->widgets; + widget_array = &gui_api->gui->widgets; break; case WidgetLayerFullscreen: - widget_array = &gui->widgets_fs; + widget_array = &gui_api->gui->widgets_fs; break; case WidgetLayerDialog: - widget_array = &gui->widgets_dialog; + widget_array = &gui_api->gui->widgets_dialog; break; - default: + default: break; } - assert(gui); assert(widget); assert(widget_array); - gui_event_lock(gui->event); - WidgetArray_push_back(widget_array, widget); - widget_gui_set(widget, gui); - gui_event_unlock(gui->event); + gui_event_lock(gui_api->gui->event); + WidgetArray_push_back((struct WidgetArray_s*)widget_array, widget); + widget_gui_set(widget, gui_api->gui); + gui_event_unlock(gui_api->gui->event); - gui_update(gui); + gui_update(gui_api->gui); } void gui_update(Gui* gui) { @@ -110,7 +115,7 @@ void gui_redraw(Gui* gui) { } gui_redraw_dialogs(gui); - canvas_commit(gui->canvas); + canvas_commit(gui->canvas_api); } void gui_input(Gui* gui, InputEvent* input_event) { diff --git a/applications/gui/gui.h b/applications/gui/gui.h index a65ea53d..371c0434 100644 --- a/applications/gui/gui.h +++ b/applications/gui/gui.h @@ -13,7 +13,10 @@ typedef enum { typedef struct Widget Widget; typedef struct Gui Gui; -typedef struct { - void (*add_widget)(Gui* gui, Widget* widget, WidgetLayer layer); +struct _GuiApi; +typedef struct _GuiApi GuiApi; + +struct _GuiApi { + void (*add_widget)(GuiApi* gui_api, Widget* widget, WidgetLayer layer); Gui* gui; -} GuiApi; +}; diff --git a/applications/gui/widget.c b/applications/gui/widget.c index 106ac7f1..148abdf6 100644 --- a/applications/gui/widget.c +++ b/applications/gui/widget.c @@ -7,6 +7,8 @@ #include "gui.h" #include "gui_i.h" +// TODO add mutex to widget ops + struct Widget { void* gui; bool is_enabled; @@ -14,7 +16,7 @@ struct Widget { 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)); diff --git a/applications/gui/widget_i.h b/applications/gui/widget_i.h index b0fefa44..f6cc2f14 100644 --- a/applications/gui/widget_i.h +++ b/applications/gui/widget_i.h @@ -1,7 +1,9 @@ #pragma once +#include "gui.h" + void widget_gui_set(Widget* widget, Gui* gui); -void widget_draw(Widget* widget, Canvas* canvas); +void widget_draw(Widget* widget, CanvasApi* canvas_api); void widget_input(Widget* widget, InputEvent* event); diff --git a/applications/menu/menu.c b/applications/menu/menu.c index fdef8cad..92737b87 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -4,17 +4,18 @@ #include #include +#include #include -#include #include "menu_event.h" #include "menu_item.h" struct Menu { MenuEvent* event; + // GUI - FuriRecordSubscriber* gui_record; Widget* widget; + // State MenuItem* root; MenuItem* settings; @@ -22,9 +23,9 @@ struct Menu { uint32_t position; }; -void menu_widget_callback(Canvas* canvas, void* context); +void menu_widget_callback(CanvasApi* canvas, void* context); -Menu* menu_alloc() { +Menu* menu_init() { Menu* menu = furi_alloc(sizeof(Menu)); // Event dispatcher @@ -36,8 +37,9 @@ 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("gui"); - assert(menu->gui_record); + GuiApi* gui = furi_open("gui"); + assert(gui); + gui->add_widget(gui, menu->widget, WidgetLayerFullscreen); return menu; } @@ -75,7 +77,7 @@ void menu_settings_item_add(Menu* menu, MenuItem* item) { menu_item_subitem_add(menu->settings, item); } -void menu_widget_callback(Canvas* canvas, void* context) { +void menu_widget_callback(CanvasApi* canvas, void* context) { assert(canvas); assert(context); @@ -84,20 +86,20 @@ void menu_widget_callback(Canvas* canvas, void* context) { menu_event_lock(menu->event); if(!menu->current) { - canvas_clear(canvas); - canvas_color_set(canvas, COLOR_BLACK); - canvas_font_set(canvas, CANVAS_FONT_PRIMARY); - canvas_str_draw(canvas, 2, 32, "Idle Screen"); + canvas->clear(canvas); + canvas->set_color(canvas, ColorBlack); + canvas->set_font(canvas, canvas->fonts->primary); + canvas->draw_str(canvas, 2, 32, "Idle Screen"); } else { MenuItemArray_t* items = menu_item_get_subitems(menu->current); - canvas_clear(canvas); - canvas_color_set(canvas, COLOR_BLACK); - canvas_font_set(canvas, CANVAS_FONT_SECONDARY); + canvas->clear(canvas); + canvas->set_color(canvas, ColorBlack); + canvas->set_font(canvas, canvas->fonts->secondary); for(size_t i = 0; i < 5; i++) { size_t shift_position = i + menu->position + MenuItemArray_size(*items) - 2; shift_position = shift_position % (MenuItemArray_size(*items)); MenuItem* item = *MenuItemArray_get(*items, shift_position); - canvas_str_draw(canvas, 2, 12 * (i + 1), menu_item_get_label(item)); + canvas->draw_str(canvas, 2, 12 * (i + 1), menu_item_get_label(item)); } } @@ -172,19 +174,14 @@ void menu_exit(Menu* menu) { } void menu_task(void* p) { - Menu* menu = menu_alloc(); - menu_build_main(menu); - - // Register widget - GUI* gui = furi_take(menu->gui_record); - assert(gui); - gui_widget_fs_add(gui, menu->widget); - furi_commit(menu->gui_record); + Menu* menu = menu_init(); + menu_build_main(menu); if(!furi_create_deprecated("menu", menu, sizeof(menu))) { printf("[menu_task] cannot create the menu record\n"); furiac_exit(NULL); } + furiac_ready(); while(1) { diff --git a/applications/startup.h b/applications/startup.h index 2f96ce08..58c8c11d 100644 --- a/applications/startup.h +++ b/applications/startup.h @@ -37,7 +37,7 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { #endif #ifdef APP_GUI - {.app = gui_task, .name = "gui_task", .libs = {1, FURI_LIB{"display_u8g2"}}}, + {.app = gui_task, .name = "gui_task", .libs = {0}}, #endif #ifdef APP_MENU From f9bda68ef84036b5708e102e06cf34e81f72a245 Mon Sep 17 00:00:00 2001 From: aanper Date: Thu, 15 Oct 2020 18:57:21 +0300 Subject: [PATCH 06/14] lint --- applications/gui/canvas.c | 5 +---- applications/gui/canvas.h | 10 +++++----- applications/gui/gui.c | 19 ++++++++++--------- applications/gui/widget.c | 2 +- applications/menu/menu.c | 4 ++-- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index 5a8d7307..6dc7962c 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -18,10 +18,7 @@ CanvasApi* canvas_api_init() { CanvasApi* api = furi_alloc(sizeof(CanvasApi)); u8g2_Setup_st7565_erc12864_alt_f( - &api->canvas.fb, - U8G2_R0, - u8x8_hw_spi_stm32, - u8g2_gpio_and_delay_stm32); + &api->canvas.fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); // send init sequence to the display, display is in sleep mode after this u8g2_InitDisplay(&api->canvas.fb); diff --git a/applications/gui/canvas.h b/applications/gui/canvas.h index 3d77e8fe..27dd2efe 100644 --- a/applications/gui/canvas.h +++ b/applications/gui/canvas.h @@ -4,15 +4,15 @@ #include typedef enum { - ColorWhite = 0x00, - ColorBlack = 0x01, + ColorWhite = 0x00, + ColorBlack = 0x01, } Color; typedef const uint8_t* Font; typedef struct { - Font primary; - Font secondary; + Font primary; + Font secondary; } Fonts; struct _CanvasApi; @@ -31,7 +31,7 @@ typedef struct { struct _CanvasApi { Canvas canvas; Fonts* fonts; - + uint8_t (*width)(CanvasApi* canvas); uint8_t (*height)(CanvasApi* canvas); diff --git a/applications/gui/gui.c b/applications/gui/gui.c index e03971eb..6be88315 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -32,20 +32,21 @@ void gui_add_widget(GuiApi* gui_api, Widget* widget, WidgetLayer layer) { WidgetArray_t* widget_array = NULL; switch(layer) { - case WidgetLayerStatusBar: - widget_array = &gui_api->gui->widgets_status_bar; + case WidgetLayerStatusBar: + widget_array = &gui_api->gui->widgets_status_bar; break; - case WidgetLayerMain: - widget_array = &gui_api->gui->widgets; + case WidgetLayerMain: + widget_array = &gui_api->gui->widgets; break; - case WidgetLayerFullscreen: - widget_array = &gui_api->gui->widgets_fs; + case WidgetLayerFullscreen: + widget_array = &gui_api->gui->widgets_fs; break; - case WidgetLayerDialog: - widget_array = &gui_api->gui->widgets_dialog; + case WidgetLayerDialog: + widget_array = &gui_api->gui->widgets_dialog; break; - default: break; + default: + break; } assert(widget); diff --git a/applications/gui/widget.c b/applications/gui/widget.c index 148abdf6..3277c24d 100644 --- a/applications/gui/widget.c +++ b/applications/gui/widget.c @@ -70,7 +70,7 @@ void widget_draw(Widget* widget, CanvasApi* canvas_api) { assert(widget->gui); if(widget->draw_callback) { - widget->draw_callback(canvas_api, widget->draw_callback_context); + widget->draw_callback(canvas_api, widget->draw_callback_context); } } diff --git a/applications/menu/menu.c b/applications/menu/menu.c index 92737b87..156e7f60 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -15,7 +15,7 @@ struct Menu { // GUI Widget* widget; - + // State MenuItem* root; MenuItem* settings; @@ -175,7 +175,7 @@ void menu_exit(Menu* menu) { void menu_task(void* p) { Menu* menu = menu_init(); - menu_build_main(menu); + menu_build_main(menu); if(!furi_create_deprecated("menu", menu, sizeof(menu))) { printf("[menu_task] cannot create the menu record\n"); From 1e40f873a5e4ccc7362718acbe63c981e5b40c5c Mon Sep 17 00:00:00 2001 From: aanper Date: Thu, 15 Oct 2020 19:15:53 +0300 Subject: [PATCH 07/14] backlight control --- applications/applications.mk | 1 + .../backlight-control/backlight-control.c | 30 +++++++++++++++++++ applications/startup.h | 2 ++ 3 files changed, 33 insertions(+) create mode 100644 applications/backlight-control/backlight-control.c diff --git a/applications/applications.mk b/applications/applications.mk index d60ed2d5..e8f61573 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -81,6 +81,7 @@ APP_GUI ?= 0 ifeq ($(APP_GUI), 1) CFLAGS += -DAPP_GUI C_SOURCES += $(wildcard $(APP_DIR)/gui/*.c) +C_SOURCES += $(wildcard $(APP_DIR)/backlight-control/*.c) endif ifeq ($(APP_DISPLAY), 1) diff --git a/applications/backlight-control/backlight-control.c b/applications/backlight-control/backlight-control.c new file mode 100644 index 00000000..ef22f3df --- /dev/null +++ b/applications/backlight-control/backlight-control.c @@ -0,0 +1,30 @@ +#include "flipper.h" + +static void event_cb(const void* value, size_t size, void* ctx) { + xSemaphoreGive((SemaphoreHandle_t*)ctx); +} + +const uint32_t BACKLIGHT_TIME = 10000; + +void backlight_control(void* p) { + // TODO use FURI + HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_SET); + + StaticSemaphore_t event_descriptor; + SemaphoreHandle_t update = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor); + + // open record + furi_open_deprecated("input_events", false, false, event_cb, NULL, (void*)update); + + // we ready to work + furiac_ready(); + + while(1) { + // wait for event + if(xSemaphoreTake(update, BACKLIGHT_TIME) == pdTRUE) { + HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_SET); + } else { + HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_RESET); + } + } +} \ No newline at end of file diff --git a/applications/startup.h b/applications/startup.h index 58c8c11d..847009dc 100644 --- a/applications/startup.h +++ b/applications/startup.h @@ -26,6 +26,7 @@ void coreglitch_demo_0(void* p); void u8g2_qrcode(void* p); void fatfs_list(void* p); void gui_task(void* p); +void backlight_control(void* p); const FlipperStartupApp FLIPPER_STARTUP[] = { #ifdef APP_DISPLAY @@ -37,6 +38,7 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { #endif #ifdef APP_GUI + {.app = backlight_control, .name = "backlight_control", .libs = {1, FURI_LIB{"input_task"}}}, {.app = gui_task, .name = "gui_task", .libs = {0}}, #endif From 2806a3ce3d9a16ace33d13b95372de24693b6b8e Mon Sep 17 00:00:00 2001 From: aanper Date: Thu, 15 Oct 2020 19:16:11 +0300 Subject: [PATCH 08/14] add forgotten u8g2 periphery --- applications/gui/u8g2_periphery.c | 114 ++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 applications/gui/u8g2_periphery.c diff --git a/applications/gui/u8g2_periphery.c b/applications/gui/u8g2_periphery.c new file mode 100644 index 00000000..db12c506 --- /dev/null +++ b/applications/gui/u8g2_periphery.c @@ -0,0 +1,114 @@ +#include "u8g2/u8g2.h" +#include "flipper.h" + +extern SPI_HandleTypeDef hspi1; + +// TODO: fix log +#ifdef DEBUG +#undef DEBUG +#endif + +uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { + switch(msg) { + //Initialize SPI peripheral + case U8X8_MSG_GPIO_AND_DELAY_INIT: + /* HAL initialization contains all what we need so we can skip this part. */ + break; + + //Function which implements a delay, arg_int contains the amount of ms + case U8X8_MSG_DELAY_MILLI: + osDelay(arg_int); + break; + + //Function which delays 10us + case U8X8_MSG_DELAY_10MICRO: + delay_us(10); + break; + + //Function which delays 100ns + case U8X8_MSG_DELAY_100NANO: + asm("nop"); + break; + + // Function to define the logic level of the RESET line + case U8X8_MSG_GPIO_RESET: +#ifdef DEBUG + fuprintf(log, "[u8g2] rst %d\n", arg_int); +#endif + + // TODO change it to FuriRecord pin + HAL_GPIO_WritePin( + DISPLAY_RST_GPIO_Port, DISPLAY_RST_Pin, arg_int ? GPIO_PIN_SET : GPIO_PIN_RESET); + break; + + default: +#ifdef DEBUG + fufuprintf(log, "[u8g2] unknown io %d\n", msg); +#endif + + return 0; //A message was received which is not implemented, return 0 to indicate an error + } + + return 1; // command processed successfully. +} + +uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { + switch(msg) { + case U8X8_MSG_BYTE_SEND: +#ifdef DEBUG + fuprintf(log, "[u8g2] send %d bytes %02X\n", arg_int, ((uint8_t*)arg_ptr)[0]); +#endif + + // TODO change it to FuriRecord SPI + HAL_SPI_Transmit(&hspi1, (uint8_t*)arg_ptr, arg_int, 10000); + break; + + case U8X8_MSG_BYTE_SET_DC: +#ifdef DEBUG + fuprintf(log, "[u8g2] dc %d\n", arg_int); +#endif + + // TODO change it to FuriRecord pin + HAL_GPIO_WritePin( + DISPLAY_DI_GPIO_Port, DISPLAY_DI_Pin, arg_int ? GPIO_PIN_SET : GPIO_PIN_RESET); + break; + + case U8X8_MSG_BYTE_INIT: +#ifdef DEBUG + fuprintf(log, "[u8g2] init\n"); +#endif + + // TODO change it to FuriRecord pin + HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_RESET); + break; + + case U8X8_MSG_BYTE_START_TRANSFER: +#ifdef DEBUG + fuprintf(log, "[u8g2] start\n"); +#endif + + // TODO change it to FuriRecord pin + HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_RESET); + asm("nop"); + break; + + case U8X8_MSG_BYTE_END_TRANSFER: +#ifdef DEBUG + fuprintf(log, "[u8g2] end\n"); +#endif + + asm("nop"); + // TODO change it to FuriRecord pin + HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_SET); + break; + + default: +#ifdef DEBUG + fuprintf(log, "[u8g2] unknown xfer %d\n", msg); +#endif + + return 0; + } + + return 1; +} From d715767cef509a7b4de0d836ba13a771ed3d266e Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Fri, 16 Oct 2020 15:16:54 +0300 Subject: [PATCH 09/14] GUI: osWaitForeverfor in queue put, simplify osMessageQueueGet. --- applications/gui/gui_event.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/applications/gui/gui_event.c b/applications/gui/gui_event.c index 8d0914c2..44b4d5fc 100644 --- a/applications/gui/gui_event.c +++ b/applications/gui/gui_event.c @@ -19,7 +19,7 @@ void gui_event_input_events_callback(const void* value, size_t size, void* ctx) message.type = GuiMessageTypeInput; message.input = *(InputEvent*)value; - osMessageQueuePut(gui_event->mqueue, &message, 0, 0); + osMessageQueuePut(gui_event->mqueue, &message, 0, osWaitForever); } GuiEvent* gui_event_alloc() { @@ -67,8 +67,7 @@ GuiMessage gui_event_message_next(GuiEvent* gui_event) { assert(gui_event); GuiMessage message; gui_event_unlock(gui_event); - while(osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever) != osOK) { - }; + assert(osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever) == osOK); gui_event_lock(gui_event); return message; } From e213954d2da3d3cbefc81559032ebb2059b0d39a Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Fri, 16 Oct 2020 15:18:36 +0300 Subject: [PATCH 10/14] Menu: item callback function context, event osWaitForever timeouts. --- applications/menu/menu.c | 30 ++++++++++++++---------------- applications/menu/menu_event.c | 4 ++-- applications/menu/menu_item.c | 27 ++++++++++++++++++++++----- applications/menu/menu_item.h | 6 +++--- 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/applications/menu/menu.c b/applications/menu/menu.c index 156e7f60..0ef37d67 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -49,22 +49,21 @@ void menu_build_main(Menu* menu) { // Root point menu->root = menu_item_alloc_menu(NULL, NULL); - menu_item_add(menu, menu_item_alloc_function("Sub 1 gHz", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("125 kHz RFID", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Infrared", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("I-Button", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("USB", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Bluetooth", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("GPIO / HW", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("NFC", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("U2F", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Tamagotchi", NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Plugins", NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Sub 1 gHz", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("125 kHz RFID", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Infrared", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("I-Button", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("USB", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Bluetooth", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("GPIO / HW", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("U2F", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Tamagotchi", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Plugins", NULL, NULL, NULL)); menu->settings = menu_item_alloc_menu("Setting", NULL); - menu_item_subitem_add(menu->settings, menu_item_alloc_function("one", NULL, NULL)); - menu_item_subitem_add(menu->settings, menu_item_alloc_function("two", NULL, NULL)); - menu_item_subitem_add(menu->settings, menu_item_alloc_function("three", NULL, NULL)); + menu_item_subitem_add(menu->settings, menu_item_alloc_function("one", NULL, NULL, NULL)); + menu_item_subitem_add(menu->settings, menu_item_alloc_function("two", NULL, NULL, NULL)); + menu_item_subitem_add(menu->settings, menu_item_alloc_function("three", NULL, NULL, NULL)); menu_item_add(menu, menu->settings); } @@ -149,8 +148,7 @@ void menu_ok(Menu* menu) { menu->position = 0; menu_update(menu); } else if(type == MenuItemTypeFunction) { - MenuItemCallback function = menu_item_get_function(item); - if(function) function(); + menu_item_function_call(item); } } diff --git a/applications/menu/menu_event.c b/applications/menu/menu_event.c index 82b32f8f..bd479972 100644 --- a/applications/menu/menu_event.c +++ b/applications/menu/menu_event.c @@ -19,7 +19,7 @@ void MenuEventimeout_callback(void* arg) { MenuEvent* menu_event = arg; MenuMessage message; message.type = MenuMessageTypeIdle; - osMessageQueuePut(menu_event->mqueue, &message, 0, 0); + osMessageQueuePut(menu_event->mqueue, &message, 0, osWaitForever); } MenuEvent* menu_event_alloc() { @@ -92,5 +92,5 @@ void menu_event_input_callback(InputEvent* input_event, void* context) { message.type = MenuMessageTypeUnknown; } - osMessageQueuePut(menu_event->mqueue, &message, 0, 0); + osMessageQueuePut(menu_event->mqueue, &message, 0, osWaitForever); } diff --git a/applications/menu/menu_item.c b/applications/menu/menu_item.c index 57072bc2..e4d3143f 100644 --- a/applications/menu/menu_item.c +++ b/applications/menu/menu_item.c @@ -10,6 +10,8 @@ struct MenuItem { void* icon; MenuItem* parent; void* data; + MenuItemCallback callback; + void* callback_context; }; MenuItem* menu_item_alloc() { @@ -31,27 +33,34 @@ MenuItem* menu_item_alloc_menu(const char* label, void* icon) { return menu_item; } -MenuItem* menu_item_alloc_function(const char* label, void* icon, MenuItemCallback function) { +MenuItem* menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context) { MenuItem* menu_item = menu_item_alloc(); menu_item->type = MenuItemTypeFunction; menu_item->label = label; menu_item->icon = icon; - menu_item->data = function; + menu_item->callback = callback; + menu_item->callback_context = context; return menu_item; } void menu_item_release(MenuItem* menu_item) { - if(menu_item->type == MenuItemTypeMenu) free(menu_item->data); + assert(menu_item); + if(menu_item->type == MenuItemTypeMenu) { + //TODO: iterate and release + free(menu_item->data); + } free(menu_item); } MenuItem* menu_item_get_parent(MenuItem* menu_item) { + assert(menu_item); return menu_item->parent; } void menu_item_subitem_add(MenuItem* menu_item, MenuItem* sub_item) { + assert(menu_item); assert(menu_item->type == MenuItemTypeMenu); MenuItemArray_t* items = menu_item->data; sub_item->parent = menu_item; @@ -59,31 +68,39 @@ void menu_item_subitem_add(MenuItem* menu_item, MenuItem* sub_item) { } uint8_t menu_item_get_type(MenuItem* menu_item) { + assert(menu_item); return menu_item->type; } void menu_item_set_label(MenuItem* menu_item, const char* label) { + assert(menu_item); menu_item->label = label; } const char* menu_item_get_label(MenuItem* menu_item) { + assert(menu_item); return menu_item->label; } void menu_item_set_icon(MenuItem* menu_item, void* icon) { + assert(menu_item); menu_item->icon = icon; } void* menu_item_get_icon(MenuItem* menu_item) { + assert(menu_item); return menu_item->icon; } MenuItemArray_t* menu_item_get_subitems(MenuItem* menu_item) { + assert(menu_item); assert(menu_item->type == MenuItemTypeMenu); return menu_item->data; } -MenuItemCallback menu_item_get_function(MenuItem* menu_item) { +void menu_item_function_call(MenuItem* menu_item) { + assert(menu_item); assert(menu_item->type == MenuItemTypeFunction); - return menu_item->data; + + if(menu_item->callback) menu_item->callback(menu_item->callback_context); } diff --git a/applications/menu/menu_item.h b/applications/menu/menu_item.h index 57b81124..19f1a38e 100644 --- a/applications/menu/menu_item.h +++ b/applications/menu/menu_item.h @@ -9,13 +9,13 @@ typedef enum { } MenuItemType; typedef struct MenuItem MenuItem; -typedef void (*MenuItemCallback)(); +typedef void (*MenuItemCallback)(void *context); ARRAY_DEF(MenuItemArray, MenuItem*, M_PTR_OPLIST); MenuItem* menu_item_alloc_menu(const char* label, void* icon); -MenuItem* menu_item_alloc_function(const char* label, void* icon, MenuItemCallback function); +MenuItem* menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context); void menu_item_release(MenuItem* menu_item); @@ -33,4 +33,4 @@ void* menu_item_get_icon(MenuItem* menu_item); MenuItemArray_t* menu_item_get_subitems(MenuItem* menu_item); -MenuItemCallback menu_item_get_function(MenuItem* menu_item); +void menu_item_function_call(MenuItem* menu_item); From 23478fd175b9c3eb02430446217bce01c30a286d Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Fri, 16 Oct 2020 16:11:51 +0300 Subject: [PATCH 11/14] Menu: code format --- applications/menu/menu_item.c | 3 ++- applications/menu/menu_item.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/applications/menu/menu_item.c b/applications/menu/menu_item.c index e4d3143f..87c081c1 100644 --- a/applications/menu/menu_item.c +++ b/applications/menu/menu_item.c @@ -33,7 +33,8 @@ MenuItem* menu_item_alloc_menu(const char* label, void* icon) { return menu_item; } -MenuItem* menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context) { +MenuItem* +menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context) { MenuItem* menu_item = menu_item_alloc(); menu_item->type = MenuItemTypeFunction; diff --git a/applications/menu/menu_item.h b/applications/menu/menu_item.h index 19f1a38e..06838d6e 100644 --- a/applications/menu/menu_item.h +++ b/applications/menu/menu_item.h @@ -9,13 +9,14 @@ typedef enum { } MenuItemType; typedef struct MenuItem MenuItem; -typedef void (*MenuItemCallback)(void *context); +typedef void (*MenuItemCallback)(void* context); ARRAY_DEF(MenuItemArray, MenuItem*, M_PTR_OPLIST); MenuItem* menu_item_alloc_menu(const char* label, void* icon); -MenuItem* menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context); +MenuItem* +menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context); void menu_item_release(MenuItem* menu_item); From 1a36dfc5d32eed8148a3f7d0078494ab35cf0403 Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Fri, 16 Oct 2020 16:34:36 +0300 Subject: [PATCH 12/14] GUI: hide canvas inside --- applications/gui/canvas.c | 87 +++++++++++++++++++++++---------------- applications/gui/canvas.h | 29 +++---------- applications/menu/menu.c | 4 +- 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index 6dc7962c..c353bca3 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -4,6 +4,16 @@ #include #include +typedef struct { + CanvasApi api; + + u8g2_t fb; + uint8_t offset_x; + uint8_t offset_y; + uint8_t width; + uint8_t height; +} Canvas; + uint8_t canvas_width(CanvasApi* api); uint8_t canvas_height(CanvasApi* api); void canvas_clear(CanvasApi* api); @@ -15,30 +25,26 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); CanvasApi* canvas_api_init() { - CanvasApi* api = furi_alloc(sizeof(CanvasApi)); + Canvas* canvas = furi_alloc(sizeof(Canvas)); u8g2_Setup_st7565_erc12864_alt_f( - &api->canvas.fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); + &canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); // send init sequence to the display, display is in sleep mode after this - u8g2_InitDisplay(&api->canvas.fb); - u8g2_SetContrast(&api->canvas.fb, 36); + u8g2_InitDisplay(&canvas->fb); + u8g2_SetContrast(&canvas->fb, 36); - u8g2_SetPowerSave(&api->canvas.fb, 0); // wake up display - u8g2_SendBuffer(&api->canvas.fb); + u8g2_SetPowerSave(&canvas->fb, 0); // wake up display + u8g2_SendBuffer(&canvas->fb); - api->width = canvas_width; - api->height = canvas_height; - api->clear = canvas_clear; - api->set_color = canvas_color_set; - api->set_font = canvas_font_set; - api->draw_str = canvas_str_draw; + canvas->api.width = canvas_width; + canvas->api.height = canvas_height; + canvas->api.clear = canvas_clear; + canvas->api.set_color = canvas_color_set; + canvas->api.set_font = canvas_font_set; + canvas->api.draw_str = canvas_str_draw; - api->fonts = furi_alloc(sizeof(Fonts)); - api->fonts->primary = u8g2_font_Born2bSportyV2_tr; - api->fonts->secondary = u8g2_font_HelvetiPixel_tr; - - return api; + return (CanvasApi*)canvas; } void canvas_api_free(CanvasApi* api) { @@ -48,9 +54,9 @@ void canvas_api_free(CanvasApi* api) { void canvas_commit(CanvasApi* api) { assert(api); - - u8g2_SetPowerSave(&api->canvas.fb, 0); // wake up display - u8g2_SendBuffer(&api->canvas.fb); + Canvas* canvas = (Canvas *)api; + u8g2_SetPowerSave(&canvas->fb, 0); // wake up display + u8g2_SendBuffer(&canvas->fb); } void canvas_frame_set( @@ -60,43 +66,54 @@ void canvas_frame_set( uint8_t width, uint8_t height) { assert(api); - api->canvas.offset_x = offset_x; - api->canvas.offset_y = offset_y; - api->canvas.width = width; - api->canvas.height = height; + Canvas* canvas = (Canvas*)api; + canvas->offset_x = offset_x; + canvas->offset_y = offset_y; + canvas->width = width; + canvas->height = height; } uint8_t canvas_width(CanvasApi* api) { assert(api); - - return api->canvas.width; + Canvas* canvas = (Canvas *)api; + return canvas->width; } uint8_t canvas_height(CanvasApi* api) { assert(api); - - return api->canvas.height; + Canvas* canvas = (Canvas *)api; + return canvas->height; } void canvas_clear(CanvasApi* api) { assert(api); - u8g2_ClearBuffer(&api->canvas.fb); + Canvas* canvas = (Canvas *)api; + u8g2_ClearBuffer(&canvas->fb); } void canvas_color_set(CanvasApi* api, Color color) { assert(api); - u8g2_SetDrawColor(&api->canvas.fb, color); + Canvas* canvas = (Canvas *)api; + u8g2_SetDrawColor(&canvas->fb, color); } void canvas_font_set(CanvasApi* api, Font font) { assert(api); - u8g2_SetFontMode(&api->canvas.fb, 1); - u8g2_SetFont(&api->canvas.fb, font); + Canvas* canvas = (Canvas *)api; + u8g2_SetFontMode(&canvas->fb, 1); + if (font == FontPrimary) { + u8g2_SetFont(&canvas->fb, u8g2_font_Born2bSportyV2_tr); + } else if (font == FontSecondary) { + u8g2_SetFont(&canvas->fb, u8g2_font_HelvetiPixel_tr); + } else { + assert(0); + } } 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); + Canvas* canvas = (Canvas *)api; + x += canvas->offset_x; + y += canvas->offset_y; + u8g2_DrawStr(&canvas->fb, x, y, str); } diff --git a/applications/gui/canvas.h b/applications/gui/canvas.h index 27dd2efe..237a75de 100644 --- a/applications/gui/canvas.h +++ b/applications/gui/canvas.h @@ -8,30 +8,13 @@ typedef enum { ColorBlack = 0x01, } Color; -typedef const uint8_t* Font; - -typedef struct { - Font primary; - Font secondary; -} Fonts; - -struct _CanvasApi; - -typedef struct _CanvasApi CanvasApi; - -// Canvas is private but we need its declaration here -typedef struct { - u8g2_t fb; - uint8_t offset_x; - uint8_t offset_y; - uint8_t width; - uint8_t height; -} Canvas; - -struct _CanvasApi { - Canvas canvas; - Fonts* fonts; +typedef enum { + FontPrimary = 0x00, + FontSecondary = 0x01, +} Font; +typedef struct CanvasApi CanvasApi; +struct CanvasApi { uint8_t (*width)(CanvasApi* canvas); uint8_t (*height)(CanvasApi* canvas); diff --git a/applications/menu/menu.c b/applications/menu/menu.c index 0ef37d67..a0261bf5 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -87,13 +87,13 @@ void menu_widget_callback(CanvasApi* canvas, void* context) { if(!menu->current) { canvas->clear(canvas); canvas->set_color(canvas, ColorBlack); - canvas->set_font(canvas, canvas->fonts->primary); + canvas->set_font(canvas, FontPrimary); canvas->draw_str(canvas, 2, 32, "Idle Screen"); } else { MenuItemArray_t* items = menu_item_get_subitems(menu->current); canvas->clear(canvas); canvas->set_color(canvas, ColorBlack); - canvas->set_font(canvas, canvas->fonts->secondary); + canvas->set_font(canvas, FontSecondary); for(size_t i = 0; i < 5; i++) { size_t shift_position = i + menu->position + MenuItemArray_size(*items) - 2; shift_position = shift_position % (MenuItemArray_size(*items)); From 491343b683929fc1745e3338b78a932dd6803799 Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Fri, 16 Oct 2020 16:36:05 +0300 Subject: [PATCH 13/14] GUI: reformat sources --- applications/gui/canvas.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index c353bca3..842397bd 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -54,7 +54,7 @@ void canvas_api_free(CanvasApi* api) { void canvas_commit(CanvasApi* api) { assert(api); - Canvas* canvas = (Canvas *)api; + Canvas* canvas = (Canvas*)api; u8g2_SetPowerSave(&canvas->fb, 0); // wake up display u8g2_SendBuffer(&canvas->fb); } @@ -75,35 +75,35 @@ void canvas_frame_set( uint8_t canvas_width(CanvasApi* api) { assert(api); - Canvas* canvas = (Canvas *)api; + Canvas* canvas = (Canvas*)api; return canvas->width; } uint8_t canvas_height(CanvasApi* api) { assert(api); - Canvas* canvas = (Canvas *)api; + Canvas* canvas = (Canvas*)api; return canvas->height; } void canvas_clear(CanvasApi* api) { assert(api); - Canvas* canvas = (Canvas *)api; + Canvas* canvas = (Canvas*)api; u8g2_ClearBuffer(&canvas->fb); } void canvas_color_set(CanvasApi* api, Color color) { assert(api); - Canvas* canvas = (Canvas *)api; + Canvas* canvas = (Canvas*)api; u8g2_SetDrawColor(&canvas->fb, color); } void canvas_font_set(CanvasApi* api, Font font) { assert(api); - Canvas* canvas = (Canvas *)api; + Canvas* canvas = (Canvas*)api; u8g2_SetFontMode(&canvas->fb, 1); - if (font == FontPrimary) { + if(font == FontPrimary) { u8g2_SetFont(&canvas->fb, u8g2_font_Born2bSportyV2_tr); - } else if (font == FontSecondary) { + } else if(font == FontSecondary) { u8g2_SetFont(&canvas->fb, u8g2_font_HelvetiPixel_tr); } else { assert(0); @@ -112,7 +112,7 @@ void canvas_font_set(CanvasApi* api, Font font) { void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str) { assert(api); - Canvas* canvas = (Canvas *)api; + Canvas* canvas = (Canvas*)api; x += canvas->offset_x; y += canvas->offset_y; u8g2_DrawStr(&canvas->fb, x, y, str); From f0800e579f785c71998cae4ed03f36826a482392 Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Fri, 16 Oct 2020 18:25:06 +0300 Subject: [PATCH 14/14] GUI: GuiApi isolation --- applications/gui/gui.c | 37 ++++++++++++++++--------------------- applications/gui/gui.h | 8 ++------ applications/gui/gui_i.h | 2 ++ applications/gui/widget.c | 2 +- applications/gui/widget_i.h | 2 +- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 6be88315..38243562 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -15,6 +15,7 @@ ARRAY_DEF(WidgetArray, Widget*, M_PTR_OPLIST); struct Gui { + GuiApi api; GuiEvent* event; CanvasApi* canvas_api; WidgetArray_t widgets_status_bar; @@ -25,39 +26,37 @@ struct Gui { void gui_add_widget(GuiApi* gui_api, Widget* widget, WidgetLayer layer) { assert(gui_api); - assert(gui_api->gui); + assert(widget); + Gui* gui = (Gui*)gui_api; // TODO add mutex on widget array - WidgetArray_t* widget_array = NULL; switch(layer) { case WidgetLayerStatusBar: - widget_array = &gui_api->gui->widgets_status_bar; + widget_array = &gui->widgets_status_bar; break; case WidgetLayerMain: - widget_array = &gui_api->gui->widgets; + widget_array = &gui->widgets; break; case WidgetLayerFullscreen: - widget_array = &gui_api->gui->widgets_fs; + widget_array = &gui->widgets_fs; break; case WidgetLayerDialog: - widget_array = &gui_api->gui->widgets_dialog; + widget_array = &gui->widgets_dialog; break; - default: break; } - assert(widget); assert(widget_array); - gui_event_lock(gui_api->gui->event); - WidgetArray_push_back((struct WidgetArray_s*)widget_array, widget); - widget_gui_set(widget, gui_api->gui); - gui_event_unlock(gui_api->gui->event); + gui_event_lock(gui->event); + WidgetArray_push_back(*widget_array, widget); + widget_gui_set(widget, gui); + gui_event_unlock(gui->event); - gui_update(gui_api->gui); + gui_update(gui); } void gui_update(Gui* gui) { @@ -133,6 +132,7 @@ void gui_input(Gui* gui, InputEvent* input_event) { Gui* gui_alloc() { Gui* gui = furi_alloc(sizeof(Gui)); + // Initialize widget arrays WidgetArray_init(gui->widgets_status_bar); WidgetArray_init(gui->widgets); @@ -143,22 +143,17 @@ Gui* gui_alloc() { gui->event = gui_event_alloc(); // Drawing canvas api - gui->canvas_api = canvas_api_init(); + gui->api.add_widget = gui_add_widget; + return gui; } void gui_task(void* p) { Gui* gui = gui_alloc(); - - GuiApi gui_api = { - .add_widget = gui_add_widget, - .gui = gui, - }; - // Create FURI record - if(!furi_create("gui", &gui_api)) { + if(!furi_create("gui", gui)) { printf("[gui_task] cannot create the gui record\n"); furiac_exit(NULL); } diff --git a/applications/gui/gui.h b/applications/gui/gui.h index 371c0434..8db1cc20 100644 --- a/applications/gui/gui.h +++ b/applications/gui/gui.h @@ -11,12 +11,8 @@ typedef enum { } WidgetLayer; typedef struct Widget Widget; -typedef struct Gui Gui; -struct _GuiApi; -typedef struct _GuiApi GuiApi; - -struct _GuiApi { +typedef struct GuiApi GuiApi; +struct GuiApi { void (*add_widget)(GuiApi* gui_api, Widget* widget, WidgetLayer layer); - Gui* gui; }; diff --git a/applications/gui/gui_i.h b/applications/gui/gui_i.h index 6a9bf2a0..a64874c1 100644 --- a/applications/gui/gui_i.h +++ b/applications/gui/gui_i.h @@ -1,3 +1,5 @@ #pragma once +typedef struct Gui Gui; + void gui_update(Gui* gui); diff --git a/applications/gui/widget.c b/applications/gui/widget.c index 3277c24d..4b22679d 100644 --- a/applications/gui/widget.c +++ b/applications/gui/widget.c @@ -10,7 +10,7 @@ // TODO add mutex to widget ops struct Widget { - void* gui; + Gui* gui; bool is_enabled; WidgetDrawCallback draw_callback; void* draw_callback_context; diff --git a/applications/gui/widget_i.h b/applications/gui/widget_i.h index f6cc2f14..b3d481e9 100644 --- a/applications/gui/widget_i.h +++ b/applications/gui/widget_i.h @@ -1,6 +1,6 @@ #pragma once -#include "gui.h" +#include "gui_i.h" void widget_gui_set(Widget* widget, Gui* gui);