ui: move all C lvgl/zig code into lvgl.zig and drv.zig
the idea is for all zig code to use C LVGL only via this new module lvgl.zig, all display and input driver/devices is handled by drv.zig. this makes C/zig nicely compartmentalized in just a handful places.pull/20/head
parent
5c60b92f85
commit
021c810dc7
@ -0,0 +1,28 @@
|
|||||||
|
///! input and display drivers support in zig.
|
||||||
|
const std = @import("std");
|
||||||
|
const buildopts = @import("build_options");
|
||||||
|
|
||||||
|
const lvgl = @import("lvgl.zig");
|
||||||
|
|
||||||
|
const logger = std.log.scoped(.drv);
|
||||||
|
|
||||||
|
extern "c" fn nm_disp_init() ?*lvgl.LvDisp;
|
||||||
|
extern "c" fn nm_indev_init() c_int;
|
||||||
|
|
||||||
|
/// initalize a display and make it active for the UI to use.
|
||||||
|
/// requires lvgl.init() to have been already called.
|
||||||
|
// TODO: rewrite lv_drivers/display/fbdev.c to make fbdev_init return an error
|
||||||
|
pub fn initDisplay() !*lvgl.LvDisp {
|
||||||
|
if (nm_disp_init()) |disp| {
|
||||||
|
return disp;
|
||||||
|
}
|
||||||
|
return error.DisplayInitFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// initialize input devices: touch screen and possibly keyboard if using SDL.
|
||||||
|
pub fn initInput() !void {
|
||||||
|
const res = nm_indev_init();
|
||||||
|
if (res != 0) {
|
||||||
|
return error.InputInitFailed;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
///! LVGL types in zig
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
/// initalize LVGL internals.
|
||||||
|
/// must be called before any other UI functions.
|
||||||
|
pub fn init() void {
|
||||||
|
init_once.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
var init_once = std.once(lvglInit);
|
||||||
|
|
||||||
|
fn lvglInit() void {
|
||||||
|
lv_log_register_print_cb(nm_lvgl_log);
|
||||||
|
lv_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// logs LV_LOG_xxx messages from LVGL lib
|
||||||
|
const lvgl_logger = std.log.scoped(.lvgl);
|
||||||
|
|
||||||
|
export fn nm_lvgl_log(msg: [*:0]const u8) void {
|
||||||
|
const s = std.mem.span(msg);
|
||||||
|
// info level log messages are by default printed only in Debug and ReleaseSafe build modes.
|
||||||
|
lvgl_logger.debug("{s}", .{std.mem.trimRight(u8, s, "\n")});
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "c" fn lv_init() void;
|
||||||
|
extern "c" fn lv_log_register_print_cb(*const fn (msg: [*:0]const u8) callconv(.C) void) void;
|
||||||
|
|
||||||
|
/// represents lv_timer_t in C.
|
||||||
|
pub const LvTimer = opaque {};
|
||||||
|
pub const LvTimerCallback = *const fn (timer: *LvTimer) callconv(.C) void;
|
||||||
|
/// the timer handler is the LVGL busy-wait loop iteration.
|
||||||
|
pub extern "c" fn lv_timer_handler() u32;
|
||||||
|
pub extern "c" fn lv_timer_create(callback: LvTimerCallback, period_ms: u32, userdata: ?*anyopaque) ?*LvTimer;
|
||||||
|
pub extern "c" fn lv_timer_del(timer: *LvTimer) void;
|
||||||
|
pub extern "c" fn lv_timer_set_repeat_count(timer: *LvTimer, n: i32) void;
|
||||||
|
|
||||||
|
/// represents lv_obj_t type in C.
|
||||||
|
pub const LvObj = opaque {};
|
||||||
|
/// delete and deallocate an object and all its children from UI tree.
|
||||||
|
pub extern "c" fn lv_obj_del(obj: *LvObj) void;
|
||||||
|
|
||||||
|
/// represents lv_indev_t in C, an input device such as touchscreen or a keyboard.
|
||||||
|
pub const LvIndev = opaque {};
|
||||||
|
/// deallocate and delete an input device from LVGL registry.
|
||||||
|
pub extern "c" fn lv_indev_delete(indev: *LvIndev) void;
|
||||||
|
/// return next device in the list or head if indev is null.
|
||||||
|
pub extern "c" fn lv_indev_get_next(indev: ?*LvIndev) ?*LvIndev;
|
||||||
|
|
||||||
|
/// represents lv_disp_t in C.
|
||||||
|
pub const LvDisp = opaque {};
|
||||||
|
/// return elapsed time since last user activity on a specific display
|
||||||
|
/// or any if disp is null.
|
||||||
|
pub extern "c" fn lv_disp_get_inactive_time(disp: ?*LvDisp) u32;
|
||||||
|
/// make it so as if a user activity happened.
|
||||||
|
/// this resets an internal counter in lv_disp_get_inactive_time.
|
||||||
|
pub extern "c" fn lv_disp_trig_activity(disp: ?*LvDisp) void;
|
||||||
|
/// force redraw dirty areas.
|
||||||
|
pub extern "c" fn lv_refr_now(disp: ?*LvDisp) void;
|
@ -0,0 +1,22 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const lvgl = @import("lvgl.zig");
|
||||||
|
const drv = @import("drv.zig");
|
||||||
|
|
||||||
|
const logger = std.log.scoped(.ui);
|
||||||
|
|
||||||
|
extern "c" fn nm_ui_init(disp: *lvgl.LvDisp) c_int;
|
||||||
|
|
||||||
|
pub fn init() !void {
|
||||||
|
lvgl.init();
|
||||||
|
const disp = try drv.initDisplay();
|
||||||
|
drv.initInput() catch |err| {
|
||||||
|
// TODO: or continue without the touchpad?
|
||||||
|
// at the very least must disable screen blanking timeout in case of a failure.
|
||||||
|
// otherwise, impossible to wake up the screen. */
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
if (nm_ui_init(disp) != 0) {
|
||||||
|
return error.UiInitFailure;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue