aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/peripherals/gpio.spec.ts14
-rw-r--r--src/peripherals/gpio.ts16
2 files changed, 22 insertions, 8 deletions
diff --git a/src/peripherals/gpio.spec.ts b/src/peripherals/gpio.spec.ts
index 692deaa..31963a9 100644
--- a/src/peripherals/gpio.spec.ts
+++ b/src/peripherals/gpio.spec.ts
@@ -1,5 +1,5 @@
import { CPU } from '../cpu/cpu';
-import { AVRIOPort, portBConfig, PinState, portDConfig } from './gpio';
+import { AVRIOPort, portBConfig, PinState, portDConfig, PinOverrideMode } from './gpio';
// CPU registers
const SREG = 95;
@@ -76,6 +76,18 @@ describe('GPIO', () => {
expect(cpu.data[PINB]).toEqual(0x4); // PINB should return port value
});
+ it('should update the PIN register on output compare (OCR) match (issue #102)', () => {
+ const cpu = new CPU(new Uint16Array(1024));
+ const port = new AVRIOPort(cpu, portBConfig);
+ cpu.writeData(DDRB, 1 << 1);
+ cpu.gpioTimerHooks[PORTB](1, PinOverrideMode.Set, PORTB);
+ expect(port.pinState(1)).toBe(PinState.High);
+ expect(cpu.data[PINB]).toBe(1 << 1);
+ cpu.gpioTimerHooks[PORTB](1, PinOverrideMode.Clear, PORTB);
+ expect(port.pinState(1)).toBe(PinState.Low);
+ expect(cpu.data[PINB]).toBe(0);
+ });
+
describe('removeListener', () => {
it('should remove the given listener', () => {
const cpu = new CPU(new Uint16Array(1024));
diff --git a/src/peripherals/gpio.ts b/src/peripherals/gpio.ts
index f787c23..bf5e53c 100644
--- a/src/peripherals/gpio.ts
+++ b/src/peripherals/gpio.ts
@@ -213,15 +213,15 @@ export class AVRIOPort {
cpu.writeHooks[portConfig.DDR] = (value: u8) => {
const portValue = cpu.data[portConfig.PORT];
cpu.data[portConfig.DDR] = value;
- this.updatePinRegister(portValue, value);
this.writeGpio(portValue, value);
+ this.updatePinRegister(value);
return true;
};
cpu.writeHooks[portConfig.PORT] = (value: u8) => {
const ddrMask = cpu.data[portConfig.DDR];
cpu.data[portConfig.PORT] = value;
- this.updatePinRegister(value, ddrMask);
this.writeGpio(value, ddrMask);
+ this.updatePinRegister(ddrMask);
return true;
};
cpu.writeHooks[portConfig.PIN] = (value: u8) => {
@@ -230,8 +230,8 @@ export class AVRIOPort {
const ddrMask = cpu.data[portConfig.DDR];
const portValue = oldPortValue ^ value;
cpu.data[portConfig.PORT] = portValue;
- this.updatePinRegister(portValue, ddrMask);
this.writeGpio(portValue, ddrMask);
+ this.updatePinRegister(ddrMask);
return true;
};
// The following hook is used by the timer compare output to override GPIO pins:
@@ -258,7 +258,9 @@ export class AVRIOPort {
break;
}
}
- this.writeGpio(cpu.data[portConfig.PORT], cpu.data[portConfig.DDR]);
+ const ddrMask = cpu.data[portConfig.DDR];
+ this.writeGpio(cpu.data[portConfig.PORT], ddrMask);
+ this.updatePinRegister(ddrMask);
};
// External interrupts
@@ -355,11 +357,11 @@ export class AVRIOPort {
if (value) {
this.pinValue |= bitMask;
}
- this.updatePinRegister(this.cpu.data[this.portConfig.PORT], this.cpu.data[this.portConfig.DDR]);
+ this.updatePinRegister(this.cpu.data[this.portConfig.DDR]);
}
- private updatePinRegister(port: u8, ddr: u8) {
- const newPin = (this.pinValue & ~ddr) | (port & ddr);
+ private updatePinRegister(ddr: u8) {
+ const newPin = (this.pinValue & ~ddr) | (this.lastValue & ddr);
this.cpu.data[this.portConfig.PIN] = newPin;
if (this.lastPin !== newPin) {
for (let index = 0; index < 8; index++) {