diff --git a/drivers/README.md b/drivers/README.md index 7bfe2c62c..fc533b3fb 100644 --- a/drivers/README.md +++ b/drivers/README.md @@ -383,7 +383,7 @@ pub const Clock_Device = struct { - `sleep_us(time_us)` - Sleep for N microseconds (polls if no custom sleep) - `sleep_ms(time_ms)` - Sleep for N milliseconds - `make_timeout(duration)` - Create deadline from current time + duration -- `is_reached(absolute_time)` - Check if time point has passed +- `Timeout.is_reached()` - Check if time point has passed **Usage Example**: ```zig @@ -394,7 +394,7 @@ const timeout = clock.make_timeout(mdf.time.Duration.from_ms(100)); // Poll with timeout while (!is_ready()) { - if (clock.is_reached(timeout)) { + if (timeout.is_reached()) { return error.Timeout; } } diff --git a/drivers/base/Clock_Device.zig b/drivers/base/Clock_Device.zig index 9d7b57b3f..62fa21b30 100644 --- a/drivers/base/Clock_Device.zig +++ b/drivers/base/Clock_Device.zig @@ -18,18 +18,32 @@ ptr: *anyopaque, /// Virtual table for the digital i/o functions. vtable: *const VTable, -/// API -pub fn is_reached(td: Clock_Device, time: mdf.time.Absolute) bool { +/// Object created by make_timeout to perform to hold +/// a duration. +pub const Timeout = struct { + clock: Clock_Device, + time: mdf.time.Absolute, + + pub fn is_reached(self: @This()) bool { + return self.clock.is_reached(self.time); + } + + pub fn diff(self: @This()) mdf.time.Duration { + return self.time.diff(self.clock.get_time_since_boot()); + } +}; + +fn is_reached(td: Clock_Device, time: mdf.time.Absolute) bool { const now = td.get_time_since_boot(); return time.is_reached_by(now); } -pub fn make_timeout(td: Clock_Device, timeout: mdf.time.Duration) mdf.time.Absolute { - return @as(mdf.time.Absolute, @enumFromInt(td.get_time_since_boot().to_us() + timeout.to_us())); -} - -pub fn make_timeout_us(td: Clock_Device, timeout_us: u64) mdf.time.Absolute { - return @as(mdf.time.Absolute, @enumFromInt(td.get_time_since_boot().to_us() + timeout_us)); +/// API +pub fn make_timeout(td: Clock_Device, timeout: mdf.time.Duration) Timeout { + return .{ + .clock = td, + .time = td.get_time_since_boot().add_duration(timeout), + }; } pub fn sleep_ms(td: Clock_Device, time_ms: u32) void { @@ -44,8 +58,8 @@ pub fn sleep_us(td: Clock_Device, time_us: u64) void { } // Otherwise, fall back to polling - const end_time = td.make_timeout_us(time_us); - while (!td.is_reached(end_time)) {} + const end_time = td.make_timeout(.from_us(time_us)); + while (!end_time.is_reached()) {} } /// VTable methods @@ -116,17 +130,12 @@ test Test_Device { ttd.elapse_time(2); try std.testing.expectEqual(2, td.get_time_since_boot().to_us()); - try std.testing.expect(!td.is_reached(@enumFromInt(4))); - ttd.elapse_time(2); - try std.testing.expect(td.is_reached(@enumFromInt(4))); - // Timeouts - try std.testing.expectEqual( - 54, - @intFromEnum(td.make_timeout(mdf.time.Duration.from_us(50))), - ); - ttd.elapse_time(50); - try std.testing.expectEqual(104, @intFromEnum(td.make_timeout_us(50))); + const timeout = td.make_timeout(.from_us(50)); + ttd.elapse_time(40); + try std.testing.expectEqual(mdf.time.Duration.from_us(10), timeout.diff()); + ttd.elapse_time(10); + try std.testing.expect(timeout.is_reached()); try std.testing.expectEqual(0, ttd.get_total_sleep_time()); td.sleep_ms(1000); diff --git a/drivers/led/ws2812.zig b/drivers/led/ws2812.zig index 446a2a881..531849737 100644 --- a/drivers/led/ws2812.zig +++ b/drivers/led/ws2812.zig @@ -18,7 +18,7 @@ pub fn WS2812(options: struct { dev: options.Datagram_Device, clock_dev: options.Clock_Device, - next_write_time: ?mdf.time.Absolute = null, + next_write_time: ?mdf.base.Clock_Device.Timeout = null, buffer: [buffer_size]u8 = undefined, /// Initializes the driver. @@ -36,9 +36,8 @@ pub fn WS2812(options: struct { // ensures that a reset takes place between writes if (self.next_write_time) |next_write_time| { - const now = self.clock_dev.get_time_since_boot(); - if (!next_write_time.is_reached_by(now)) { - self.clock_dev.sleep_us(next_write_time.diff(now).to_us()); + if (!next_write_time.is_reached()) { + self.clock_dev.sleep_us(next_write_time.diff().to_us()); } } @@ -63,7 +62,7 @@ pub fn WS2812(options: struct { try self.dev.write(self.buffer[0..i]); - self.next_write_time = self.clock_dev.make_timeout_us(300); + self.next_write_time = self.clock_dev.make_timeout(.from_us(300)); } }; }