Skip to content

Commit a0ead2b

Browse files
committed
Refactor for NuttX
1 parent 521b7c7 commit a0ead2b

File tree

4 files changed

+295
-264
lines changed

4 files changed

+295
-264
lines changed

feature-phone.wasm

6.94 KB
Binary file not shown.

feature-phone.zig

+6-264
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@
44
const std = @import("std");
55
const builtin = @import("builtin");
66

7-
/// Import the WebAssembly Logger
8-
const wasmlog = @import("wasmlog.zig");
9-
107
/// Import the LVGL Module
118
const lvgl = @import("lvgl.zig");
129

1310
/// Import the LVGL Library from C
1411
const c = lvgl.c;
1512

13+
/// Import the functions specific to WebAssembly and Apache NuttX RTOS
14+
pub usingnamespace switch (builtin.cpu.arch) {
15+
.wasm32, .wasm64 => @import("wasm.zig"),
16+
else => @import("nuttx.zig"),
17+
};
18+
1619
///////////////////////////////////////////////////////////////////////////////
1720
// Main Function
1821

@@ -31,60 +34,6 @@ pub export fn lv_demo_widgets() void {
3134
// JavaScript should call handleTimer periodically to handle LVGL Tasks
3235
}
3336

34-
/// Init the LVGL Display and Input
35-
pub export fn initDisplay() void {
36-
// Create the Memory Allocator for malloc
37-
memory_allocator = std.heap.FixedBufferAllocator.init(&memory_buffer);
38-
39-
// Set the Custom Logger for LVGL
40-
c.lv_log_register_print_cb(custom_logger);
41-
42-
// Init LVGL
43-
c.lv_init();
44-
45-
// Fetch pointers to Display Driver and Display Buffer
46-
const disp_drv = c.get_disp_drv();
47-
const disp_buf = c.get_disp_buf();
48-
49-
// Init Display Buffer and Display Driver as pointers
50-
c.init_disp_buf(disp_buf);
51-
c.init_disp_drv(disp_drv, // Display Driver
52-
disp_buf, // Display Buffer
53-
flushDisplay, // Callback Function to Flush Display
54-
720, // Horizontal Resolution
55-
1280 // Vertical Resolution
56-
);
57-
58-
// Register the Display Driver
59-
const disp = c.lv_disp_drv_register(disp_drv);
60-
_ = disp;
61-
62-
// Register the Input Device
63-
// https://docs.lvgl.io/8.3/porting/indev.html
64-
indev_drv = std.mem.zeroes(c.lv_indev_drv_t);
65-
c.lv_indev_drv_init(&indev_drv);
66-
indev_drv.type = c.LV_INDEV_TYPE_POINTER;
67-
indev_drv.read_cb = readInput;
68-
_ = c.register_input(&indev_drv);
69-
}
70-
71-
/// LVGL Callback Function to Flush Display
72-
export fn flushDisplay(disp_drv: ?*c.lv_disp_drv_t, area: [*c]const c.lv_area_t, color_p: [*c]c.lv_color_t) void {
73-
_ = area;
74-
_ = color_p;
75-
// Call the Web Browser JavaScript to render the LVGL Canvas Buffer
76-
render();
77-
78-
// Notify LVGL that the display is flushed
79-
c.lv_disp_flush_ready(disp_drv);
80-
}
81-
82-
/// Return a WebAssembly Pointer to the LVGL Canvas Buffer for JavaScript Rendering
83-
export fn getCanvasBuffer() [*]u8 {
84-
const buf = c.get_canvas_buffer();
85-
return @ptrCast([*]u8, buf);
86-
}
87-
8837
///////////////////////////////////////////////////////////////////////////////
8938
// Create Widgets
9039

@@ -266,216 +215,9 @@ var display_style: c.lv_style_t = undefined;
266215
var call_style: c.lv_style_t = undefined;
267216
var digit_style: c.lv_style_t = undefined;
268217

