From 625deb93504f8cea6704775cfdfae3acb7ebc797 Mon Sep 17 00:00:00 2001 From: Evan Typanski Date: Sun, 12 Feb 2023 19:18:12 -0500 Subject: [PATCH] Add "good" timing I don't get why the delay is off by a factor of 32. None of the prescaling factors are even 32, it goes 8, 64, 256, 1024. Where does 32 come from? Why is it not in Arduino's code? I have a 16 MHz crystal. What the heck man? Oh well. --- microzig | 2 +- src/main.zig | 41 ++++++++++++++++++++----------------- src/time.zig | 57 +++++++++++++++++++++++++++++++++++----------------- 3 files changed, 63 insertions(+), 37 deletions(-) diff --git a/microzig b/microzig index 8b0221f..bddbbd7 160000 --- a/microzig +++ b/microzig @@ -1 +1 @@ -Subproject commit 8b0221ff2fad55b734d3c9ae4c7e94a8574e5297 +Subproject commit bddbbd74029b00df818c93d33a9fb342816bfe14 diff --git a/src/main.zig b/src/main.zig index 4d67a38..dc0504b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,29 +1,34 @@ -const std = @import("std"); const gpio = @import("gpio.zig"); const pins = @import("pins.zig"); +const time = @import("time.zig"); pub fn main() void { - // This baud should match what you pass in build + time.init(); // Onboard LED gpio.pinMode(pins.led_builtin, .out); - // Wired LED - gpio.pinMode(8, .out); - // Button - gpio.pinMode(3, .in); - while (true) { gpio.toggle(pins.led_builtin); - if (gpio.digitalRead(3) == .low) { - gpio.digitalWrite(8, .low); - } else { - gpio.digitalWrite(8, .high); - } + time.delay(1000); + } +} - // Hard code a busy wait. Will add delays eventually. - var i: u32 = 0; - while (i < 100000) : (i += 1) { - // For some reason need to nop the busy wait - asm volatile ("nop"); +// Interrupt stuff in root for timer +pub const interrupts = struct { + pub fn TIMER0_OVF() void { + // Dunno if we need locals like in Arduino standard library to keep in + // registers. But I'll do it anyway + var m = time.timer0_millis; + var f = time.timer0_fract; + + m += time.millis_inc; + f += time.fract_inc; + if (f >= time.fract_max) { + f -= time.fract_max; + m += 1; } + + time.timer0_fract = f; + time.timer0_millis = m; + time.timer0_overflow_count += 1; } -} +}; diff --git a/src/time.zig b/src/time.zig index 9f37882..c6c9125 100644 --- a/src/time.zig +++ b/src/time.zig @@ -1,36 +1,57 @@ //! Timing functions such as delay. -const serial = @import("serial.zig"); -const chip = @import("microzig").chip; +const micro = @import("microzig"); const regs = @import("microzig").chip.registers; const std = @import("std"); -const Allocator = std.mem.Allocator; -const cpu_freq = 16000000; -const clock_cycles_per_microsecond = cpu_freq / 1000000; +const clock_cycles_per_microsecond = micro.clock.get().cpu / 1000000; +const microseconds_per_timer0_overflow = clock_cycles_to_microseconds(64 * 256); +pub const millis_inc = (microseconds_per_timer0_overflow / 1000); -var timer0_overflow_count = 0; +pub const fract_inc: u8 = ((microseconds_per_timer0_overflow % 1000) >> 3); +pub const fract_max: u8 = (1000 >> 3); -fn init() void { - regs.TC0.TCCR0B.modify(.{ .CS0 = 0x5 }); +pub var timer0_overflow_count: u64 = 0; +pub var timer0_millis: u64 = 0; +pub var timer0_fract: u8 = 0; + +fn clock_cycles_to_microseconds(a: u64) u64 { + return ((a) / clock_cycles_per_microsecond); +} + +fn microseconds_to_clock_cycles(a: u64) u64 { + return ((a) * clock_cycles_per_microsecond); +} + +// This will eventually move from time. Probably. Just most of this stuff +// is enabling timers and interrupts on them +pub fn init() void { + // Enable interrupts + regs.CPU.SREG.modify(.{ .I = 0x1 }); + regs.TC0.TIMSK0.modify(.{ .TOIE0 = 0x1 }); + // Set clock mode + regs.TC0.TCCR0B.modify(.{ .CS0 = 0x1 }); regs.TC0.TCCR0A.modify(.{ .WGM0 = 0x1 }); } -fn micros() u32 { - // TODO: Need to care more about flags, interrupts, stuff like that. - // TODO: Care about overflow in timer register - return regs.TC0.TCNT0.*; +fn micros() u64 { + const oldSREG = regs.CPU.SREG.*; + micro.cpu.cli(); + var m = timer0_overflow_count; + const t = regs.TC0.TCNT0.*; + if (regs.TC0.TIFR0.read().TOV0 == 1 and t < 255) { + m += 1; + } + regs.CPU.SREG.* = oldSREG; + return ((m << 8) + t) * (64 / clock_cycles_per_microsecond); } pub fn delay(ms: u64) void { - init(); - var var_ms = comptime ms; + // Please tell me why in the world I need this 32 here + var var_ms = comptime ms * 32; var start = micros(); while (var_ms > 0) { - //if (micros() == start) { - //var_ms -= 1; - //} - while ((var_ms > 0) and (micros() >= start)) { + while ((var_ms > 0) and ((micros() - start) >= 1000)) { var_ms -= 1; start += 1000; }