From daf3ac7dbe4350f7bd87c009c719fbaef01a0ad5 Mon Sep 17 00:00:00 2001 From: Uri Shaked Date: Sun, 12 Apr 2020 23:45:42 +0300 Subject: test(timer): add more 16-bit timer tests also fix some issues found by @gfeun and the tests --- src/peripherals/timer.spec.ts | 49 ++++++++++++++++++++++++++++++++++++++++--- src/peripherals/timer.ts | 20 +++++++++--------- 2 files changed, 56 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/peripherals/timer.spec.ts b/src/peripherals/timer.spec.ts index 7750f26..9f50239 100644 --- a/src/peripherals/timer.spec.ts +++ b/src/peripherals/timer.spec.ts @@ -203,19 +203,62 @@ describe('timer', () => { }); describe('16 bit timers', () => { + it('should increment 16-bit TCNT by 1', () => { + const timer = new AVRTimer(cpu, timer1Config); + cpu.writeData(0x85, 0x22); // TCNT1 <- 0x2233 + cpu.writeData(0x84, 0x33); // ... + expect(timer.TCNT).toEqual(0x2233); + cpu.writeData(0x80, 0x0); // WGM1 <- 0 (Normal) + cpu.writeData(0x81, 0x1); // TCCR1B.CS <- 1 + cpu.cycles = 1; + timer.tick(); + expect(cpu.dataView.getUint16(0x84, true)).toEqual(0x2234); // TCNT1 should increment + }); + it('should set OCF0A flag when timer equals OCRA (16 bit mode)', () => { const timer = new AVRTimer(cpu, timer1Config); cpu.writeData(0x84, 0xee); // TCNT1 <- 0x10ee cpu.writeData(0x85, 0x10); // ... cpu.writeData(0x88, 0xef); // OCR1A <- 0x10ef cpu.writeData(0x89, 0x10); // ... - cpu.writeData(0x80, 0x0); // WGM1 <- 0 (Normal) - cpu.writeData(0x81, 0x1); // TCCR1B.CS <- 1 + cpu.writeData(0x80, 0x0); // TCCR1A <- 0 (Normal Mode) + cpu.writeData(0x81, 0x1); // TCCR1B <- CS10 cpu.cycles = 1; timer.tick(); - expect(cpu.data[0x36]).toEqual(2); // TIFR0 should have OCF0A bit on + expect(cpu.data[0x36]).toEqual(2); // TIFR1 should have OCF1A bit on expect(cpu.pc).toEqual(0); expect(cpu.cycles).toEqual(1); }); + + it('should generate an overflow interrupt if timer overflows and interrupts enabled', () => { + const timer = new AVRTimer(cpu, timer1Config); + cpu.writeData(0x85, 0x3); // TCNT1 <- 0x3ff + cpu.writeData(0x84, 0xff); // ... + cpu.writeData(0x80, 0x3); // TCCR1A <- WGM10 | WGM11 (Fast PWM, 10-bit) + cpu.writeData(0x81, 0x9); // TCCR1B <- WGM12 | CS10 + console.log(timer.CS); + cpu.data[0x6f] = 0x1; // TIMSK1: TOIE1 + cpu.data[95] = 0x80; // SREG: I------- + cpu.cycles = 1; + timer.tick(); + expect(cpu.dataView.getUint16(0x84, true)).toEqual(0); // TCNT should be 0 + expect(cpu.data[0x36]).toEqual(0); // TOV bit in TIFR should be clear + expect(cpu.pc).toEqual(0x1a); + expect(cpu.cycles).toEqual(3); + }); + + it('should reset the timer once it reaches ICR value in mode 12', () => { + const timer = new AVRTimer(cpu, timer1Config); + cpu.writeData(0x85, 0x50); // TCNT1 <- 0x500f + cpu.writeData(0x84, 0x0f); // ... + cpu.writeData(0x87, 0x50); // ICR1 <- 0x5010 + cpu.writeData(0x86, 0x10); // ... + cpu.writeData(0x81, 0x19); // TCCR1B <- WGM13 | WGM12 | CS10 + cpu.cycles = 2; // 2 cycles should increment timer twice, beyond ICR1 + timer.tick(); + expect(cpu.dataView.getUint16(0x84, true)).toEqual(0); // TCNT should be 0 + expect(cpu.data[0x36]).toEqual(0); // TOV bit in TIFR should be clear + expect(cpu.cycles).toEqual(2); + }); }); }); diff --git a/src/peripherals/timer.ts b/src/peripherals/timer.ts index ea66671..6e805ee 100644 --- a/src/peripherals/timer.ts +++ b/src/peripherals/timer.ts @@ -206,11 +206,15 @@ export class AVRTimer { this.registerHook(config.OCRB, (value: u16) => { this.ocrB = value; }); - cpu.writeHooks[config.TCCRA] = () => { + cpu.writeHooks[config.TCCRA] = (value) => { + this.cpu.data[config.TCCRA] = value; this.updateWGMConfig(); + return true; }; - cpu.writeHooks[config.TCCRB] = () => { + cpu.writeHooks[config.TCCRB] = (value) => { + this.cpu.data[config.TCCRB] = value; this.updateWGMConfig(); + return true; }; } @@ -237,7 +241,7 @@ export class AVRTimer { set TCNT(value: u16) { this.cpu.data[this.config.TCNT] = value & 0xff; if (this.config.bits === 16) { - this.cpu.data[this.config.TCNT + 1] = (value >> 16) & 0xff; + this.cpu.data[this.config.TCNT + 1] = (value >> 8) & 0xff; } } @@ -255,7 +259,7 @@ export class AVRTimer { get ICR() { // Only available for 16-bit timers - return this.cpu.data[this.config.ICR]; + return (this.cpu.data[this.config.ICR + 1] << 8) | this.cpu.data[this.config.ICR]; } get CS() { @@ -280,12 +284,8 @@ export class AVRTimer { private registerHook(address: number, hook: (value: u16) => void) { if (this.config.bits === 16) { - this.cpu.writeHooks[address] = (value: u8) => { - hook(this.cpu.data[address + 1] | value); - }; - this.cpu.writeHooks[address + 1] = (value: u8) => { - hook((value << 8) | this.cpu.data[address]); - }; + this.cpu.writeHooks[address] = (value: u8) => hook((this.cpu.data[address + 1] << 8) | value); + this.cpu.writeHooks[address + 1] = (value: u8) => hook((value << 8) | this.cpu.data[address]); } else { this.cpu.writeHooks[address] = hook; } -- cgit v1.2.3