const std = @import("std"); const pico = @import("microzig").hal; const FULL_AXIS = 4096; // u12 const QUARTER = FULL_AXIS / 4; const pin_conf = pico.pins.GlobalConfiguration{ .GPIO22 = .{ .name = "neopixel", .function = .PIO0 }, .GPIO26 = .{ .name = "xaxis", .function = .ADC0 }, .GPIO27 = .{ .name = "yaxis", .function = .ADC1 }, .GPIO28 = .{ .name = "button", .direction = .in, .pull = .up }, }; const pins = pin_conf.pins(); const pio: pico.pio.Pio = .pio0; const sm: pico.pio.StateMachine = .sm0; const led_pin = pico.gpio.num(22); pub fn main() !void { pin_conf.apply(); pio.gpio_init(led_pin); pio.sm_set_pindir(sm, @intFromEnum(led_pin), 1, .out); const cycles_per_bit: comptime_int = ws2812_program.defines[0].value + //T1 ws2812_program.defines[1].value + //T2 ws2812_program.defines[2].value; //T3 const div = @as(f32, @floatFromInt(pico.clock_config.sys.?.frequency())) / (800_000 * cycles_per_bit); pio.sm_load_and_start_program(sm, ws2812_program, .{ .clkdiv = pico.pio.ClkDivOptions.from_float(div), .pin_mappings = .{ .side_set = .{ .base = @intFromEnum(led_pin), .count = 1, }, }, .shift = .{ .out_shiftdir = .left, .autopull = true, .pull_threshold = 24, .join_tx = true, }, }) catch unreachable; pio.sm_set_enabled(sm, true); // ACTUAL LOGIC const Colors = enum(u32) { red = 0x00ff0000, green = 0xff000000, blue = 0x0000ff00, white = 0xffffff00, }; var color: Colors = .white; while (true) { // reading inputs if (pins.button.read() == 0) { pico.time.sleep_ms(20); if (pins.button.read() == 0) { color = switch (color) { .white => .red, .red => .green, .green => .blue, .blue => .white, }; while (pins.button.read() == 0) { asm volatile ("" ::: "memory"); } } } const x = pico.adc.convert_one_shot_blocking(pins.xaxis) catch 0; // const y = pico.adc.convert_one_shot_blocking(pins.yaxos) catch 0; // writing outputs // TODO: this is unfinished switch (x) { 0...QUARTER - 1 => { pio.sm_blocking_write(sm, @intFromEnum(color)); }, QUARTER...2 * QUARTER - 1 => { pio.sm_blocking_write(sm, 0x00000000); pio.sm_blocking_write(sm, @intFromEnum(color)); }, 2 * QUARTER...3 * QUARTER - 1 => { pio.sm_blocking_write(sm, 0x00000000); pio.sm_blocking_write(sm, 0x00000000); pio.sm_blocking_write(sm, @intFromEnum(color)); }, else => { pio.sm_blocking_write(sm, 0x00000000); pio.sm_blocking_write(sm, 0x00000000); pio.sm_blocking_write(sm, 0x00000000); pio.sm_blocking_write(sm, @intFromEnum(color)); }, } pico.time.sleep_ms(100); } } const ws2812_program = blk: { @setEvalBranchQuota(10_000); break :blk pico.pio.assemble( \\; \\; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. \\; \\; SPDX-License-Identifier: BSD-3-Clause \\; \\.program ws2812 \\.side_set 1 \\ \\.define public T1 2 \\.define public T2 5 \\.define public T3 3 \\ \\.wrap_target \\bitloop: \\ out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls \\ jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse \\do_one: \\ jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse \\do_zero: \\ nop side 0 [T2 - 1] ; Or drive low, for a short pulse \\.wrap , .{}).get_program_by_name("ws2812"); };