Rust bindings API review #51
|
@ -2,7 +2,7 @@ use embedded_graphics::pixelcolor::Rgb565;
|
|||
use embedded_graphics::prelude::*;
|
||||
use embedded_graphics_simulator::{OutputSettingsBuilder, SimulatorDisplay, Window};
|
||||
use lvgl;
|
||||
use lvgl::display::{Display, DisplayBuffer, DisplayDriver};
|
||||
use lvgl::display::Display;
|
||||
|
||||
type ColorSpace = Rgb565;
|
||||
|
||||
|
@ -17,7 +17,5 @@ fn main() {
|
|||
|
||||
// LVGL usage
|
||||
lvgl::init();
|
||||
|
||||
let mut display_diver = DisplayDriver::new(DisplayBuffer::new(), embedded_graphics_display);
|
||||
let gui = lvgl::disp_drv_register(&mut display_diver).unwrap();
|
||||
Display::register(embedded_graphics_display).unwrap();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @file lv_conf.h
|
||||
*
|
||||
* Configuration file for v7.10.1
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -82,7 +82,7 @@ typedef int16_t lv_coord_t;
|
|||
/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
|
||||
# define LV_MEM_SIZE (1048576U) // 1Mb
|
||||
|
||||
/* Complier prefix for a big array declaration */
|
||||
/* Compiler prefix for a big array declaration */
|
||||
# define LV_MEM_ATTR
|
||||
|
||||
/* Set an address for the memory pool instead of allocating it as an array.
|
||||
|
@ -97,6 +97,10 @@ typedef int16_t lv_coord_t;
|
|||
# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/
|
||||
#endif /*LV_MEM_CUSTOM*/
|
||||
|
||||
/* Use the standard memcpy and memset instead of LVGL's own functions.
|
||||
* The standard functions might or might not be faster depending on their implementation. */
|
||||
#define LV_MEMCPY_MEMSET_STD 0
|
||||
|
||||
/* Garbage Collector settings
|
||||
* Used if lvgl is binded to higher level language and the memory is managed by that language */
|
||||
#define LV_ENABLE_GC 0
|
||||
|
@ -123,14 +127,13 @@ typedef int16_t lv_coord_t;
|
|||
#define LV_INDEV_DEF_DRAG_THROW 10
|
||||
|
||||
/* Long press time in milliseconds.
|
||||
* Time to send `LV_EVENT_LONG_PRESSSED`) */
|
||||
* Time to send `LV_EVENT_LONG_PRESSED`) */
|
||||
#define LV_INDEV_DEF_LONG_PRESS_TIME 400
|
||||
|
||||
/* Repeated trigger period in long press [ms]
|
||||
* Time between `LV_EVENT_LONG_PRESSED_REPEAT */
|
||||
#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100
|
||||
|
||||
|
||||
/* Gesture threshold in pixels */
|
||||
#define LV_INDEV_DEF_GESTURE_LIMIT 50
|
||||
|
||||
|
@ -150,7 +153,7 @@ typedef void * lv_anim_user_data_t;
|
|||
|
||||
#endif
|
||||
|
||||
/* 1: Enable shadow drawing*/
|
||||
/* 1: Enable shadow drawing on rectangles*/
|
||||
#define LV_USE_SHADOW 1
|
||||
#if LV_USE_SHADOW
|
||||
/* Allow buffering some shadow calculation
|
||||
|
@ -160,6 +163,15 @@ typedef void * lv_anim_user_data_t;
|
|||
#define LV_SHADOW_CACHE_SIZE 0
|
||||
#endif
|
||||
|
||||
/*1: enable outline drawing on rectangles*/
|
||||
#define LV_USE_OUTLINE 1
|
||||
|
||||
/*1: enable pattern drawing on rectangles*/
|
||||
#define LV_USE_PATTERN 1
|
||||
|
||||
/*1: enable value string drawing on rectangles*/
|
||||
#define LV_USE_VALUE_STR 1
|
||||
|
||||
/* 1: Use other blend modes than normal (`LV_BLEND_MODE_...`)*/
|
||||
#define LV_USE_BLEND_MODES 1
|
||||
|
||||
|
@ -178,6 +190,22 @@ typedef void * lv_group_user_data_t;
|
|||
/* 1: Enable GPU interface*/
|
||||
#define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */
|
||||
#define LV_USE_GPU_STM32_DMA2D 0
|
||||
/*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor
|
||||
e.g. "stm32f769xx.h" or "stm32f429xx.h" */
|
||||
#define LV_GPU_DMA2D_CMSIS_INCLUDE
|
||||
|
||||
/*1: Use PXP for CPU off-load on NXP RTxxx platforms */
|
||||
#define LV_USE_GPU_NXP_PXP 0
|
||||
|
||||
/*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c)
|
||||
* and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol FSL_RTOS_FREE_RTOS
|
||||
* has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected.
|
||||
*0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init()
|
||||
* */
|
||||
#define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
|
||||
|
||||
/*1: Use VG-Lite for CPU offload on NXP RTxxx platforms */
|
||||
#define LV_USE_GPU_NXP_VG_LITE 0
|
||||
|
||||
/* 1: Enable file system (might be required for images */
|
||||
#define LV_USE_FILESYSTEM 1
|
||||
|
@ -194,6 +222,7 @@ typedef void * lv_fs_drv_user_data_t;
|
|||
|
||||
/*1: Use the functions and types from the older API if possible */
|
||||
#define LV_USE_API_EXTENSION_V6 1
|
||||
#define LV_USE_API_EXTENSION_V7 1
|
||||
|
||||
/*========================
|
||||
* Image decoder and cache
|
||||
|
@ -210,7 +239,7 @@ typedef void * lv_fs_drv_user_data_t;
|
|||
* (I.e. no new image decoder is added)
|
||||
* With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
|
||||
* However the opened images might consume additional RAM.
|
||||
* LV_IMG_CACHE_DEF_SIZE must be >= 1 */
|
||||
* Set it to 0 to disable caching */
|
||||
#define LV_IMG_CACHE_DEF_SIZE 1
|
||||
|
||||
/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/
|
||||
|
@ -219,6 +248,10 @@ typedef void * lv_img_decoder_user_data_t;
|
|||
/*=====================
|
||||
* Compiler settings
|
||||
*====================*/
|
||||
|
||||
/* For big endian systems set to 1 */
|
||||
#define LV_BIG_ENDIAN_SYSTEM 0
|
||||
|
||||
/* Define a custom attribute to `lv_tick_inc` function */
|
||||
#define LV_ATTRIBUTE_TICK_INC
|
||||
|
||||
|
@ -228,9 +261,14 @@ typedef void * lv_img_decoder_user_data_t;
|
|||
/* Define a custom attribute to `lv_disp_flush_ready` function */
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
|
||||
/* Required alignment size for buffers */
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN_SIZE
|
||||
|
||||
/* With size optimization (-Os) the compiler might not align data to
|
||||
* 4 or 8 byte boundary. This alignment will be explicitly applied where needed.
|
||||
* E.g. __attribute__((aligned(4))) */
|
||||
* 4 or 8 byte boundary. Some HW may need even 32 or 64 bytes.
|
||||
* This alignment will be explicitly applied where needed.
|
||||
* LV_ATTRIBUTE_MEM_ALIGN_SIZE should be used to specify required align size.
|
||||
* E.g. __attribute__((aligned(LV_ATTRIBUTE_MEM_ALIGN_SIZE))) */
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
|
||||
/* Attribute to mark large constant arrays for example
|
||||
|
@ -249,6 +287,10 @@ typedef void * lv_img_decoder_user_data_t;
|
|||
*/
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning
|
||||
|
||||
/* Prefix variables that are used in GPU accelerated operations, often these need to be
|
||||
* placed in RAM sections that are DMA accessible */
|
||||
#define LV_ATTRIBUTE_DMA
|
||||
|
||||
/*===================
|
||||
* HAL settings
|
||||
*==================*/
|
||||
|
@ -257,8 +299,8 @@ typedef void * lv_img_decoder_user_data_t;
|
|||
* It removes the need to manually update the tick with `lv_tick_inc`) */
|
||||
#define LV_TICK_CUSTOM 0
|
||||
#if LV_TICK_CUSTOM == 1
|
||||
#define LV_TICK_CUSTOM_INCLUDE "something.h" /*Header for the sys time function*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current systime in ms*/
|
||||
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
|
||||
#endif /*LV_TICK_CUSTOM*/
|
||||
|
||||
typedef void * lv_disp_drv_user_data_t; /*Type of user data in the display driver*/
|
||||
|
@ -330,15 +372,17 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
|||
|
||||
/* The built-in fonts contains the ASCII range and some Symbols with 4 bit-per-pixel.
|
||||
* The symbols are available via `LV_SYMBOL_...` defines
|
||||
* More info about fonts: https://docs.lvgl.com/#Fonts
|
||||
* More info about fonts: https://docs.lvgl.io/v7/en/html/overview/font.html
|
||||
* To create a new font go to: https://lvgl.com/ttf-font-to-c-array
|
||||
*/
|
||||
|
||||
/* Montserrat fonts with bpp = 4
|
||||
* https://fonts.google.com/specimen/Montserrat */
|
||||
#define LV_FONT_MONTSERRAT_8 0
|
||||
#define LV_FONT_MONTSERRAT_10 0
|
||||
#define LV_FONT_MONTSERRAT_12 0
|
||||
#define LV_FONT_MONTSERRAT_14 0
|
||||
#define LV_FONT_MONTSERRAT_16 1
|
||||
#define LV_FONT_MONTSERRAT_14 1
|
||||
#define LV_FONT_MONTSERRAT_16 0
|
||||
#define LV_FONT_MONTSERRAT_18 0
|
||||
#define LV_FONT_MONTSERRAT_20 0
|
||||
#define LV_FONT_MONTSERRAT_22 0
|
||||
|
@ -365,6 +409,7 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
|||
/*Pixel perfect monospace font
|
||||
* http://pelulamu.net/unscii/ */
|
||||
#define LV_FONT_UNSCII_8 0
|
||||
#define LV_FONT_UNSCII_16 0
|
||||
|
||||
/* Optionally declare your custom fonts here.
|
||||
* You can use these fonts as default font too
|
||||
|
@ -379,11 +424,20 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
|||
* but with > 10,000 characters if you see issues probably you need to enable it.*/
|
||||
#define LV_FONT_FMT_TXT_LARGE 0
|
||||
|
||||
/* Enables/disables support for compressed fonts. If it's disabled, compressed
|
||||
* glyphs cannot be processed by the library and won't be rendered.
|
||||
*/
|
||||
#define LV_USE_FONT_COMPRESSED 1
|
||||
|
||||
/* Enable subpixel rendering */
|
||||
#define LV_USE_FONT_SUBPX 1
|
||||
#if LV_USE_FONT_SUBPX
|
||||
/* Set the pixel order of the display.
|
||||
* Important only if "subpx fonts" are used.
|
||||
* With "normal" font it doesn't matter.
|
||||
*/
|
||||
#define LV_FONT_SUBPX_BGR 0
|
||||
#endif
|
||||
|
||||
/*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void * lv_font_user_data_t;
|
||||
|
@ -396,34 +450,37 @@ typedef void * lv_font_user_data_t;
|
|||
|
||||
/* No theme, you can apply your styles as you need
|
||||
* No flags. Set LV_THEME_DEFAULT_FLAG 0 */
|
||||
#define LV_USE_THEME_EMPTY 1
|
||||
#define LV_USE_THEME_EMPTY 1
|
||||
|
||||
/*Simple to the create your theme based on it
|
||||
* No flags. Set LV_THEME_DEFAULT_FLAG 0 */
|
||||
#define LV_USE_THEME_TEMPLATE 1
|
||||
#define LV_USE_THEME_TEMPLATE 1
|
||||
|
||||
/* A fast and impressive theme.
|
||||
* Flags:
|
||||
* LV_THEME_MATERIAL_FLAG_LIGHT: light theme
|
||||
* LV_THEME_MATERIAL_FLAG_DARK: dark theme*/
|
||||
#define LV_USE_THEME_MATERIAL 1
|
||||
* LV_THEME_MATERIAL_FLAG_DARK: dark theme
|
||||
* LV_THEME_MATERIAL_FLAG_NO_TRANSITION: disable transitions (state change animations)
|
||||
* LV_THEME_MATERIAL_FLAG_NO_FOCUS: disable indication of focused state)
|
||||
* */
|
||||
#define LV_USE_THEME_MATERIAL 1
|
||||
|
||||
/* Mono-color theme for monochrome displays.
|
||||
* If LV_THEME_DEFAULT_COLOR_PRIMARY is LV_COLOR_BLACK the
|
||||
* texts and borders will be black and the background will be
|
||||
* white. Else the colors are inverted.
|
||||
* No flags. Set LV_THEME_DEFAULT_FLAG 0 */
|
||||
#define LV_USE_THEME_MONO 1
|
||||
#define LV_USE_THEME_MONO 1
|
||||
|
||||
#define LV_THEME_DEFAULT_INCLUDE <stdint.h> /*Include a header for the init. function*/
|
||||
#define LV_THEME_DEFAULT_INIT lv_theme_material_init
|
||||
#define LV_THEME_DEFAULT_COLOR_PRIMARY LV_COLOR_RED
|
||||
#define LV_THEME_DEFAULT_COLOR_SECONDARY LV_COLOR_BLUE
|
||||
#define LV_THEME_DEFAULT_COLOR_PRIMARY lv_color_hex(0x01a2b1)
|
||||
#define LV_THEME_DEFAULT_COLOR_SECONDARY lv_color_hex(0x44d1b6)
|
||||
#define LV_THEME_DEFAULT_FLAG LV_THEME_MATERIAL_FLAG_LIGHT
|
||||
#define LV_THEME_DEFAULT_FONT_SMALL &lv_font_montserrat_16
|
||||
#define LV_THEME_DEFAULT_FONT_NORMAL &lv_font_montserrat_16
|
||||
#define LV_THEME_DEFAULT_FONT_SUBTITLE &lv_font_montserrat_16
|
||||
#define LV_THEME_DEFAULT_FONT_TITLE &lv_font_montserrat_16
|
||||
#define LV_THEME_DEFAULT_FONT_SMALL &lv_font_montserrat_14
|
||||
#define LV_THEME_DEFAULT_FONT_NORMAL &lv_font_montserrat_14
|
||||
#define LV_THEME_DEFAULT_FONT_SUBTITLE &lv_font_montserrat_14
|
||||
#define LV_THEME_DEFAULT_FONT_TITLE &lv_font_montserrat_14
|
||||
|
||||
/*=================
|
||||
* Text settings
|
||||
|
@ -456,7 +513,7 @@ typedef void * lv_font_user_data_t;
|
|||
|
||||
/* Support bidirectional texts.
|
||||
* Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
* The direction will be processed according to the Unicode Bidirectioanl Algorithm:
|
||||
* The direction will be processed according to the Unicode Bidirectional Algorithm:
|
||||
* https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#define LV_USE_BIDI 0
|
||||
#if LV_USE_BIDI
|
||||
|
@ -498,7 +555,7 @@ typedef void * lv_obj_user_data_t;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/
|
||||
/*1: enable `lv_obj_realign()` based on `lv_obj_align()` parameters*/
|
||||
#define LV_USE_OBJ_REALIGN 1
|
||||
|
||||
/* Enable to make the object clickable on a larger area.
|
||||
|
@ -529,6 +586,9 @@ typedef void * lv_obj_user_data_t;
|
|||
|
||||
/*Calendar (dependencies: -)*/
|
||||
#define LV_USE_CALENDAR 1
|
||||
#if LV_USE_CALENDAR
|
||||
# define LV_CALENDAR_WEEK_STARTS_MONDAY 0
|
||||
#endif
|
||||
|
||||
/*Canvas (dependencies: lv_img)*/
|
||||
#define LV_USE_CANVAS 1
|
||||
|
@ -613,7 +673,7 @@ typedef void * lv_obj_user_data_t;
|
|||
* 1: Some extra precision
|
||||
* 2: Best precision
|
||||
*/
|
||||
# define LV_LINEMETER_PRECISE 0
|
||||
# define LV_LINEMETER_PRECISE 1
|
||||
#endif
|
||||
|
||||
/*Mask (dependencies: -)*/
|
||||
|
@ -667,6 +727,7 @@ typedef void * lv_obj_user_data_t;
|
|||
#define LV_USE_TABLE 1
|
||||
#if LV_USE_TABLE
|
||||
# define LV_TABLE_COL_MAX 12
|
||||
# define LV_TABLE_CELL_STYLE_CNT 4
|
||||
#endif
|
||||
|
||||
/*Tab (dependencies: lv_page, lv_btnm)*/
|
||||
|
|
|
@ -17,6 +17,8 @@ cty = "0.2.1"
|
|||
embedded-graphics = "0.6.2"
|
||||
cstr_core = "0.2.3"
|
||||
bitflags = "1.2.1"
|
||||
parking_lot = "0.11.1"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[features]
|
||||
alloc = ["cstr_core/alloc"]
|
||||
|
@ -35,22 +37,18 @@ heapless = "0.5.5"
|
|||
[[example]]
|
||||
name = "app"
|
||||
path = "../examples/app.rs"
|
||||
required-features = ["alloc"]
|
||||
|
||||
[[example]]
|
||||
name = "demo"
|
||||
path = "../examples/demo.rs"
|
||||
required-features = ["alloc"]
|
||||
|
||||
[[example]]
|
||||
name = "bar"
|
||||
path = "../examples/bar.rs"
|
||||
required-features = ["alloc"]
|
||||
|
||||
[[example]]
|
||||
name = "button_click"
|
||||
path = "../examples/button_click.rs"
|
||||
required-features = ["alloc"]
|
||||
|
||||
[[example]]
|
||||
name = "gauge"
|
||||
|
@ -59,4 +57,3 @@ path = "../examples/gauge.rs"
|
|||
[[example]]
|
||||
name = "arc"
|
||||
path = "../examples/arc.rs"
|
||||
required-features = ["lvgl_alloc"]
|
||||
|
|
|
@ -9,12 +9,12 @@ pub struct LvglAlloc;
|
|||
unsafe impl GlobalAlloc for LvglAlloc {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
// Make sure LVGL is initialized!
|
||||
crate::lvgl_init();
|
||||
crate::init();
|
||||
lvgl_sys::lv_mem_alloc(layout.size() as lvgl_sys::size_t) as *mut u8
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
|
||||
crate::lvgl_init();
|
||||
crate::init();
|
||||
lvgl_sys::lv_mem_free(ptr as *const cty::c_void)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use crate::{Color, LvError, LvResult, Obj};
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use crate::functions::CoreError;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use crate::Box;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use crate::{disp_drv_register, disp_get_default, get_str_act};
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use crate::{Color, Obj};
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::{ManuallyDrop, MaybeUninit};
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use core::ptr;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use core::mem::MaybeUninit;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use core::ptr::NonNull;
|
||||
use core::{ptr, result};
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use embedded_graphics::drawable;
|
||||
use embedded_graphics::prelude::*;
|
||||
|
||||
|
@ -11,29 +14,51 @@ const REFRESH_BUFFER_LEN: usize = 2;
|
|||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
// Declare a buffer for the refresh rate
|
||||
pub(crate) const BUF_SIZE: usize = lvgl_sys::LV_HOR_RES_MAX as usize * REFRESH_BUFFER_LEN;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
pub enum DisplayError {
|
||||
NotAvailable,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
FailedToRegister,
|
||||
NotRegistered,
|
||||
}
|
||||
|
||||
type Result<T> = result::Result<T, DisplayError>;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Display {
|
||||
disp: NonNull<lvgl_sys::lv_disp_t>,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
pub(crate) disp: NonNull<lvgl_sys::lv_disp_t>,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
|
||||
impl Display {
|
||||
pub(crate) fn from_raw(disp: NonNull<lvgl_sys::lv_disp_t>) -> Self {
|
||||
Self { disp }
|
||||
}
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
pub fn register<C>(embedded_graphics_display: impl DrawTarget<C>) -> Result<Self>
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
where
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
C: PixelColor + From<Color>,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
{
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let mut display_diver = DisplayDriver::new(DisplayBuffer::new(), embedded_graphics_display);
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
Ok(disp_drv_register(&mut display_diver)?)
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
pub fn get_str_act(&self) -> Result<Obj> {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
Ok(get_str_act(Some(&self))?)
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
impl Default for Display {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
fn default() -> Self {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
disp_get_default().expect("LVGL must be initialized")
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct DefaultDisplay {}
|
||||
|
||||
impl DefaultDisplay {
|
||||
pub fn get_screen_active() -> Result<Obj, DisplayError> {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
Err(DisplayError::NotRegistered)
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
/// Gets the screen active of the default display.
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
pub fn get_scr_act() -> Result<Obj> {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
Ok(get_str_act(None)?)
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,11 +71,11 @@ impl DisplayBuffer {
|
|||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
pub fn new() -> Self {
|
||||
let disp_buf = unsafe {
|
||||
let mut disp_buf = MaybeUninit::uninit();
|
||||
let mut refresh_buffer = ManuallyDrop::new([lvgl_sys::lv_color_t::default(); BUF_SIZE]);
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let refresh_buffer = Box::new([lvgl_sys::lv_color_t::default(); BUF_SIZE]);
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
lvgl_sys::lv_disp_buf_init(
|
||||
disp_buf.as_mut_ptr(),
|
||||
refresh_buffer.as_mut_ptr() as *mut cty::c_void,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
Box::into_raw(refresh_buffer) as *mut cty::c_void,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
ptr::null_mut(),
|
||||
lvgl_sys::LV_HOR_RES_MAX * REFRESH_BUFFER_LEN as u32,
|
||||
);
|
||||
|
@ -78,20 +103,26 @@ where
|
|||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
C: PixelColor + From<Color>,
|
||||
{
|
||||
pub fn new(display_buffer: DisplayBuffer, native_display: T) -> Self {
|
||||
let mut disp_buf = ManuallyDrop::new(display_buffer.disp_buf);
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let mut native_display = ManuallyDrop::new(DisplayUserData {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
display: native_display,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
phantom: PhantomData,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
});
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let mut disp_drv = unsafe {
|
||||
let mut disp_drv = MaybeUninit::uninit();
|
||||
lvgl_sys::lv_disp_drv_init(disp_drv.as_mut_ptr());
|
||||
disp_drv.assume_init()
|
||||
};
|
||||
disp_drv.buffer = &mut *disp_buf as *mut lvgl_sys::lv_disp_buf_t;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
disp_drv.user_data = &mut native_display as *mut _ as lvgl_sys::lv_disp_drv_user_data_t;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
// We need to add to a `Box`, so it's copied to a memory location in the "heap" (LVGL statically allocated heap).
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let disp_buf = Box::new(display_buffer.disp_buf);
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
disp_drv.buffer = Box::into_raw(disp_buf) as *mut lvgl_sys::lv_disp_buf_t;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let native_display = Box::new(DisplayUserData {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
display: native_display,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
phantom: PhantomData,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
});
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
disp_drv.user_data =
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
Box::into_raw(native_display) as *mut _ as lvgl_sys::lv_disp_drv_user_data_t;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
disp_drv.flush_cb = Some(disp_flush_trampoline::<T, C>);
|
||||
|
||||
// We do not store any memory that can be accidentally deallocated by on the Rust side.
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
Self {
|
||||
disp_drv,
|
||||
phantom_color: PhantomData,
|
||||
|
@ -147,16 +178,49 @@ unsafe extern "C" fn disp_flush_trampoline<T, C>(
|
|||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
}
|
||||
|
||||
// impl Default for DisplayDriver {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
// fn default() -> Self {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
// Self::new(DisplayBuffer::new())
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
// }
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
// }
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
pub struct DisplayDriverBuilder {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
disp_buf: Option<DisplayBuffer>,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
impl From<CoreError> for DisplayError {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
fn from(err: CoreError) -> Self {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use DisplayError::*;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
match err {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
CoreError::ResourceNotAvailable => NotAvailable,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
CoreError::OperationFailed => NotAvailable,
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
|
||||
impl DisplayDriverBuilder {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
pub fn with_callback() {}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
#[cfg(test)]
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
mod tests {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use super::*;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
use crate::tests;
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
#[test]
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
fn get_scr_act_return_display() {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
tests::initialize_test();
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let _screen = get_str_act(None).expect("We can get the active screen");
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
#[test]
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
fn get_default_display() {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
tests::initialize_test();
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let display = Display::default();
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let _screen_direct = display
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
.get_str_act()
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
.expect("Return screen directly from the display instance");
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let _screen_default =
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
DefaultDisplay::get_scr_act().expect("Return screen from the default display");
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
#[test]
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
fn register_display_directly() -> Result<()> {
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
tests::initialize_test();
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let display = Display::default();
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
let _screen = display
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
.get_str_act()
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
.expect("Return screen directly from the display instance");
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
Ok(())
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
||||
}
|
||||
|
|
|||
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
TODO: Remove this code duplication. TODO: Remove this code duplication.
I use a I use a `Mutex` here, to satisfy the Rust guarantees. But maybe it is not necessary... some food for thought.
|
|
@ -1,16 +1,44 @@
|
|||
use crate::display::{Display, DisplayDriver, DisplayError};
|
||||
use crate::Color;
|
||||
use crate::display::{Display, DisplayDriver};
|
||||
use crate::{Color, Obj, Widget};
|
||||
use core::ptr::NonNull;
|
||||
use embedded_graphics::drawable;
|
||||
use core::{ptr, result};
|
||||
use embedded_graphics::prelude::*;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum CoreError {
|
||||
ResourceNotAvailable,
|
||||
OperationFailed,
|
||||
}
|
||||
|
||||
type Result<T> = result::Result<T, CoreError>;
|
||||
|
||||
/// Register own buffer
|
||||
pub fn disp_drv_register<C: PixelColor + From<Color>, T: DrawTarget<C>>(
|
||||
disp_drv: &mut DisplayDriver<T, C>,
|
||||
) -> Result<Display, DisplayError> {
|
||||
) -> Result<Display> {
|
||||
let disp_ptr = unsafe {
|
||||
lvgl_sys::lv_disp_drv_register(&mut disp_drv.disp_drv as *mut lvgl_sys::lv_disp_drv_t)
|
||||
};
|
||||
Ok(Display::from_raw(
|
||||
NonNull::new(disp_ptr).ok_or(DisplayError::FailedToRegister)?,
|
||||
NonNull::new(disp_ptr).ok_or(CoreError::OperationFailed)?,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn disp_get_default() -> Result<Display> {
|
||||
let disp_ptr = unsafe { lvgl_sys::lv_disp_get_default() };
|
||||
Ok(Display::from_raw(
|
||||
NonNull::new(disp_ptr).ok_or(CoreError::OperationFailed)?,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn get_str_act(disp: Option<&Display>) -> Result<Obj> {
|
||||
let scr_ptr = unsafe {
|
||||
lvgl_sys::lv_disp_get_scr_act(
|
||||
disp.map(|d| d.disp.as_ptr())
|
||||
.unwrap_or(ptr::null_mut() as *mut lvgl_sys::lv_disp_t),
|
||||
)
|
||||
};
|
||||
Ok(Obj::from_raw(
|
||||
NonNull::new(scr_ptr).ok_or(CoreError::ResourceNotAvailable)?,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
#[macro_use]
|
||||
mod lv_core;
|
||||
|
||||
#[cfg(feature = "lvgl_alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
|
@ -31,14 +37,6 @@ use ::alloc::boxed::Box;
|
|||
#[cfg(feature = "lvgl_alloc")]
|
||||
mod allocator;
|
||||
|
||||
pub mod display;
|
||||
mod functions;
|
||||
mod support;
|
||||
mod ui;
|
||||
#[macro_use]
|
||||
mod lv_core;
|
||||
pub mod widgets;
|
||||
|
||||
#[cfg(not(feature = "lvgl_alloc"))]
|
||||
pub(crate) mod mem;
|
||||
|
||||
|
@ -49,18 +47,25 @@ pub(crate) mod mem;
|
|||
#[cfg(not(feature = "lvgl_alloc"))]
|
||||
use crate::mem::Box;
|
||||
|
||||
pub mod display;
|
||||
mod functions;
|
||||
mod support;
|
||||
mod ui;
|
||||
pub mod widgets;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
pub use functions::*;
|
||||
pub use lv_core::*;
|
||||
use parking_lot::Mutex;
|
||||
pub use support::*;
|
||||
pub use ui::*;
|
||||
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
// Initialize LVGL only once.
|
||||
static LVGL_INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||
lazy_static! {
|
||||
static ref MUTEX: Mutex<AtomicBool> = Mutex::new(AtomicBool::new(false));
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
if LVGL_INITIALIZED
|
||||
let initialized = MUTEX.lock();
|
||||
if initialized
|
||||
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_ok()
|
||||
{
|
||||
|
@ -69,3 +74,24 @@ pub fn init() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
use crate::display::Display;
|
||||
use embedded_graphics::mock_display::MockDisplay;
|
||||
use embedded_graphics::pixelcolor::Rgb565;
|
||||
|
||||
pub(crate) fn initialize_test() {
|
||||
init();
|
||||
|
||||
static RUN_ONCE: Mutex<Option<u8>> = parking_lot::const_mutex(None);
|
||||
let mut run_once = RUN_ONCE.lock();
|
||||
|
||||
if run_once.is_none() {
|
||||
let embedded_graphics_display: MockDisplay<Rgb565> = Default::default();
|
||||
let _ = Display::register(embedded_graphics_display).unwrap();
|
||||
*run_once = Some(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,10 +35,7 @@ pub trait Widget: NativeObject {
|
|||
|
||||
/// Construct an instance of the object from a raw pointer.
|
||||
///
|
||||
/// # Safety
|
||||
/// Provided the LVGL library can allocate memory this should be safe.
|
||||
///
|
||||
unsafe fn from_raw(raw_pointer: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self;
|
||||
fn from_raw(raw_pointer: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self;
|
||||
|
||||
fn add_style(&self, part: Self::Part, style: Style) -> LvResult<()> {
|
||||
unsafe {
|
||||
|
@ -104,7 +101,7 @@ impl Widget for Obj {
|
|||
type SpecialEvent = ();
|
||||
type Part = Part;
|
||||
|
||||
unsafe fn from_raw(raw: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self {
|
||||
fn from_raw(raw: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self {
|
||||
Self { raw: raw.as_ptr() }
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +164,7 @@ macro_rules! define_object {
|
|||
type SpecialEvent = $event_type;
|
||||
type Part = $part_type;
|
||||
|
||||
unsafe fn from_raw(raw_pointer: core::ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self {
|
||||
fn from_raw(raw_pointer: core::ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self {
|
||||
Self {
|
||||
core: $crate::Obj::from_raw(raw_pointer),
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ pub(crate) struct Box<T>(NonNull<T>);
|
|||
|
||||
impl<T> Box<T> {
|
||||
/// Allocate memory using LVGL memory API and place `T` in the LVGL tracked memory.
|
||||
pub fn new(value: T) -> Box<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
let size = mem::size_of::<T>();
|
||||
let inner = unsafe {
|
||||
let ptr = lvgl_sys::lv_mem_alloc(size as lvgl_sys::size_t) as *mut T;
|
||||
|
@ -29,15 +29,15 @@ impl<T> Box<T> {
|
|||
p
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
panic!("Could not allocate memory {} bytes", size);
|
||||
panic!("Could not allocate memory {} bytes: {:?}", size, mem_info());
|
||||
})
|
||||
};
|
||||
Box(inner)
|
||||
Self(inner)
|
||||
}
|
||||
|
||||
pub fn into_raw(self) -> *mut T {
|
||||
let b = mem::ManuallyDrop::new(self);
|
||||
b.0.as_ptr()
|
||||
let b = mem::ManuallyDrop::new(self.0);
|
||||
b.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,14 +69,33 @@ impl<T> AsMut<T> for Box<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn mem_info() -> lvgl_sys::lv_mem_monitor_t {
|
||||
let mut info = lvgl_sys::lv_mem_monitor_t {
|
||||
total_size: 0,
|
||||
free_cnt: 0,
|
||||
free_size: 0,
|
||||
free_biggest_size: 0,
|
||||
used_cnt: 0,
|
||||
max_used: 0,
|
||||
used_pct: 0,
|
||||
frag_pct: 0,
|
||||
};
|
||||
unsafe {
|
||||
lvgl_sys::lv_mem_monitor(&mut info as *mut _);
|
||||
}
|
||||
info
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::mem::mem_info;
|
||||
use crate::*;
|
||||
use std::vec::Vec;
|
||||
Probably just need to make safe bindings for this simple function and add to the public API. It's useful for app debugging. Probably just need to make safe bindings for this simple function and add to the public API. It's useful for app debugging.
|
||||
|
||||
#[test]
|
||||
fn place_value_in_lv_mem() {
|
||||
crate::lvgl_init();
|
||||
tests::initialize_test();
|
||||
|
||||
let v = Box::new(5);
|
||||
drop(v);
|
||||
|
@ -86,7 +105,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn place_complex_value_in_lv_mem() {
|
||||
crate::lvgl_init();
|
||||
tests::initialize_test();
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
|
@ -135,21 +154,4 @@ mod test {
|
|||
// If this fails, we are leaking memory! BOOM! \o/
|
||||
assert_eq!(initial_mem_info.free_size, final_info.free_size)
|
||||
}
|
||||
|
||||
fn mem_info() -> lvgl_sys::lv_mem_monitor_t {
|
||||
let mut info = lvgl_sys::lv_mem_monitor_t {
|
||||
total_size: 0,
|
||||
free_cnt: 0,
|
||||
free_size: 0,
|
||||
free_biggest_size: 0,
|
||||
used_cnt: 0,
|
||||
max_used: 0,
|
||||
used_pct: 0,
|
||||
frag_pct: 0,
|
||||
};
|
||||
unsafe {
|
||||
lvgl_sys::lv_mem_monitor(&mut info as *mut _);
|
||||
}
|
||||
info
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::Box;
|
||||
use crate::{Color, Event, LvError, LvResult, Obj, Widget};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::{ManuallyDrop, MaybeUninit};
|
||||
use core::mem::MaybeUninit;
|
||||
use core::ptr;
|
||||
use core::ptr::NonNull;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
|
TODO: Remove this code duplication.