aboutsummaryrefslogtreecommitdiff
path: root/src/peripherals/timer.spec.ts
diff options
context:
space:
mode:
authorUri Shaked2020-12-26 00:24:54 +0200
committerUri Shaked2020-12-26 00:24:54 +0200
commit02e5b211c6e31ca8f9ec19ff6ec52d4f5bbef568 (patch)
tree67a624b2baf932d2dfe7ef709ac32ead8e423ff8 /src/peripherals/timer.spec.ts
parent0.14.6 (diff)
downloadavr8js-02e5b211c6e31ca8f9ec19ff6ec52d4f5bbef568.tar.gz
avr8js-02e5b211c6e31ca8f9ec19ff6ec52d4f5bbef568.tar.bz2
avr8js-02e5b211c6e31ca8f9ec19ff6ec52d4f5bbef568.zip
fix(timer): Overflow interrupt fires twice #80
fix #80
Diffstat (limited to '')
-rw-r--r--src/peripherals/timer.spec.ts46
1 files changed, 40 insertions, 6 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);