44const std = @import ("std" );
55const builtin = @import ("builtin" );
66
7- /// Import the WebAssembly Logger
8- const wasmlog = @import ("wasmlog.zig" );
9-
107/// Import the LVGL Module
118const lvgl = @import ("lvgl.zig" );
129
1310/// Import the LVGL Library from C
1411const 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;
266215var call_style : c.lv_style_t = undefined ;
267216var 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
422222const assert = std .debug .assert ;
423223const 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- }
0 commit comments