RIKRRTK5ZNVTCDJBS2O54P36TSQXENEZ2DYXJ3WPFW7ZQ6CF4DMQC const std = @import("std");const microzig = @import("microzig");const pico = microzig.hal;const peripherals = microzig.chip.peripherals;// XXX: hardcoded!pub const PID_INTERRUPT_MS = 1000;// TODO: use fixed point arithmetics here!const VariableType = f32;// PID State variablesvar err_sum: VariableType = 0;var err_last: VariableType = 0;kp: VariableType,ki: VariableType,kd: VariableType,// TODO: make an initWithInterrupt function to set up periodic interruptspub fn init(interrupt: u10, kp: VariableType, ki: VariableType, kd: VariableType) @This() {const pid = @This(){.kp = kp,.ki = ki * interrupt,.kd = kd / interrupt,};return pid;}pub fn compute(self: @This(), input: VariableType, sp: VariableType) VariableType {// Calculate errorsconst err: VariableType = sp - input;err_sum += err;const err_diff: VariableType = err - err_last;// Calculate PID outputconst output: VariableType = self.kp * err + self.ki * err_sum + self.kd * err_diff;// Update stateerr_last = err;// re-enable interruptsetAlarm(PID_INTERRUPT_MS);return output;}// XXX: make this non-public!pub fn setAlarm(ms: u32) void {const current = pico.time.get_time_since_boot();const target = current.add_duration(microzig.drivers.time.Duration.from_ms(ms));peripherals.TIMER.ALARM0.write_raw(@truncate(@intFromEnum(target)));}
fn timerInterrupt() callconv(.c) void {const cs = microzig.interrupt.enter_critical_section();defer cs.leave();std.log.info("timer_interrupt called!", .{});peripherals.TIMER.INTR.modify(.{ .ALARM_0 = 1 });setAlarm(1_000);}fn gpioInterrupt() callconv(.c) void {// const cs = microzig.interrupt.enter_critical_section();// defer cs.leave();// XXX: this could be const without the .Debug code...var state = peripherals.IO_BANK0.PROC0_INTS1.read();if (builtin.mode == .Debug) {const fstate = peripherals.IO_BANK0.PROC0_INTF1.read();if (fstate.GPIO15_LEVEL_LOW == 1) state.GPIO15_EDGE_LOW = 1;if (fstate.GPIO15_LEVEL_HIGH == 1) state.GPIO15_EDGE_HIGH = 1;// disable forcingperipherals.IO_BANK0.PROC0_INTF1.modify(.{.GPIO15_EDGE_HIGH = 0,.GPIO15_EDGE_LOW = 0,});}// aknowledge interruptperipherals.IO_BANK0.INTR1.modify(.{ .GPIO15_EDGE_LOW = 1, .GPIO15_EDGE_HIGH = 1 });// std.log.debug("gpioInterrupt LOW: {d} HIGH: {d}", .{ state.GPIO15_EDGE_LOW, state.GPIO15_EDGE_HIGH });
if (state.GPIO15_EDGE_HIGH == 1) {ddc.signalRising();} else if (state.GPIO15_EDGE_LOW == 1) {ddc.signalFalling();}}fn setAlarm(ms: u32) void {const current = pico.time.get_time_since_boot();const target = current.add_duration(microzig.drivers.time.Duration.from_ms(ms));// peripherals.TIMER.ALARM0.write_raw(@intCast(@intFromEnum(target) & 0xffffffff));peripherals.TIMER.ALARM0.write_raw(@truncate(@intFromEnum(target)));}
// TODO: could be useful for watchdog updating// timer interrupt// setAlarm(1_000);// peripherals.TIMER.INTE.toggle(.{ .ALARM_0 = 1 });// interrupt.enable(.TIMER_IRQ_0);
pico.multicore.launch_core1(core1);while (pico.multicore.fifo.read()) |rec| {std.log.debug("CPU FIFO: {}", .{rec});pico.multicore.fifo.write_blocking(rec);}
fn core1() void {std.log.debug("core1 is up and running", .{});// timer interrupt for PIDPID.setAlarm(PID.PID_INTERRUPT_MS);peripherals.TIMER.INTE.toggle(.{ .ALARM_0 = 1 });interrupt.enable(.TIMER_IRQ_0);while (true) {microzig.cpu.wfi();}}fn timerInterrupt() callconv(.c) void {const cs = microzig.interrupt.enter_critical_section();defer cs.leave();// acknowledge interruptperipherals.TIMER.INTR.modify(.{ .ALARM_0 = 1 });const sp: f32 = 50;const input: f32 = undefined;const output = pid.compute(input, sp);std.log.debug("SP: {d} in: {d} out: {d}", .{ sp, input, output });}fn gpioInterrupt() callconv(.c) void {// const cs = microzig.interrupt.enter_critical_section();// defer cs.leave();// XXX: this could be const without the .Debug code...var state = peripherals.IO_BANK0.PROC0_INTS1.read();if (builtin.mode == .Debug) {const fstate = peripherals.IO_BANK0.PROC0_INTF1.read();if (fstate.GPIO15_LEVEL_LOW == 1) state.GPIO15_EDGE_LOW = 1;if (fstate.GPIO15_LEVEL_HIGH == 1) state.GPIO15_EDGE_HIGH = 1;// disable forcingperipherals.IO_BANK0.PROC0_INTF1.modify(.{.GPIO15_EDGE_HIGH = 0,.GPIO15_EDGE_LOW = 0,});}// aknowledge interruptperipherals.IO_BANK0.INTR1.modify(.{ .GPIO15_EDGE_LOW = 1, .GPIO15_EDGE_HIGH = 1 });// std.log.debug("gpioInterrupt LOW: {d} HIGH: {d}", .{ state.GPIO15_EDGE_LOW, state.GPIO15_EDGE_HIGH });if (state.GPIO15_EDGE_HIGH == 1) {ddc.signalRising();} else if (state.GPIO15_EDGE_LOW == 1) {ddc.signalFalling();}}