aboutsummaryrefslogtreecommitdiff
path: root/src/peripherals
diff options
context:
space:
mode:
authorUri Shaked2020-05-10 09:01:53 +0300
committerUri Shaked2020-05-10 09:01:53 +0300
commiteed745eaca8af2a5f8a7a4e40e84828b8c155dc8 (patch)
tree714f6766006dea0d216996939207965eace1b8b6 /src/peripherals
parentrefactor(demo): use pinState() method (diff)
downloadavr8js-eed745eaca8af2a5f8a7a4e40e84828b8c155dc8.tar.gz
avr8js-eed745eaca8af2a5f8a7a4e40e84828b8c155dc8.tar.bz2
avr8js-eed745eaca8af2a5f8a7a4e40e84828b8c155dc8.zip
feat(gpio): add setPin() function
close #26
Diffstat (limited to 'src/peripherals')
-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);