From 29fa68118d827e951ea1c9139e470838cf8d090e Mon Sep 17 00:00:00 2001 From: Sergei Gavrilov Date: Wed, 7 Feb 2024 12:38:20 +1000 Subject: [PATCH 1/2] GUI: canvas commit callback has been moved to canvas. Direct Draw apps can now be streamed via RPC. (#3397) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/services/gui/canvas.c | 55 ++++++++++++++++++++++++++++ applications/services/gui/canvas_i.h | 51 ++++++++++++++++++++++++++ applications/services/gui/gui.c | 27 ++------------ applications/services/gui/gui_i.h | 13 ------- 4 files changed, 110 insertions(+), 36 deletions(-) diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 44adcd939..897f0ae13 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -18,6 +18,12 @@ Canvas* canvas_init() { Canvas* canvas = malloc(sizeof(Canvas)); canvas->compress_icon = compress_icon_alloc(); + // Initialize mutex + canvas->mutex = furi_mutex_alloc(FuriMutexTypeNormal); + + // Initialize callback array + CanvasCallbackPairArray_init(canvas->canvas_callback_pair); + // Setup u8g2 u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); canvas->orientation = CanvasOrientationHorizontal; @@ -36,9 +42,21 @@ Canvas* canvas_init() { void canvas_free(Canvas* canvas) { furi_assert(canvas); compress_icon_free(canvas->compress_icon); + CanvasCallbackPairArray_clear(canvas->canvas_callback_pair); + furi_mutex_free(canvas->mutex); free(canvas); } +static void canvas_lock(Canvas* canvas) { + furi_assert(canvas); + furi_check(furi_mutex_acquire(canvas->mutex, FuriWaitForever) == FuriStatusOk); +} + +static void canvas_unlock(Canvas* canvas) { + furi_assert(canvas); + furi_check(furi_mutex_release(canvas->mutex) == FuriStatusOk); +} + void canvas_reset(Canvas* canvas) { furi_assert(canvas); @@ -52,6 +70,18 @@ void canvas_reset(Canvas* canvas) { void canvas_commit(Canvas* canvas) { furi_assert(canvas); u8g2_SendBuffer(&canvas->fb); + + // Iterate over callbacks + canvas_lock(canvas); + for + M_EACH(p, canvas->canvas_callback_pair, CanvasCallbackPairArray_t) { + p->callback( + canvas_get_buffer(canvas), + canvas_get_buffer_size(canvas), + canvas_get_orientation(canvas), + p->context); + } + canvas_unlock(canvas); } uint8_t* canvas_get_buffer(Canvas* canvas) { @@ -542,3 +572,28 @@ void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) { CanvasOrientation canvas_get_orientation(const Canvas* canvas) { return canvas->orientation; } + +void canvas_add_framebuffer_callback(Canvas* canvas, CanvasCommitCallback callback, void* context) { + furi_assert(canvas); + + const CanvasCallbackPair p = {callback, context}; + + canvas_lock(canvas); + furi_assert(!CanvasCallbackPairArray_count(canvas->canvas_callback_pair, p)); + CanvasCallbackPairArray_push_back(canvas->canvas_callback_pair, p); + canvas_unlock(canvas); +} + +void canvas_remove_framebuffer_callback( + Canvas* canvas, + CanvasCommitCallback callback, + void* context) { + furi_assert(canvas); + + const CanvasCallbackPair p = {callback, context}; + + canvas_lock(canvas); + furi_assert(CanvasCallbackPairArray_count(canvas->canvas_callback_pair, p) == 1); + CanvasCallbackPairArray_remove_val(canvas->canvas_callback_pair, p); + canvas_unlock(canvas); +} \ No newline at end of file diff --git a/applications/services/gui/canvas_i.h b/applications/services/gui/canvas_i.h index f3b8f17ad..73502b719 100644 --- a/applications/services/gui/canvas_i.h +++ b/applications/services/gui/canvas_i.h @@ -8,6 +8,30 @@ #include "canvas.h" #include #include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*CanvasCommitCallback)( + uint8_t* data, + size_t size, + CanvasOrientation orientation, + void* context); + +typedef struct { + CanvasCommitCallback callback; + void* context; +} CanvasCallbackPair; + +ARRAY_DEF(CanvasCallbackPairArray, CanvasCallbackPair, M_POD_OPLIST); + +#define M_OPL_CanvasCallbackPairArray_t() ARRAY_OPLIST(CanvasCallbackPairArray, M_POD_OPLIST) + +ALGO_DEF(CanvasCallbackPairArray, CanvasCallbackPairArray_t); /** Canvas structure */ @@ -19,6 +43,8 @@ struct Canvas { uint8_t width; uint8_t height; CompressIcon* compress_icon; + CanvasCallbackPairArray_t canvas_callback_pair; + FuriMutex* mutex; }; /** Allocate memory and initialize canvas @@ -97,3 +123,28 @@ void canvas_draw_u8g2_bitmap( uint8_t height, const uint8_t* bitmap, uint8_t rotation); + +/** Add canvas commit callback. + * + * This callback will be called upon Canvas commit. + * + * @param canvas Canvas instance + * @param callback CanvasCommitCallback + * @param context CanvasCommitCallback context + */ +void canvas_add_framebuffer_callback(Canvas* canvas, CanvasCommitCallback callback, void* context); + +/** Remove canvas commit callback. + * + * @param canvas Canvas instance + * @param callback CanvasCommitCallback + * @param context CanvasCommitCallback context + */ +void canvas_remove_framebuffer_callback( + Canvas* canvas, + CanvasCommitCallback callback, + void* context); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 0bdc999b7..9deaf23fe 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -265,14 +265,6 @@ static void gui_redraw(Gui* gui) { } canvas_commit(gui->canvas); - for - M_EACH(p, gui->canvas_callback_pair, CanvasCallbackPairArray_t) { - p->callback( - canvas_get_buffer(gui->canvas), - canvas_get_buffer_size(gui->canvas), - canvas_get_orientation(gui->canvas), - p->context); - } } while(false); gui_unlock(gui); @@ -473,12 +465,7 @@ void gui_view_port_send_to_back(Gui* gui, ViewPort* view_port) { void gui_add_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context) { furi_assert(gui); - const CanvasCallbackPair p = {callback, context}; - - gui_lock(gui); - furi_assert(!CanvasCallbackPairArray_count(gui->canvas_callback_pair, p)); - CanvasCallbackPairArray_push_back(gui->canvas_callback_pair, p); - gui_unlock(gui); + canvas_add_framebuffer_callback(gui->canvas, callback, context); // Request redraw gui_update(gui); @@ -487,12 +474,7 @@ void gui_add_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, vo void gui_remove_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context) { furi_assert(gui); - const CanvasCallbackPair p = {callback, context}; - - gui_lock(gui); - furi_assert(CanvasCallbackPairArray_count(gui->canvas_callback_pair, p) == 1); - CanvasCallbackPairArray_remove_val(gui->canvas_callback_pair, p); - gui_unlock(gui); + canvas_remove_framebuffer_callback(gui->canvas, callback, context); } size_t gui_get_framebuffer_size(const Gui* gui) { @@ -542,20 +524,19 @@ Gui* gui_alloc() { gui->thread_id = furi_thread_get_current_id(); // Allocate mutex gui->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - furi_check(gui->mutex); + // Layers for(size_t i = 0; i < GuiLayerMAX; i++) { ViewPortArray_init(gui->layers[i]); } + // Drawing canvas gui->canvas = canvas_init(); - CanvasCallbackPairArray_init(gui->canvas_callback_pair); // Input gui->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); gui->input_events = furi_record_open(RECORD_INPUT_EVENTS); - furi_check(gui->input_events); furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui); return gui; diff --git a/applications/services/gui/gui_i.h b/applications/services/gui/gui_i.h index a5e269e03..3ca9c05c9 100644 --- a/applications/services/gui/gui_i.h +++ b/applications/services/gui/gui_i.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include "canvas.h" @@ -44,17 +43,6 @@ ARRAY_DEF(ViewPortArray, ViewPort*, M_PTR_OPLIST); -typedef struct { - GuiCanvasCommitCallback callback; - void* context; -} CanvasCallbackPair; - -ARRAY_DEF(CanvasCallbackPairArray, CanvasCallbackPair, M_POD_OPLIST); - -#define M_OPL_CanvasCallbackPairArray_t() ARRAY_OPLIST(CanvasCallbackPairArray, M_POD_OPLIST) - -ALGO_DEF(CanvasCallbackPairArray, CanvasCallbackPairArray_t); - /** Gui structure */ struct Gui { // Thread and lock @@ -66,7 +54,6 @@ struct Gui { bool direct_draw; ViewPortArray_t layers[GuiLayerMAX]; Canvas* canvas; - CanvasCallbackPairArray_t canvas_callback_pair; // Input FuriMessageQueue* input_queue; From afd41aade1bc1a9a8de23e7754ef4e8c441c0865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Wed, 7 Feb 2024 16:09:29 +0700 Subject: [PATCH 2/2] FuriHal: various GPIO improvements (#3406) --- furi/core/common_defines.h | 4 ++++ targets/f7/furi_hal/furi_hal_gpio.c | 32 +++++++++++++++++++++-------- targets/f7/furi_hal/furi_hal_gpio.h | 1 - 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/furi/core/common_defines.h b/furi/core/common_defines.h index b0062e659..2fc12dedb 100644 --- a/furi/core/common_defines.h +++ b/furi/core/common_defines.h @@ -21,6 +21,10 @@ extern "C" { #define FURI_PACKED __attribute__((packed)) #endif +#ifndef FURI_ALWAYS_STATIC_INLINE +#define FURI_ALWAYS_STATIC_INLINE __attribute__((always_inline)) static inline +#endif + #ifndef FURI_IS_IRQ_MASKED #define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U) #endif diff --git a/targets/f7/furi_hal/furi_hal_gpio.c b/targets/f7/furi_hal/furi_hal_gpio.c index d5221aba9..1e703b5d1 100644 --- a/targets/f7/furi_hal/furi_hal_gpio.c +++ b/targets/f7/furi_hal/furi_hal_gpio.c @@ -129,11 +129,9 @@ void furi_hal_gpio_init_ex( LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); LL_SYSCFG_SetEXTISource(sys_exti_port, sys_exti_line); if(mode == GpioModeInterruptRise || mode == GpioModeInterruptRiseFall) { - LL_EXTI_EnableIT_0_31(exti_line); LL_EXTI_EnableRisingTrig_0_31(exti_line); } if(mode == GpioModeInterruptFall || mode == GpioModeInterruptRiseFall) { - LL_EXTI_EnableIT_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) { @@ -149,6 +147,7 @@ void furi_hal_gpio_init_ex( if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port && LL_EXTI_IsEnabledIT_0_31(exti_line)) { LL_EXTI_DisableIT_0_31(exti_line); + LL_EXTI_ClearFlag_0_31(exti_line); LL_EXTI_DisableRisingTrig_0_31(exti_line); LL_EXTI_DisableFallingTrig_0_31(exti_line); } @@ -199,11 +198,15 @@ void furi_hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, vo furi_assert(cb); FURI_CRITICAL_ENTER(); + uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); furi_check(gpio_interrupt[pin_num].callback == NULL); gpio_interrupt[pin_num].callback = cb; gpio_interrupt[pin_num].context = ctx; - gpio_interrupt[pin_num].ready = true; + + const uint32_t exti_line = GET_EXTI_LINE(gpio->pin); + LL_EXTI_EnableIT_0_31(exti_line); + FURI_CRITICAL_EXIT(); } @@ -211,10 +214,13 @@ void furi_hal_gpio_enable_int_callback(const GpioPin* gpio) { furi_assert(gpio); FURI_CRITICAL_ENTER(); + uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); if(gpio_interrupt[pin_num].callback) { - gpio_interrupt[pin_num].ready = true; + const uint32_t exti_line = GET_EXTI_LINE(gpio->pin); + LL_EXTI_EnableIT_0_31(exti_line); } + FURI_CRITICAL_EXIT(); } @@ -222,8 +228,11 @@ void furi_hal_gpio_disable_int_callback(const GpioPin* gpio) { furi_assert(gpio); FURI_CRITICAL_ENTER(); - uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); - gpio_interrupt[pin_num].ready = false; + + const uint32_t exti_line = GET_EXTI_LINE(gpio->pin); + LL_EXTI_DisableIT_0_31(exti_line); + LL_EXTI_ClearFlag_0_31(exti_line); + FURI_CRITICAL_EXIT(); } @@ -231,15 +240,20 @@ void furi_hal_gpio_remove_int_callback(const GpioPin* gpio) { furi_assert(gpio); FURI_CRITICAL_ENTER(); + + const uint32_t exti_line = GET_EXTI_LINE(gpio->pin); + LL_EXTI_DisableIT_0_31(exti_line); + LL_EXTI_ClearFlag_0_31(exti_line); + uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); gpio_interrupt[pin_num].callback = NULL; gpio_interrupt[pin_num].context = NULL; - gpio_interrupt[pin_num].ready = false; + FURI_CRITICAL_EXIT(); } -static void furi_hal_gpio_int_call(uint16_t pin_num) { - if(gpio_interrupt[pin_num].callback && gpio_interrupt[pin_num].ready) { +FURI_ALWAYS_STATIC_INLINE void furi_hal_gpio_int_call(uint16_t pin_num) { + if(gpio_interrupt[pin_num].callback) { gpio_interrupt[pin_num].callback(gpio_interrupt[pin_num].context); } } diff --git a/targets/f7/furi_hal/furi_hal_gpio.h b/targets/f7/furi_hal/furi_hal_gpio.h index 0999971bc..9e78872bb 100644 --- a/targets/f7/furi_hal/furi_hal_gpio.h +++ b/targets/f7/furi_hal/furi_hal_gpio.h @@ -24,7 +24,6 @@ typedef void (*GpioExtiCallback)(void* ctx); typedef struct { GpioExtiCallback callback; void* context; - volatile bool ready; } GpioInterrupt; /**