269-
///////////////////////////////////////////////////////////////////////////////
270-
// LVGL Input
271-
272-
/// Called by JavaScript to execute LVGL Tasks periodically, passing the Elapsed Milliseconds
273-
export fn handleTimer(ms: i32) i32 {
274-
// Set the Elapsed Milliseconds, don't allow time rewind
275-
if (ms > elapsed_ms) {
276-
elapsed_ms = @intCast(u32, ms);
277-
}
278-
// Handle LVGL Tasks
279-
_ = c.lv_timer_handler();
280-
return 0;
281-
}
282-
283-
/// Called by JavaScript to notify Mouse Down and Mouse Up.
284-
/// Return 1 if we're still waiting for LVGL to process the last input.
285-
export fn notifyInput(pressed: i32, x: i32, y: i32) i32 {
286-
// If LVGL hasn't processed the last input, try again later
287-
if (input_updated) {
288-
return 1;
289-
}
290-
291-
// Save the Input State and Input Coordinates
292-
if (pressed == 0) {
293-
input_state = c.LV_INDEV_STATE_RELEASED;
294-
} else {
295-
input_state = c.LV_INDEV_STATE_PRESSED;
296-
}
297-
input_x = @intCast(c.lv_coord_t, x);
298-
input_y = @intCast(c.lv_coord_t, y);
299-
input_updated = true;
300-
return 0;
301-
}
302-
303-
/// LVGL Callback Function to read Input Device
304-
export fn readInput(drv: [*c]c.lv_indev_drv_t, data: [*c]c.lv_indev_data_t) void {
305-
_ = drv;
306-
if (input_updated) {
307-
input_updated = false;
308-
c.set_input_data(data, input_state, input_x, input_y);
309-
debug("readInput: state={}, x={}, y={}", .{ input_state, input_x, input_y });
310-
}
311-
}
312-
313-
/// True if LVGL Input State has been updated
314-
var input_updated: bool = false;
315-
316-
/// LVGL Input State and Coordinates
317-
var input_state: c.lv_indev_state_t = 0;
318-
var input_x: c.lv_coord_t = 0;
319-
var input_y: c.lv_coord_t = 0;
320-
321-
/// LVGL Input Device Driver (std.mem.zeroes crashes the compiler)
322-
var indev_drv: c.lv_indev_drv_t = undefined;
323-
324-
///////////////////////////////////////////////////////////////////////////////
325-
// LVGL Porting Layer for WebAssembly
326-
327-
/// TODO: Return the number of elapsed milliseconds
328-
export fn millis() u32 {
329-
elapsed_ms += 1;
330-
return elapsed_ms;
331-
}
332-
333-
/// Number of elapsed milliseconds
334-
var elapsed_ms: u32 = 0;
335-
336-
/// On Assertion Failure, print a Stack Trace and halt
337-
export fn lv_assert_handler() void {
338-
@panic("*** lv_assert_handler: ASSERTION FAILED");
339-
}
340-
341-
/// Custom Logger for LVGL that writes to JavaScript Console
342-
export fn custom_logger(buf: [*c]const u8) void {
343-
wasmlog.Console.log("{s}", .{buf});
344-
}
345-
346-
///////////////////////////////////////////////////////////////////////////////
347-
// Memory Allocator for malloc
348-
349-
/// Zig replacement for malloc
350-
export fn malloc(size: usize) ?*anyopaque {
351-
// TODO: Save the slice length
352-
const mem = memory_allocator.allocator().alloc(u8, size) catch {
353-
@panic("*** malloc error: out of memory");
354-
};
355-
return mem.ptr;
356-
}
357-
358-
/// Zig replacement for realloc
359-
export fn realloc(old_mem: [*c]u8, size: usize) ?*anyopaque {
360-
// TODO: Call realloc instead
361-
// const mem = memory_allocator.allocator().realloc(old_mem[0..???], size) catch {
362-
// @panic("*** realloc error: out of memory");
363-
// };
364-
const mem = memory_allocator.allocator().alloc(u8, size) catch {
365-
@panic("*** realloc error: out of memory");
366-
};
367-
_ = memcpy(mem.ptr, old_mem, size);
368-
if (old_mem != null) {
369-
// TODO: How to free without the slice length?
370-
// memory_allocator.allocator().free(old_mem[0..???]);
371-
}
372-
return mem.ptr;
373-
}
374-
375-
/// Zig replacement for free
376-
export fn free(mem: [*c]u8) void {
377-
if (mem == null) {
378-
@panic("*** free error: pointer is null");
379-
}
380-
// TODO: How to free without the slice length?
381-
// memory_allocator.allocator().free(mem[0..???]);
382-
}
383-
384-
/// Memory Allocator for malloc
385-
var memory_allocator: std.heap.FixedBufferAllocator = undefined;
386-
387-
/// Memory Buffer for malloc
388-
var memory_buffer = std.mem.zeroes([1024 * 1024]u8);
389-
390-
///////////////////////////////////////////////////////////////////////////////
391-
// Logging
392-
393-
/// Called by Zig for `std.log.debug`, `std.log.info`, `std.log.err`, ...
394-
/// https://gist.github.com/leecannon/d6f5d7e5af5881c466161270347ce84d
395-
pub fn log(
396-
comptime _message_level: std.log.Level,
397-
comptime _scope: @Type(.EnumLiteral),
398-
comptime format: []const u8,
399-
args: anytype,
400-
) void {
401-
_ = _message_level;
402-
_ = _scope;
403-
404-
// Format the message
405-
var buf: [100]u8 = undefined; // Limit to 100 chars
406-
var slice = std.fmt.bufPrint(&buf, format, args) catch {
407-
wasmlog.Console.log("*** log error: buf too small", .{});
408-
return;
409-
};
410-
411-
// Print the formatted message
412-
wasmlog.Console.log("{s}", .{slice});
413-
}
414-
415218
///////////////////////////////////////////////////////////////////////////////
416219
// Imported Functions and Variables
417220

