4
4
const std = @import ("std" );
5
5
const builtin = @import ("builtin" );
6
6
7
- /// Import the WebAssembly Logger
8
- const wasmlog = @import ("wasmlog.zig" );
9
-
10
7
/// Import the LVGL Module
11
8
const lvgl = @import ("lvgl.zig" );
12
9
13
10
/// Import the LVGL Library from C
14
11
const c = lvgl .c ;
15
12
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
+
16
19
///////////////////////////////////////////////////////////////////////////////
17
20
// Main Function
18
21
@@ -31,60 +34,6 @@ pub export fn lv_demo_widgets() void {
31
34
// JavaScript should call handleTimer periodically to handle LVGL Tasks
32
35
}
33
36
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
-
88
37
///////////////////////////////////////////////////////////////////////////////
89
38
// Create Widgets
90
39
@@ -266,216 +215,9 @@ var display_style: c.lv_style_t = undefined;
266
215
var call_style : c.lv_style_t = undefined ;
267
216
var digit_style : c.lv_style_t = undefined ;
268
217
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
-
415
218
///////////////////////////////////////////////////////////////////////////////
416
219
// Imported Functions and Variables
417
220
418
- /// JavaScript Functions imported into Zig WebAssembly
419
- extern fn render () void ;
420
-
421
221
/// Aliases for Zig Standard Library
422
222
const assert = std .debug .assert ;
423
223
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
- }
0 commit comments