aboutsummaryrefslogtreecommitdiff
path: root/src/peripherals/timer.ts
diff options
context:
space:
mode:
authorUri Shaked2020-12-09 15:46:53 +0200
committerUri Shaked2020-12-09 15:49:41 +0200
commit9c1288f18889ae3bd10869a9f6ebc53defa3024b (patch)
tree1857fe48d3e2d32a39cfe810a0dfdd7d96526b3a /src/peripherals/timer.ts
parentrefactor: central interrupt handling #38 (diff)
downloadavr8js-9c1288f18889ae3bd10869a9f6ebc53defa3024b.tar.gz
avr8js-9c1288f18889ae3bd10869a9f6ebc53defa3024b.tar.bz2
avr8js-9c1288f18889ae3bd10869a9f6ebc53defa3024b.zip
perf!: centeral timekeeping
This should improve performance, especially when running simulations with multiple peripherals. For instance, the demo project now runs at ~322%, up from ~185% in AVR8js 0.13.1. BREAKING CHANGE: `tick()` methods were removed from individual peripherals. You now need to call `cpu.tick()` instead.
Diffstat (limited to 'src/peripherals/timer.ts')
-rw-r--r--src/peripherals/timer.ts30
1 files changed, 25 insertions, 5 deletions
diff --git a/src/peripherals/timer.ts b/src/peripherals/timer.ts
index 81c1e47..b8a6668 100644
--- a/src/peripherals/timer.ts
+++ b/src/peripherals/timer.ts
@@ -245,6 +245,7 @@ export class AVRTimer {
private timerMode: TimerMode;
private topValue: TimerTopValue;
private tcnt: u16 = 0;
+ private tcntNext: u16 = 0;
private compA: CompBitsValue;
private compB: CompBitsValue;
private tcntUpdated = false;
@@ -280,7 +281,7 @@ export class AVRTimer {
constructor(private cpu: CPU, private config: AVRTimerConfig) {
this.updateWGMConfig();
this.cpu.readHooks[config.TCNT] = (addr: u8) => {
- this.tick();
+ this.count(false);
if (this.config.bits === 16) {
this.cpu.data[addr + 1] = this.tcnt >> 8;
}
@@ -288,9 +289,10 @@ export class AVRTimer {
};
this.cpu.writeHooks[config.TCNT] = (value: u8) => {
- this.tcnt = (this.highByteTemp << 8) | value;
+ this.tcntNext = (this.highByteTemp << 8) | value;
this.countingUp = true;
this.tcntUpdated = true;
+ this.cpu.updateClockEvent(this.count, 0);
this.timerUpdated();
};
this.cpu.writeHooks[config.OCRA] = (value: u8) => {
@@ -324,8 +326,10 @@ export class AVRTimer {
};
cpu.writeHooks[config.TCCRB] = (value) => {
this.cpu.data[config.TCCRB] = value;
- this.tcntUpdated = true;
this.divider = this.config.dividers[this.CS];
+ this.reschedule();
+ this.tcntUpdated = true;
+ this.cpu.updateClockEvent(this.count, 0);
this.updateWGMConfig();
return true;
};
@@ -348,6 +352,11 @@ export class AVRTimer {
this.lastCycle = 0;
this.ocrA = 0;
this.ocrB = 0;
+ this.icr = 0;
+ this.tcnt = 0;
+ this.tcntNext = 0;
+ this.tcntUpdated = false;
+ this.countingUp = false;
}
get TCCRA() {
@@ -389,7 +398,7 @@ export class AVRTimer {
this.topValue = topValue;
}
- tick() {
+ count = (reschedule = true) => {
const { divider, lastCycle } = this;
const delta = this.cpu.cycles - lastCycle;
if (divider && delta >= divider) {
@@ -411,7 +420,18 @@ export class AVRTimer {
this.cpu.setInterruptFlag(this.OVF);
}
}
- this.tcntUpdated = false;
+ if (this.tcntUpdated) {
+ this.tcnt = this.tcntNext;
+ this.tcntUpdated = false;
+ }
+ if (reschedule) {
+ this.cpu.addClockEvent(this.count, this.lastCycle + divider - this.cpu.cycles);
+ }
+ };
+
+ private reschedule() {
+ this.cpu.clearClockEvent(this.count);
+ this.cpu.addClockEvent(this.count, this.lastCycle + this.divider - this.cpu.cycles);
}
private phasePwmCount(value: u16, delta: u8) {