Skip to content

Commit

Permalink
fix(timer): Phase Correct mode overruns #119
Browse files Browse the repository at this point in the history
  • Loading branch information
urish committed Mar 22, 2022
1 parent e6bf51a commit 67638ca
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 2 deletions.
52 changes: 52 additions & 0 deletions src/peripherals/timer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,58 @@ describe('timer', () => {
expect(cpu.readData(R17)).toEqual(0x4);
expect(cpu.readData(R18)).toEqual(0x1);
});

it('should update OCR0A when TCNT0=TOP and TOP=0 in PWM Phase Correct mode (issue #119)', () => {
const { program, instructionCount } = asmProgram(`
; Set waveform generation mode (WGM) to PWM, Phase Correct
LDI r16, 0x01 ; TCCR0A = (1 << WGM00);
OUT 0x24, r16
LDI r16, 0x09 ; TCCR0B = (1 << WGM02) | (1 << CS00);
OUT 0x25, r16
LDI r16, 0x0 ; TCNT0 = 0x0;
OUT 0x26, r16
IN r17, 0x26 ; R17 = TCNT; // TCNT0 should read 0x0
IN r18, 0x26 ; R18 = TCNT; // TCNT0 should read 0x0
LDI r16, 0x2 ; OCR0A = 0x2; // TCNT0 should read 0x0
OUT 0x27, r16 ; // TCNT0 should read 0x1
NOP ; // TCNT0 should read 0x2
IN r19, 0x26 ; R19 = TCNT; // TCNT0 should read 0x1
`);

const cpu = new CPU(program);
new AVRTimer(cpu, timer0Config);

const runner = new TestProgramRunner(cpu);
runner.runInstructions(instructionCount);

expect(cpu.readData(R17)).toEqual(0);
expect(cpu.readData(R18)).toEqual(0);
expect(cpu.readData(R19)).toEqual(0x1);
});

it('should not overrun when TOP < current value in Phase Correct mode (issue #119)', () => {
const { program, instructionCount } = asmProgram(`
; Set waveform generation mode (WGM) to PWM, Phase Correct
LDI r16, 0x01 ; TCCR0A = (1 << WGM00);
OUT 0x24, r16
LDI r16, 0x09 ; TCCR0B = (1 << WGM02) | (1 << CS00);
OUT 0x25, r16
LDI r16, 0xff ; TCNT0 = 0xff;
OUT 0x26, r16
IN r17, 0x26 ; R17 = TCNT; // TCNT0 should read 255
`);

const cpu = new CPU(program);
const timer = new AVRTimer(cpu, timer0Config);

const runner = new TestProgramRunner(cpu);
runner.runInstructions(instructionCount);

expect(cpu.readData(R17)).toEqual(255);
expect(timer.debugTCNT).toEqual(0); // TCNT should wrap
});
});

describe('16 bit timers', () => {
Expand Down
17 changes: 15 additions & 2 deletions src/peripherals/timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,11 @@ export class AVRTimer {
}
}

/** Expose the raw value of TCNT, for use by the unit tests */
get debugTCNT() {
return this.tcnt;
}

private updateWGMConfig() {
const { config, WGM } = this;
const wgmModes = config.bits === 16 ? wgmModes16Bit : wgmModes8Bit;
Expand Down Expand Up @@ -637,7 +642,15 @@ export class AVRTimer {
};

private phasePwmCount(value: u16, delta: u8) {
const { ocrA, ocrB, ocrC, hasOCRC, TOP, tcntUpdated } = this;
const { ocrA, ocrB, ocrC, hasOCRC, TOP, MAX, tcntUpdated } = this;
if (!value && !TOP) {
delta = 0;
if (this.ocrUpdateMode === OCRUpdateMode.Top) {
this.ocrA = this.nextOcrA;
this.ocrB = this.nextOcrB;
this.ocrC = this.nextOcrC;
}
}
while (delta > 0) {
if (this.countingUp) {
value++;
Expand Down Expand Up @@ -683,7 +696,7 @@ export class AVRTimer {
}
delta--;
}
return value;
return value & MAX;
}

private timerUpdated(value: number, prevValue: number) {
Expand Down

0 comments on commit 67638ca

Please sign in to comment.