ac6502 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -12
- package/dist/components/IO/ACIA.d.ts +76 -0
- package/dist/components/IO/ACIA.js +282 -0
- package/dist/components/IO/ACIA.js.map +1 -0
- package/dist/components/IO/Attachments/Attachment.d.ts +112 -0
- package/dist/components/IO/Attachments/Attachment.js +71 -0
- package/dist/components/IO/Attachments/Attachment.js.map +1 -0
- package/dist/components/IO/Attachments/JoystickAttachment.d.ts +53 -0
- package/dist/components/IO/Attachments/JoystickAttachment.js +90 -0
- package/dist/components/IO/Attachments/JoystickAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.d.ts +63 -0
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.js +489 -0
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/KeyboardMatrixAttachment.d.ts +44 -0
- package/dist/components/IO/Attachments/KeyboardMatrixAttachment.js +274 -0
- package/dist/components/IO/Attachments/KeyboardMatrixAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/KeypadAttachment.d.ts +47 -0
- package/dist/components/IO/Attachments/KeypadAttachment.js +141 -0
- package/dist/components/IO/Attachments/KeypadAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/LCDAttachment.d.ts +110 -0
- package/dist/components/IO/Attachments/LCDAttachment.js +716 -0
- package/dist/components/IO/Attachments/LCDAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/SNESAttachment.d.ts +85 -0
- package/dist/components/IO/Attachments/SNESAttachment.js +184 -0
- package/dist/components/IO/Attachments/SNESAttachment.js.map +1 -0
- package/dist/components/IO/Empty.d.ts +9 -0
- package/dist/components/IO/Empty.js +5 -7
- package/dist/components/IO/Empty.js.map +1 -1
- package/dist/components/IO/GPIOCard.d.ts +5 -5
- package/dist/components/IO/GPIOCard.js.map +1 -1
- package/dist/components/IO/RAMBank.d.ts +37 -0
- package/dist/components/IO/RAMBank.js +63 -0
- package/dist/components/IO/RAMBank.js.map +1 -0
- package/dist/components/IO/RTC.d.ts +107 -0
- package/dist/components/IO/RTC.js +483 -0
- package/dist/components/IO/RTC.js.map +1 -0
- package/dist/components/IO/Sound.d.ts +120 -0
- package/dist/components/IO/Sound.js +622 -0
- package/dist/components/IO/Sound.js.map +1 -0
- package/dist/components/IO/Storage.d.ts +74 -0
- package/dist/components/IO/Storage.js +409 -0
- package/dist/components/IO/Storage.js.map +1 -0
- package/dist/components/IO/Terminal.d.ts +19 -0
- package/dist/components/IO/Terminal.js +33 -0
- package/dist/components/IO/Terminal.js.map +1 -0
- package/dist/components/IO/VIA.d.ts +105 -0
- package/dist/components/IO/VIA.js +597 -0
- package/dist/components/IO/VIA.js.map +1 -0
- package/dist/components/IO/Video.d.ts +141 -0
- package/dist/components/IO/Video.js +630 -0
- package/dist/components/IO/Video.js.map +1 -0
- package/dist/components/Machine.d.ts +20 -24
- package/dist/components/Machine.js +249 -166
- package/dist/components/Machine.js.map +1 -1
- package/dist/index.js +28 -14
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +16 -16
- package/dist/lib.js +32 -32
- package/dist/lib.js.map +1 -1
- package/dist/tests/IO/ACIA.test.d.ts +1 -0
- package/dist/tests/IO/ACIA.test.js +423 -0
- package/dist/tests/IO/ACIA.test.js.map +1 -0
- package/dist/tests/IO/Attachments/Attachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/Attachment.test.js +339 -0
- package/dist/tests/IO/Attachments/Attachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/JoystickAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/JoystickAttachment.test.js +126 -0
- package/dist/tests/IO/Attachments/JoystickAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/KeyboardEncoderAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/KeyboardEncoderAttachment.test.js +779 -0
- package/dist/tests/IO/Attachments/KeyboardEncoderAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/KeyboardMatrixAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/KeyboardMatrixAttachment.test.js +355 -0
- package/dist/tests/IO/Attachments/KeyboardMatrixAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/KeypadAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/KeypadAttachment.test.js +323 -0
- package/dist/tests/IO/Attachments/KeypadAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/LCDAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/LCDAttachment.test.js +627 -0
- package/dist/tests/IO/Attachments/LCDAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/SNESAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/SNESAttachment.test.js +331 -0
- package/dist/tests/IO/Attachments/SNESAttachment.test.js.map +1 -0
- package/dist/tests/IO/Empty.test.d.ts +1 -0
- package/dist/tests/IO/Empty.test.js +121 -0
- package/dist/tests/IO/Empty.test.js.map +1 -0
- package/dist/tests/IO/GPIOCard.test.js.map +1 -1
- package/dist/tests/IO/RAMBank.test.d.ts +1 -0
- package/dist/tests/IO/RAMBank.test.js +229 -0
- package/dist/tests/IO/RAMBank.test.js.map +1 -0
- package/dist/tests/IO/RTC.test.d.ts +1 -0
- package/dist/tests/IO/RTC.test.js +177 -0
- package/dist/tests/IO/RTC.test.js.map +1 -0
- package/dist/tests/IO/Sound.test.d.ts +1 -0
- package/dist/tests/IO/Sound.test.js +528 -0
- package/dist/tests/IO/Sound.test.js.map +1 -0
- package/dist/tests/IO/Storage.test.d.ts +1 -0
- package/dist/tests/IO/Storage.test.js +656 -0
- package/dist/tests/IO/Storage.test.js.map +1 -0
- package/dist/tests/IO/VIA.test.d.ts +1 -0
- package/dist/tests/IO/VIA.test.js +503 -0
- package/dist/tests/IO/VIA.test.js.map +1 -0
- package/dist/tests/IO/Video.test.d.ts +1 -0
- package/dist/tests/IO/Video.test.js +549 -0
- package/dist/tests/IO/Video.test.js.map +1 -0
- package/dist/tests/Machine.test.js +27 -42
- package/dist/tests/Machine.test.js.map +1 -1
- package/package.json +1 -1
- package/src/components/IO/{SerialCard.ts → ACIA.ts} +2 -2
- package/src/components/IO/{GPIOAttachments/GPIOAttachment.ts → Attachments/Attachment.ts} +2 -2
- package/src/components/IO/{GPIOAttachments/GPIOJoystickAttachment.ts → Attachments/JoystickAttachment.ts} +3 -3
- package/src/components/IO/{GPIOAttachments/GPIOKeyboardEncoderAttachment.ts → Attachments/KeyboardEncoderAttachment.ts} +3 -3
- package/src/components/IO/{GPIOAttachments/GPIOKeyboardMatrixAttachment.ts → Attachments/KeyboardMatrixAttachment.ts} +5 -5
- package/src/components/IO/{GPIOAttachments/GPIOKeypadAttachment.ts → Attachments/KeypadAttachment.ts} +3 -3
- package/src/components/IO/{GPIOAttachments/GPIOLCDAttachment.ts → Attachments/LCDAttachment.ts} +7 -7
- package/src/components/IO/{EmptyCard.ts → Empty.ts} +1 -1
- package/src/components/IO/{RAMCard.ts → RAMBank.ts} +8 -8
- package/src/components/IO/{RTCCard.ts → RTC.ts} +1 -1
- package/src/components/IO/{SoundCard.ts → Sound.ts} +2 -2
- package/src/components/IO/{StorageCard.ts → Storage.ts} +70 -73
- package/src/components/IO/{DevOutputBoard.ts → Terminal.ts} +2 -2
- package/src/components/IO/{GPIOCard.ts → VIA.ts} +64 -64
- package/src/components/IO/{VideoCard.ts → Video.ts} +1 -1
- package/src/components/Machine.ts +276 -176
- package/src/index.ts +34 -21
- package/src/lib.ts +16 -16
- package/src/tests/IO/{SerialCard.test.ts → ACIA.test.ts} +5 -5
- package/src/tests/IO/{GPIOAttachments/GPIOAttachment.test.ts → Attachments/Attachment.test.ts} +12 -12
- package/src/tests/IO/{GPIOAttachments/GPIOJoystickAttachment.test.ts → Attachments/JoystickAttachment.test.ts} +23 -23
- package/src/tests/IO/{GPIOAttachments/GPIOKeyboardEncoderAttachment.test.ts → Attachments/KeyboardEncoderAttachment.test.ts} +4 -4
- package/src/tests/IO/{GPIOAttachments/GPIOKeyboardMatrixAttachment.test.ts → Attachments/KeyboardMatrixAttachment.test.ts} +5 -5
- package/src/tests/IO/{GPIOAttachments/GPIOKeypadAttachment.test.ts → Attachments/KeypadAttachment.test.ts} +38 -38
- package/src/tests/IO/{GPIOAttachments/GPIOLCDAttachment.test.ts → Attachments/LCDAttachment.test.ts} +12 -12
- package/src/tests/IO/Empty.test.ts +143 -0
- package/src/tests/IO/{RAMCard.test.ts → RAMBank.test.ts} +33 -33
- package/src/tests/IO/{RTCCard.test.ts → RTC.test.ts} +6 -6
- package/src/tests/IO/{SoundCard.test.ts → Sound.test.ts} +6 -6
- package/src/tests/IO/{StorageCard.test.ts → Storage.test.ts} +34 -25
- package/src/tests/IO/{GPIOCard.test.ts → VIA.test.ts} +7 -7
- package/src/tests/IO/{VideoCard.test.ts → Video.test.ts} +13 -13
- package/src/tests/Machine.test.ts +31 -38
package/README.md
CHANGED
|
@@ -183,18 +183,18 @@ src/
|
|
|
183
183
|
│ ├── Cart.ts # Cartridge support
|
|
184
184
|
│ ├── IO.ts # I/O interface
|
|
185
185
|
│ └── IO/ # I/O peripheral implementations
|
|
186
|
-
│ ├──
|
|
187
|
-
│ ├──
|
|
188
|
-
│ ├──
|
|
189
|
-
│ ├──
|
|
190
|
-
│ ├──
|
|
191
|
-
│ ├──
|
|
192
|
-
│ ├──
|
|
193
|
-
│ └──
|
|
194
|
-
│ ├──
|
|
195
|
-
│ ├──
|
|
196
|
-
│ ├──
|
|
197
|
-
│ └──
|
|
186
|
+
│ ├── VIA.ts
|
|
187
|
+
│ ├── RAMBank.ts
|
|
188
|
+
│ ├── RTC.ts
|
|
189
|
+
│ ├── ACIA.ts
|
|
190
|
+
│ ├── Sound.ts
|
|
191
|
+
│ ├── Storage.ts
|
|
192
|
+
│ ├── Video.ts
|
|
193
|
+
│ └── Attachments/
|
|
194
|
+
│ ├── Attachment.ts
|
|
195
|
+
│ ├── JoystickAttachment.ts
|
|
196
|
+
│ ├── KeyboardEncoderAttachment.ts
|
|
197
|
+
│ └── KeyboardMatrixAttachment.ts
|
|
198
198
|
└── tests/ # Comprehensive test suite
|
|
199
199
|
```
|
|
200
200
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { IO } from '../IO';
|
|
2
|
+
/**
|
|
3
|
+
* ACIA - Emulates a 6551 ACIA (Asynchronous Communications Interface Adapter)
|
|
4
|
+
*
|
|
5
|
+
* Register Map:
|
|
6
|
+
* $00: Data Register (read/write)
|
|
7
|
+
* $01: Status Register (read) / Programmed Reset (write)
|
|
8
|
+
* $02: Command Register (write)
|
|
9
|
+
* $03: Control Register (write)
|
|
10
|
+
*/
|
|
11
|
+
export declare class ACIA implements IO {
|
|
12
|
+
raiseIRQ: () => void;
|
|
13
|
+
raiseNMI: () => void;
|
|
14
|
+
transmit?: (data: number) => void;
|
|
15
|
+
private dataRegister;
|
|
16
|
+
private statusRegister;
|
|
17
|
+
private commandRegister;
|
|
18
|
+
private controlRegister;
|
|
19
|
+
private transmitBuffer;
|
|
20
|
+
private receiveBuffer;
|
|
21
|
+
private parityError;
|
|
22
|
+
private framingError;
|
|
23
|
+
private overrun;
|
|
24
|
+
private irqFlag;
|
|
25
|
+
private echoMode;
|
|
26
|
+
private cycleCounter;
|
|
27
|
+
private baudRate;
|
|
28
|
+
/**
|
|
29
|
+
* Read from ACIA register
|
|
30
|
+
*/
|
|
31
|
+
read(address: number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Write to ACIA register
|
|
34
|
+
*/
|
|
35
|
+
write(address: number, data: number): void;
|
|
36
|
+
/**
|
|
37
|
+
* Read data from receive buffer
|
|
38
|
+
*/
|
|
39
|
+
private readData;
|
|
40
|
+
/**
|
|
41
|
+
* Write data to transmit buffer
|
|
42
|
+
*/
|
|
43
|
+
private writeData;
|
|
44
|
+
/**
|
|
45
|
+
* Read status register
|
|
46
|
+
*/
|
|
47
|
+
private readStatus;
|
|
48
|
+
/**
|
|
49
|
+
* Write to command register
|
|
50
|
+
*/
|
|
51
|
+
private writeCommand;
|
|
52
|
+
/**
|
|
53
|
+
* Write to control register
|
|
54
|
+
*/
|
|
55
|
+
private writeControl;
|
|
56
|
+
/**
|
|
57
|
+
* Get baud rate from control register code
|
|
58
|
+
*/
|
|
59
|
+
private getBaudRate;
|
|
60
|
+
/**
|
|
61
|
+
* Programmed reset
|
|
62
|
+
*/
|
|
63
|
+
private programmedReset;
|
|
64
|
+
/**
|
|
65
|
+
* Tick - emulate ACIA timing
|
|
66
|
+
*/
|
|
67
|
+
tick(frequency: number): void;
|
|
68
|
+
/**
|
|
69
|
+
* Reset the ACIA
|
|
70
|
+
*/
|
|
71
|
+
reset(coldStart: boolean): void;
|
|
72
|
+
/**
|
|
73
|
+
* Receive data from external source
|
|
74
|
+
*/
|
|
75
|
+
onData(data: number): void;
|
|
76
|
+
}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ACIA = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ACIA - Emulates a 6551 ACIA (Asynchronous Communications Interface Adapter)
|
|
6
|
+
*
|
|
7
|
+
* Register Map:
|
|
8
|
+
* $00: Data Register (read/write)
|
|
9
|
+
* $01: Status Register (read) / Programmed Reset (write)
|
|
10
|
+
* $02: Command Register (write)
|
|
11
|
+
* $03: Control Register (write)
|
|
12
|
+
*/
|
|
13
|
+
class ACIA {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.raiseIRQ = () => { };
|
|
16
|
+
this.raiseNMI = () => { };
|
|
17
|
+
// Registers
|
|
18
|
+
this.dataRegister = 0;
|
|
19
|
+
this.statusRegister = 0x10; // Transmit Data Register Empty
|
|
20
|
+
this.commandRegister = 0;
|
|
21
|
+
this.controlRegister = 0;
|
|
22
|
+
// Buffers
|
|
23
|
+
this.transmitBuffer = [];
|
|
24
|
+
this.receiveBuffer = [];
|
|
25
|
+
// Status flags
|
|
26
|
+
this.parityError = false;
|
|
27
|
+
this.framingError = false;
|
|
28
|
+
this.overrun = false;
|
|
29
|
+
this.irqFlag = false;
|
|
30
|
+
this.echoMode = false;
|
|
31
|
+
// Timing
|
|
32
|
+
this.cycleCounter = 0;
|
|
33
|
+
this.baudRate = 115200;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read from ACIA register
|
|
37
|
+
*/
|
|
38
|
+
read(address) {
|
|
39
|
+
const register = address & 0x03;
|
|
40
|
+
switch (register) {
|
|
41
|
+
case 0x00: // Data Register
|
|
42
|
+
return this.readData();
|
|
43
|
+
case 0x01: // Status Register
|
|
44
|
+
return this.readStatus();
|
|
45
|
+
case 0x02: // Command Register
|
|
46
|
+
return this.commandRegister;
|
|
47
|
+
case 0x03: // Control Register
|
|
48
|
+
return this.controlRegister;
|
|
49
|
+
default:
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Write to ACIA register
|
|
55
|
+
*/
|
|
56
|
+
write(address, data) {
|
|
57
|
+
const register = address & 0x03;
|
|
58
|
+
switch (register) {
|
|
59
|
+
case 0x00: // Data Register
|
|
60
|
+
this.writeData(data);
|
|
61
|
+
break;
|
|
62
|
+
case 0x01: // Programmed Reset
|
|
63
|
+
this.programmedReset();
|
|
64
|
+
break;
|
|
65
|
+
case 0x02: // Command Register
|
|
66
|
+
this.writeCommand(data);
|
|
67
|
+
break;
|
|
68
|
+
case 0x03: // Control Register
|
|
69
|
+
this.writeControl(data);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Read data from receive buffer
|
|
75
|
+
*/
|
|
76
|
+
readData() {
|
|
77
|
+
if (this.receiveBuffer.length > 0) {
|
|
78
|
+
const data = this.receiveBuffer.shift();
|
|
79
|
+
this.dataRegister = data;
|
|
80
|
+
// Update status: clear Receive Data Register Full
|
|
81
|
+
this.statusRegister &= ~0x08;
|
|
82
|
+
// Check for overrun if more data arrives
|
|
83
|
+
if (this.receiveBuffer.length === 0) {
|
|
84
|
+
this.overrun = false;
|
|
85
|
+
this.statusRegister &= ~0x04;
|
|
86
|
+
}
|
|
87
|
+
// Clear IRQ if receive IRQ was enabled
|
|
88
|
+
if ((this.commandRegister & 0x04) && this.receiveBuffer.length === 0) {
|
|
89
|
+
this.irqFlag = false;
|
|
90
|
+
this.statusRegister &= ~0x80;
|
|
91
|
+
}
|
|
92
|
+
return data;
|
|
93
|
+
}
|
|
94
|
+
return this.dataRegister;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Write data to transmit buffer
|
|
98
|
+
*/
|
|
99
|
+
writeData(data) {
|
|
100
|
+
this.transmitBuffer.push(data & 0xFF);
|
|
101
|
+
// Clear Transmit Data Register Empty flag
|
|
102
|
+
this.statusRegister &= ~0x10;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Read status register
|
|
106
|
+
*/
|
|
107
|
+
readStatus() {
|
|
108
|
+
let status = 0;
|
|
109
|
+
// Bit 0: Parity Error
|
|
110
|
+
if (this.parityError)
|
|
111
|
+
status |= 0x01;
|
|
112
|
+
// Bit 1: Framing Error
|
|
113
|
+
if (this.framingError)
|
|
114
|
+
status |= 0x02;
|
|
115
|
+
// Bit 2: Overrun
|
|
116
|
+
if (this.overrun)
|
|
117
|
+
status |= 0x04;
|
|
118
|
+
// Bit 3: Receive Data Register Full
|
|
119
|
+
if (this.receiveBuffer.length > 0)
|
|
120
|
+
status |= 0x08;
|
|
121
|
+
// Bit 4: Transmit Data Register Empty
|
|
122
|
+
if (this.transmitBuffer.length === 0)
|
|
123
|
+
status |= 0x10;
|
|
124
|
+
// Bit 5: Data Carrier Detect (DCD) - always clear (connected)
|
|
125
|
+
status &= ~0x20;
|
|
126
|
+
// Bit 6: Data Set Ready (DSR) - always set (ready)
|
|
127
|
+
status |= 0x40;
|
|
128
|
+
// Bit 7: Interrupt (IRQ)
|
|
129
|
+
if (this.irqFlag)
|
|
130
|
+
status |= 0x80;
|
|
131
|
+
this.statusRegister = status;
|
|
132
|
+
return status;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Write to command register
|
|
136
|
+
*/
|
|
137
|
+
writeCommand(data) {
|
|
138
|
+
this.commandRegister = data & 0xFF;
|
|
139
|
+
// Bits 0-1: DTR control
|
|
140
|
+
// const dtrControl = data & 0x03
|
|
141
|
+
// Bit 2: Receive IRQ Enable
|
|
142
|
+
const receiveIRQEnabled = (data & 0x04) !== 0;
|
|
143
|
+
// Bits 3-4: Transmit control and IRQ enable
|
|
144
|
+
// const transmitControl = (data >> 3) & 0x03
|
|
145
|
+
// Bit 5: Echo mode
|
|
146
|
+
this.echoMode = (data & 0x20) !== 0;
|
|
147
|
+
// Bits 6-7: Parity control
|
|
148
|
+
// const parityControl = (data >> 6) & 0x03
|
|
149
|
+
// Handle receive IRQ
|
|
150
|
+
if (receiveIRQEnabled && this.receiveBuffer.length > 0) {
|
|
151
|
+
this.irqFlag = true;
|
|
152
|
+
this.statusRegister |= 0x80;
|
|
153
|
+
this.raiseIRQ();
|
|
154
|
+
}
|
|
155
|
+
else if (!receiveIRQEnabled) {
|
|
156
|
+
this.irqFlag = false;
|
|
157
|
+
this.statusRegister &= ~0x80;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Write to control register
|
|
162
|
+
*/
|
|
163
|
+
writeControl(data) {
|
|
164
|
+
this.controlRegister = data & 0xFF;
|
|
165
|
+
// Bits 0-3: Baud rate
|
|
166
|
+
const baudRateCode = data & 0x0F;
|
|
167
|
+
this.baudRate = this.getBaudRate(baudRateCode);
|
|
168
|
+
// Bit 4: Receiver clock source (internal/external)
|
|
169
|
+
const receiverClockSource = (data & 0x10) !== 0;
|
|
170
|
+
// Bits 5-6: Word length (5, 6, 7, or 8 bits)
|
|
171
|
+
const wordLength = ((data >> 5) & 0x03) + 5;
|
|
172
|
+
// Bit 7: Stop bits (1 or 2)
|
|
173
|
+
const stopBits = (data & 0x80) ? 2 : 1;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get baud rate from control register code
|
|
177
|
+
*/
|
|
178
|
+
getBaudRate(code) {
|
|
179
|
+
const baudRates = [
|
|
180
|
+
115200, // 0000 (actually 16x external clock, using 115200 as default)
|
|
181
|
+
50, // 0001
|
|
182
|
+
75, // 0010
|
|
183
|
+
110, // 0011
|
|
184
|
+
135, // 0100
|
|
185
|
+
150, // 0101
|
|
186
|
+
300, // 0110
|
|
187
|
+
600, // 0111
|
|
188
|
+
1200, // 1000
|
|
189
|
+
1800, // 1001
|
|
190
|
+
2400, // 1010
|
|
191
|
+
3600, // 1011
|
|
192
|
+
4800, // 1100
|
|
193
|
+
7200, // 1101
|
|
194
|
+
9600, // 1110
|
|
195
|
+
19200 // 1111
|
|
196
|
+
];
|
|
197
|
+
return baudRates[code] || 115200;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Programmed reset
|
|
201
|
+
*/
|
|
202
|
+
programmedReset() {
|
|
203
|
+
this.statusRegister = 0x10; // Transmit Data Register Empty
|
|
204
|
+
this.parityError = false;
|
|
205
|
+
this.framingError = false;
|
|
206
|
+
this.overrun = false;
|
|
207
|
+
this.irqFlag = false;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Tick - emulate ACIA timing
|
|
211
|
+
*/
|
|
212
|
+
tick(frequency) {
|
|
213
|
+
this.cycleCounter++;
|
|
214
|
+
// Calculate cycles per byte: (CPU_CLOCK / baud_rate) * bits_per_frame
|
|
215
|
+
// Assuming 10 bits per frame (1 start + 8 data + 1 stop)
|
|
216
|
+
const cyclesPerByte = Math.floor((frequency / this.baudRate) * 10);
|
|
217
|
+
// Simulate transmission based on actual baud rate
|
|
218
|
+
if (this.cycleCounter >= cyclesPerByte && this.transmitBuffer.length > 0) {
|
|
219
|
+
this.cycleCounter = 0;
|
|
220
|
+
// Transmit one byte
|
|
221
|
+
const byte = this.transmitBuffer.shift();
|
|
222
|
+
if (byte !== undefined && this.transmit) {
|
|
223
|
+
this.transmit(byte);
|
|
224
|
+
}
|
|
225
|
+
// Set Transmit Data Register Empty if buffer is empty
|
|
226
|
+
if (this.transmitBuffer.length === 0) {
|
|
227
|
+
this.statusRegister |= 0x10;
|
|
228
|
+
// Trigger transmit complete IRQ if enabled
|
|
229
|
+
if ((this.commandRegister & 0x18) === 0x08) {
|
|
230
|
+
this.irqFlag = true;
|
|
231
|
+
this.statusRegister |= 0x80;
|
|
232
|
+
this.raiseIRQ();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Reset the ACIA
|
|
239
|
+
*/
|
|
240
|
+
reset(coldStart) {
|
|
241
|
+
this.dataRegister = 0;
|
|
242
|
+
this.statusRegister = 0x10; // Transmit Data Register Empty
|
|
243
|
+
this.commandRegister = 0;
|
|
244
|
+
this.controlRegister = 0;
|
|
245
|
+
this.transmitBuffer = [];
|
|
246
|
+
this.receiveBuffer = [];
|
|
247
|
+
this.parityError = false;
|
|
248
|
+
this.framingError = false;
|
|
249
|
+
this.overrun = false;
|
|
250
|
+
this.irqFlag = false;
|
|
251
|
+
this.echoMode = false;
|
|
252
|
+
this.cycleCounter = 0;
|
|
253
|
+
this.baudRate = 115200;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Receive data from external source
|
|
257
|
+
*/
|
|
258
|
+
onData(data) {
|
|
259
|
+
if (this.receiveBuffer.length > 0 && (this.statusRegister & 0x08)) {
|
|
260
|
+
// Overrun condition: data arrives before previous data was read
|
|
261
|
+
this.overrun = true;
|
|
262
|
+
this.statusRegister |= 0x04;
|
|
263
|
+
}
|
|
264
|
+
this.receiveBuffer.push(data & 0xFF);
|
|
265
|
+
// Set Receive Data Register Full flag
|
|
266
|
+
this.statusRegister |= 0x08;
|
|
267
|
+
// Trigger receive IRQ if enabled
|
|
268
|
+
if (this.commandRegister & 0x04) {
|
|
269
|
+
this.irqFlag = true;
|
|
270
|
+
this.statusRegister |= 0x80;
|
|
271
|
+
this.raiseIRQ();
|
|
272
|
+
}
|
|
273
|
+
// Echo mode: automatically transmit received data
|
|
274
|
+
if (this.echoMode) {
|
|
275
|
+
this.transmitBuffer.push(data & 0xFF);
|
|
276
|
+
// Clear Transmit Data Register Empty flag
|
|
277
|
+
this.statusRegister &= ~0x10;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
exports.ACIA = ACIA;
|
|
282
|
+
//# sourceMappingURL=ACIA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ACIA.js","sourceRoot":"","sources":["../../../src/components/IO/ACIA.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for devices that can be attached to GPIO ports
|
|
3
|
+
*/
|
|
4
|
+
export interface Attachment {
|
|
5
|
+
/**
|
|
6
|
+
* Reset the attachment to its initial state
|
|
7
|
+
*/
|
|
8
|
+
reset(): void;
|
|
9
|
+
/**
|
|
10
|
+
* Update the attachment state based on CPU clock ticks
|
|
11
|
+
* @param cpuFrequency - The CPU frequency in Hz
|
|
12
|
+
*/
|
|
13
|
+
tick(cpuFrequency: number): void;
|
|
14
|
+
/**
|
|
15
|
+
* Read data from Port A
|
|
16
|
+
* @param ddr - Data Direction Register value
|
|
17
|
+
* @param or - Output Register value
|
|
18
|
+
* @returns The data to be read from the port
|
|
19
|
+
*/
|
|
20
|
+
readPortA(ddr: number, or: number): number;
|
|
21
|
+
/**
|
|
22
|
+
* Read data from Port B
|
|
23
|
+
* @param ddr - Data Direction Register value
|
|
24
|
+
* @param or - Output Register value
|
|
25
|
+
* @returns The data to be read from the port
|
|
26
|
+
*/
|
|
27
|
+
readPortB(ddr: number, or: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* Write data to Port A
|
|
30
|
+
* @param value - The value being written
|
|
31
|
+
* @param ddr - Data Direction Register value
|
|
32
|
+
*/
|
|
33
|
+
writePortA(value: number, ddr: number): void;
|
|
34
|
+
/**
|
|
35
|
+
* Write data to Port B
|
|
36
|
+
* @param value - The value being written
|
|
37
|
+
* @param ddr - Data Direction Register value
|
|
38
|
+
*/
|
|
39
|
+
writePortB(value: number, ddr: number): void;
|
|
40
|
+
/**
|
|
41
|
+
* Check if the attachment is enabled
|
|
42
|
+
* @returns true if enabled, false otherwise
|
|
43
|
+
*/
|
|
44
|
+
isEnabled(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Get the priority of this attachment (lower values = higher priority)
|
|
47
|
+
* @returns The priority value
|
|
48
|
+
*/
|
|
49
|
+
getPriority(): number;
|
|
50
|
+
/**
|
|
51
|
+
* Clear interrupt flags
|
|
52
|
+
* @param ca1 - Clear CA1 interrupt
|
|
53
|
+
* @param ca2 - Clear CA2 interrupt
|
|
54
|
+
* @param cb1 - Clear CB1 interrupt
|
|
55
|
+
* @param cb2 - Clear CB2 interrupt
|
|
56
|
+
*/
|
|
57
|
+
clearInterrupts(ca1: boolean, ca2: boolean, cb1: boolean, cb2: boolean): void;
|
|
58
|
+
/**
|
|
59
|
+
* Update control line states
|
|
60
|
+
* @param ca1 - CA1 control line state
|
|
61
|
+
* @param ca2 - CA2 control line state
|
|
62
|
+
* @param cb1 - CB1 control line state
|
|
63
|
+
* @param cb2 - CB2 control line state
|
|
64
|
+
*/
|
|
65
|
+
updateControlLines(ca1: boolean, ca2: boolean, cb1: boolean, cb2: boolean): void;
|
|
66
|
+
/**
|
|
67
|
+
* Check if CA1 interrupt is pending
|
|
68
|
+
* @returns true if interrupt is pending
|
|
69
|
+
*/
|
|
70
|
+
hasCA1Interrupt(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Check if CA2 interrupt is pending
|
|
73
|
+
* @returns true if interrupt is pending
|
|
74
|
+
*/
|
|
75
|
+
hasCA2Interrupt(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Check if CB1 interrupt is pending
|
|
78
|
+
* @returns true if interrupt is pending
|
|
79
|
+
*/
|
|
80
|
+
hasCB1Interrupt(): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Check if CB2 interrupt is pending
|
|
83
|
+
* @returns true if interrupt is pending
|
|
84
|
+
*/
|
|
85
|
+
hasCB2Interrupt(): boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Base abstract class for GPIO attachments with common functionality
|
|
89
|
+
*/
|
|
90
|
+
export declare abstract class AttachmentBase implements Attachment {
|
|
91
|
+
protected priority: number;
|
|
92
|
+
protected enabled: boolean;
|
|
93
|
+
protected ca1Interrupt: boolean;
|
|
94
|
+
protected ca2Interrupt: boolean;
|
|
95
|
+
protected cb1Interrupt: boolean;
|
|
96
|
+
protected cb2Interrupt: boolean;
|
|
97
|
+
constructor(priority: number, ca1Interrupt?: boolean, ca2Interrupt?: boolean, cb1Interrupt?: boolean, cb2Interrupt?: boolean);
|
|
98
|
+
reset(): void;
|
|
99
|
+
tick(cpuFrequency: number): void;
|
|
100
|
+
readPortA(ddr: number, or: number): number;
|
|
101
|
+
readPortB(ddr: number, or: number): number;
|
|
102
|
+
writePortA(value: number, ddr: number): void;
|
|
103
|
+
writePortB(value: number, ddr: number): void;
|
|
104
|
+
isEnabled(): boolean;
|
|
105
|
+
getPriority(): number;
|
|
106
|
+
clearInterrupts(ca1: boolean, ca2: boolean, cb1: boolean, cb2: boolean): void;
|
|
107
|
+
updateControlLines(ca1: boolean, ca2: boolean, cb1: boolean, cb2: boolean): void;
|
|
108
|
+
hasCA1Interrupt(): boolean;
|
|
109
|
+
hasCA2Interrupt(): boolean;
|
|
110
|
+
hasCB1Interrupt(): boolean;
|
|
111
|
+
hasCB2Interrupt(): boolean;
|
|
112
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AttachmentBase = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Base abstract class for GPIO attachments with common functionality
|
|
6
|
+
*/
|
|
7
|
+
class AttachmentBase {
|
|
8
|
+
constructor(priority, ca1Interrupt = false, ca2Interrupt = false, cb1Interrupt = false, cb2Interrupt = false) {
|
|
9
|
+
this.priority = priority;
|
|
10
|
+
this.enabled = true;
|
|
11
|
+
this.ca1Interrupt = ca1Interrupt;
|
|
12
|
+
this.ca2Interrupt = ca2Interrupt;
|
|
13
|
+
this.cb1Interrupt = cb1Interrupt;
|
|
14
|
+
this.cb2Interrupt = cb2Interrupt;
|
|
15
|
+
}
|
|
16
|
+
reset() {
|
|
17
|
+
this.enabled = true;
|
|
18
|
+
this.ca1Interrupt = false;
|
|
19
|
+
this.ca2Interrupt = false;
|
|
20
|
+
this.cb1Interrupt = false;
|
|
21
|
+
this.cb2Interrupt = false;
|
|
22
|
+
}
|
|
23
|
+
tick(cpuFrequency) {
|
|
24
|
+
// Default: no action
|
|
25
|
+
}
|
|
26
|
+
readPortA(ddr, or) {
|
|
27
|
+
return 0xFF;
|
|
28
|
+
}
|
|
29
|
+
readPortB(ddr, or) {
|
|
30
|
+
return 0xFF;
|
|
31
|
+
}
|
|
32
|
+
writePortA(value, ddr) {
|
|
33
|
+
// Default: no action
|
|
34
|
+
}
|
|
35
|
+
writePortB(value, ddr) {
|
|
36
|
+
// Default: no action
|
|
37
|
+
}
|
|
38
|
+
isEnabled() {
|
|
39
|
+
return this.enabled;
|
|
40
|
+
}
|
|
41
|
+
getPriority() {
|
|
42
|
+
return this.priority;
|
|
43
|
+
}
|
|
44
|
+
clearInterrupts(ca1, ca2, cb1, cb2) {
|
|
45
|
+
if (ca1)
|
|
46
|
+
this.ca1Interrupt = false;
|
|
47
|
+
if (ca2)
|
|
48
|
+
this.ca2Interrupt = false;
|
|
49
|
+
if (cb1)
|
|
50
|
+
this.cb1Interrupt = false;
|
|
51
|
+
if (cb2)
|
|
52
|
+
this.cb2Interrupt = false;
|
|
53
|
+
}
|
|
54
|
+
updateControlLines(ca1, ca2, cb1, cb2) {
|
|
55
|
+
// Default: no action
|
|
56
|
+
}
|
|
57
|
+
hasCA1Interrupt() {
|
|
58
|
+
return this.ca1Interrupt;
|
|
59
|
+
}
|
|
60
|
+
hasCA2Interrupt() {
|
|
61
|
+
return this.ca2Interrupt;
|
|
62
|
+
}
|
|
63
|
+
hasCB1Interrupt() {
|
|
64
|
+
return this.cb1Interrupt;
|
|
65
|
+
}
|
|
66
|
+
hasCB2Interrupt() {
|
|
67
|
+
return this.cb2Interrupt;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.AttachmentBase = AttachmentBase;
|
|
71
|
+
//# sourceMappingURL=Attachment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Attachment.js","sourceRoot":"","sources":["../../../../src/components/IO/Attachments/Attachment.ts"],"names":[],"mappings":";;;AAoGA;;GAEG;AACH,MAAsB,cAAc;IAQlC,YACE,QAAgB,EAChB,eAAwB,KAAK,EAC7B,eAAwB,KAAK,EAC7B,eAAwB,KAAK,EAC7B,eAAwB,KAAK;QAE7B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAChC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAChC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAChC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;IAClC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QACzB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QACzB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QACzB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;IAC3B,CAAC;IAED,IAAI,CAAC,YAAoB;QACvB,qBAAqB;IACvB,CAAC;IAED,SAAS,CAAC,GAAW,EAAE,EAAU;QAC/B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,SAAS,CAAC,GAAW,EAAE,EAAU;QAC/B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,UAAU,CAAC,KAAa,EAAE,GAAW;QACnC,qBAAqB;IACvB,CAAC;IAED,UAAU,CAAC,KAAa,EAAE,GAAW;QACnC,qBAAqB;IACvB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,eAAe,CAAC,GAAY,EAAE,GAAY,EAAE,GAAY,EAAE,GAAY;QACpE,IAAI,GAAG;YAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QAClC,IAAI,GAAG;YAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QAClC,IAAI,GAAG;YAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QAClC,IAAI,GAAG;YAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;IACpC,CAAC;IAED,kBAAkB,CAAC,GAAY,EAAE,GAAY,EAAE,GAAY,EAAE,GAAY;QACvE,qBAAqB;IACvB,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAA;IAC1B,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAA;IAC1B,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAA;IAC1B,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAA;IAC1B,CAAC;CACF;AArFD,wCAqFC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { AttachmentBase } from './Attachment';
|
|
2
|
+
/**
|
|
3
|
+
* JoystickAttachment - Emulates a joystick/gamepad connected to GPIO port
|
|
4
|
+
*
|
|
5
|
+
* Buttons are active-low (0 = pressed, 1 = released)
|
|
6
|
+
* Can be attached to either Port A or Port B
|
|
7
|
+
*/
|
|
8
|
+
export declare class JoystickAttachment extends AttachmentBase {
|
|
9
|
+
static readonly BUTTON_UP = 1;
|
|
10
|
+
static readonly BUTTON_DOWN = 2;
|
|
11
|
+
static readonly BUTTON_LEFT = 4;
|
|
12
|
+
static readonly BUTTON_RIGHT = 8;
|
|
13
|
+
static readonly BUTTON_A = 16;
|
|
14
|
+
static readonly BUTTON_B = 32;
|
|
15
|
+
static readonly BUTTON_SELECT = 64;
|
|
16
|
+
static readonly BUTTON_START = 128;
|
|
17
|
+
private buttonState;
|
|
18
|
+
private attachedToPortA;
|
|
19
|
+
constructor(attachToPortA?: boolean, priority?: number);
|
|
20
|
+
reset(): void;
|
|
21
|
+
readPortA(ddr: number, or: number): number;
|
|
22
|
+
readPortB(ddr: number, or: number): number;
|
|
23
|
+
/**
|
|
24
|
+
* Update the joystick button state
|
|
25
|
+
* @param buttons - Button state byte (1 = pressed, 0 = released)
|
|
26
|
+
*/
|
|
27
|
+
updateJoystick(buttons: number): void;
|
|
28
|
+
/**
|
|
29
|
+
* Get the current button state
|
|
30
|
+
* @returns The button state byte
|
|
31
|
+
*/
|
|
32
|
+
getButtonState(): number;
|
|
33
|
+
/**
|
|
34
|
+
* Check if a specific button is pressed
|
|
35
|
+
* @param button - Button bit mask to check
|
|
36
|
+
* @returns true if button is pressed
|
|
37
|
+
*/
|
|
38
|
+
isButtonPressed(button: number): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Press a button (set its bit)
|
|
41
|
+
* @param button - Button bit mask to press
|
|
42
|
+
*/
|
|
43
|
+
pressButton(button: number): void;
|
|
44
|
+
/**
|
|
45
|
+
* Release a button (clear its bit)
|
|
46
|
+
* @param button - Button bit mask to release
|
|
47
|
+
*/
|
|
48
|
+
releaseButton(button: number): void;
|
|
49
|
+
/**
|
|
50
|
+
* Clear all button presses
|
|
51
|
+
*/
|
|
52
|
+
releaseAllButtons(): void;
|
|
53
|
+
}
|