aboutsummaryrefslogtreecommitdiff
path: root/src/peripherals
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/peripherals/timer.spec.ts46
-rw-r--r--src/peripherals/timer.ts6
2 files changed, 45 insertions, 7 deletions
diff --git a/src/peripherals/timer.spec.ts b/src/peripherals/timer.spec.ts
index cdb2c4c..3b5026c 100644
--- a/src/peripherals/timer.spec.ts
+++ b/src/peripherals/timer.spec.ts
@@ -101,17 +101,28 @@ describe('timer', () => {
expect(tcnt).toEqual(0); // TCNT should stay 0
});
- it('should set TOV if timer overflows', () => {
+ it('should set the TOV flag when timer reaches the 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();
- cpu.cycles = 2;
+ expect(cpu.readData(TCNT0)).toEqual(0xff);
+ expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0);
+ });
+
+ it('should set the TOV if timer overflows past TOP without reaching TOP', () => {
+ const cpu = new CPU(new Uint16Array(0x1000));
+ new AVRTimer(cpu, timer0Config);
+ cpu.writeData(TCNT0, 0xfe);
+ cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
+ cpu.cycles = 1;
cpu.tick();
- const tcnt = cpu.readData(TCNT0);
- expect(tcnt).toEqual(0);
+ expect(cpu.readData(TCNT0)).toEqual(0xfe);
+ cpu.cycles += 4;
+ cpu.tick();
+ expect(cpu.readData(TCNT0)).toEqual(0x2);
expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0);
});
@@ -152,7 +163,7 @@ describe('timer', () => {
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
cpu.cycles = 1;
cpu.tick();
- cpu.data[TIMSK0] = TOIE0;
+ cpu.writeData(TIMSK0, TOIE0);
cpu.data[SREG] = 0x80; // SREG: I-------
cpu.cycles = 2;
cpu.tick();
@@ -180,7 +191,7 @@ describe('timer', () => {
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
cpu.cycles = 1;
cpu.tick();
- cpu.data[TIMSK0] = 2;
+ cpu.writeData(TIMSK0, 2);
cpu.data[SREG] = 0x80; // SREG: I-------
cpu.cycles = 2;
cpu.tick();
@@ -305,6 +316,29 @@ describe('timer', () => {
expect(cpu.data[TIFR0]).toEqual(OCF0A | TOV0);
});
+ it('should not set the TOV bit twice on overflow (issue #80)', () => {
+ const cpu = new CPU(new Uint16Array(0x1000));
+ new AVRTimer(cpu, timer0Config);
+ cpu.writeData(TCNT0, 0xfe);
+ cpu.writeData(OCR0A, 0xff);
+ cpu.writeData(TCCR0A, WGM01); // WGM: CTC
+ cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
+
+ cpu.cycles = 1;
+ cpu.tick();
+
+ cpu.cycles = 2;
+ cpu.tick();
+ expect(cpu.readData(TCNT0)).toEqual(0xff);
+ expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0);
+ cpu.data[TIFR0] &= ~TOV0; // Clear the TOV0 bit
+
+ cpu.cycles = 3;
+ cpu.tick();
+ expect(cpu.readData(TCNT0)).toEqual(0);
+ expect(cpu.data[TIFR0] & TOV0).toEqual(0);
+ });
+
it('should set OCF0B flag when timer equals OCRB', () => {
const cpu = new CPU(new Uint16Array(0x1000));
new AVRTimer(cpu, timer0Config);
diff --git a/src/peripherals/timer.ts b/src/peripherals/timer.ts
index 957aa78..6ea29e3 100644
--- a/src/peripherals/timer.ts
+++ b/src/peripherals/timer.ts
@@ -445,7 +445,7 @@ 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) &&
+ (newVal === TOP || (overflow && val < TOP)) &&
(this.tovUpdateMode == TOVUpdateMode.Top || TOP === this.MAX)
) {
cpu.setInterruptFlag(this.OVF);
@@ -453,7 +453,11 @@ export class AVRTimer {
}
}
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.