const std = @import("std"); const builtin = @import("builtin"); const idf = @import("esp_idf"); const ver = idf.ver.Version; const mem = std.mem; const led = idf.led; comptime { @export(&main, .{ .name = "app_main" }); } const LED_STRIP_USE_DMA = false; const LED_STRIP_LED_COUNT = 5; const LED_STRIP_MEMORY_BLOCK_WORDS = 0; const LED_STRIP_GPIO_PIN = 38; fn configureLED() !led.LedStripHandle { // LED strip general initialization using wrapped types const strip_config = led.LedStripConfig.ws2812(LED_STRIP_GPIO_PIN, LED_STRIP_LED_COUNT); // LED strip backend configuration: RMT var rmt_config = led.LedStripRmtConfig.default; rmt_config.mem_block_symbols = LED_STRIP_MEMORY_BLOCK_WORDS; if (LED_STRIP_USE_DMA) { // Set DMA flag if needed rmt_config.flags = 1; // with_dma bit } var led_strip: led.LedStripHandle = null; const strip = try led.newRmtDevice(&strip_config, &rmt_config, &led_strip); log.info("Created LED strip object with RMT backend", .{}); return strip; } fn ledStripTask(led_strip_ptr: ?*anyopaque) callconv(.c) void { const led_strip: led.LedStripHandle = @ptrCast(@alignCast(led_strip_ptr.?)); var led_on_off = false; log.info("Start blinking LED strip", .{}); while (true) { if (led_on_off) { // Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color var i: u32 = 0; while (i < LED_STRIP_LED_COUNT) : (i += 1) { led.setPixel(led_strip, i, 5, 5, 5) catch |err| { log.err("Failed to set LED pixel {}: {s}", .{ i, @errorName(err) }); }; } // Refresh the strip to send data led.refresh(led_strip) catch |err| { log.err("Failed to refresh LED strip: {s}", .{@errorName(err)}); }; log.info("LED ON!", .{}); } else { // Set all LED off to clear all pixels led.clear(led_strip) catch |err| { log.err("Failed to clear LED strip: {s}", .{@errorName(err)}); }; log.info("LED OFF!", .{}); } led_on_off = !led_on_off; idf.rtos.Task.delayMs(500); } } fn main() callconv(.c) void { // This allocator is safe to use as the backing allocator w/ arena allocator // custom allocators (based on old raw_c_allocator) // idf.heap.HeapCapsAllocator // idf.heap.MultiHeapAllocator // idf.heap.VPortAllocator var heap = idf.heap.HeapCapsAllocator.init(.{ .@"8bit" = true }); var arena = std.heap.ArenaAllocator.init(heap.allocator()); defer arena.deinit(); const allocator = arena.allocator(); log.info("Hello, world from Zig!", .{}); log.info( \\[Zig Info] \\* Version: {s} \\* Compiler Backend: {s} , .{ @as([]const u8, builtin.zig_version_string), @tagName(builtin.zig_backend), }); log.info( \\[ESP-IDF Info] \\* Version: {s} , .{ver.get().toString(allocator)}); log.info( \\[Memory Info] \\* Total: {d} \\* Free: {d} \\* Minimum: {d} , .{ heap.totalSize(), heap.freeSize(), heap.minimumFreeSize(), }); log.info("Let's have a look at your shiny {s} - {s} system! :)", .{ @tagName(builtin.cpu.arch), builtin.cpu.model.name, }); arraylist(allocator) catch |err| { log.err("Error: {s}", .{@errorName(err)}); }; // Configure and initialize LED strip const led_strip = configureLED() catch |err| { log.err("Failed to configure LED strip: {s}", .{@errorName(err)}); @panic("LED strip initialization failed"); }; if (builtin.mode == .Debug) heap.dump(); // FreeRTOS Tasks — Task.create returns !Handle; on failure panic with a clear message. _ = idf.rtos.Task.create(ledStripTask, "led_strip", 1024 * 4, led_strip, 5) catch @panic("Error: LED strip task not created!"); _ = idf.rtos.Task.create(fooTask, "foo", 1024 * 3, null, 1) catch @panic("Task foo not created"); _ = idf.rtos.Task.create(barTask, "bar", 1024 * 3, null, 2) catch @panic("Task bar not created"); } fn blinkLED(delay_ms: u32) !void { try idf.gpio.Direction.set(.@"18", .output); while (true) { log.info("LED: ON", .{}); try idf.gpio.Level.set(.@"18", 1); idf.rtos.Task.delayMs(delay_ms); log.info("LED: OFF", .{}); try idf.gpio.Level.set(.@"18", 0); idf.rtos.Task.delayMs(delay_ms); } } fn arraylist(allocator: mem.Allocator) !void { var arr: std.ArrayList(u32) = .empty; defer arr.deinit(allocator); try arr.append(allocator, 10); try arr.append(allocator, 20); try arr.append(allocator, 30); for (arr.items) |value| { idf.log.ESP_LOG(allocator, idf.log.default_level, "EXAMPLE", "Arr value: {}\n", .{value}); } } export fn blinkTask(_: ?*anyopaque) callconv(.c) void { blinkLED(1000) catch |err| @panic(@errorName(err)); } export fn fooTask(_: ?*anyopaque) callconv(.c) void { while (true) { log.info("Demo_Task foo printing..", .{}); idf.rtos.Task.delayMs(2000); } } export fn barTask(_: ?*anyopaque) callconv(.c) void { while (true) { log.info("Demo_Task bar printing..", .{}); idf.rtos.Task.delayMs(1000); } } pub const panic = idf.esp_panic.panic; const log = std.log.scoped(idf.log.default_log_scope); pub const std_options: std.Options = .{ .log_level = switch (builtin.mode) { .Debug => .debug, else => .info, }, .logFn = idf.log.espLogFn, };