Files

120 lines
4.7 KiB
Zig

// requires: idf.py add-dependency espressif/led_strip
const sys = @import("sys");
const errors = @import("error");
pub const LedModel = enum(sys.led_model_t) {
ws2812 = sys.LED_MODEL_WS2812,
sk6812 = sys.LED_MODEL_SK6812,
ws2811 = sys.LED_MODEL_WS2811,
ws2816 = sys.LED_MODEL_WS2816,
invalid = sys.LED_MODEL_INVALID,
};
pub const LedStripHandle = sys.led_strip_handle_t;
pub const ColorComponentFormat = extern union {
format: packed struct {
r_pos: u2, // Position of the red channel in the color order: 0~3
g_pos: u2, // Position of the green channel in the color order: 0~3
b_pos: u2, // Position of the blue channel in the color order: 0~3
w_pos: u2, // Position of the white channel in the color order: 0~3
reserved: u19, // Reserved
bytes_per_color: u2, // Bytes per color component: 1 or 2. If set to 0, it will fallback to 1
num_components: u3, // Number of color components per pixel: 3 or 4. If set to 0, it will fallback to 3
},
format_id: u32,
};
pub const PixelFormat = enum(u32) {
grb = 0x00, // default WS2812
rgb = 0x01,
grbw = 0x10,
rgbw = 0x11,
};
pub const LedStripConfig = extern struct {
strip_gpio_num: i32,
max_leds: u32,
led_model: LedModel,
color_component_format: ColorComponentFormat,
// flags: sys.struct_led_strip_extra_flags_29, // opaque
flags: u32 = 0, // most users leave = 0; see component for bits
pub fn init(gpio: u32, count: u32, model: LedModel, format_id: u32) LedStripConfig {
return .{
.strip_gpio_num = @intCast(gpio),
.max_leds = count,
.led_model = model,
.color_component_format = .{ .format_id = format_id },
.flags = 0,
};
}
pub fn ws2812(gpio: u32, count: u32) LedStripConfig {
return init(gpio, count, .ws2812, @intFromEnum(PixelFormat.grb));
}
};
pub const LedStripRmtConfig = struct {
clk_src: sys.rmt_clock_source_t,
resolution_hz: u32,
mem_block_symbols: usize = 0, // 0 = default/auto
// flags: sys.struct_led_strip_rmt_extra_config_33, // opaque
flags: u32 = 0,
pub fn init_10mhz() LedStripRmtConfig {
return .{
.clk_src = sys.RMT_CLK_SRC_DEFAULT,
.resolution_hz = 10_000_000,
.mem_block_symbols = 0,
.flags = 0,
};
}
// Very common setting in examples
pub const default = init_10mhz();
};
pub const LedStripSpiConfig = struct {
clk_src: sys.spi_clock_source_t,
spi_bus: sys.spi_host_device_t,
// flags: sys.struct_unnamed_34, // opaque
flags: u32 = 0,
};
// ───────────────────────────────────────────────
// API functions
/// Creates RMT-backed LED strip
pub fn newRmtDevice(led_config: *const LedStripConfig, rmt_config: *const LedStripRmtConfig, handle: *LedStripHandle) !LedStripHandle {
const result = sys.led_strip_new_rmt_device(@ptrCast(led_config), @ptrCast(rmt_config), @ptrCast(handle));
try errors.espCheckError(result);
return handle.*;
}
/// Creates SPI-backed LED strip
pub fn newSpiDevice(led_config: *const LedStripConfig, spi_config: *const LedStripSpiConfig, handle: *LedStripHandle) !LedStripHandle {
const result = sys.led_strip_new_spi_device(@ptrCast(led_config), @ptrCast(spi_config), @ptrCast(handle));
try errors.espCheckError(result);
return handle.*;
}
/// Set one RGB pixel
pub fn setPixel(strip: LedStripHandle, index: u32, r: u8, g: u8, b: u8) !void {
// The C API takes u32 — we clamp/convert for safety
return try errors.espCheckError(sys.led_strip_set_pixel(strip, index, @as(u32, r), @as(u32, g), @as(u32, b)));
}
/// Variant that also sets white channel (SK6812 RGBW etc.)
pub fn setPixelRgbw(strip: LedStripHandle, index: u32, r: u8, g: u8, b: u8, w: u8) !void {
return try errors.espCheckError(sys.led_strip_set_pixel_rgbw(strip, index, @as(u32, r), @as(u32, g), @as(u32, b), @as(u32, w)));
}
/// HSV variant (convenience — internally converts to RGB)
pub fn setPixelHsv(strip: LedStripHandle, index: u32, hue: u16, sat: u8, val: u8) !void {
return try errors.espCheckError(sys.led_strip_set_pixel_hsv(strip, index, hue, sat, val));
}
/// Push all buffered pixel data to the strip
pub fn refresh(strip: LedStripHandle) !void {
return try errors.espCheckError(sys.led_strip_refresh(strip));
}
/// Turn all LEDs off
pub fn clear(strip: LedStripHandle) !void {
return try errors.espCheckError(sys.led_strip_clear(strip));
}
/// Free resources
pub fn deinit(strip: LedStripHandle) !void {
return try errors.espCheckError(sys.led_strip_del(strip));
}