fix: clean up frequency timer implementations
This commit is contained in:
parent
87eb0cc808
commit
3cd02a44cf
40
src/apu.zig
40
src/apu.zig
|
@ -966,24 +966,20 @@ const WaveDevice = struct {
|
||||||
|
|
||||||
fn reloadTimer(self: *Self, value: u11) void {
|
fn reloadTimer(self: *Self, value: u11) void {
|
||||||
self.sched.removeScheduledEvent(.{ .ApuChannel = 2 });
|
self.sched.removeScheduledEvent(.{ .ApuChannel = 2 });
|
||||||
const timer = (2048 - @as(u64, value)) * 4;
|
|
||||||
self.timer = @truncate(u11, timer);
|
|
||||||
|
|
||||||
self.sched.push(.{ .ApuChannel = 2 }, timer * tickInterval);
|
self.timer = (@as(u16, 2048) - value) * 2;
|
||||||
|
self.sched.push(.{ .ApuChannel = 2 }, @as(u64, self.timer) * tickInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleTimerOverflow(self: *Self, cnt_freq: io.Frequency, cnt_sel: io.WaveSelect, late: u64) void {
|
fn handleTimerOverflow(self: *Self, cnt_freq: io.Frequency, cnt_sel: io.WaveSelect, late: u64) void {
|
||||||
const timer = (2048 - @as(u64, cnt_freq.frequency.read())) * 2;
|
|
||||||
|
|
||||||
self.timer = @truncate(u12, timer);
|
|
||||||
|
|
||||||
if (cnt_sel.dimension.read()) {
|
if (cnt_sel.dimension.read()) {
|
||||||
self.offset = (self.offset + 1) % 0x40; // 0x20 bytes (both banks), which contain 2 samples each
|
self.offset = (self.offset + 1) % 0x40; // 0x20 bytes (both banks), which contain 2 samples each
|
||||||
} else {
|
} else {
|
||||||
self.offset = (self.offset + 1) % 0x20; // 0x10 bytes, which contain 2 samples each
|
self.offset = (self.offset + 1) % 0x20; // 0x10 bytes, which contain 2 samples each
|
||||||
}
|
}
|
||||||
|
|
||||||
self.sched.push(.{ .ApuChannel = 2 }, timer * tickInterval -| late);
|
self.timer = (@as(u16, 2048) - cnt_freq.frequency.read()) * 2;
|
||||||
|
self.sched.push(.{ .ApuChannel = 2 }, @as(u64, self.timer) * tickInterval -| late);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample(self: *const Self, cnt: io.WaveSelect) u4 {
|
fn sample(self: *const Self, cnt: io.WaveSelect) u4 {
|
||||||
|
@ -1046,7 +1042,7 @@ const SquareWave = struct {
|
||||||
|
|
||||||
pos: u3,
|
pos: u3,
|
||||||
sched: *Scheduler,
|
sched: *Scheduler,
|
||||||
timer: u12,
|
timer: u16,
|
||||||
|
|
||||||
pub fn init(sched: *Scheduler) Self {
|
pub fn init(sched: *Scheduler) Self {
|
||||||
return .{
|
return .{
|
||||||
|
@ -1089,22 +1085,19 @@ const SquareWave = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleTimerOverflow(self: *Self, comptime kind: ChannelKind, cnt: io.Frequency, late: u64) void {
|
fn handleTimerOverflow(self: *Self, comptime kind: ChannelKind, cnt: io.Frequency, late: u64) void {
|
||||||
const timer = (2048 - @as(u64, cnt.frequency.read())) * 4;
|
|
||||||
|
|
||||||
self.timer = @truncate(u12, timer);
|
|
||||||
self.pos +%= 1;
|
self.pos +%= 1;
|
||||||
|
|
||||||
self.sched.push(.{ .ApuChannel = if (kind == .Ch1) 0 else 1 }, timer * tickInterval -| late);
|
self.timer = (@as(u16, 2048) - cnt.frequency.read()) * 4;
|
||||||
|
self.sched.push(.{ .ApuChannel = if (kind == .Ch1) 0 else 1 }, @as(u64, self.timer) * tickInterval -| late);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloadTimer(self: *Self, comptime kind: ChannelKind, value: u11) void {
|
fn reloadTimer(self: *Self, comptime kind: ChannelKind, value: u11) void {
|
||||||
self.sched.removeScheduledEvent(.{ .ApuChannel = if (kind == .Ch1) 0 else 1 });
|
self.sched.removeScheduledEvent(.{ .ApuChannel = if (kind == .Ch1) 0 else 1 });
|
||||||
|
|
||||||
const tmp: u64 = (2048 - @as(u64, value)) * 4; // What Freq Timer should be assuming no weird behaviour
|
const tmp = (@as(u16, 2048) - value) * 4; // What Freq Timer should be assuming no weird behaviour
|
||||||
const timer = (tmp & ~@as(u64, 0x3)) | self.timer & 0x3; // Keep the last two bits from the old timer
|
self.timer = (tmp & ~@as(u16, 0x3)) | self.timer & 0x3; // Keep the last two bits from the old timer;
|
||||||
self.timer = @truncate(u12, timer);
|
|
||||||
|
|
||||||
self.sched.push(.{ .ApuChannel = if (kind == .Ch1) 0 else 1 }, timer * tickInterval);
|
self.sched.push(.{ .ApuChannel = if (kind == .Ch1) 0 else 1 }, @as(u64, self.timer) * tickInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample(self: *const Self, cnt: io.Duty) u1 {
|
fn sample(self: *const Self, cnt: io.Duty) u1 {
|
||||||
|
@ -1163,14 +1156,17 @@ const Lfsr = struct {
|
||||||
self.sched.removeScheduledEvent(.{ .ApuChannel = 3 });
|
self.sched.removeScheduledEvent(.{ .ApuChannel = 3 });
|
||||||
|
|
||||||
const div = Self.divisor(poly.div_ratio.read());
|
const div = Self.divisor(poly.div_ratio.read());
|
||||||
const timer = @as(u64, div << poly.shift.read());
|
const timer = div << poly.shift.read();
|
||||||
|
self.sched.push(.{ .ApuChannel = 3 }, @as(u64, timer) * tickInterval);
|
||||||
self.sched.push(.{ .ApuChannel = 3 }, timer * tickInterval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleTimerOverflow(self: *Self, poly: io.PolyCounter, late: u64) void {
|
fn handleTimerOverflow(self: *Self, poly: io.PolyCounter, late: u64) void {
|
||||||
|
// Obscure: "Using a noise channel clock shift of 14 or 15
|
||||||
|
// results in the LFSR receiving no clocks."
|
||||||
|
if (poly.shift.read() >= 14) return;
|
||||||
|
|
||||||
const div = Self.divisor(poly.div_ratio.read());
|
const div = Self.divisor(poly.div_ratio.read());
|
||||||
const timer = @as(u64, div << poly.shift.read());
|
const timer = div << poly.shift.read();
|
||||||
|
|
||||||
const tmp = (self.shift & 1) ^ ((self.shift & 2) >> 1);
|
const tmp = (self.shift & 1) ^ ((self.shift & 2) >> 1);
|
||||||
self.shift = (self.shift >> 1) | (tmp << 14);
|
self.shift = (self.shift >> 1) | (tmp << 14);
|
||||||
|
@ -1178,7 +1174,7 @@ const Lfsr = struct {
|
||||||
if (poly.width.read())
|
if (poly.width.read())
|
||||||
self.shift = (self.shift & ~@as(u15, 0x40)) | tmp << 6;
|
self.shift = (self.shift & ~@as(u15, 0x40)) | tmp << 6;
|
||||||
|
|
||||||
self.sched.push(.{ .ApuChannel = 3 }, timer * tickInterval -| late);
|
self.sched.push(.{ .ApuChannel = 3 }, @as(u64, timer) * tickInterval -| late);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn divisor(code: u3) u16 {
|
fn divisor(code: u3) u16 {
|
||||||
|
|
Loading…
Reference in New Issue