aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorUri Shaked2020-12-25 01:45:03 +0200
committerUri Shaked2020-12-25 01:45:03 +0200
commitcf6d4910d1cd320b93d26548fcd500a8b1b2864b (patch)
tree981d9ff79688b2f68c58243a4699819729bb6137 /src
parent0.14.5 (diff)
downloadavr8js-cf6d4910d1cd320b93d26548fcd500a8b1b2864b.tar.gz
avr8js-cf6d4910d1cd320b93d26548fcd500a8b1b2864b.tar.bz2
avr8js-cf6d4910d1cd320b93d26548fcd500a8b1b2864b.zip
fix(timer): Output Compare sometimes misses Compare Match #79
fix #79
Diffstat (limited to 'src')
-rw-r--r--src/peripherals/timer.spec.ts31
-rw-r--r--src/peripherals/timer.ts20
2 files changed, 45 insertions, 6 deletions
diff --git a/src/peripherals/timer.spec.ts b/src/peripherals/timer.spec.ts
index 1b4d4d7..cdb2c4c 100644
--- a/src/peripherals/timer.spec.ts
+++ b/src/peripherals/timer.spec.ts
@@ -541,6 +541,37 @@ describe('timer', () => {
expect(gpioCallback).toHaveBeenCalledWith(6, PinOverrideMode.Set, 0x2b);
});
+ it('should not miss Compare Match when executing multi-cycle instruction (issue #79)', () => {
+ const { program, instructionCount } = asmProgram(`
+ LDI r16, 0x10 ; OCR0A = 0x10; // <- TOP value
+ OUT 0x27, r16
+ ; Set waveform generation mode (WGM) to normal, enable OC0A (Set on match)
+ LDI r16, 0xc0 ; TCCR0A = (1 << COM0A1) | (1 << COM0A0);
+ OUT 0x24, r16
+ LDI r16, 0x1 ; TCCR0B = (1 << CS00);
+ OUT 0x25, r16
+ LDI r16, 0xf ; TCNT0 = 0xf;
+ OUT 0x26, r16
+ RJMP 1 ; TCNT0 will be 0x11 (RJMP takes 2 cycles)
+ `);
+
+ const cpu = new CPU(program);
+ new AVRTimer(cpu, timer0Config);
+
+ // Listen to Port D's internal callback
+ const gpioCallback = jest.fn();
+ cpu.gpioTimerHooks[PORTD] = gpioCallback;
+
+ const runner = new TestProgramRunner(cpu);
+ runner.runInstructions(instructionCount);
+
+ expect(cpu.readData(TCNT0)).toEqual(0x11);
+ expect(gpioCallback).toHaveBeenCalledWith(6, PinOverrideMode.Enable, 0x2b);
+
+ // Verify that Compare Match has occured and set the OC0A pin (PD6 on ATmega328p)
+ expect(gpioCallback).toHaveBeenCalledWith(6, PinOverrideMode.Set, 0x2b);
+ });
+
it('should only update OCR0A when TCNT0=TOP in PWM Phase Correct mode (issue #76)', () => {
const { program, instructionCount } = asmProgram(`
LDI r16, 0x4 ; OCR0A = 0x4;
diff --git a/src/peripherals/timer.ts b/src/peripherals/timer.ts
index 71c1982..957aa78 100644
--- a/src/peripherals/timer.ts
+++ b/src/peripherals/timer.ts
@@ -300,7 +300,7 @@ export class AVRTimer {
this.tcntUpdated = true;
this.cpu.updateClockEvent(this.count, 0);
if (this.divider) {
- this.timerUpdated();
+ this.timerUpdated(this.tcntNext, this.tcntNext);
}
};
this.cpu.writeHooks[config.OCRA] = (value: u8) => {
@@ -432,7 +432,7 @@ export class AVRTimer {
// A CPU write overrides (has priority over) all counter clear or count operations.
if (!this.tcntUpdated) {
this.tcnt = newVal;
- this.timerUpdated();
+ this.timerUpdated(newVal, val);
}
if (!phasePwm) {
@@ -498,15 +498,23 @@ export class AVRTimer {
return value;
}
- private timerUpdated() {
- const value = this.tcnt;
- if (value === this.ocrA) {
+ private timerUpdated(value: number, prevValue: number) {
+ const { ocrA, ocrB, countingUp } = this;
+ if (
+ (countingUp && prevValue < ocrA && value >= ocrA) ||
+ (countingUp && prevValue > value && ocrA >= value) ||
+ (!countingUp && prevValue > ocrA && value <= ocrA)
+ ) {
this.cpu.setInterruptFlag(this.OCFA);
if (this.compA) {
this.updateCompPin(this.compA, 'A');
}
}
- if (value === this.ocrB) {
+ if (
+ (countingUp && prevValue < ocrB && value >= ocrB) ||
+ (countingUp && prevValue > value && ocrB >= value) ||
+ (!countingUp && prevValue > ocrB && value <= ocrB)
+ ) {
this.cpu.setInterruptFlag(this.OCFB);
if (this.compB) {
this.updateCompPin(this.compB, 'B');
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.