418-
/// JavaScript Functions imported into Zig WebAssembly
419-
extern fn render() void;
420-
421221
/// Aliases for Zig Standard Library
422222
const assert = std.debug.assert;
423223
const debug = std.log.debug;
424-
425-
///////////////////////////////////////////////////////////////////////////////
426-
// C Standard Library
427-
// From zig-macos-x86_64-0.10.0-dev.2351+b64a1d5ab/lib/zig/c.zig
428-
429-
export fn memset(dest: ?[*]u8, c2: u8, len: usize) callconv(.C) ?[*]u8 {
430-
@setRuntimeSafety(false);
431-
432-
if (len != 0) {
433-
var d = dest.?;
434-
var n = len;
435-
while (true) {
436-
d.* = c2;
437-
n -= 1;
438-
if (n == 0) break;
439-
d += 1;
440-
}
441-
}
442-
443-
return dest;
444-
}
445-
446-
export fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 {
447-
@setRuntimeSafety(false);
448-
449-
if (len != 0) {
450-
var d = dest.?;
451-
var s = src.?;
452-
var n = len;
453-
while (true) {
454-
d[0] = s[0];
455-
n -= 1;
456-
if (n == 0) break;
457-
d += 1;
458-
s += 1;
459-
}
460-
}
461-
462-
return dest;
463-
}
464-
465-
export fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.C) [*:0]u8 {
466-
var i: usize = 0;
467-
while (src[i] != 0) : (i += 1) {
468-
dest[i] = src[i];
469-
}
470-
dest[i] = 0;
471-
472-
return dest;
473-
}
474-
475-
export fn strcmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.C) c_int {
476-
return std.cstr.cmp(s1, s2);
477-
}
478-
479-
export fn strlen(s: [*:0]const u8) callconv(.C) usize {
480-
return std.mem.len(s);
481-
}

nuttx.zig

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//! LVGL Functions specific to Apache NuttX RTOS

0 commit comments

Comments
 (0)