Skip to content

Commit 19e53fa

Browse files
committed
fix(timer): delay() is inaccurate #81
fix #81
1 parent cdc8bd9 commit 19e53fa

File tree

2 files changed

+26
-21
lines changed

2 files changed

+26
-21
lines changed

src/peripherals/timer.spec.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,20 @@ describe('timer', () => {
101101
expect(tcnt).toEqual(0); // TCNT should stay 0
102102
});
103103

104-
it('should set the TOV flag when timer reaches the TOP value', () => {
104+
it('should set the TOV flag when timer wraps above TOP value', () => {
105105
const cpu = new CPU(new Uint16Array(0x1000));
106106
new AVRTimer(cpu, timer0Config);
107107
cpu.writeData(TCNT0, 0xff);
108108
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
109+
109110
cpu.cycles = 1;
110111
cpu.tick();
111112
expect(cpu.readData(TCNT0)).toEqual(0xff);
113+
expect(cpu.data[TIFR0] & TOV0).toEqual(0);
114+
115+
cpu.cycles++;
116+
cpu.tick();
117+
expect(cpu.readData(TCNT0)).toEqual(0);
112118
expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0);
113119
});
114120

@@ -294,11 +300,13 @@ describe('timer', () => {
294300
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
295301
cpu.cycles = 1;
296302
cpu.tick();
297-
cpu.cycles = 2;
303+
cpu.cycles++;
304+
cpu.tick();
305+
cpu.cycles++;
298306
cpu.tick();
299307
const tcnt = cpu.readData(TCNT0);
300-
expect(tcnt).toEqual(0x1f);
301-
expect(cpu.data[TIFR0]).toEqual(OCF0A); // TOV0 clear
308+
expect(tcnt).toEqual(0);
309+
expect(cpu.data[TIFR0] & TOV0).toEqual(0); // TOV0 clear
302310
});
303311

304312
it('should set the TOV bit when TOP == MAX in CTC mode (issue #75)', () => {
@@ -310,11 +318,16 @@ describe('timer', () => {
310318
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
311319
cpu.cycles = 1;
312320
cpu.tick();
313-
cpu.cycles = 2;
321+
322+
cpu.cycles++;
314323
cpu.tick();
315-
const tcnt = cpu.readData(TCNT0);
316-
expect(tcnt).toEqual(0xff);
317-
expect(cpu.data[TIFR0]).toEqual(OCF0A | TOV0);
324+
expect(cpu.readData(TCNT0)).toEqual(0xff);
325+
expect(cpu.data[TIFR0] & TOV0).toEqual(0); // TOV clear
326+
327+
cpu.cycles++;
328+
cpu.tick();
329+
expect(cpu.readData(TCNT0)).toEqual(0);
330+
expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); // TOV set
318331
});
319332

320333
it('should not set the TOV bit twice on overflow (issue #80)', () => {
@@ -328,16 +341,15 @@ describe('timer', () => {
328341
cpu.cycles = 1;
329342
cpu.tick();
330343

331-
cpu.cycles = 2;
344+
cpu.cycles++;
332345
cpu.tick();
333346
expect(cpu.readData(TCNT0)).toEqual(0xff);
334-
expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0);
335-
cpu.data[TIFR0] &= ~TOV0; // Clear the TOV0 bit
347+
expect(cpu.data[TIFR0] & TOV0).toEqual(0); // TOV clear
336348

337-
cpu.cycles = 3;
349+
cpu.cycles++;
338350
cpu.tick();
339351
expect(cpu.readData(TCNT0)).toEqual(0);
340-
expect(cpu.data[TIFR0] & TOV0).toEqual(0);
352+
expect(cpu.data[TIFR0] & TOV0).toEqual(TOV0); // TOV set
341353
});
342354

343355
it('should set OCF0B flag when timer equals OCRB', () => {

src/peripherals/timer.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -481,20 +481,13 @@ export class AVRTimer {
481481

482482
// OCRUpdateMode.Bottom only occurs in Phase Correct modes, handled by phasePwmCount().
483483
// Thus we only handle TOVUpdateMode.Top or TOVUpdateMode.Max here.
484-
if (
485-
(newVal === TOP || (overflow && val < TOP)) &&
486-
(this.tovUpdateMode == TOVUpdateMode.Top || TOP === this.MAX)
487-
) {
484+
if (overflow && (this.tovUpdateMode == TOVUpdateMode.Top || TOP === this.MAX)) {
488485
cpu.setInterruptFlag(this.OVF);
489486
}
490487
}
491488
}
492489
if (this.tcntUpdated) {
493-
const { TOP } = this;
494490
this.tcnt = this.tcntNext;
495-
if (this.tcnt === TOP && (this.tovUpdateMode == TOVUpdateMode.Top || TOP === this.MAX)) {
496-
cpu.setInterruptFlag(this.OVF);
497-
}
498491
this.tcntUpdated = false;
499492
}
500493
if (this.updateDivider) {

0 commit comments

Comments
 (0)