// TODO: upstream these helper functions
// TODO: rp2350 support?
const std = @import("std");
const microzig = @import("microzig");
const rp2xxx = microzig.hal;
const peripherals = microzig.chip.peripherals;
const Scenario = packed struct(u4) {
low: u1 = 0,
high: u1 = 0,
fall: u1 = 0,
rise: u1 = 0,
};
const Destination = packed struct {
dormant_wake: u1 = 0,
proc0: u1 = 0,
proc1: u1 = 0,
};
const Bank = packed struct {
io_bank0: Destination = @bitCast(@as(u3, 0)),
io_qspi: Destination = @bitCast(@as(u3, 0)),
};
pub fn enable_interrupt(gpio: rp2xxx.gpio.Pin, bank: Bank, mask: Scenario) void {
const shift: u5 = @intCast(@intFromEnum(gpio) % 8 * 4);
const shifted_mask: u32 = @as(u32, @intCast(@as(u4, @bitCast(mask)))) << shift;
if (@as(u3, @bitCast(bank.io_bank0)) != 0) {
const b = peripherals.IO_BANK0;
switch (@intFromEnum(gpio)) {
0...7 => {
if (bank.io_bank0.dormant_wake == 1) b.DORMANT_WAKE_INTE0.raw |= shifted_mask;
if (bank.io_bank0.proc0 == 1) b.PROC0_INTE0.raw |= shifted_mask;
if (bank.io_bank0.proc1 == 1) b.PROC1_INTE0.raw |= shifted_mask;
},
8...15 => {
if (bank.io_bank0.dormant_wake == 1) b.DORMANT_WAKE_INTE1.raw |= shifted_mask;
if (bank.io_bank0.proc0 == 1) b.PROC0_INTE1.raw |= shifted_mask;
if (bank.io_bank0.proc1 == 1) b.PROC1_INTE1.raw |= shifted_mask;
},
16...23 => {
if (bank.io_bank0.dormant_wake == 1) b.DORMANT_WAKE_INTE2.raw |= shifted_mask;
if (bank.io_bank0.proc0 == 1) b.PROC0_INTE2.raw |= shifted_mask;
if (bank.io_bank0.proc1 == 1) b.PROC1_INTE2.raw |= shifted_mask;
},
24...29 => {
if (bank.io_bank0.dormant_wake == 1) b.DORMANT_WAKE_INTE3.raw |= shifted_mask;
if (bank.io_bank0.proc0 == 1) b.PROC0_INTE3.raw |= shifted_mask;
if (bank.io_bank0.proc1 == 1) b.PROC1_INTE3.raw |= shifted_mask;
},
else => @panic("the RP2040 only has GPIO 0-29"),
}
// Enable this interrupt type
rp2xxx.irq.enable(.IO_IRQ_BANK0);
}
if (@as(u3, @bitCast(bank.io_qspi)) != 0) {
const b = peripherals.IO_QSPI;
if (bank.io_qspi.dormant_wake == 1) b.DORMANT_WAKE_INTE.raw |= shifted_mask;
if (bank.io_qspi.proc0 == 1) b.PROC0_INTE.raw |= shifted_mask;
if (bank.io_qspi.proc1 == 1) b.PROC1_INTE.raw |= shifted_mask;
// Enable this interrupt type
rp2xxx.irq.enable(.IO_IRQ_QSPI);
}
// Enable CPU interrupt handling
rp2xxx.irq.globally_enable();
}
pub fn disable_interrupt(gpio: rp2xxx.gpio.Pin, bank: Bank, mask: Scenario) void {
const shift: u5 = @intCast(@intFromEnum(gpio) % 8 * 4);
const shifted_mask: u32 = @as(u32, @intCast(@as(u4, @bitCast(mask)))) << shift;
if (@as(u3, @bitCast(bank.io_bank0)) != 0) {
const b = peripherals.IO_BANK0;
switch (@intFromEnum(gpio)) {
0...7 => {
if (bank.io_bank0.dormant_wake == 1) b.DORMANT_WAKE_INTE0.raw ^= shifted_mask;
if (bank.io_bank0.proc0 == 1) b.PROC0_INTE0.raw ^= shifted_mask;
if (bank.io_bank0.proc1 == 1) b.PROC1_INTE0.raw ^= shifted_mask;
},
8...15 => {
if (bank.io_bank0.dormant_wake == 1) b.DORMANT_WAKE_INTE1.raw ^= shifted_mask;
if (bank.io_bank0.proc0 == 1) b.PROC0_INTE1.raw ^= shifted_mask;
if (bank.io_bank0.proc1 == 1) b.PROC1_INTE1.raw ^= shifted_mask;
},
16...23 => {
if (bank.io_bank0.dormant_wake == 1) b.DORMANT_WAKE_INTE2.raw ^= shifted_mask;
if (bank.io_bank0.proc0 == 1) b.PROC0_INTE2.raw ^= shifted_mask;
if (bank.io_bank0.proc1 == 1) b.PROC1_INTE2.raw ^= shifted_mask;
},
24...29 => {
if (bank.io_bank0.dormant_wake == 1) b.DORMANT_WAKE_INTE3.raw ^= shifted_mask;
if (bank.io_bank0.proc0 == 1) b.PROC0_INTE3.raw ^= shifted_mask;
if (bank.io_bank0.proc1 == 1) b.PROC1_INTE3.raw ^= shifted_mask;
},
else => @panic("the RP2040 only has GPIO 0-29"),
}
}
if (@as(u3, @bitCast(bank.io_qspi)) != 0) {
const b = peripherals.IO_QSPI;
if (bank.io_qspi.dormant_wake == 1) b.DORMANT_WAKE_INTE.raw ^= shifted_mask;
if (bank.io_qspi.proc0 == 1) b.PROC0_INTE.raw ^= shifted_mask;
if (bank.io_qspi.proc1 == 1) b.PROC1_INTE.raw ^= shifted_mask;
}
}