aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/peripherals/gpio.spec.ts23
-rw-r--r--src/peripherals/gpio.ts20
2 files changed, 43 insertions, 0 deletions
diff --git a/src/peripherals/gpio.spec.ts b/src/peripherals/gpio.spec.ts
index f3b1a0f..1dfaf7d 100644
--- a/src/peripherals/gpio.spec.ts
+++ b/src/peripherals/gpio.spec.ts
@@ -93,4 +93,27 @@ describe('GPIO', () => {
expect(listener).toHaveBeenCalled();
});
});
+
+ describe('setPin', () => {
+ it('should set the value of the given pin', () => {
+ const cpu = new CPU(new Uint16Array(1024));
+ const port = new AVRIOPort(cpu, portBConfig);
+ cpu.writeData(0x24, 0); // DDRB <- 0
+ port.setPin(4, true);
+ expect(cpu.data[0x23]).toEqual(0x10);
+ port.setPin(4, false);
+ expect(cpu.data[0x23]).toEqual(0x0);
+ });
+
+ it('should only update PIN register when pin in Input mode', () => {
+ const cpu = new CPU(new Uint16Array(1024));
+ const port = new AVRIOPort(cpu, portBConfig);
+ cpu.writeData(0x24, 0x10); // DDRB <- 0x10
+ cpu.writeData(0x25, 0x0); // PORTB <- 0x0
+ port.setPin(4, true);
+ expect(cpu.data[0x23]).toEqual(0x0);
+ cpu.writeData(0x24, 0x0); // DDRB <- 0x0
+ expect(cpu.data[0x23]).toEqual(0x10);
+ });
+ });
});
diff --git a/src/peripherals/gpio.ts b/src/peripherals/gpio.ts
index ba3217b..e3c8eaa 100644
--- a/src/peripherals/gpio.ts
+++ b/src/peripherals/gpio.ts
@@ -92,10 +92,12 @@ export enum PinState {
export class AVRIOPort {
private listeners: GPIOListener[] = [];
+ private pinValue: u8 = 0;
constructor(private cpu: CPU, private portConfig: AVRPortConfig) {
cpu.writeHooks[portConfig.DDR] = (value, oldValue) => {
const portValue = cpu.data[portConfig.PORT];
+ this.updatePinRegister(portValue, value);
this.writeGpio(value & portValue, oldValue & oldValue);
};
cpu.writeHooks[portConfig.PORT] = (value: u8, oldValue: u8) => {
@@ -103,6 +105,7 @@ export class AVRIOPort {
cpu.data[portConfig.PORT] = value;
value &= ddrMask;
cpu.data[portConfig.PIN] = (cpu.data[portConfig.PIN] & ~ddrMask) | value;
+ this.updatePinRegister(value, ddrMask);
this.writeGpio(value, oldValue & ddrMask);
return true;
};
@@ -145,6 +148,23 @@ export class AVRIOPort {
}
}
+ /**
+ * Sets the input value for the given pin. This is the value that
+ * will be returned when reading from the PIN register.
+ */
+ setPin(index: number, value: boolean) {
+ const bitMask = 1 << index;
+ this.pinValue &= ~bitMask;
+ if (value) {
+ this.pinValue |= bitMask;
+ }
+ this.updatePinRegister(this.cpu.data[this.portConfig.PORT], this.cpu.data[this.portConfig.DDR]);
+ }
+
+ private updatePinRegister(port: u8, ddr: u8) {
+ this.cpu.data[this.portConfig.PIN] = (this.pinValue & ~ddr) | (port & ddr);
+ }
+
private writeGpio(value: u8, oldValue: u8) {
for (const listener of this.listeners) {
listener(value, oldValue);