Merge branch 'ofw_dev' into dev

This commit is contained in:
MX 2024-02-09 12:48:37 +03:00
commit afad5e4407
No known key found for this signature in database
GPG Key ID: 7CCC66B7DBDD1C83
7 changed files with 133 additions and 53 deletions

View File

@ -19,6 +19,12 @@ Canvas* canvas_init() {
Canvas* canvas = malloc(sizeof(Canvas)); Canvas* canvas = malloc(sizeof(Canvas));
canvas->compress_icon = compress_icon_alloc(); 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 // Setup u8g2
u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
canvas->orientation = CanvasOrientationHorizontal; canvas->orientation = CanvasOrientationHorizontal;
@ -37,9 +43,21 @@ Canvas* canvas_init() {
void canvas_free(Canvas* canvas) { void canvas_free(Canvas* canvas) {
furi_assert(canvas); furi_assert(canvas);
compress_icon_free(canvas->compress_icon); compress_icon_free(canvas->compress_icon);
CanvasCallbackPairArray_clear(canvas->canvas_callback_pair);
furi_mutex_free(canvas->mutex);
free(canvas); 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) { void canvas_reset(Canvas* canvas) {
furi_assert(canvas); furi_assert(canvas);
@ -53,6 +71,18 @@ void canvas_reset(Canvas* canvas) {
void canvas_commit(Canvas* canvas) { void canvas_commit(Canvas* canvas) {
furi_assert(canvas); furi_assert(canvas);
u8g2_SendBuffer(&canvas->fb); 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) { uint8_t* canvas_get_buffer(Canvas* canvas) {
@ -567,3 +597,28 @@ void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) {
CanvasOrientation canvas_get_orientation(const Canvas* canvas) { CanvasOrientation canvas_get_orientation(const Canvas* canvas) {
return canvas->orientation; 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);
}

View File

@ -8,11 +8,31 @@
#include "canvas.h" #include "canvas.h"
#include <u8g2.h> #include <u8g2.h>
#include <toolbox/compress.h> #include <toolbox/compress.h>
#include <m-array.h>
#include <m-algo.h>
#include <furi.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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 /** Canvas structure
*/ */
struct Canvas { struct Canvas {
@ -23,6 +43,8 @@ struct Canvas {
uint8_t width; uint8_t width;
uint8_t height; uint8_t height;
CompressIcon* compress_icon; CompressIcon* compress_icon;
CanvasCallbackPairArray_t canvas_callback_pair;
FuriMutex* mutex;
}; };
/** Allocate memory and initialize canvas /** Allocate memory and initialize canvas
@ -102,6 +124,27 @@ void canvas_draw_u8g2_bitmap(
const uint8_t* bitmap, const uint8_t* bitmap,
uint8_t rotation); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -265,14 +265,6 @@ static void gui_redraw(Gui* gui) {
} }
canvas_commit(gui->canvas); 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); } while(false);
gui_unlock(gui); 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) { void gui_add_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context) {
furi_assert(gui); furi_assert(gui);
const CanvasCallbackPair p = {callback, context}; canvas_add_framebuffer_callback(gui->canvas, 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);
// Request redraw // Request redraw
gui_update(gui); 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) { void gui_remove_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context) {
furi_assert(gui); furi_assert(gui);
const CanvasCallbackPair p = {callback, context}; canvas_remove_framebuffer_callback(gui->canvas, 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);
} }
size_t gui_get_framebuffer_size(const Gui* gui) { size_t gui_get_framebuffer_size(const Gui* gui) {
@ -542,20 +524,19 @@ Gui* gui_alloc() {
gui->thread_id = furi_thread_get_current_id(); gui->thread_id = furi_thread_get_current_id();
// Allocate mutex // Allocate mutex
gui->mutex = furi_mutex_alloc(FuriMutexTypeNormal); gui->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
furi_check(gui->mutex);
// Layers // Layers
for(size_t i = 0; i < GuiLayerMAX; i++) { for(size_t i = 0; i < GuiLayerMAX; i++) {
ViewPortArray_init(gui->layers[i]); ViewPortArray_init(gui->layers[i]);
} }
// Drawing canvas // Drawing canvas
gui->canvas = canvas_init(); gui->canvas = canvas_init();
CanvasCallbackPairArray_init(gui->canvas_callback_pair);
// Input // Input
gui->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); gui->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
gui->input_events = furi_record_open(RECORD_INPUT_EVENTS); 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); furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui);
return gui; return gui;

View File

@ -10,7 +10,6 @@
#include <furi.h> #include <furi.h>
#include <furi_hal_rtc.h> #include <furi_hal_rtc.h>
#include <m-array.h> #include <m-array.h>
#include <m-algo.h>
#include <stdio.h> #include <stdio.h>
#include "canvas.h" #include "canvas.h"
@ -44,17 +43,6 @@
ARRAY_DEF(ViewPortArray, ViewPort*, M_PTR_OPLIST); 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 */ /** Gui structure */
struct Gui { struct Gui {
// Thread and lock // Thread and lock
@ -66,7 +54,6 @@ struct Gui {
bool direct_draw; bool direct_draw;
ViewPortArray_t layers[GuiLayerMAX]; ViewPortArray_t layers[GuiLayerMAX];
Canvas* canvas; Canvas* canvas;
CanvasCallbackPairArray_t canvas_callback_pair;
// Input // Input
FuriMessageQueue* input_queue; FuriMessageQueue* input_queue;

View File

@ -21,6 +21,10 @@ extern "C" {
#define FURI_PACKED __attribute__((packed)) #define FURI_PACKED __attribute__((packed))
#endif #endif
#ifndef FURI_ALWAYS_STATIC_INLINE
#define FURI_ALWAYS_STATIC_INLINE __attribute__((always_inline)) static inline
#endif
#ifndef FURI_IS_IRQ_MASKED #ifndef FURI_IS_IRQ_MASKED
#define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U) #define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
#endif #endif

View File

@ -129,11 +129,9 @@ void furi_hal_gpio_init_ex(
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT);
LL_SYSCFG_SetEXTISource(sys_exti_port, sys_exti_line); LL_SYSCFG_SetEXTISource(sys_exti_port, sys_exti_line);
if(mode == GpioModeInterruptRise || mode == GpioModeInterruptRiseFall) { if(mode == GpioModeInterruptRise || mode == GpioModeInterruptRiseFall) {
LL_EXTI_EnableIT_0_31(exti_line);
LL_EXTI_EnableRisingTrig_0_31(exti_line); LL_EXTI_EnableRisingTrig_0_31(exti_line);
} }
if(mode == GpioModeInterruptFall || mode == GpioModeInterruptRiseFall) { if(mode == GpioModeInterruptFall || mode == GpioModeInterruptRiseFall) {
LL_EXTI_EnableIT_0_31(exti_line);
LL_EXTI_EnableFallingTrig_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line);
} }
if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) { 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 && if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port &&
LL_EXTI_IsEnabledIT_0_31(exti_line)) { LL_EXTI_IsEnabledIT_0_31(exti_line)) {
LL_EXTI_DisableIT_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_DisableRisingTrig_0_31(exti_line);
LL_EXTI_DisableFallingTrig_0_31(exti_line); LL_EXTI_DisableFallingTrig_0_31(exti_line);
} }
@ -199,14 +198,15 @@ void furi_hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, vo
furi_assert(cb); furi_assert(cb);
FURI_CRITICAL_ENTER(); FURI_CRITICAL_ENTER();
uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio);
volatile GpioInterrupt* interrupt = &gpio_interrupt[pin_num]; furi_check(gpio_interrupt[pin_num].callback == NULL);
furi_check( gpio_interrupt[pin_num].callback = cb;
(interrupt->callback == NULL) || gpio_interrupt[pin_num].context = ctx;
((interrupt->callback == cb) && (interrupt->context == ctx)));
interrupt->callback = cb; const uint32_t exti_line = GET_EXTI_LINE(gpio->pin);
interrupt->context = ctx; LL_EXTI_EnableIT_0_31(exti_line);
interrupt->ready = true;
FURI_CRITICAL_EXIT(); FURI_CRITICAL_EXIT();
} }
@ -214,10 +214,13 @@ void furi_hal_gpio_enable_int_callback(const GpioPin* gpio) {
furi_assert(gpio); furi_assert(gpio);
FURI_CRITICAL_ENTER(); FURI_CRITICAL_ENTER();
uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio);
if(gpio_interrupt[pin_num].callback) { 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(); FURI_CRITICAL_EXIT();
} }
@ -225,8 +228,11 @@ void furi_hal_gpio_disable_int_callback(const GpioPin* gpio) {
furi_assert(gpio); furi_assert(gpio);
FURI_CRITICAL_ENTER(); 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(); FURI_CRITICAL_EXIT();
} }
@ -234,15 +240,20 @@ void furi_hal_gpio_remove_int_callback(const GpioPin* gpio) {
furi_assert(gpio); furi_assert(gpio);
FURI_CRITICAL_ENTER(); 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); uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].callback = NULL; gpio_interrupt[pin_num].callback = NULL;
gpio_interrupt[pin_num].context = NULL; gpio_interrupt[pin_num].context = NULL;
gpio_interrupt[pin_num].ready = false;
FURI_CRITICAL_EXIT(); FURI_CRITICAL_EXIT();
} }
static void furi_hal_gpio_int_call(uint16_t pin_num) { FURI_ALWAYS_STATIC_INLINE void furi_hal_gpio_int_call(uint16_t pin_num) {
if(gpio_interrupt[pin_num].callback && gpio_interrupt[pin_num].ready) { if(gpio_interrupt[pin_num].callback) {
gpio_interrupt[pin_num].callback(gpio_interrupt[pin_num].context); gpio_interrupt[pin_num].callback(gpio_interrupt[pin_num].context);
} }
} }

View File

@ -24,7 +24,6 @@ typedef void (*GpioExtiCallback)(void* ctx);
typedef struct { typedef struct {
GpioExtiCallback callback; GpioExtiCallback callback;
void* context; void* context;
volatile bool ready;
} GpioInterrupt; } GpioInterrupt;
/** /**