From 14dfcef719d06eec1dec34219607f84406f7e02b Mon Sep 17 00:00:00 2001 From: Uri Shaked Date: Mon, 21 Dec 2020 17:07:04 +0200 Subject: fix(timer): Output Compare issue #74 output compare doesn't work when the OCR register (OCRnA/OCRnB) equals to 0 fix #74 --- src/peripherals/timer.spec.ts | 29 +++++++++++++++++++++++------ src/peripherals/timer.ts | 9 +++++---- 2 files changed, 28 insertions(+), 10 deletions(-) (limited to 'src/peripherals') diff --git a/src/peripherals/timer.spec.ts b/src/peripherals/timer.spec.ts index 583e759..1b4d4d7 100644 --- a/src/peripherals/timer.spec.ts +++ b/src/peripherals/timer.spec.ts @@ -112,7 +112,7 @@ describe('timer', () => { cpu.tick(); const tcnt = cpu.readData(TCNT0); expect(tcnt).toEqual(0); - expect(cpu.data[TIFR0]).toEqual(TOV0); + expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); }); it('should clear the TOV flag when writing 1 to the TOV bit, and not trigger the interrupt', () => { @@ -124,9 +124,9 @@ describe('timer', () => { cpu.tick(); cpu.cycles = 2; cpu.tick(); - expect(cpu.data[TIFR0]).toEqual(TOV0); + expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); cpu.writeData(TIFR0, TOV0); - expect(cpu.data[TIFR0]).toEqual(0); + expect(cpu.data[TIFR0] & TOV0).toEqual(0); }); it('should set TOV if timer overflows in FAST PWM mode', () => { @@ -142,7 +142,7 @@ describe('timer', () => { cpu.tick(); const tcnt = cpu.readData(TCNT0); expect(tcnt).toEqual(0); - expect(cpu.data[TIFR0]).toEqual(TOV0); + expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); }); it('should generate an overflow interrupt if timer overflows and interrupts enabled', () => { @@ -202,7 +202,7 @@ describe('timer', () => { cpu.data[SREG] = 0x0; // SREG: -------- cpu.cycles = 2; cpu.tick(); - expect(cpu.data[TIFR0]).toEqual(TOV0); + expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); expect(cpu.pc).toEqual(0); expect(cpu.cycles).toEqual(2); }); @@ -218,7 +218,24 @@ describe('timer', () => { cpu.data[SREG] = 0x80; // SREG: I------- cpu.cycles = 2; cpu.tick(); - expect(cpu.data[TIFR0]).toEqual(TOV0); + expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); + expect(cpu.pc).toEqual(0); + expect(cpu.cycles).toEqual(2); + }); + + it('should set OCF0A/B flags when OCRA/B == 0 and the timer equals to OCRA (issue #74)', () => { + const cpu = new CPU(new Uint16Array(0x1000)); + new AVRTimer(cpu, timer0Config); + cpu.writeData(TCNT0, 0xff); + cpu.writeData(OCR0A, 0x0); + cpu.writeData(OCR0B, 0x0); + cpu.writeData(TCCR0A, 0x0); // WGM: Normal + cpu.writeData(TCCR0B, CS00); // Set prescaler to 1 + cpu.cycles = 1; + cpu.tick(); + cpu.cycles = 2; + cpu.tick(); + expect(cpu.data[TIFR0] & (OCF0A | OCF0B)).toEqual(OCF0A | OCF0B); expect(cpu.pc).toEqual(0); expect(cpu.cycles).toEqual(2); }); diff --git a/src/peripherals/timer.ts b/src/peripherals/timer.ts index f10a49b..71c1982 100644 --- a/src/peripherals/timer.ts +++ b/src/peripherals/timer.ts @@ -299,7 +299,9 @@ export class AVRTimer { this.countingUp = true; this.tcntUpdated = true; this.cpu.updateClockEvent(this.count, 0); - this.timerUpdated(); + if (this.divider) { + this.timerUpdated(); + } }; this.cpu.writeHooks[config.OCRA] = (value: u8) => { this.nextOcrA = (this.highByteTemp << 8) | value; @@ -498,14 +500,13 @@ export class AVRTimer { private timerUpdated() { const value = this.tcnt; - - if (this.ocrA && value === this.ocrA) { + if (value === this.ocrA) { this.cpu.setInterruptFlag(this.OCFA); if (this.compA) { this.updateCompPin(this.compA, 'A'); } } - if (this.ocrB && value === this.ocrB) { + if (value === this.ocrB) { this.cpu.setInterruptFlag(this.OCFB); if (this.compB) { this.updateCompPin(this.compB, 'B'); -- cgit v1.2.3