phaser-ags / zig /kernel /timer.zig
SNAPKITTYWEST's picture
October 2026 main drop: mirror from GitHub
829b19c verified
Raw History Blame Contribute Delete
2.76 kB
//! SPDX-License-Identifier: AGPL-3.0-or-later
//! Copyright 2025 Ahmad Ali Parr / SnapKitty οΏ½ https://github.com/SNAPKITTYWEST/phaser-ags
//! ═══════════════════════════════════════════════════════════════════
//! PHASER AGS β€” RISC-V timer + CLINT (complete, no stubs)
//! Full tick management with scheduler callback and compare setup.
//! ═══════════════════════════════════════════════════════════════════
const std = @import("std");
const driver = @import("driver.zig");
const CLINT_BASE: u32 = 0x02000000;
const MTIME_OFF: u32 = 0xBFF8;
const MTIMECMP_OFF: u32 = 0x4000;
inline fn clintRead64(offset: u32) u64 {
const lo = driver.regRead(u32, CLINT_BASE + offset);
const hi = driver.regRead(u32, CLINT_BASE + offset + 4);
return @as(u64, hi) << 32 | @as(u64, lo);
}
inline fn clintWrite64(offset: u32, val: u64) void {
driver.regWrite(u32, CLINT_BASE + offset + 4, @intCast(val >> 32));
driver.regWrite(u32, CLINT_BASE + offset, @intCast(val & 0xFFFFFFFF));
}
pub fn getTime() u64 {
var lo: u32 = undefined;
var hi: u32 = undefined;
while (true) {
hi = driver.regRead(u32, CLINT_BASE + MTIME_OFF + 4);
lo = driver.regRead(u32, CLINT_BASE + MTIME_OFF);
const hi2 = driver.regRead(u32, CLINT_BASE + MTIME_OFF + 4);
if (hi == hi2) break;
}
return @as(u64, hi) << 32 | @as(u64, lo);
}
pub fn setCompare(val: u64) void {
clintWrite64(MTIMECMP_OFF, val);
}
var tick_interval: u64 = 0;
var tick_count: u64 = 0;
var timer_callback: ?*const fn () void = null;
pub fn init(freq_hz: u64, tick_ms: u64) void {
tick_interval = (freq_hz * tick_ms) / 1000;
if (tick_interval == 0) tick_interval = 1;
tick_count = 0;
const now = getTime();
setCompare(now + tick_interval);
driver.csrSet(driver.CSR.MIE, 1 << 7); // MTIE
driver.Uart.puts("Timer: ");
driver.Uart.putHex(@intCast(tick_interval));
driver.Uart.puts(" ticks/irq (");
driver.Uart.putHex(@intCast(tick_ms));
driver.Uart.puts(" ms @ ");
driver.Uart.putHex(@intCast(freq_hz));
driver.Uart.puts(" Hz)\n");
}
pub fn setCallback(cb: *const fn () void) void {
timer_callback = cb;
}
pub fn getTickCount() u64 {
return tick_count;
}
pub fn getTickInterval() u64 {
return tick_interval;
}
pub fn ackTick() void {
tick_count += 1;
}
pub fn advanceCompare() void {
const now = getTime();
setCompare(now + tick_interval);
if (timer_callback) |cb| {
cb();
}
}