diff --git a/src/hal/dma.zig b/src/hal/dma.zig index 248e333..ded0a8c 100644 --- a/src/hal/dma.zig +++ b/src/hal/dma.zig @@ -7,7 +7,8 @@ const DMA = chip.peripherals.DMA; const hw = @import("hw.zig"); -var claimed_channels: u12 = 0; +const num_channels = 12; +var claimed_channels = std.PackedIntArray(bool, num_channels).initAllTo(false); pub const Dreq = enum(u6) { uart0_tx = 20, @@ -15,31 +16,38 @@ pub const Dreq = enum(u6) { _, }; -pub fn num(n: u4) Channel { - assert(n < 12); +pub fn channel(n: u4) Channel { + assert(n < num_channels); return @intToEnum(Channel, n); } -pub fn claim_unused_channel() ?Channel {} +pub fn claim_unused_channel() ?Channel { + for (0..num_channels) |i| { + if (claimed_channels.get(i)) { + claimed_channels.set(i, true); + return channel(i); + } + } + + return null; +} pub const Channel = enum(u4) { _, /// panics if the channel is already claimed - pub fn claim(channel: Channel) void { - _ = channel; - @panic("TODO"); + pub fn claim(chan: Channel) void { + if (chan.is_claimed()) + @panic("channel is already claimed!"); } - pub fn unclaim(channel: Channel) void { - _ = channel; - @panic("TODO"); + pub fn unclaim(chan: Channel) void { + claimed_channels.set(@enumToInt(chan), false); } - pub fn is_claimed(channel: Channel) bool { - _ = channel; - @panic("TODO"); + pub fn is_claimed(chan: Channel) bool { + return claimed_channels.get(@enumToInt(chan)); } const Regs = extern struct { @@ -67,9 +75,9 @@ pub const Channel = enum(u4) { al3_trans_count: u32, }; - fn get_regs(channel: Channel) *volatile Regs { + fn get_regs(chan: Channel) *volatile Regs { const regs = @ptrCast(*volatile [12]Regs, &DMA.CH0_READ_ADDR); - return ®s[@enumToInt(channel)]; + return ®s[@enumToInt(chan)]; } pub const TransferConfig = struct { @@ -86,13 +94,13 @@ pub const Channel = enum(u4) { }; pub fn trigger_transfer( - channel: Channel, + chan: Channel, write_addr: u32, read_addr: u32, count: u32, config: TransferConfig, ) void { - const regs = channel.get_regs(); + const regs = chan.get_regs(); regs.read_addr = read_addr; regs.write_addr = write_addr; regs.trans_count = count; @@ -109,23 +117,23 @@ pub const Channel = enum(u4) { }); } - pub fn set_irq0_enabled(channel: Channel, enabled: bool) void { + pub fn set_irq0_enabled(chan: Channel, enabled: bool) void { if (enabled) { const inte0_set = hw.set_alias_raw(&DMA.INTE0); - inte0_set.* = @as(u32, 1) << @enumToInt(channel); + inte0_set.* = @as(u32, 1) << @enumToInt(chan); } else { const inte0_clear = hw.clear_alias_raw(&DMA.INTE0); - inte0_clear.* = @as(u32, 1) << @enumToInt(channel); + inte0_clear.* = @as(u32, 1) << @enumToInt(chan); } } - pub fn acknowledge_irq0(channel: Channel) void { + pub fn acknowledge_irq0(chan: Channel) void { const ints0_set = hw.set_alias_raw(&DMA.INTS0); - ints0_set.* = @as(u32, 1) << @enumToInt(channel); + ints0_set.* = @as(u32, 1) << @enumToInt(chan); } - pub fn is_busy(channel: Channel) bool { - const regs = channel.get_regs(); + pub fn is_busy(chan: Channel) bool { + const regs = chan.get_regs(); return regs.ctrl_trig.read().BUSY == 1; } }; diff --git a/src/hal/time.zig b/src/hal/time.zig index d7f815b..e6cace5 100644 --- a/src/hal/time.zig +++ b/src/hal/time.zig @@ -6,14 +6,58 @@ const TIMER = microzig.chip.peripherals.TIMER; pub const Absolute = enum(u64) { _, - pub fn reached(time: Absolute) bool { - const now = get_time_since_boot(); - return now.to_us() >= time.to_us(); + pub fn from_us(us: u64) Absolute { + return @intToEnum(Absolute, us); } pub fn to_us(time: Absolute) u64 { return @enumToInt(time); } + + pub fn is_reached_by(deadline: Absolute, point: Absolute) bool { + return deadline.to_us() <= point.to_us(); + } + + pub fn is_reached(time: Absolute) bool { + const now = get_time_since_boot(); + return time.is_reached_by(now); + } + + pub fn diff(future: Absolute, past: Absolute) Duration { + return Duration.from_us(future.to_us() - past.to_us()); + } + + pub fn add_duration(time: Absolute, dur: Duration) Absolute { + return Absolute.from_us(time.to_us() + dur.to_us()); + } +}; + +pub const Duration = enum(u64) { + _, + + pub fn from_us(us: u64) Duration { + return @intToEnum(Duration, us); + } + + pub fn from_ms(ms: u64) Duration { + return from_us(1000 * ms); + } + + pub fn to_us(duration: Duration) u64 { + return @enumToInt(duration); + } + + pub fn less_than(self: Duration, other: Duration) bool { + return self.to_us() < other.to_us(); + } + + pub fn minus(self: Duration, other: Duration) Duration { + return from_us(self.to_us() - other.to_us()); + } + + pub fn plus(self: Duration, other: Duration) Duration { + return from_us(self.to_us() + other.to_us()); + } }; pub fn get_time_since_boot() Absolute { @@ -39,5 +83,5 @@ pub fn sleep_ms(time_ms: u32) void { pub fn sleep_us(time_us: u64) void { const end_time = make_timeout_us(time_us); - while (!end_time.reached()) {} + while (!end_time.is_reached()) {} }