diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/peripherals/gpio.spec.ts | 14 | ||||
| -rw-r--r-- | src/peripherals/gpio.ts | 16 |
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++) { |
