Skip to content

Commit

Permalink
PRT timer fixes: off-by-one countdown fixed, zero reload functioning …
Browse files Browse the repository at this point in the history
…as 65536 period implemented
  • Loading branch information
tomm committed Jan 12, 2025
1 parent 04946ab commit 9c6e5ab
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 21 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
members = ["agon-light-emulator-debugger", "agon-ez80-emulator", "agon-cli-emulator"]

[workspace.package]
version = "0.9.80"
version = "0.9.81"
edition = "2021"
authors = ["Tom Morton <[email protected]>"]
license = "GPL-3.0"
Expand Down
70 changes: 54 additions & 16 deletions agon-ez80-emulator/src/prt_timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,29 +81,25 @@ impl PrtTimer {
}
if self.ctl & RST_EN != 0 {
self.counter = self.reload;
self.step_ = 0;
self.ctl &= !RST_EN;
}
let clk_div = self.clk_div();
self.step_ = self.step_.wrapping_add(clock_ticks);
if self.step_ >= clk_div {
self.step_ -= clk_div;
self.counter = self.counter.wrapping_sub(1);
if self.counter == 0 {
if self.ctl & PRT_MODE != 0 {
// set PRT_IRQ
self.ctl |= 0x80;

if self.ctl & PRT_MODE == 0 {
// clear RST_EN and PRT_EN
self.ctl &= 0b1111_1100;
} else {
// continuous mode: reload counter
self.counter = self.reload;
}
//println("Elapsed {}", self.t_.elapsed());
//self.t_ = std::time::Instant::now();
} else {
self.counter -= 1;
if self.counter == 0 {
// set PRT_IRQ
self.ctl |= 0x80;

if self.ctl & PRT_MODE == 0 {
// clear RST_EN and PRT_EN
self.ctl &= 0b1111_1100;
}
}
}
}
}
Expand Down Expand Up @@ -140,6 +136,23 @@ mod tests {
assert_eq!(timer.read_ctl(), 0x0);
}

#[test]
fn test_timer_single_pass_65536() {
// try with 65536 timer duration
let mut timer = PrtTimer::new();
// enable
timer.write_ctl(3);
assert_eq!(timer.counter, 0);
for _i in 0..65535 {
timer.apply_ticks(4);
}
assert_eq!(timer.counter, 1);
timer.apply_ticks(4);
assert_eq!(timer.counter, 0);
timer.apply_ticks(4);
assert_eq!(timer.counter, 0);
}

#[test]
fn test_timer_continuous() {
let mut timer = PrtTimer::new();
Expand All @@ -157,14 +170,39 @@ mod tests {
timer.apply_ticks(0);
assert_eq!(timer.counter, 1);
timer.apply_ticks(4);
// in continuous mode, timer counter never goes to zero: it resets to reload value instead
assert_eq!(timer.counter, 2);
timer.apply_ticks(4);
assert_eq!(timer.counter, 1);
// first read - PRT_IRQ set
assert_eq!(timer.read_ctl(), 0x91);
// second read - PRT_IRQ has been cleared
assert_eq!(timer.read_ctl(), 0x11);
}

#[test]
fn test_timer_continuous_65536() {
// try with 65536 timer duration
let mut timer = PrtTimer::new();
// enable
timer.write_ctl(3 | 0x10);
assert_eq!(timer.counter, 0);
println!("last call");
for _i in 0..65535 {
timer.apply_ticks(4);
}
// no interrupt yet
assert_eq!(timer.read_ctl(), 0x11);
assert_eq!(timer.counter, 1);
timer.apply_ticks(4);
assert_eq!(timer.counter, 2);
assert_eq!(timer.counter, 0);

// first read - PRT_IRQ set
assert_eq!(timer.read_ctl(), 0x91);
// second read - PRT_IRQ has been cleared
assert_eq!(timer.read_ctl(), 0x11);

timer.apply_ticks(4);
assert_eq!(timer.counter, 65535);
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions docs/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ vdu 23 0 &88 250 0 50 0 0

## CPU bugs

- [ ] prt 16khz rtc source?
- [ ] Mixed mode push ((ismixed<<1) | isadl) to stack. I haven't implemented the ismixed part

## Mañana mañana
Expand Down

0 comments on commit 9c6e5ab

Please sign in to comment.