Skip to content

Commit

Permalink
test(timer): add more 16-bit timer tests
Browse files Browse the repository at this point in the history
also fix some issues found by @gfeun and the tests
  • Loading branch information
urish committed Apr 12, 2020
1 parent 619652d commit daf3ac7
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 13 deletions.
49 changes: 46 additions & 3 deletions src/peripherals/timer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
});
20 changes: 10 additions & 10 deletions src/peripherals/timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
}

Expand All @@ -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;
}
}

Expand All @@ -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() {
Expand All @@ -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;
}
Expand Down

0 comments on commit daf3ac7

Please sign in to comment.