Skip to content

Commit

Permalink
Add "good" timing
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
evantypanski committed Feb 13, 2023
1 parent 7e22531 commit 625deb9
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 37 deletions.
2 changes: 1 addition & 1 deletion microzig
41 changes: 23 additions & 18 deletions src/main.zig
Original file line number Diff line number Diff line change
@@ -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;
}
}
};
57 changes: 39 additions & 18 deletions src/time.zig
Original file line number Diff line number Diff line change
@@ -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;
}
Expand Down

0 comments on commit 625deb9

Please sign in to comment.