aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUri Shaked2020-12-29 20:33:25 +0200
committerUri Shaked2020-12-29 20:33:25 +0200
commit19e53fa42473b13271768894b250cd897edcd1f5 (patch)
treeb72d3b97a11d22ff1ef0f307c96edcbbecb3cba2
parent0.14.8 (diff)
downloadavr8js-19e53fa42473b13271768894b250cd897edcd1f5.tar.gz
avr8js-19e53fa42473b13271768894b250cd897edcd1f5.tar.bz2
avr8js-19e53fa42473b13271768894b250cd897edcd1f5.zip
fix(timer): delay() is inaccurate #81
fix #81
-rw-r--r--src/peripherals/timer.spec.ts38
-rw-r--r--src/peripherals/timer.ts9
2 files changed, 26 insertions, 21 deletions
diff --git a/src/peripherals/timer.spec.ts b/src/peripherals/timer.spec.ts
index 1fa0dc6..68f6a66 100644
--- a/src/peripherals/timer.spec.ts
+++ b/src/peripherals/timer.spec.ts
@@ -101,14 +101,20 @@ describe('timer', () => {
expect(tcnt).toEqual(0); // TCNT should stay 0
});
- it('should set the TOV flag when timer reaches the TOP value', () => {
+ it('should set the TOV flag when timer wraps above TOP value', () => {
const cpu = new CPU(new Uint16Array(0x1000));
new AVRTimer(cpu, timer0Config);
cpu.writeData(TCNT0, 0xff);
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
+
cpu.cycles = 1;
cpu.tick();
expect(cpu.readData(TCNT0)).toEqual(0xff);
+ expect(cpu.data[TIFR0] & TOV0).toEqual(0);
+
+ cpu.cycles++;
+ cpu.tick();
+ expect(cpu.readData(TCNT0)).toEqual(0);
expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0);
});
@@ -294,11 +300,13 @@ describe('timer', () => {
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
cpu.cycles = 1;
cpu.tick();
- cpu.cycles = 2;
+ cpu.cycles++;
+ cpu.tick();
+ cpu.cycles++;
cpu.tick();
const tcnt = cpu.readData(TCNT0);
- expect(tcnt).toEqual(0x1f);
- expect(cpu.data[TIFR0]).toEqual(OCF0A); // TOV0 clear
+ expect(tcnt).toEqual(0);
+ expect(cpu.data[TIFR0] & TOV0).toEqual(0); // TOV0 clear
});
it('should set the TOV bit when TOP == MAX in CTC mode (issue #75)', () => {
@@ -310,11 +318,16 @@ describe('timer', () => {
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
cpu.cycles = 1;
cpu.tick();
- cpu.cycles = 2;
+
+ cpu.cycles++;
cpu.tick();
- const tcnt = cpu.readData(TCNT0);
- expect(tcnt).toEqual(0xff);
- expect(cpu.data[TIFR0]).toEqual(OCF0A | TOV0);
+ expect(cpu.readData(TCNT0)).toEqual(0xff);
+ expect(cpu.data[TIFR0] & TOV0).toEqual(0); // TOV clear
+
+ cpu.cycles++;
+ cpu.tick();
+ expect(cpu.readData(TCNT0)).toEqual(0);
+ expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); // TOV set
});
it('should not set the TOV bit twice on overflow (issue #80)', () => {
@@ -328,16 +341,15 @@ describe('timer', () => {
cpu.cycles = 1;
cpu.tick();
- cpu.cycles = 2;
+ cpu.cycles++;
cpu.tick();
expect(cpu.readData(TCNT0)).toEqual(0xff);
- expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0);
- cpu.data[TIFR0] &= ~TOV0; // Clear the TOV0 bit
+ expect(cpu.data[TIFR0] & TOV0).toEqual(0); // TOV clear
- cpu.cycles = 3;
+ cpu.cycles++;
cpu.tick();
expect(cpu.readData(TCNT0)).toEqual(0);
- expect(cpu.data[TIFR0] & TOV0).toEqual(0);
+ expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); // TOV set
});
it('should set OCF0B flag when timer equals OCRB', () => {
diff --git a/src/peripherals/timer.ts b/src/peripherals/timer.ts
index b1a64d9..e620459 100644
--- a/src/peripherals/timer.ts
+++ b/src/peripherals/timer.ts
@@ -481,20 +481,13 @@ export class AVRTimer {
// OCRUpdateMode.Bottom only occurs in Phase Correct modes, handled by phasePwmCount().
// Thus we only handle TOVUpdateMode.Top or TOVUpdateMode.Max here.
- if (
- (newVal === TOP || (overflow && val < TOP)) &&
- (this.tovUpdateMode == TOVUpdateMode.Top || TOP === this.MAX)
- ) {
+ if (overflow && (this.tovUpdateMode == TOVUpdateMode.Top || TOP === this.MAX)) {
cpu.setInterruptFlag(this.OVF);
}
}
}
if (this.tcntUpdated) {
- const { TOP } = this;
this.tcnt = this.tcntNext;
- if (this.tcnt === TOP && (this.tovUpdateMode == TOVUpdateMode.Top || TOP === this.MAX)) {
- cpu.setInterruptFlag(this.OVF);
- }
this.tcntUpdated = false;
}
if (this.updateDivider) {
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.