├── docs ├── prototype.jpg ├── action_shots.jpg └── tiny_adapter_and_connector.jpg ├── .gitignore ├── AppleII-Keyboard ├── AppleII-Keyboard.pdf ├── sym-lib-table ├── fp-lib-table ├── outputs │ ├── AppleII-Keyboard-NPTH.drl │ ├── AppleII-Keyboard-F_Paste.gbr │ ├── AppleII-Keyboard-Edge_Cuts.gbr │ ├── AppleII-Keyboard-PTH.drl │ ├── AppleII-Keyboard-B_Paste.gbr │ ├── AppleII-Keyboard-B_Silkscreen.gbr │ ├── AppleII-Keyboard-F_Mask.gbr │ ├── AppleII-Keyboard-B_Mask.gbr │ ├── AppleII-Keyboard-job.gbrjob │ ├── AppleII-Keyboard-NPTH-drl_map.gbr │ ├── AppleII-Keyboard-F_Cu.gbr │ └── AppleII-Keyboard-F_Silkscreen.gbr ├── Libraries │ ├── footprints │ │ └── Connector_Project.pretty │ │ │ ├── DIP-14_W7.62mm_Socket.kicad_mod │ │ │ └── DIP-16_W7.62mm_UndersidePins.kicad_mod │ └── symbols │ │ └── Diode_Project.kicad_sym └── AppleII-Keyboard.kicad_pro ├── src ├── PS2_Monitor │ ├── config.h │ ├── FIFO.h │ ├── PS2Interface.h │ ├── PS2_Monitor.ino │ └── PS2Keyboard.h ├── AppleII_PS2_Keyboard │ ├── config.h │ ├── Latch7.h │ ├── FIFO.h │ ├── PS2Interface.h │ ├── AppleII_PS2_Keyboard.ino │ ├── build │ │ └── diy_attiny.avr.attiny24_diy │ │ │ └── AppleII_PS2_Keyboard.ino.hex │ ├── PS2Keyboard.h │ └── AppleIIKeyboardTranslation.h └── scripts │ ├── appleii_asciicodes.txt │ ├── ps2_scancodes.txt │ └── generate_table.py ├── AppleII-Keyboard-Connector ├── AppleII-Keyboard-Connector.pdf ├── fp-lib-table ├── sym-lib-table ├── outputs │ ├── AppleII-Keyboard-Connector-NPTH.drl │ ├── AppleII-Keyboard-Connector-B_Paste.gbr │ ├── AppleII-Keyboard-Connector-F_Paste.gbr │ ├── AppleII-Keyboard-Connector-B_Silkscreen.gbr │ ├── AppleII-Keyboard-Connector-Edge_Cuts.gbr │ ├── AppleII-Keyboard-Connector-PTH.drl │ ├── AppleII-Keyboard-Connector-B_Mask.gbr │ ├── AppleII-Keyboard-Connector-F_Mask.gbr │ ├── AppleII-Keyboard-Connector-F_Silkscreen.gbr │ ├── AppleII-Keyboard-Connector-job.gbrjob │ └── AppleII-Keyboard-Connector-NPTH-drl_map.gbr ├── Libraries │ ├── footprints │ │ └── Connector_Project.pretty │ │ │ └── Mini_DIN_round_6_canned.kicad_mod │ └── symbols │ │ └── Connector_Project.kicad_sym └── AppleII-Keyboard-Connector.kicad_pro ├── .gitattributes ├── LICENSE └── README.md /docs/prototype.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markadev/AppleII-Keyboard/HEAD/docs/prototype.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | fp-info-cache 2 | *-backups 3 | *.bak 4 | *.kicad_prl 5 | *.lck 6 | 7 | build 8 | *.lst 9 | -------------------------------------------------------------------------------- /docs/action_shots.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markadev/AppleII-Keyboard/HEAD/docs/action_shots.jpg -------------------------------------------------------------------------------- /docs/tiny_adapter_and_connector.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markadev/AppleII-Keyboard/HEAD/docs/tiny_adapter_and_connector.jpg -------------------------------------------------------------------------------- /AppleII-Keyboard/AppleII-Keyboard.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markadev/AppleII-Keyboard/HEAD/AppleII-Keyboard/AppleII-Keyboard.pdf -------------------------------------------------------------------------------- /src/PS2_Monitor/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // PS/2 interface configuration 4 | #define PS2_CLOCK_PIN 7 5 | #define PS2_DATA_PIN 8 6 | #define PS2_RX_BUFFER_SIZE 16 7 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/AppleII-Keyboard-Connector.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markadev/AppleII-Keyboard/HEAD/AppleII-Keyboard-Connector/AppleII-Keyboard-Connector.pdf -------------------------------------------------------------------------------- /AppleII-Keyboard/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (version 7) 3 | (lib (name "Diode_Project")(type "KiCad")(uri "${KIPRJMOD}/Libraries/symbols/Diode_Project.kicad_sym")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /AppleII-Keyboard/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (version 7) 3 | (lib (name "Connector_Project")(type "KiCad")(uri "${KIPRJMOD}/Libraries/footprints/Connector_Project.pretty")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (version 7) 3 | (lib (name "Connector_Project")(type "KiCad")(uri "${KIPRJMOD}/Libraries/footprints/Connector_Project.pretty")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (version 7) 3 | (lib (name "Connector_Project")(type "KiCad")(uri "${KIPRJMOD}/Libraries/symbols/Connector_Project.kicad_sym")(options "")(descr "")) 4 | ) 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Handle line endings automatically for files detected as text 2 | # and leave all files detected as binary untouched. 3 | * text=auto 4 | 5 | *.jpg binary 6 | *.pdf binary 7 | *.png binary 8 | *.svg binary 9 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-NPTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 9.0.4} date 2025-09-30T15:31:31-0400 3 | ; FORMAT={-:-/ absolute / metric / decimal} 4 | ; #@! TF.CreationDate,2025-09-30T15:31:31-04:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.4 6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH 7 | FMAT,2 8 | METRIC 9 | % 10 | G90 11 | G05 12 | M30 13 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-NPTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 9.0.4} date 2025-09-30T15:46:30-0400 3 | ; FORMAT={-:-/ absolute / metric / decimal} 4 | ; #@! TF.CreationDate,2025-09-30T15:46:30-04:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.4 6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH 7 | FMAT,2 8 | METRIC 9 | % 10 | G90 11 | G05 12 | M30 13 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-F_Paste.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:28-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Paste,Top*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:28* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | G04 APERTURE END LIST* 15 | M02* 16 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-B_Paste.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:46:20-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard-Connector,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Paste,Bot*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:46:20* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | G04 APERTURE END LIST* 15 | M02* 16 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-F_Paste.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:46:20-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard-Connector,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Paste,Top*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:46:20* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | G04 APERTURE END LIST* 15 | M02* 16 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-B_Silkscreen.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:46:20-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard-Connector,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Legend,Bot*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:46:20* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | G04 APERTURE END LIST* 15 | M02* 16 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:46:20-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard-Connector,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Profile,NP*% 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:46:20* 9 | %MOMM*% 10 | %LPD*% 11 | G01* 12 | G04 APERTURE LIST* 13 | %TA.AperFunction,Profile*% 14 | %ADD10C,0.100000*% 15 | %TD*% 16 | G04 APERTURE END LIST* 17 | D10* 18 | X135000000Y-90000000D02* 19 | X165000000Y-90000000D01* 20 | X159000000Y-111000000D02* 21 | X141000000Y-111000000D01* 22 | X165000000Y-90000000D02* 23 | X165000000Y-105000000D01* 24 | X135000000Y-105000000D02* 25 | X135000000Y-90000000D01* 26 | X141000000Y-111000000D02* 27 | X135000000Y-105000000D01* 28 | X165000000Y-105000000D02* 29 | X159000000Y-111000000D01* 30 | M02* 31 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:28-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Profile,NP*% 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:28* 9 | %MOMM*% 10 | %LPD*% 11 | G01* 12 | G04 APERTURE LIST* 13 | %TA.AperFunction,Profile*% 14 | %ADD10C,0.100000*% 15 | %TD*% 16 | G04 APERTURE END LIST* 17 | D10* 18 | X142000000Y-113000000D02* 19 | X141000000Y-112000000D01* 20 | X142000000Y-78000000D02* 21 | X158000000Y-78000000D01* 22 | X141000000Y-112000000D02* 23 | X141000000Y-79000000D01* 24 | X141000000Y-79000000D02* 25 | X142000000Y-78000000D01* 26 | X158000000Y-78000000D02* 27 | X159000000Y-79000000D01* 28 | X159000000Y-79000000D02* 29 | X159000000Y-112000000D01* 30 | X159000000Y-112000000D02* 31 | X158000000Y-113000000D01* 32 | X158000000Y-113000000D02* 33 | X142000000Y-113000000D01* 34 | M02* 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2025 Mark Aikens 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-PTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 9.0.4} date 2025-09-30T15:46:30-0400 3 | ; FORMAT={-:-/ absolute / metric / decimal} 4 | ; #@! TF.CreationDate,2025-09-30T15:46:30-04:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.4 6 | ; #@! TF.FileFunction,Plated,1,2,PTH 7 | FMAT,2 8 | METRIC 9 | ; #@! TA.AperFunction,Plated,PTH,ViaDrill 10 | T1C0.300 11 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill 12 | T2C0.800 13 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill 14 | T3C1.000 15 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill 16 | T4C2.300 17 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill 18 | T5C3.200 19 | % 20 | G90 21 | G05 22 | T1 23 | X149.86Y-102.87 24 | X150.495Y-98.425 25 | X153.67Y-102.87 26 | T2 27 | X146.6Y-96.52 28 | X146.6Y-99.02 29 | X148.7Y-96.52 30 | X151.3Y-96.52 31 | X153.4Y-96.52 32 | X153.4Y-99.02 33 | T3 34 | X146.19Y-105.41 35 | X146.19Y-107.95 36 | X148.73Y-105.41 37 | X148.73Y-107.95 38 | X151.27Y-105.41 39 | X151.27Y-107.95 40 | X153.81Y-105.41 41 | X153.81Y-107.95 42 | T4 43 | X143.25Y-93.52 44 | X150.0Y-92.72 45 | X156.75Y-93.52 46 | T5 47 | X138.5Y-99.0 48 | X161.5Y-99.0 49 | M30 50 | -------------------------------------------------------------------------------- /src/AppleII_PS2_Keyboard/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(ARDUINO_ATTINY24_DIY) 4 | 5 | // PS/2 interface configuration 6 | #define PS2_CLOCK_PIN 10 /* PB0 */ 7 | #define PS2_DATA_PIN 9 /* PB1 */ 8 | #define PS2_RX_BUFFER_SIZE 16 9 | 10 | // AppleII interface configuration 11 | #define AII_RESET_PIN 8 /* PB2 */ 12 | #define AII_STROBE_PIN 0 /* PA0 */ 13 | #define AII_DATA_PIN_0 3 /* PA3 */ 14 | #define AII_DATA_PIN_1 1 /* PA1 */ 15 | #define AII_DATA_PIN_2 5 /* PA5 */ 16 | #define AII_DATA_PIN_3 4 /* PA4 */ 17 | #define AII_DATA_PIN_4 7 /* PA7 */ 18 | #define AII_DATA_PIN_5 2 /* PA2 */ 19 | #define AII_DATA_PIN_6 6 /* PA6 */ 20 | 21 | #else 22 | 23 | // PS/2 interface configuration 24 | #define PS2_CLOCK_PIN 7 25 | #define PS2_DATA_PIN 8 26 | #define PS2_RX_BUFFER_SIZE 16 27 | 28 | // AppleII interface configuration 29 | #define AII_RESET_PIN 0 30 | #define AII_STROBE_PIN 1 31 | #define AII_DATA_PIN_0 20 32 | #define AII_DATA_PIN_1 21 33 | #define AII_DATA_PIN_2 18 34 | #define AII_DATA_PIN_3 19 35 | #define AII_DATA_PIN_4 4 36 | #define AII_DATA_PIN_5 3 37 | #define AII_DATA_PIN_6 5 38 | 39 | #endif -------------------------------------------------------------------------------- /src/scripts/appleii_asciicodes.txt: -------------------------------------------------------------------------------- 1 | Space 0xa0 0xa0 0xa0 0xa0 2 | 0 0xb0 0xb0 0xb0 0xb0 3 | 1! 0xb1 0xb1 0xa1 0xa1 4 | 2" 0xb2 0xb2 0xa2 0xa2 5 | 3# 0xb3 0xb3 0xa3 0xa3 6 | 4$ 0xb4 0xb4 0xa4 0xa4 7 | 5% 0xb5 0xb5 0xa5 0xa5 8 | 6& 0xb6 0xb6 0xa6 0xa6 9 | 7' 0xb7 0xb7 0xa7 0xa7 10 | 8( 0xb8 0xb8 0xa8 0xa8 11 | 9) 0xb9 0xb9 0xa9 0xa9 12 | :* 0xba 0xba 0xaa 0xaa 13 | ;+ 0xbb 0xbb 0xab 0xab 14 | ,< 0xac 0xac 0xbc 0xbc 15 | -= 0xad 0xad 0xbd 0xbd 16 | .> 0xae 0xae 0xbe 0xbe 17 | /? 0xaf 0xaf 0xbf 0xbf 18 | A 0xc1 0x81 0xc1 0x81 19 | B 0xc2 0x82 0xc2 0x82 20 | C 0xc3 0x83 0xc3 0x83 21 | D 0xc4 0x84 0xc4 0x84 22 | E 0xc5 0x85 0xc5 0x85 23 | F 0xc6 0x86 0xc6 0x86 24 | G 0xc7 0x87 0xc7 0x87 25 | H 0xc8 0x88 0xc8 0x88 26 | I 0xc9 0x89 0xc9 0x89 27 | J 0xca 0x8a 0xca 0x8a 28 | K 0xcb 0x8b 0xcb 0x8b 29 | L 0xcc 0x8c 0xcc 0x8c 30 | M] 0xcd 0x8e 0xdd 0x9d 31 | N^ 0xce 0x8e 0xde 0x9e 32 | O 0xcf 0x8f 0xcf 0x8f 33 | P@ 0xd0 0x90 0xc0 0x80 34 | Q 0xd1 0x91 0xd1 0x91 35 | R 0xd2 0x92 0xd2 0x92 36 | S 0xd3 0x93 0xd3 0x93 37 | T 0xd4 0x94 0xd4 0x94 38 | U 0xd5 0x95 0xd5 0x95 39 | V 0xd6 0x96 0xd6 0x96 40 | W 0xd7 0x97 0xd7 0x97 41 | X 0xd8 0x98 0xd8 0x98 42 | Y 0xd9 0x99 0xd9 0x99 43 | Z 0xda 0x9a 0xda 0x9a 44 | LeftArrow 0x88 0x88 0x88 0x88 45 | RightArrow 0x95 0x95 0x95 0x95 46 | Escape 0x9b 0x9b 0x9b 0x9b 47 | Enter 0x8d 0x8d 0x8d 0x8d 48 | PrtScr 0x00 0xff 0x00 0xff 49 | -------------------------------------------------------------------------------- /src/AppleII_PS2_Keyboard/Latch7.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "config.h" 4 | 5 | 6 | class Latch7 { 7 | public: 8 | void setup() { 9 | digitalWrite(AII_STROBE_PIN, 0); // strobe is active-high 10 | pinMode(AII_STROBE_PIN, OUTPUT); 11 | pinMode(AII_DATA_PIN_0, OUTPUT); 12 | pinMode(AII_DATA_PIN_1, OUTPUT); 13 | pinMode(AII_DATA_PIN_2, OUTPUT); 14 | pinMode(AII_DATA_PIN_3, OUTPUT); 15 | pinMode(AII_DATA_PIN_4, OUTPUT); 16 | pinMode(AII_DATA_PIN_5, OUTPUT); 17 | pinMode(AII_DATA_PIN_6, OUTPUT); 18 | } 19 | 20 | void write(uint8_t value) { 21 | digitalWrite(AII_DATA_PIN_0, value & 0x01); 22 | digitalWrite(AII_DATA_PIN_1, (value >> 1) & 0x01); 23 | digitalWrite(AII_DATA_PIN_2, (value >> 2) & 0x01); 24 | digitalWrite(AII_DATA_PIN_3, (value >> 3) & 0x01); 25 | digitalWrite(AII_DATA_PIN_4, (value >> 4) & 0x01); 26 | digitalWrite(AII_DATA_PIN_5, (value >> 5) & 0x01); 27 | digitalWrite(AII_DATA_PIN_6, (value >> 6) & 0x01); 28 | 29 | // Ref p.90 of "The Apple II Circuit Description" for timing info 30 | delayMicroseconds(12); 31 | digitalWrite(AII_STROBE_PIN, 1); 32 | delayMicroseconds(12); 33 | digitalWrite(AII_STROBE_PIN, 0); 34 | delayMicroseconds(12); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-PTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 9.0.4} date 2025-09-30T15:31:31-0400 3 | ; FORMAT={-:-/ absolute / metric / decimal} 4 | ; #@! TF.CreationDate,2025-09-30T15:31:31-04:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.4 6 | ; #@! TF.FileFunction,Plated,1,2,PTH 7 | FMAT,2 8 | METRIC 9 | ; #@! TA.AperFunction,Plated,PTH,ViaDrill 10 | T1C0.300 11 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill 12 | T2C0.800 13 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill 14 | T3C1.000 15 | % 16 | G90 17 | G05 18 | T1 19 | X156.845Y-83.185 20 | T2 21 | X143.51Y-90.17 22 | X143.51Y-92.71 23 | X143.51Y-95.25 24 | X143.51Y-97.79 25 | X143.51Y-100.33 26 | X143.51Y-102.87 27 | X143.51Y-105.41 28 | X143.51Y-107.95 29 | X147.32Y-90.17 30 | X147.32Y-92.71 31 | X147.32Y-95.25 32 | X147.32Y-97.79 33 | X147.32Y-100.33 34 | X147.32Y-102.87 35 | X147.32Y-105.41 36 | X147.44Y-111.125 37 | X151.13Y-90.17 38 | X151.13Y-92.71 39 | X151.13Y-95.25 40 | X151.13Y-97.79 41 | X151.13Y-100.33 42 | X151.13Y-102.87 43 | X151.13Y-105.41 44 | X151.13Y-107.95 45 | X154.94Y-90.17 46 | X154.94Y-92.71 47 | X154.94Y-95.25 48 | X154.94Y-97.79 49 | X154.94Y-100.33 50 | X154.94Y-102.87 51 | X154.94Y-105.41 52 | X154.94Y-111.125 53 | T3 54 | X146.05Y-80.01 55 | X146.05Y-82.55 56 | X148.59Y-80.01 57 | X148.59Y-82.55 58 | X151.13Y-80.01 59 | X151.13Y-82.55 60 | X153.67Y-80.01 61 | X153.67Y-82.55 62 | M30 63 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-B_Mask.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:46:20-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard-Connector,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Soldermask,Bot*% 6 | %TF.FilePolarity,Negative*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:46:20* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | %ADD10C,5.600000*% 15 | %ADD11R,1.700000X1.700000*% 16 | %ADD12C,1.700000*% 17 | %ADD13C,1.200000*% 18 | %ADD14C,3.300000*% 19 | G04 APERTURE END LIST* 20 | D10* 21 | %TO.C,H2*% 22 | X161500000Y-99000000D03* 23 | %TD*% 24 | D11* 25 | %TO.C,J1*% 26 | X146190000Y-107950000D03* 27 | D12* 28 | X146190000Y-105410000D03* 29 | X148730000Y-107950000D03* 30 | X148730000Y-105410000D03* 31 | X151270000Y-107950000D03* 32 | X151270000Y-105410000D03* 33 | X153810000Y-107950000D03* 34 | X153810000Y-105410000D03* 35 | %TD*% 36 | D13* 37 | %TO.C,J2*% 38 | X148700000Y-96520000D03* 39 | X151300000Y-96520000D03* 40 | X146600000Y-96520000D03* 41 | X153400000Y-96520000D03* 42 | X146600000Y-99020000D03* 43 | X153400000Y-99020000D03* 44 | D14* 45 | X143250000Y-93520000D03* 46 | X150000000Y-92720000D03* 47 | X156750000Y-93520000D03* 48 | %TD*% 49 | D10* 50 | %TO.C,H1*% 51 | X138500000Y-99000000D03* 52 | %TD*% 53 | M02* 54 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-F_Mask.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:46:20-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard-Connector,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Soldermask,Top*% 6 | %TF.FilePolarity,Negative*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:46:20* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | %ADD10C,5.600000*% 15 | %ADD11R,1.700000X1.700000*% 16 | %ADD12C,1.700000*% 17 | %ADD13C,1.200000*% 18 | %ADD14C,3.300000*% 19 | G04 APERTURE END LIST* 20 | D10* 21 | %TO.C,H2*% 22 | X161500000Y-99000000D03* 23 | %TD*% 24 | D11* 25 | %TO.C,J1*% 26 | X146190000Y-107950000D03* 27 | D12* 28 | X146190000Y-105410000D03* 29 | X148730000Y-107950000D03* 30 | X148730000Y-105410000D03* 31 | X151270000Y-107950000D03* 32 | X151270000Y-105410000D03* 33 | X153810000Y-107950000D03* 34 | X153810000Y-105410000D03* 35 | %TD*% 36 | D13* 37 | %TO.C,J2*% 38 | X148700000Y-96520000D03* 39 | X151300000Y-96520000D03* 40 | X146600000Y-96520000D03* 41 | X153400000Y-96520000D03* 42 | X146600000Y-99020000D03* 43 | X153400000Y-99020000D03* 44 | D14* 45 | X143250000Y-93520000D03* 46 | X150000000Y-92720000D03* 47 | X156750000Y-93520000D03* 48 | %TD*% 49 | D10* 50 | %TO.C,H1*% 51 | X138500000Y-99000000D03* 52 | %TD*% 53 | M02* 54 | -------------------------------------------------------------------------------- /src/scripts/ps2_scancodes.txt: -------------------------------------------------------------------------------- 1 | 01 F_9 2 | 03 F_5 3 | 04 F_3 4 | 05 F_1 5 | 06 F_2 6 | 07 F_12 7 | 09 F_10 8 | 0A F_8 9 | 0B F_6 10 | 0C F_4 11 | 0D Tab 12 | 0E `~ 13 | 11 LeftAlt 14 | 12 Shift 15 | 14 Ctrl 16 | 15 Q 17 | 16 1! 18 | 1A Z 19 | 1B S 20 | 1C A 21 | 1D W 22 | 1E 2@ 23 | 21 C 24 | 22 X 25 | 23 D 26 | 24 E 27 | 25 4$ 28 | 26 3# 29 | 29 Space 30 | 2A V 31 | 2B F 32 | 2C T 33 | 2D R 34 | 2E 5% 35 | 31 N 36 | 32 B 37 | 33 H 38 | 34 G 39 | 35 Y 40 | 36 6^ 41 | 3A M 42 | 3B J 43 | 3C U 44 | 3D 7& 45 | 3E 8* 46 | 41 ,< 47 | 42 K 48 | 43 I 49 | 44 O 50 | 45 0) 51 | 46 9( 52 | 49 .> 53 | 4A /? 54 | 4B L 55 | 4C ;: 56 | 4D P 57 | 4E -_ 58 | 52 '" 59 | 54 [{ 60 | 55 =+ 61 | 58 CapsLock 62 | 59 Shift 63 | 5A Enter 64 | 5B ]} 65 | 5D \| 66 | 66 Backspace 67 | 69 KeyPad1 68 | 6B KeyPad4 69 | 6C KeyPad7 70 | 70 KeyPad0 71 | 71 KeyPad. 72 | 72 KeyPad2 73 | 73 KeyPad5 74 | 74 KeyPad6 75 | 75 KeyPad8 76 | 76 Escape 77 | 77 NumLock 78 | 78 F_11 79 | 79 KeyPad+ 80 | 7A KeyPad3 81 | 7B KeyPad- 82 | 7C KeyPad* 83 | 7D KeyPad9 84 | 7E ScrollLock 85 | 83 F_7 86 | E011 RightAlt 87 | E014 Ctrl 88 | E01F Windows 89 | E027 Windows 90 | E02F Menus 91 | E04A KeyPad/ 92 | E05A KeyPadEnter 93 | E069 End 94 | E06B LeftArrow 95 | E06C Home 96 | E070 Insert 97 | E071 Delete 98 | E072 DownArrow 99 | E074 RightArrow 100 | E075 UpArrow 101 | E07A PageDown 102 | E07C PrtScr 103 | E07D PageUp 104 | -------------------------------------------------------------------------------- /src/PS2_Monitor/FIFO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | template 7 | class FIFO { 8 | public: 9 | static_assert(N <= 256, "FIFO size cannot exceed 256 entries"); 10 | 11 | FIFO(); 12 | 13 | bool isFull() const; 14 | bool isEmpty() const; 15 | void push(T value); 16 | T pop(); 17 | 18 | private: 19 | uint8_t m_head; 20 | uint8_t m_tail; 21 | T m_buffer[N]; 22 | }; 23 | 24 | 25 | template 26 | inline FIFO::FIFO() : m_head(0), m_tail(0) 27 | { 28 | } 29 | 30 | 31 | template 32 | inline bool FIFO::isFull() const { 33 | // if the tail is right behind the head then there's no more space 34 | return (((m_tail + 1) % N) == m_head); 35 | } 36 | 37 | 38 | template 39 | inline bool FIFO::isEmpty() const { 40 | // if the tail isn't ahead of the head then we don't have any data 41 | return (m_head == m_tail); 42 | } 43 | 44 | 45 | template 46 | inline void FIFO::push(T value) { 47 | uint8_t next_tail = (m_tail + 1) % N; 48 | if(next_tail != m_head) { 49 | m_buffer[m_tail] = value; 50 | m_tail = next_tail; 51 | } 52 | } 53 | 54 | 55 | template 56 | inline T FIFO::pop() { 57 | if(isEmpty()) { 58 | return 0; 59 | } 60 | 61 | T value = m_buffer[m_head]; 62 | m_head = (m_head + 1) % N; 63 | return value; 64 | } 65 | -------------------------------------------------------------------------------- /src/AppleII_PS2_Keyboard/FIFO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | template 7 | class FIFO { 8 | public: 9 | static_assert(N <= 256, "FIFO size cannot exceed 256 entries"); 10 | 11 | FIFO(); 12 | 13 | bool isFull() const; 14 | bool isEmpty() const; 15 | void push(T value); 16 | T pop(); 17 | 18 | private: 19 | uint8_t m_head; 20 | uint8_t m_tail; 21 | T m_buffer[N]; 22 | }; 23 | 24 | 25 | template 26 | inline FIFO::FIFO() : m_head(0), m_tail(0) 27 | { 28 | } 29 | 30 | 31 | template 32 | inline bool FIFO::isFull() const { 33 | // if the tail is right behind the head then there's no more space 34 | return (((m_tail + 1) % N) == m_head); 35 | } 36 | 37 | 38 | template 39 | inline bool FIFO::isEmpty() const { 40 | // if the tail isn't ahead of the head then we don't have any data 41 | return (m_head == m_tail); 42 | } 43 | 44 | 45 | template 46 | inline void FIFO::push(T value) { 47 | uint8_t next_tail = (m_tail + 1) % N; 48 | if(next_tail != m_head) { 49 | m_buffer[m_tail] = value; 50 | m_tail = next_tail; 51 | } 52 | } 53 | 54 | 55 | template 56 | inline T FIFO::pop() { 57 | if(isEmpty()) { 58 | return 0; 59 | } 60 | 61 | T value = m_buffer[m_head]; 62 | m_head = (m_head + 1) % N; 63 | return value; 64 | } 65 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-B_Paste.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:28-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Paste,Bot*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:28* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | G04 Aperture macros list* 15 | %AMRoundRect* 16 | 0 Rectangle with rounded corners* 17 | 0 $1 Rounding radius* 18 | 0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners* 19 | 0 Add a 4 corners polygon primitive as box body* 20 | 4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0* 21 | 0 Add four circle primitives for the rounded corners* 22 | 1,1,$1+$1,$2,$3* 23 | 1,1,$1+$1,$4,$5* 24 | 1,1,$1+$1,$6,$7* 25 | 1,1,$1+$1,$8,$9* 26 | 0 Add four rect primitives between the rounded corners* 27 | 20,1,$1+$1,$2,$3,$4,$5,0* 28 | 20,1,$1+$1,$4,$5,$6,$7,0* 29 | 20,1,$1+$1,$6,$7,$8,$9,0* 30 | 20,1,$1+$1,$8,$9,$2,$3,0*% 31 | G04 Aperture macros list end* 32 | %ADD10RoundRect,0.162500X0.837500X0.162500X-0.837500X0.162500X-0.837500X-0.162500X0.837500X-0.162500X0*% 33 | G04 APERTURE END LIST* 34 | D10* 35 | %TO.C,D1*% 36 | X154110000Y-84775000D03* 37 | X154110000Y-85725000D03* 38 | X154110000Y-86675000D03* 39 | X150690000Y-86675000D03* 40 | X150690000Y-85725000D03* 41 | X150690000Y-84775000D03* 42 | %TD*% 43 | M02* 44 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-B_Silkscreen.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:28-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Legend,Bot*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:28* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | %ADD10C,0.150000*% 15 | %ADD11C,0.120000*% 16 | G04 APERTURE END LIST* 17 | D10* 18 | X157583094Y-86179819D02* 19 | X157583094Y-85179819D01* 20 | X157583094Y-85179819D02* 21 | X157344999Y-85179819D01* 22 | X157344999Y-85179819D02* 23 | X157202142Y-85227438D01* 24 | X157202142Y-85227438D02* 25 | X157106904Y-85322676D01* 26 | X157106904Y-85322676D02* 27 | X157059285Y-85417914D01* 28 | X157059285Y-85417914D02* 29 | X157011666Y-85608390D01* 30 | X157011666Y-85608390D02* 31 | X157011666Y-85751247D01* 32 | X157011666Y-85751247D02* 33 | X157059285Y-85941723D01* 34 | X157059285Y-85941723D02* 35 | X157106904Y-86036961D01* 36 | X157106904Y-86036961D02* 37 | X157202142Y-86132200D01* 38 | X157202142Y-86132200D02* 39 | X157344999Y-86179819D01* 40 | X157344999Y-86179819D02* 41 | X157583094Y-86179819D01* 42 | X156059285Y-86179819D02* 43 | X156630713Y-86179819D01* 44 | X156344999Y-86179819D02* 45 | X156344999Y-85179819D01* 46 | X156344999Y-85179819D02* 47 | X156440237Y-85322676D01* 48 | X156440237Y-85322676D02* 49 | X156535475Y-85417914D01* 50 | X156535475Y-85417914D02* 51 | X156630713Y-85465533D01* 52 | D11* 53 | %TO.C,D1*% 54 | X152320000Y-84215000D02* 55 | X151520000Y-84215000D01* 56 | X152320000Y-84215000D02* 57 | X153120000Y-84215000D01* 58 | X153280000Y-87285000D02* 59 | X151520000Y-87285000D01* 60 | X153620000Y-84265000D02* 61 | X153380000Y-83935000D01* 62 | X153860000Y-83935000D01* 63 | X153620000Y-84265000D01* 64 | G36* 65 | X153620000Y-84265000D02* 66 | G01* 67 | X153380000Y-83935000D01* 68 | X153860000Y-83935000D01* 69 | X153620000Y-84265000D01* 70 | G37* 71 | %TD*% 72 | M02* 73 | -------------------------------------------------------------------------------- /src/PS2_Monitor/PS2Interface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "FIFO.h" 5 | #include "config.h" 6 | 7 | 8 | // Class to read and buffer the bytes from a PS/2 interface 9 | class PS2Interface { 10 | public: 11 | PS2Interface() : m_prevMillis(0), m_rxCount(-1), m_rxData(0) {} 12 | 13 | // Setup the I/O pins 14 | void setup(); 15 | 16 | // Returns the next data byte received from the keyboard or 0 if there is none. 17 | uint8_t getDataByte(); 18 | 19 | // Handles the falling clock edge by reading the next data bit 20 | void onClockFallingEdge(); 21 | 22 | private: 23 | unsigned long m_prevMillis; 24 | int8_t m_rxCount; 25 | uint8_t m_rxData; 26 | FIFO m_rxBuffer; 27 | }; 28 | 29 | 30 | void PS2Interface::setup() { 31 | pinMode(PS2_CLOCK_PIN, INPUT_PULLUP); 32 | pinMode(PS2_DATA_PIN, INPUT_PULLUP); 33 | } 34 | 35 | 36 | uint8_t PS2Interface::getDataByte() { 37 | noInterrupts(); 38 | uint8_t b = m_rxBuffer.pop(); 39 | interrupts(); 40 | return b; 41 | } 42 | 43 | 44 | void PS2Interface::onClockFallingEdge() { 45 | unsigned long now = millis(); 46 | if(now - m_prevMillis > 50) { 47 | // auto-reset if too long 48 | m_rxCount = -1; 49 | } 50 | m_prevMillis = now; 51 | 52 | int dataBit = digitalRead(PS2_DATA_PIN); 53 | if(m_rxCount < 0) { 54 | // check for a start bit 55 | if(dataBit == 0) { 56 | m_rxCount = 0; 57 | m_rxData = 0; 58 | } 59 | } else if(m_rxCount < 8) { 60 | // got a data bit, received LSB to MSB 61 | m_rxData |= (dataBit << m_rxCount); 62 | m_rxCount++; 63 | } else if(m_rxCount == 8) { 64 | // received the parity bit (odd) 65 | if(parity_even_bit(m_rxData) != dataBit) { 66 | m_rxCount++; 67 | } else { 68 | // bad parity 69 | m_rxCount = -1; 70 | } 71 | } else if(m_rxCount == 9) { 72 | // check for the stop bit 73 | if(dataBit == 1) { 74 | m_rxBuffer.push(m_rxData); 75 | } 76 | m_rxCount = -1; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/AppleII_PS2_Keyboard/PS2Interface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "FIFO.h" 5 | #include "config.h" 6 | 7 | 8 | // Class to read and buffer the bytes from a PS/2 interface 9 | class PS2Interface { 10 | public: 11 | PS2Interface() : m_prevMillis(0), m_rxCount(-1), m_rxData(0) {} 12 | 13 | // Setup the I/O pins 14 | void setup(); 15 | 16 | // Returns the next data byte received from the keyboard or 0 if there is none. 17 | uint8_t getDataByte(); 18 | 19 | // Handles the falling clock edge by reading the next data bit 20 | void onClockFallingEdge(); 21 | 22 | private: 23 | unsigned long m_prevMillis; 24 | int8_t m_rxCount; 25 | uint8_t m_rxData; 26 | FIFO m_rxBuffer; 27 | }; 28 | 29 | 30 | void PS2Interface::setup() { 31 | pinMode(PS2_CLOCK_PIN, INPUT_PULLUP); 32 | pinMode(PS2_DATA_PIN, INPUT_PULLUP); 33 | } 34 | 35 | 36 | uint8_t PS2Interface::getDataByte() { 37 | noInterrupts(); 38 | uint8_t b = m_rxBuffer.pop(); 39 | interrupts(); 40 | return b; 41 | } 42 | 43 | 44 | void PS2Interface::onClockFallingEdge() { 45 | unsigned long now = millis(); 46 | if(now - m_prevMillis > 50) { 47 | // auto-reset if too long 48 | m_rxCount = -1; 49 | } 50 | m_prevMillis = now; 51 | 52 | int dataBit = digitalRead(PS2_DATA_PIN); 53 | if(m_rxCount < 0) { 54 | // check for a start bit 55 | if(dataBit == 0) { 56 | m_rxCount = 0; 57 | m_rxData = 0; 58 | } 59 | } else if(m_rxCount < 8) { 60 | // got a data bit, received LSB to MSB 61 | m_rxData |= (dataBit << m_rxCount); 62 | m_rxCount++; 63 | } else if(m_rxCount == 8) { 64 | // received the parity bit (odd) 65 | if(parity_even_bit(m_rxData) != dataBit) { 66 | m_rxCount++; 67 | } else { 68 | // bad parity 69 | m_rxCount = -1; 70 | } 71 | } else if(m_rxCount == 9) { 72 | // check for the stop bit 73 | if(dataBit == 1) { 74 | m_rxBuffer.push(m_rxData); 75 | } 76 | m_rxCount = -1; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/PS2_Monitor/PS2_Monitor.ino: -------------------------------------------------------------------------------- 1 | // This sketch will receive codes from the PS2 keyboard and print them to the serial console 2 | 3 | #include "Arduino.h" 4 | #include "PS2Keyboard.h" 5 | #include "config.h" 6 | 7 | 8 | #if defined(ARDUINO_AVR_LEONARDO) 9 | # if ((PS2_CLOCK_PIN >= 8 && PS2_CLOCK_PIN <= 11) || (PS2_CLOCK_PIN >= 14 && PS2_CLOCK_PIN <= 17) || (PS2_CLOCK_PIN >= A8 && PS2_CLOCK_PIN <= A10)) 10 | # define USE_INTERRUPT_PCINT0 1 11 | # endif 12 | #elif defined(ARDUINO_ATTINY24_DIY) 13 | # if PS2_CLOCK_PIN < 8 14 | # define USE_INTERRUPT_PCINT0 1 15 | # else 16 | # define USE_INTERRUPT_PCINT1 1 17 | # endif 18 | #endif 19 | 20 | 21 | PS2Keyboard kbd; 22 | 23 | 24 | #if USE_INTERRUPT_PCINT0 25 | 26 | ISR(PCINT0_vect) { 27 | if(digitalRead(PS2_CLOCK_PIN) == 0) 28 | kbd.onClockFallingEdge(); 29 | } 30 | 31 | #elif USE_INTERRUPT_PCINT1 32 | 33 | ISR(PCINT1_vect) { 34 | if(digitalRead(PS2_CLOCK_PIN) == 0) 35 | kbd.onClockFallingEdge(); 36 | } 37 | 38 | #else 39 | 40 | void clockEdgeIntHandler() { 41 | kbd.onClockFallingEdge(); 42 | } 43 | 44 | #endif 45 | 46 | 47 | void setup() { 48 | #ifndef ARDUINO_ATTINY24_DIY 49 | Serial.begin(115200); 50 | #endif 51 | 52 | kbd.setup(); 53 | 54 | #if USE_INTERRUPT_PCINT0 || USE_INTERRUPT_PCINT1 55 | if(digitalPinToPCICR(PS2_CLOCK_PIN)) { 56 | // enable interrupt when the pin state changes 57 | *digitalPinToPCICR(PS2_CLOCK_PIN) |= (1 << digitalPinToPCICRbit(PS2_CLOCK_PIN)); 58 | *digitalPinToPCMSK(PS2_CLOCK_PIN) |= (1 << digitalPinToPCMSKbit(PS2_CLOCK_PIN)); 59 | } else 60 | #else 61 | if(digitalPinToInterrupt(PS2_CLOCK_PIN) != NOT_AN_INTERRUPT) { 62 | // attach external interrupt on pin's falling edge 63 | attachInterrupt(digitalPinToInterrupt(PS2_CLOCK_PIN), clockEdgeIntHandler, FALLING); 64 | } else 65 | #endif 66 | { 67 | // Cause a linking failure if the PS2_CLOCK_PIN doesn't support the interrupts. 68 | // This is preferable to failing silently at runtime. 69 | extern void invalid_PS2_CLOCK_PIN(); 70 | invalid_PS2_CLOCK_PIN(); 71 | } 72 | } 73 | 74 | 75 | void loop() { 76 | uint16_t d = kbd.getKeypress(); 77 | if(d != 0) { 78 | #ifndef ARDUINO_ATTINY24_DIY 79 | Serial.print(d, HEX); 80 | Serial.write('\n'); 81 | #endif 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-F_Mask.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:28-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Soldermask,Top*% 6 | %TF.FilePolarity,Negative*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:28* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | G04 Aperture macros list* 15 | %AMRoundRect* 16 | 0 Rectangle with rounded corners* 17 | 0 $1 Rounding radius* 18 | 0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners* 19 | 0 Add a 4 corners polygon primitive as box body* 20 | 4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0* 21 | 0 Add four circle primitives for the rounded corners* 22 | 1,1,$1+$1,$2,$3* 23 | 1,1,$1+$1,$4,$5* 24 | 1,1,$1+$1,$6,$7* 25 | 1,1,$1+$1,$8,$9* 26 | 0 Add four rect primitives between the rounded corners* 27 | 20,1,$1+$1,$2,$3,$4,$5,0* 28 | 20,1,$1+$1,$4,$5,$6,$7,0* 29 | 20,1,$1+$1,$6,$7,$8,$9,0* 30 | 20,1,$1+$1,$8,$9,$2,$3,0*% 31 | G04 Aperture macros list end* 32 | %ADD10C,1.600000*% 33 | %ADD11RoundRect,0.250000X0.550000X0.550000X-0.550000X0.550000X-0.550000X-0.550000X0.550000X-0.550000X0*% 34 | %ADD12R,1.700000X1.700000*% 35 | %ADD13C,1.700000*% 36 | G04 APERTURE END LIST* 37 | D10* 38 | %TO.C,C1*% 39 | X154940000Y-111125000D03* 40 | X147440000Y-111125000D03* 41 | %TD*% 42 | D11* 43 | %TO.C,J1*% 44 | X151130000Y-107950000D03* 45 | D10* 46 | X151130000Y-105410000D03* 47 | X151130000Y-102870000D03* 48 | X151130000Y-100330000D03* 49 | X151130000Y-97790000D03* 50 | X151130000Y-95250000D03* 51 | X151130000Y-92710000D03* 52 | X151130000Y-90170000D03* 53 | X143510000Y-90170000D03* 54 | X143510000Y-92710000D03* 55 | X143510000Y-95250000D03* 56 | X143510000Y-97790000D03* 57 | X143510000Y-100330000D03* 58 | X143510000Y-102870000D03* 59 | X143510000Y-105410000D03* 60 | X143510000Y-107950000D03* 61 | %TD*% 62 | D12* 63 | %TO.C,J2*% 64 | X153670000Y-80010000D03* 65 | D13* 66 | X153670000Y-82550000D03* 67 | X151130000Y-80010000D03* 68 | X151130000Y-82550000D03* 69 | X148590000Y-80010000D03* 70 | X148590000Y-82550000D03* 71 | X146050000Y-80010000D03* 72 | X146050000Y-82550000D03* 73 | %TD*% 74 | D11* 75 | %TO.C,U1*% 76 | X154940000Y-105410000D03* 77 | D10* 78 | X154940000Y-102870000D03* 79 | X154940000Y-100330000D03* 80 | X154940000Y-97790000D03* 81 | X154940000Y-95250000D03* 82 | X154940000Y-92710000D03* 83 | X154940000Y-90170000D03* 84 | X147320000Y-90170000D03* 85 | X147320000Y-92710000D03* 86 | X147320000Y-95250000D03* 87 | X147320000Y-97790000D03* 88 | X147320000Y-100330000D03* 89 | X147320000Y-102870000D03* 90 | X147320000Y-105410000D03* 91 | %TD*% 92 | M02* 93 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-B_Mask.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:28-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Soldermask,Bot*% 6 | %TF.FilePolarity,Negative*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:28* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | G04 Aperture macros list* 15 | %AMRoundRect* 16 | 0 Rectangle with rounded corners* 17 | 0 $1 Rounding radius* 18 | 0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners* 19 | 0 Add a 4 corners polygon primitive as box body* 20 | 4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0* 21 | 0 Add four circle primitives for the rounded corners* 22 | 1,1,$1+$1,$2,$3* 23 | 1,1,$1+$1,$4,$5* 24 | 1,1,$1+$1,$6,$7* 25 | 1,1,$1+$1,$8,$9* 26 | 0 Add four rect primitives between the rounded corners* 27 | 20,1,$1+$1,$2,$3,$4,$5,0* 28 | 20,1,$1+$1,$4,$5,$6,$7,0* 29 | 20,1,$1+$1,$6,$7,$8,$9,0* 30 | 20,1,$1+$1,$8,$9,$2,$3,0*% 31 | G04 Aperture macros list end* 32 | %ADD10C,1.600000*% 33 | %ADD11RoundRect,0.250000X0.550000X0.550000X-0.550000X0.550000X-0.550000X-0.550000X0.550000X-0.550000X0*% 34 | %ADD12R,1.700000X1.700000*% 35 | %ADD13C,1.700000*% 36 | %ADD14RoundRect,0.162500X0.837500X0.162500X-0.837500X0.162500X-0.837500X-0.162500X0.837500X-0.162500X0*% 37 | G04 APERTURE END LIST* 38 | D10* 39 | %TO.C,C1*% 40 | X154940000Y-111125000D03* 41 | X147440000Y-111125000D03* 42 | %TD*% 43 | D11* 44 | %TO.C,J1*% 45 | X151130000Y-107950000D03* 46 | D10* 47 | X151130000Y-105410000D03* 48 | X151130000Y-102870000D03* 49 | X151130000Y-100330000D03* 50 | X151130000Y-97790000D03* 51 | X151130000Y-95250000D03* 52 | X151130000Y-92710000D03* 53 | X151130000Y-90170000D03* 54 | X143510000Y-90170000D03* 55 | X143510000Y-92710000D03* 56 | X143510000Y-95250000D03* 57 | X143510000Y-97790000D03* 58 | X143510000Y-100330000D03* 59 | X143510000Y-102870000D03* 60 | X143510000Y-105410000D03* 61 | X143510000Y-107950000D03* 62 | %TD*% 63 | D12* 64 | %TO.C,J2*% 65 | X153670000Y-80010000D03* 66 | D13* 67 | X153670000Y-82550000D03* 68 | X151130000Y-80010000D03* 69 | X151130000Y-82550000D03* 70 | X148590000Y-80010000D03* 71 | X148590000Y-82550000D03* 72 | X146050000Y-80010000D03* 73 | X146050000Y-82550000D03* 74 | %TD*% 75 | D11* 76 | %TO.C,U1*% 77 | X154940000Y-105410000D03* 78 | D10* 79 | X154940000Y-102870000D03* 80 | X154940000Y-100330000D03* 81 | X154940000Y-97790000D03* 82 | X154940000Y-95250000D03* 83 | X154940000Y-92710000D03* 84 | X154940000Y-90170000D03* 85 | X147320000Y-90170000D03* 86 | X147320000Y-92710000D03* 87 | X147320000Y-95250000D03* 88 | X147320000Y-97790000D03* 89 | X147320000Y-100330000D03* 90 | X147320000Y-102870000D03* 91 | X147320000Y-105410000D03* 92 | %TD*% 93 | D14* 94 | %TO.C,D1*% 95 | X154110000Y-84775000D03* 96 | X154110000Y-85725000D03* 97 | X154110000Y-86675000D03* 98 | X150690000Y-86675000D03* 99 | X150690000Y-85725000D03* 100 | X150690000Y-84775000D03* 101 | %TD*% 102 | M02* 103 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-F_Silkscreen.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:46:20-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard-Connector,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Legend,Top*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:46:20* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | %ADD10C,0.100000*% 15 | %ADD11C,0.150000*% 16 | %ADD12C,0.120000*% 17 | %ADD13C,0.200000*% 18 | G04 APERTURE END LIST* 19 | D10* 20 | X143510000Y-107950000D02* 21 | X142240000Y-108585000D01* 22 | X142240000Y-107315000D01* 23 | X143510000Y-107950000D01* 24 | G36* 25 | X143510000Y-107950000D02* 26 | G01* 27 | X142240000Y-108585000D01* 28 | X142240000Y-107315000D01* 29 | X143510000Y-107950000D01* 30 | G37* 31 | D11* 32 | X142681666Y-105499819D02* 33 | X142681666Y-106214104D01* 34 | X142681666Y-106214104D02* 35 | X142634047Y-106356961D01* 36 | X142634047Y-106356961D02* 37 | X142538809Y-106452200D01* 38 | X142538809Y-106452200D02* 39 | X142395952Y-106499819D01* 40 | X142395952Y-106499819D02* 41 | X142300714Y-106499819D01* 42 | X143681666Y-106499819D02* 43 | X143110238Y-106499819D01* 44 | X143395952Y-106499819D02* 45 | X143395952Y-105499819D01* 46 | X143395952Y-105499819D02* 47 | X143300714Y-105642676D01* 48 | X143300714Y-105642676D02* 49 | X143205476Y-105737914D01* 50 | X143205476Y-105737914D02* 51 | X143110238Y-105785533D01* 52 | X139666666Y-92454819D02* 53 | X139666666Y-93169104D01* 54 | X139666666Y-93169104D02* 55 | X139619047Y-93311961D01* 56 | X139619047Y-93311961D02* 57 | X139523809Y-93407200D01* 58 | X139523809Y-93407200D02* 59 | X139380952Y-93454819D01* 60 | X139380952Y-93454819D02* 61 | X139285714Y-93454819D01* 62 | X140095238Y-92550057D02* 63 | X140142857Y-92502438D01* 64 | X140142857Y-92502438D02* 65 | X140238095Y-92454819D01* 66 | X140238095Y-92454819D02* 67 | X140476190Y-92454819D01* 68 | X140476190Y-92454819D02* 69 | X140571428Y-92502438D01* 70 | X140571428Y-92502438D02* 71 | X140619047Y-92550057D01* 72 | X140619047Y-92550057D02* 73 | X140666666Y-92645295D01* 74 | X140666666Y-92645295D02* 75 | X140666666Y-92740533D01* 76 | X140666666Y-92740533D02* 77 | X140619047Y-92883390D01* 78 | X140619047Y-92883390D02* 79 | X140047619Y-93454819D01* 80 | X140047619Y-93454819D02* 81 | X140666666Y-93454819D01* 82 | D12* 83 | %TO.C,J1*% 84 | X144810000Y-104030000D02* 85 | X155190000Y-104030000D01* 86 | X144810000Y-106680000D02* 87 | X144810000Y-104030000D01* 88 | X144810000Y-109330000D02* 89 | X144810000Y-107950000D01* 90 | X146190000Y-109330000D02* 91 | X144810000Y-109330000D01* 92 | X147460000Y-106680000D02* 93 | X144810000Y-106680000D01* 94 | X147460000Y-109330000D02* 95 | X147460000Y-106680000D01* 96 | X147460000Y-109330000D02* 97 | X155190000Y-109330000D01* 98 | X155190000Y-109330000D02* 99 | X155190000Y-104030000D01* 100 | D13* 101 | %TO.C,J2*% 102 | X142800000Y-99220000D02* 103 | X142800000Y-101220000D01* 104 | X142800000Y-101220000D02* 105 | X144800000Y-101220000D01* 106 | X157200000Y-99220000D02* 107 | X157200000Y-101220000D01* 108 | X157200000Y-101220000D02* 109 | X155200000Y-101220000D01* 110 | %TD*% 111 | M02* 112 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-job.gbrjob: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "GenerationSoftware": { 4 | "Vendor": "KiCad", 5 | "Application": "Pcbnew", 6 | "Version": "9.0.4" 7 | }, 8 | "CreationDate": "2025-09-30T15:31:28-04:00" 9 | }, 10 | "GeneralSpecs": { 11 | "ProjectId": { 12 | "Name": "AppleII-Keyboard", 13 | "GUID": "4170706c-6549-4492-9d4b-6579626f6172", 14 | "Revision": "B" 15 | }, 16 | "Size": { 17 | "X": 18.1, 18 | "Y": 35.1 19 | }, 20 | "LayerNumber": 2, 21 | "BoardThickness": 1.6, 22 | "Finish": "None" 23 | }, 24 | "DesignRules": [ 25 | { 26 | "Layers": "Outer", 27 | "PadToPad": 0.2, 28 | "PadToTrack": 0.2, 29 | "TrackToTrack": 0.2, 30 | "MinLineWidth": 0.2, 31 | "TrackToRegion": 0.6, 32 | "RegionToRegion": 0.6 33 | } 34 | ], 35 | "FilesAttributes": [ 36 | { 37 | "Path": "AppleII-Keyboard-F_Cu.gbr", 38 | "FileFunction": "Copper,L1,Top", 39 | "FilePolarity": "Positive" 40 | }, 41 | { 42 | "Path": "AppleII-Keyboard-B_Cu.gbr", 43 | "FileFunction": "Copper,L2,Bot", 44 | "FilePolarity": "Positive" 45 | }, 46 | { 47 | "Path": "AppleII-Keyboard-F_Paste.gbr", 48 | "FileFunction": "SolderPaste,Top", 49 | "FilePolarity": "Positive" 50 | }, 51 | { 52 | "Path": "AppleII-Keyboard-B_Paste.gbr", 53 | "FileFunction": "SolderPaste,Bot", 54 | "FilePolarity": "Positive" 55 | }, 56 | { 57 | "Path": "AppleII-Keyboard-F_Silkscreen.gbr", 58 | "FileFunction": "Legend,Top", 59 | "FilePolarity": "Positive" 60 | }, 61 | { 62 | "Path": "AppleII-Keyboard-B_Silkscreen.gbr", 63 | "FileFunction": "Legend,Bot", 64 | "FilePolarity": "Positive" 65 | }, 66 | { 67 | "Path": "AppleII-Keyboard-F_Mask.gbr", 68 | "FileFunction": "SolderMask,Top", 69 | "FilePolarity": "Negative" 70 | }, 71 | { 72 | "Path": "AppleII-Keyboard-B_Mask.gbr", 73 | "FileFunction": "SolderMask,Bot", 74 | "FilePolarity": "Negative" 75 | }, 76 | { 77 | "Path": "AppleII-Keyboard-Edge_Cuts.gbr", 78 | "FileFunction": "Profile", 79 | "FilePolarity": "Positive" 80 | } 81 | ], 82 | "MaterialStackup": [ 83 | { 84 | "Type": "Legend", 85 | "Name": "Top Silk Screen" 86 | }, 87 | { 88 | "Type": "SolderPaste", 89 | "Name": "Top Solder Paste" 90 | }, 91 | { 92 | "Type": "SolderMask", 93 | "Thickness": 0.01, 94 | "Name": "Top Solder Mask" 95 | }, 96 | { 97 | "Type": "Copper", 98 | "Thickness": 0.035, 99 | "Name": "F.Cu" 100 | }, 101 | { 102 | "Type": "Dielectric", 103 | "Thickness": 1.51, 104 | "Material": "FR4", 105 | "Name": "F.Cu/B.Cu", 106 | "Notes": "Type: dielectric layer 1 (from F.Cu to B.Cu)" 107 | }, 108 | { 109 | "Type": "Copper", 110 | "Thickness": 0.035, 111 | "Name": "B.Cu" 112 | }, 113 | { 114 | "Type": "SolderMask", 115 | "Thickness": 0.01, 116 | "Name": "Bottom Solder Mask" 117 | }, 118 | { 119 | "Type": "SolderPaste", 120 | "Name": "Bottom Solder Paste" 121 | }, 122 | { 123 | "Type": "Legend", 124 | "Name": "Bottom Silk Screen" 125 | } 126 | ] 127 | } 128 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-job.gbrjob: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "GenerationSoftware": { 4 | "Vendor": "KiCad", 5 | "Application": "Pcbnew", 6 | "Version": "9.0.4" 7 | }, 8 | "CreationDate": "2025-09-30T15:46:20-04:00" 9 | }, 10 | "GeneralSpecs": { 11 | "ProjectId": { 12 | "Name": "AppleII-Keyboard-Connector", 13 | "GUID": "4170706c-6549-4492-9d4b-6579626f6172", 14 | "Revision": "B" 15 | }, 16 | "Size": { 17 | "X": 30.1, 18 | "Y": 21.1 19 | }, 20 | "LayerNumber": 2, 21 | "BoardThickness": 1.6, 22 | "Finish": "None" 23 | }, 24 | "DesignRules": [ 25 | { 26 | "Layers": "Outer", 27 | "PadToPad": 0.2, 28 | "PadToTrack": 0.2, 29 | "TrackToTrack": 0.2, 30 | "MinLineWidth": 0.2, 31 | "TrackToRegion": 0.6, 32 | "RegionToRegion": 0.6 33 | } 34 | ], 35 | "FilesAttributes": [ 36 | { 37 | "Path": "AppleII-Keyboard-Connector-F_Cu.gbr", 38 | "FileFunction": "Copper,L1,Top", 39 | "FilePolarity": "Positive" 40 | }, 41 | { 42 | "Path": "AppleII-Keyboard-Connector-B_Cu.gbr", 43 | "FileFunction": "Copper,L2,Bot", 44 | "FilePolarity": "Positive" 45 | }, 46 | { 47 | "Path": "AppleII-Keyboard-Connector-F_Paste.gbr", 48 | "FileFunction": "SolderPaste,Top", 49 | "FilePolarity": "Positive" 50 | }, 51 | { 52 | "Path": "AppleII-Keyboard-Connector-B_Paste.gbr", 53 | "FileFunction": "SolderPaste,Bot", 54 | "FilePolarity": "Positive" 55 | }, 56 | { 57 | "Path": "AppleII-Keyboard-Connector-F_Silkscreen.gbr", 58 | "FileFunction": "Legend,Top", 59 | "FilePolarity": "Positive" 60 | }, 61 | { 62 | "Path": "AppleII-Keyboard-Connector-B_Silkscreen.gbr", 63 | "FileFunction": "Legend,Bot", 64 | "FilePolarity": "Positive" 65 | }, 66 | { 67 | "Path": "AppleII-Keyboard-Connector-F_Mask.gbr", 68 | "FileFunction": "SolderMask,Top", 69 | "FilePolarity": "Negative" 70 | }, 71 | { 72 | "Path": "AppleII-Keyboard-Connector-B_Mask.gbr", 73 | "FileFunction": "SolderMask,Bot", 74 | "FilePolarity": "Negative" 75 | }, 76 | { 77 | "Path": "AppleII-Keyboard-Connector-Edge_Cuts.gbr", 78 | "FileFunction": "Profile", 79 | "FilePolarity": "Positive" 80 | } 81 | ], 82 | "MaterialStackup": [ 83 | { 84 | "Type": "Legend", 85 | "Name": "Top Silk Screen" 86 | }, 87 | { 88 | "Type": "SolderPaste", 89 | "Name": "Top Solder Paste" 90 | }, 91 | { 92 | "Type": "SolderMask", 93 | "Thickness": 0.01, 94 | "Name": "Top Solder Mask" 95 | }, 96 | { 97 | "Type": "Copper", 98 | "Thickness": 0.035, 99 | "Name": "F.Cu" 100 | }, 101 | { 102 | "Type": "Dielectric", 103 | "Thickness": 1.51, 104 | "Material": "FR4", 105 | "Name": "F.Cu/B.Cu", 106 | "Notes": "Type: dielectric layer 1 (from F.Cu to B.Cu)" 107 | }, 108 | { 109 | "Type": "Copper", 110 | "Thickness": 0.035, 111 | "Name": "B.Cu" 112 | }, 113 | { 114 | "Type": "SolderMask", 115 | "Thickness": 0.01, 116 | "Name": "Bottom Solder Mask" 117 | }, 118 | { 119 | "Type": "SolderPaste", 120 | "Name": "Bottom Solder Paste" 121 | }, 122 | { 123 | "Type": "Legend", 124 | "Name": "Bottom Silk Screen" 125 | } 126 | ] 127 | } 128 | -------------------------------------------------------------------------------- /src/AppleII_PS2_Keyboard/AppleII_PS2_Keyboard.ino: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include "PS2Keyboard.h" 3 | #include "AppleIIKeyboardTranslation.h" 4 | #include "Latch7.h" 5 | #include "config.h" 6 | 7 | 8 | // Arduino IDE settings for Arduino Pro Micro clone: 9 | // 1. Under Tools->Board, select the Arduino Leonardo type from the Arduino AVR Boards 10 | // 11 | // Arduino IDE board settings for ATtiny 12 | // 1. Install the DIY-ATtiny board package (https://raw.githubusercontent.com/sleemanj/optiboot/master/dists/package_gogo_diy_attiny_index.json) 13 | // 2. Under Tools->Board, select the ATtiny24 type from the DIY-ATtiny board type 14 | // 3. Under Tools->Processor Version, select ATtiny24a 15 | // 4. Under Tools->Use Bootloader, select No 16 | // 5. Under Tools->Override Clock Source, select Internal Oscillator 8MHz 17 | 18 | 19 | #define ENABLE_SERIAL_DEBUG 0 20 | 21 | #if defined(ARDUINO_AVR_LEONARDO) 22 | # if ((PS2_CLOCK_PIN >= 8 && PS2_CLOCK_PIN <= 11) || (PS2_CLOCK_PIN >= 14 && PS2_CLOCK_PIN <= 17) || (PS2_CLOCK_PIN >= A8 && PS2_CLOCK_PIN <= A10)) 23 | # define USE_INTERRUPT_PCINT0 1 24 | # endif 25 | #elif defined(ARDUINO_ATTINY24_DIY) 26 | # if PS2_CLOCK_PIN < 8 27 | # define USE_INTERRUPT_PCINT0 1 28 | # else 29 | # define USE_INTERRUPT_PCINT1 1 30 | # endif 31 | #endif 32 | 33 | 34 | PS2Keyboard kbd; 35 | AppleIIKeyboardTranslation appleKbd(kbd); 36 | Latch7 appleOutputLatch; 37 | 38 | 39 | #if USE_INTERRUPT_PCINT0 40 | 41 | ISR(PCINT0_vect) { 42 | if(digitalRead(PS2_CLOCK_PIN) == 0) 43 | kbd.onClockFallingEdge(); 44 | } 45 | 46 | #elif USE_INTERRUPT_PCINT1 47 | 48 | ISR(PCINT1_vect) { 49 | if(digitalRead(PS2_CLOCK_PIN) == 0) 50 | kbd.onClockFallingEdge(); 51 | } 52 | 53 | #else 54 | 55 | void clockEdgeIntHandler() { 56 | kbd.onClockFallingEdge(); 57 | } 58 | 59 | #endif 60 | 61 | 62 | void setup() { 63 | #if ENABLE_SERIAL_DEBUG 64 | Serial.begin(115200); 65 | #endif 66 | 67 | appleOutputLatch.setup(); 68 | 69 | // leave AII_RESET_PIN configured as an INPUT so it floats 70 | digitalWrite(AII_RESET_PIN, 0); // drive low when the pin is set to output 71 | 72 | kbd.setup(); 73 | #if USE_INTERRUPT_PCINT0 || USE_INTERRUPT_PCINT1 74 | if(digitalPinToPCICR(PS2_CLOCK_PIN)) { 75 | // enable interrupt when the pin state changes 76 | *digitalPinToPCICR(PS2_CLOCK_PIN) |= (1 << digitalPinToPCICRbit(PS2_CLOCK_PIN)); 77 | *digitalPinToPCMSK(PS2_CLOCK_PIN) |= (1 << digitalPinToPCMSKbit(PS2_CLOCK_PIN)); 78 | } else 79 | #else 80 | if(digitalPinToInterrupt(PS2_CLOCK_PIN) != NOT_AN_INTERRUPT) { 81 | // attach external interrupt on pin's falling edge 82 | attachInterrupt(digitalPinToInterrupt(PS2_CLOCK_PIN), clockEdgeIntHandler, FALLING); 83 | } else 84 | #endif 85 | { 86 | // Cause a linking failure if the PS2_CLOCK_PIN doesn't support the interrupts. 87 | // This is preferable to failing silently at runtime. 88 | extern void invalid_PS2_CLOCK_PIN(); 89 | invalid_PS2_CLOCK_PIN(); 90 | } 91 | } 92 | 93 | 94 | void loop() { 95 | uint8_t d = appleKbd.getKeyCode(); 96 | if(d != 0) { 97 | #if ENABLE_SERIAL_DEBUG 98 | Serial.print(d, HEX); 99 | Serial.write('\n'); 100 | #endif 101 | 102 | if(d == 0xff) { 103 | // Special reset key sequence was pressed 104 | pinMode(AII_RESET_PIN, OUTPUT); // drive low 105 | delay(100); 106 | pinMode(AII_RESET_PIN, INPUT); // back to floating 107 | } else { 108 | appleOutputLatch.write(d); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/Libraries/footprints/Connector_Project.pretty/Mini_DIN_round_6_canned.kicad_mod: -------------------------------------------------------------------------------- 1 | (footprint "Mini_DIN_round_6_canned" 2 | (version 20241229) 3 | (generator "pcbnew") 4 | (generator_version "9.0") 5 | (layer "F.Cu") 6 | (tags "din minidin shielded") 7 | (property "Reference" "REF**" 8 | (at 0 -1.524 0) 9 | (unlocked yes) 10 | (layer "F.SilkS") 11 | (uuid "617602f2-b64f-41fe-bcaa-6cdf6d4fd3e6") 12 | (effects 13 | (font 14 | (size 1 1) 15 | (thickness 0.15) 16 | ) 17 | ) 18 | ) 19 | (property "Value" "Mini_DIN_round_6_canned" 20 | (at 0 -4.064 0) 21 | (unlocked yes) 22 | (layer "F.Fab") 23 | (uuid "2cf11d02-23b5-403f-8360-d0186bb8a37c") 24 | (effects 25 | (font 26 | (size 1 1) 27 | (thickness 0.15) 28 | ) 29 | ) 30 | ) 31 | (property "Datasheet" "" 32 | (at 0 0 0) 33 | (unlocked yes) 34 | (layer "F.Fab") 35 | (uuid "23302d16-d3ce-4156-a17d-cb4a21e620dd") 36 | (effects 37 | (font 38 | (size 1 1) 39 | (thickness 0.15) 40 | ) 41 | ) 42 | ) 43 | (property "Description" "" 44 | (at 0 0 0) 45 | (unlocked yes) 46 | (layer "F.Fab") 47 | (hide yes) 48 | (uuid "fdb5ef5c-d14c-46cb-992f-7af6b715f96d") 49 | (effects 50 | (font 51 | (size 1 1) 52 | (thickness 0.15) 53 | ) 54 | ) 55 | ) 56 | (property "Part" "Kycon KMDGX-6S-BS" 57 | (at 0 0 0) 58 | (layer "F.SilkS") 59 | (hide yes) 60 | (uuid "6a871e8a-bd65-48b5-bf70-0ceacb87a2bb") 61 | (effects 62 | (font 63 | (size 1 1) 64 | (thickness 0.1) 65 | ) 66 | ) 67 | ) 68 | (attr through_hole) 69 | (fp_line 70 | (start -7.2 11.2) 71 | (end -7.2 13.2) 72 | (stroke 73 | (width 0.2) 74 | (type solid) 75 | ) 76 | (layer "F.SilkS") 77 | (uuid "43463132-e058-4fff-8e4f-68d8e66afac6") 78 | ) 79 | (fp_line 80 | (start -7.2 13.2) 81 | (end -5.2 13.2) 82 | (stroke 83 | (width 0.2) 84 | (type solid) 85 | ) 86 | (layer "F.SilkS") 87 | (uuid "d2b0c4fd-e990-4f26-b3f5-5c4e9f88ce0c") 88 | ) 89 | (fp_line 90 | (start 7.2 11.2) 91 | (end 7.2 13.2) 92 | (stroke 93 | (width 0.2) 94 | (type solid) 95 | ) 96 | (layer "F.SilkS") 97 | (uuid "b0c807e3-9cc3-440b-9ce3-00835edc688c") 98 | ) 99 | (fp_line 100 | (start 7.2 13.2) 101 | (end 5.2 13.2) 102 | (stroke 103 | (width 0.2) 104 | (type solid) 105 | ) 106 | (layer "F.SilkS") 107 | (uuid "3425069d-9416-4815-9613-ee353f7252aa") 108 | ) 109 | (fp_rect 110 | (start -7 0) 111 | (end 7 13) 112 | (stroke 113 | (width 0.05) 114 | (type default) 115 | ) 116 | (fill no) 117 | (layer "F.CrtYd") 118 | (uuid "037df7a0-ecf2-416e-9e91-c291d504032b") 119 | ) 120 | (pad "1" thru_hole circle 121 | (at -1.3 8.5 90) 122 | (size 1.2 1.2) 123 | (drill 0.8) 124 | (layers "*.Cu" "*.Mask") 125 | (remove_unused_layers no) 126 | (uuid "ee3e9e25-fa48-4c0c-a5dd-7bb7e3ed3e32") 127 | ) 128 | (pad "2" thru_hole circle 129 | (at 1.3 8.5 90) 130 | (size 1.2 1.2) 131 | (drill 0.8) 132 | (layers "*.Cu" "*.Mask") 133 | (remove_unused_layers no) 134 | (uuid "99bf4919-351c-48bc-9005-a93e8a4dc2c2") 135 | ) 136 | (pad "3" thru_hole circle 137 | (at -3.4 8.5 90) 138 | (size 1.2 1.2) 139 | (drill 0.8) 140 | (layers "*.Cu" "*.Mask") 141 | (remove_unused_layers no) 142 | (uuid "109ce654-d76c-45f0-b984-00323c21e430") 143 | ) 144 | (pad "4" thru_hole circle 145 | (at 3.4 8.5 90) 146 | (size 1.2 1.2) 147 | (drill 0.8) 148 | (layers "*.Cu" "*.Mask") 149 | (remove_unused_layers no) 150 | (uuid "43ba3583-39e3-494a-b0f1-e4b316fa95c1") 151 | ) 152 | (pad "5" thru_hole circle 153 | (at -3.4 11 90) 154 | (size 1.2 1.2) 155 | (drill 0.8) 156 | (layers "*.Cu" "*.Mask") 157 | (remove_unused_layers no) 158 | (uuid "10aa232c-c2f6-4a57-ab15-900c429f2045") 159 | ) 160 | (pad "6" thru_hole circle 161 | (at 3.4 11 90) 162 | (size 1.2 1.2) 163 | (drill 0.8) 164 | (layers "*.Cu" "*.Mask") 165 | (remove_unused_layers no) 166 | (uuid "a9ea2f5b-9a48-4586-a59d-e1b58a6c1c3a") 167 | ) 168 | (pad "SH" thru_hole circle 169 | (at -6.75 5.5) 170 | (size 3.3 3.3) 171 | (drill 2.3) 172 | (layers "*.Cu" "*.Mask") 173 | (remove_unused_layers no) 174 | (uuid "5c5f1002-9994-4dbb-850a-8ebcdf028d83") 175 | ) 176 | (pad "SH" thru_hole circle 177 | (at 0 4.7) 178 | (size 3.3 3.3) 179 | (drill 2.3) 180 | (layers "*.Cu" "*.Mask") 181 | (remove_unused_layers no) 182 | (uuid "e9c30154-638b-4874-97ec-7f693b7ad3e1") 183 | ) 184 | (pad "SH" thru_hole circle 185 | (at 6.75 5.5) 186 | (size 3.3 3.3) 187 | (drill 2.3) 188 | (layers "*.Cu" "*.Mask") 189 | (remove_unused_layers no) 190 | (uuid "ff1d874f-199d-4200-8432-e717b3cbae66") 191 | ) 192 | (embedded_fonts no) 193 | (model "Conn_Mini_DIN_round_6_canned.stp" 194 | (offset 195 | (xyz 0 -6.5 0) 196 | ) 197 | (scale 198 | (xyz 1 1 1) 199 | ) 200 | (rotate 201 | (xyz 0 0 180) 202 | ) 203 | ) 204 | ) 205 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/outputs/AppleII-Keyboard-Connector-NPTH-drl_map.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:46:30-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard-Connector,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Drillmap*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX45Y45*% 8 | G04 Gerber Fmt 4.5, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:46:30* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | %ADD10C,0.100000*% 15 | %ADD11C,0.200000*% 16 | G04 APERTURE END LIST* 17 | D10* 18 | X13500000Y-9000000D02* 19 | X16500000Y-9000000D01* 20 | X15900000Y-11100000D02* 21 | X14100000Y-11100000D01* 22 | X16500000Y-9000000D02* 23 | X16500000Y-10500000D01* 24 | X13500000Y-10500000D02* 25 | X13500000Y-9000000D01* 26 | X14100000Y-11100000D02* 27 | X13500000Y-10500000D01* 28 | X16500000Y-10500000D02* 29 | X15900000Y-11100000D01* 30 | D11* 31 | X13755777Y-11416484D02* 32 | X13755777Y-11216484D01* 33 | X13755777Y-11216484D02* 34 | X13803396Y-11216484D01* 35 | X13803396Y-11216484D02* 36 | X13831967Y-11226008D01* 37 | X13831967Y-11226008D02* 38 | X13851015Y-11245055D01* 39 | X13851015Y-11245055D02* 40 | X13860539Y-11264103D01* 41 | X13860539Y-11264103D02* 42 | X13870062Y-11302198D01* 43 | X13870062Y-11302198D02* 44 | X13870062Y-11330769D01* 45 | X13870062Y-11330769D02* 46 | X13860539Y-11368865D01* 47 | X13860539Y-11368865D02* 48 | X13851015Y-11387912D01* 49 | X13851015Y-11387912D02* 50 | X13831967Y-11406960D01* 51 | X13831967Y-11406960D02* 52 | X13803396Y-11416484D01* 53 | X13803396Y-11416484D02* 54 | X13755777Y-11416484D01* 55 | X13955777Y-11416484D02* 56 | X13955777Y-11283150D01* 57 | X13955777Y-11321246D02* 58 | X13965301Y-11302198D01* 59 | X13965301Y-11302198D02* 60 | X13974824Y-11292674D01* 61 | X13974824Y-11292674D02* 62 | X13993872Y-11283150D01* 63 | X13993872Y-11283150D02* 64 | X14012920Y-11283150D01* 65 | X14079586Y-11416484D02* 66 | X14079586Y-11283150D01* 67 | X14079586Y-11216484D02* 68 | X14070062Y-11226008D01* 69 | X14070062Y-11226008D02* 70 | X14079586Y-11235531D01* 71 | X14079586Y-11235531D02* 72 | X14089110Y-11226008D01* 73 | X14089110Y-11226008D02* 74 | X14079586Y-11216484D01* 75 | X14079586Y-11216484D02* 76 | X14079586Y-11235531D01* 77 | X14203396Y-11416484D02* 78 | X14184348Y-11406960D01* 79 | X14184348Y-11406960D02* 80 | X14174824Y-11387912D01* 81 | X14174824Y-11387912D02* 82 | X14174824Y-11216484D01* 83 | X14308158Y-11416484D02* 84 | X14289110Y-11406960D01* 85 | X14289110Y-11406960D02* 86 | X14279586Y-11387912D01* 87 | X14279586Y-11387912D02* 88 | X14279586Y-11216484D01* 89 | X14536729Y-11416484D02* 90 | X14536729Y-11216484D01* 91 | X14536729Y-11216484D02* 92 | X14603396Y-11359341D01* 93 | X14603396Y-11359341D02* 94 | X14670062Y-11216484D01* 95 | X14670062Y-11216484D02* 96 | X14670062Y-11416484D01* 97 | X14851015Y-11416484D02* 98 | X14851015Y-11311722D01* 99 | X14851015Y-11311722D02* 100 | X14841491Y-11292674D01* 101 | X14841491Y-11292674D02* 102 | X14822443Y-11283150D01* 103 | X14822443Y-11283150D02* 104 | X14784348Y-11283150D01* 105 | X14784348Y-11283150D02* 106 | X14765301Y-11292674D01* 107 | X14851015Y-11406960D02* 108 | X14831967Y-11416484D01* 109 | X14831967Y-11416484D02* 110 | X14784348Y-11416484D01* 111 | X14784348Y-11416484D02* 112 | X14765301Y-11406960D01* 113 | X14765301Y-11406960D02* 114 | X14755777Y-11387912D01* 115 | X14755777Y-11387912D02* 116 | X14755777Y-11368865D01* 117 | X14755777Y-11368865D02* 118 | X14765301Y-11349817D01* 119 | X14765301Y-11349817D02* 120 | X14784348Y-11340293D01* 121 | X14784348Y-11340293D02* 122 | X14831967Y-11340293D01* 123 | X14831967Y-11340293D02* 124 | X14851015Y-11330769D01* 125 | X14946253Y-11283150D02* 126 | X14946253Y-11483150D01* 127 | X14946253Y-11292674D02* 128 | X14965301Y-11283150D01* 129 | X14965301Y-11283150D02* 130 | X15003396Y-11283150D01* 131 | X15003396Y-11283150D02* 132 | X15022443Y-11292674D01* 133 | X15022443Y-11292674D02* 134 | X15031967Y-11302198D01* 135 | X15031967Y-11302198D02* 136 | X15041491Y-11321246D01* 137 | X15041491Y-11321246D02* 138 | X15041491Y-11378388D01* 139 | X15041491Y-11378388D02* 140 | X15031967Y-11397436D01* 141 | X15031967Y-11397436D02* 142 | X15022443Y-11406960D01* 143 | X15022443Y-11406960D02* 144 | X15003396Y-11416484D01* 145 | X15003396Y-11416484D02* 146 | X14965301Y-11416484D01* 147 | X14965301Y-11416484D02* 148 | X14946253Y-11406960D01* 149 | X15127205Y-11397436D02* 150 | X15136729Y-11406960D01* 151 | X15136729Y-11406960D02* 152 | X15127205Y-11416484D01* 153 | X15127205Y-11416484D02* 154 | X15117682Y-11406960D01* 155 | X15117682Y-11406960D02* 156 | X15127205Y-11397436D01* 157 | X15127205Y-11397436D02* 158 | X15127205Y-11416484D01* 159 | X15127205Y-11292674D02* 160 | X15136729Y-11302198D01* 161 | X15136729Y-11302198D02* 162 | X15127205Y-11311722D01* 163 | X15127205Y-11311722D02* 164 | X15117682Y-11302198D01* 165 | X15117682Y-11302198D02* 166 | X15127205Y-11292674D01* 167 | X15127205Y-11292674D02* 168 | X15127205Y-11311722D01* 169 | M02* 170 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-NPTH-drl_map.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:31-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Drillmap*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX45Y45*% 8 | G04 Gerber Fmt 4.5, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:31* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | %ADD10C,0.100000*% 15 | %ADD11C,0.200000*% 16 | G04 APERTURE END LIST* 17 | D10* 18 | X14200000Y-11300000D02* 19 | X14100000Y-11200000D01* 20 | X14200000Y-7800000D02* 21 | X15800000Y-7800000D01* 22 | X14100000Y-11200000D02* 23 | X14100000Y-7900000D01* 24 | X14100000Y-7900000D02* 25 | X14200000Y-7800000D01* 26 | X15800000Y-7800000D02* 27 | X15900000Y-7900000D01* 28 | X15900000Y-7900000D02* 29 | X15900000Y-11200000D01* 30 | X15900000Y-11200000D02* 31 | X15800000Y-11300000D01* 32 | X15800000Y-11300000D02* 33 | X14200000Y-11300000D01* 34 | D11* 35 | X14355777Y-11616484D02* 36 | X14355777Y-11416484D01* 37 | X14355777Y-11416484D02* 38 | X14403396Y-11416484D01* 39 | X14403396Y-11416484D02* 40 | X14431967Y-11426008D01* 41 | X14431967Y-11426008D02* 42 | X14451015Y-11445055D01* 43 | X14451015Y-11445055D02* 44 | X14460539Y-11464103D01* 45 | X14460539Y-11464103D02* 46 | X14470062Y-11502198D01* 47 | X14470062Y-11502198D02* 48 | X14470062Y-11530769D01* 49 | X14470062Y-11530769D02* 50 | X14460539Y-11568865D01* 51 | X14460539Y-11568865D02* 52 | X14451015Y-11587912D01* 53 | X14451015Y-11587912D02* 54 | X14431967Y-11606960D01* 55 | X14431967Y-11606960D02* 56 | X14403396Y-11616484D01* 57 | X14403396Y-11616484D02* 58 | X14355777Y-11616484D01* 59 | X14555777Y-11616484D02* 60 | X14555777Y-11483150D01* 61 | X14555777Y-11521246D02* 62 | X14565301Y-11502198D01* 63 | X14565301Y-11502198D02* 64 | X14574824Y-11492674D01* 65 | X14574824Y-11492674D02* 66 | X14593872Y-11483150D01* 67 | X14593872Y-11483150D02* 68 | X14612920Y-11483150D01* 69 | X14679586Y-11616484D02* 70 | X14679586Y-11483150D01* 71 | X14679586Y-11416484D02* 72 | X14670062Y-11426008D01* 73 | X14670062Y-11426008D02* 74 | X14679586Y-11435531D01* 75 | X14679586Y-11435531D02* 76 | X14689110Y-11426008D01* 77 | X14689110Y-11426008D02* 78 | X14679586Y-11416484D01* 79 | X14679586Y-11416484D02* 80 | X14679586Y-11435531D01* 81 | X14803396Y-11616484D02* 82 | X14784348Y-11606960D01* 83 | X14784348Y-11606960D02* 84 | X14774824Y-11587912D01* 85 | X14774824Y-11587912D02* 86 | X14774824Y-11416484D01* 87 | X14908158Y-11616484D02* 88 | X14889110Y-11606960D01* 89 | X14889110Y-11606960D02* 90 | X14879586Y-11587912D01* 91 | X14879586Y-11587912D02* 92 | X14879586Y-11416484D01* 93 | X15136729Y-11616484D02* 94 | X15136729Y-11416484D01* 95 | X15136729Y-11416484D02* 96 | X15203396Y-11559341D01* 97 | X15203396Y-11559341D02* 98 | X15270062Y-11416484D01* 99 | X15270062Y-11416484D02* 100 | X15270062Y-11616484D01* 101 | X15451015Y-11616484D02* 102 | X15451015Y-11511722D01* 103 | X15451015Y-11511722D02* 104 | X15441491Y-11492674D01* 105 | X15441491Y-11492674D02* 106 | X15422443Y-11483150D01* 107 | X15422443Y-11483150D02* 108 | X15384348Y-11483150D01* 109 | X15384348Y-11483150D02* 110 | X15365301Y-11492674D01* 111 | X15451015Y-11606960D02* 112 | X15431967Y-11616484D01* 113 | X15431967Y-11616484D02* 114 | X15384348Y-11616484D01* 115 | X15384348Y-11616484D02* 116 | X15365301Y-11606960D01* 117 | X15365301Y-11606960D02* 118 | X15355777Y-11587912D01* 119 | X15355777Y-11587912D02* 120 | X15355777Y-11568865D01* 121 | X15355777Y-11568865D02* 122 | X15365301Y-11549817D01* 123 | X15365301Y-11549817D02* 124 | X15384348Y-11540293D01* 125 | X15384348Y-11540293D02* 126 | X15431967Y-11540293D01* 127 | X15431967Y-11540293D02* 128 | X15451015Y-11530769D01* 129 | X15546253Y-11483150D02* 130 | X15546253Y-11683150D01* 131 | X15546253Y-11492674D02* 132 | X15565301Y-11483150D01* 133 | X15565301Y-11483150D02* 134 | X15603396Y-11483150D01* 135 | X15603396Y-11483150D02* 136 | X15622443Y-11492674D01* 137 | X15622443Y-11492674D02* 138 | X15631967Y-11502198D01* 139 | X15631967Y-11502198D02* 140 | X15641491Y-11521246D01* 141 | X15641491Y-11521246D02* 142 | X15641491Y-11578388D01* 143 | X15641491Y-11578388D02* 144 | X15631967Y-11597436D01* 145 | X15631967Y-11597436D02* 146 | X15622443Y-11606960D01* 147 | X15622443Y-11606960D02* 148 | X15603396Y-11616484D01* 149 | X15603396Y-11616484D02* 150 | X15565301Y-11616484D01* 151 | X15565301Y-11616484D02* 152 | X15546253Y-11606960D01* 153 | X15727205Y-11597436D02* 154 | X15736729Y-11606960D01* 155 | X15736729Y-11606960D02* 156 | X15727205Y-11616484D01* 157 | X15727205Y-11616484D02* 158 | X15717682Y-11606960D01* 159 | X15717682Y-11606960D02* 160 | X15727205Y-11597436D01* 161 | X15727205Y-11597436D02* 162 | X15727205Y-11616484D01* 163 | X15727205Y-11492674D02* 164 | X15736729Y-11502198D01* 165 | X15736729Y-11502198D02* 166 | X15727205Y-11511722D01* 167 | X15727205Y-11511722D02* 168 | X15717682Y-11502198D01* 169 | X15717682Y-11502198D02* 170 | X15727205Y-11492674D01* 171 | X15727205Y-11492674D02* 172 | X15727205Y-11511722D01* 173 | M02* 174 | -------------------------------------------------------------------------------- /src/AppleII_PS2_Keyboard/build/diy_attiny.avr.attiny24_diy/AppleII_PS2_Keyboard.ino.hex: -------------------------------------------------------------------------------- 1 | :10000000F9C010C10FC134C10DC10CC10BC10AC16F 2 | :1000100009C108C107C107C105C104C103C102C1AB 3 | :1000200001C18888888800000000000000000000EE 4 | :1000300000000000000000000000000000000000C0 5 | :10004000000000000000959595950000000000005C 6 | :1000500000000000000000000000000000000000A0 7 | :100060000000000000000000FFFFD1D19191B1A17C 8 | :10007000B1A1000000000000000000000000DADA7A 9 | :100080009A9AD3D39393C1C18181D7D79797B2C09E 10 | :10009000B2C00000000000000000C3C38383D8D8B2 11 | :1000A0009898C4C48484C5C58585B4A4B4A4B3A3F6 12 | :1000B000B3A30000000000000000A0A0A0A0D6D6BE 13 | :1000C0009696C6C68686D4D49494D2D29292B5A57A 14 | :1000D000B5A50000000000000000CECE8E9EC2C27A 15 | :1000E0008282C8C88888C7C78787D9D99999B6DE58 16 | :1000F000B6DE000000000000000000000000CDCDD2 17 | :100100008E9DCACA8A8AD5D59595B7A6B7A6B8AA2C 18 | :10011000B8AA0000000000000000ACBCACBCCBCB17 19 | :100120008B8BC9C98989CFCF8F8FB0A9B0A9B9A846 20 | :10013000B9A80000000000000000AEBEAEBEAFBF18 21 | :10014000AFBFCCCC8C8CBBBABBBAD0D09080ADAD9D 22 | :10015000ADAD000000000000000000000000A7A2FC 23 | :10016000A7A20000000000000000BDABBDAB000076 24 | :1001700000000000000000000000000000008D8D65 25 | :100180008D8DDDDDDDDD00000000000000000000E1 26 | :10019000000000000000000000000000000000005F 27 | :1001A000000000000000000000000000000000004F 28 | :1001B000000000000000000000000000000000003F 29 | :1001C000000000000000000000000000000000002F 30 | :1001D000000000000000000000000000000000001F 31 | :1001E00000000000000000000000000000009B9BD9 32 | :1001F0009B9B190311241FBECFEDCDBF20E0A0E6CD 33 | :10020000B0E001C01D92A03CB207E1F710E0CAEFD8 34 | :10021000D0E003C02197FE0129D2C93FD107D1F711 35 | :10022000EDD02AC2EDCE1F920F920FB60F9211247D 36 | :100230008F939F93AF93BF938091600090916100E3 37 | :10024000A0916200B09163000196A11DB11D809341 38 | :10025000600090936100A0936200B0936300BF912F 39 | :10026000AF919F918F910F900FBE0F901F90189597 40 | :100270001F920F920FB60F921124CF92DF92EF923E 41 | :10028000FF920F931F932F933F934F935F936F931F 42 | :100290008F939F93AF93BF93EF93FF93B0995AC0FF 43 | :1002A0006FB7F8948091600090916100A091620016 44 | :1002B000B09163008091600090916100A091620014 45 | :1002C000B091630000916000109161002091620084 46 | :1002D0003091630042E0B695A795979587954A952A 47 | :1002E000D1F7012F122F232F3327800F911FA21F29 48 | :1002F000B31F6FBF009164001091650020916600EC 49 | :10030000309167006C017D01C01AD10AE20AF30A3C 50 | :1003100097018601033311052105310518F02FEFF0 51 | :10032000209368008093640090936500A09366001A 52 | :10033000B093670086B321E0982F927081FF20E090 53 | :100340008091680087FF1CC0911104C01092680062 54 | :1003500010926900FF91EF91BF91AF919F918F91A2 55 | :100360006F915F914F913F912F911F910F91FF904E 56 | :10037000EF90DF90CF900F900FBE0F901F901895C9 57 | :1003800030E0883074F4082E01C0220F0A94EAF796 58 | :1003900090916900292B209369008F5F80936800FA 59 | :1003A000D9CF8830A1F480916900082E82958025EC 60 | :1003B000082E8695869580258F5F81FB442740F91E 61 | :1003C00050E089E02417350749F78FEFE7CF8930F0 62 | :1003D00009F0C0CF9923C9F3E0916B0081E08E0F43 63 | :1003E0008F7090916A00891781F3F0E0EC59FF4F0C 64 | :1003F00090916900908780936B00E7CF83B782600C 65 | :1004000083BF80B7836080BF89B7816089BF12BE18 66 | :10041000789486E886B9D898D09AD39AD19AD59A02 67 | :10042000D49AD79AD29AD69A80B78F7380BFC2983F 68 | :100430008FB7F894B898C09A8FBF8FB7F894B998CF 69 | :10044000C19A8FBF8BB780628BBF80B5816080BD42 70 | :1004500067E0C12CD12C7601C39424E130E04CEC50 71 | :1004600057E0A091BE00B091BF00F89416969C9101 72 | :10047000169717968C911797981304C0789490E06C 73 | :1004800080E050C0FD01E90FF11D80859F5F9F70E6 74 | :1004900016969C9316977894882389F359969C9185 75 | :1004A0005997992351F08FEF890F59968C9359974B 76 | :1004B0008111DBCF8FEF91E035C0813E71F058960E 77 | :1004C0007C915897803F21F0803E59F4726001C0C2 78 | :1004D000716058967C935897C8CF59966C935997EA 79 | :1004E000C4CF90E071FD9160FC01C3E0F695E79503 80 | :1004F000CA95E1F7EA0FFB1FEF016A96728C8C0137 81 | :10050000077011274601570104C0880C991CAA1CCA 82 | :10051000BB1C0A95D2F758961C92589770FD39C0AB 83 | :1005200087288882A091BE00B091BF005C967C9124 84 | :100530005C97E1E072FD05C09596EC919597E69584 85 | :10054000E17074FD03C0DC967C9174FDE26085313E 86 | :10055000910508F486CF87379105F8F44597880F01 87 | :10056000991F880F991FE80FF92FF11DE659FF4FCA 88 | :10057000E491EE2309F475CFEF3F19F5BA9A85E6B9 89 | :1005800090E00197D1F48FB7F894BA98C2988FBFD2 90 | :1005900068CF80948720828E68CF8B5691408231BD 91 | :1005A000910508F05ECF880F991F880F991FE80FFB 92 | :1005B000F92FF11DEE5DFF4FDBCFFA013197F1F717 93 | :1005C000E0CFE0FF28C0DB9AE1FF27C0D99A8FB5C2 94 | :1005D0008F7C8FBDE2FF23C0DD9AE3FF22C0DC9A4F 95 | :1005E00080B78F7C80BFE4FF1EC0DF9AE5FF1DC08F 96 | :1005F000DA9A8FB58F738FBDE6FF19C0DE9AC901F5 97 | :100600000197F1F7D89AC9010197F1F7D898C90174 98 | :100610000197F1F726CFDB98D7CFD998D8CFDD98BF 99 | :10062000DCCFDC98DDCFDF98E1CFDA98E2CFDE983F 100 | :10063000E6CFCF93DF93E4E6F0E0108211821282DE 101 | :1006400013828FEF8483158216821782108E118E8B 102 | :10065000AEE7B0E080E4ED0119928A95E9F7F093F6 103 | :10066000BF00E093BE00DF91CF910895EE0FFF1F12 104 | :0C0670000590F491E02D0994F894FFCF60 105 | :00000001FF 106 | -------------------------------------------------------------------------------- /src/PS2_Monitor/PS2Keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "PS2Interface.h" 5 | 6 | 7 | // Class to receive PS/2 keyboard scan codes from a PS/2 interface. 8 | // 9 | // The scan codes returned are slightly compressed to make table lookups easier. For scan 10 | // codes with a leading E0 byte, it is replaced with a 0x01 and placed in the MSB of the 11 | // uint16_t returned. So for example, the 'Delete' key with a scan code of E071 would return 12 | // a code value of 0x0171. 13 | class PS2Keyboard : private PS2Interface { 14 | public: 15 | // Scan code values of some keys 16 | enum { 17 | SCAN_CODE_LSHIFT = 0x012, 18 | SCAN_CODE_RSHIFT = 0x059, 19 | SCAN_CODE_LCTRL = 0x014, 20 | SCAN_CODE_RCTRL = 0x114, 21 | SCAN_CODE_LALT = 0x011, 22 | SCAN_CODE_RALT = 0x111, 23 | SCAN_CODE_LWIN = 0x11f, 24 | SCAN_CODE_RWIN = 0x127, 25 | SCAN_CODE_MAX = 0x200, 26 | }; 27 | 28 | PS2Keyboard(); 29 | 30 | using PS2Interface::setup; 31 | using PS2Interface::onClockFallingEdge; 32 | 33 | // Returns the keypress received from the keyboard or 0 if there is none. 34 | uint16_t getKeypress(); 35 | 36 | // Returns a boolean value indicating if a key with the given code is currently pressed. 37 | bool isKeyPressed(uint16_t code) const; 38 | 39 | // Returns a boolean value indicating if any shift key is pressed. 40 | bool isShiftPressed() const; 41 | 42 | // Returns a boolean value indicating if any ctrl key is pressed. 43 | bool isCtrlPressed() const; 44 | 45 | // Returns a boolean value indicating if any alt key is pressed. 46 | bool isAltPressed() const; 47 | 48 | // Returns a boolean value indicating if any Windows key is pressed. 49 | bool isWinPressed() const; 50 | 51 | private: 52 | void updatePressedKeys(uint16_t code, bool isPressed); 53 | 54 | // bit definitions for m_pressedModifierKeys 55 | enum { 56 | PRESSED_LSHIFT = 0x01, 57 | PRESSED_RSHIFT = 0x02, 58 | PRESSED_LCTRL = 0x04, 59 | PRESSED_RCTRL = 0x08, 60 | PRESSED_LALT = 0x10, 61 | PRESSED_RALT = 0x20, 62 | PRESSED_LWIN = 0x40, 63 | PRESSED_RWIN = 0x80, 64 | }; 65 | 66 | // bit definitions for m_flags 67 | enum { 68 | SCANCODE_BREAK = 0x01, // next scancode is for a key-break (key being released) 69 | SCANCODE_EXTENDED = 0x02, // next scancode is extended 70 | }; 71 | 72 | uint8_t m_flags; 73 | uint8_t m_pauseBreakBytesToSkip; 74 | uint8_t m_pressedKeys[(SCAN_CODE_MAX+7) / 8]; 75 | }; 76 | 77 | 78 | PS2Keyboard::PS2Keyboard() : m_flags(0), m_pauseBreakBytesToSkip(0) { 79 | memset(m_pressedKeys, 0, sizeof(m_pressedKeys)); 80 | } 81 | 82 | 83 | uint16_t PS2Keyboard::getKeypress() { 84 | uint16_t code; 85 | 86 | while(1) { 87 | uint8_t b = getDataByte(); 88 | if(b == 0) 89 | break; 90 | 91 | if(m_pauseBreakBytesToSkip > 0) { 92 | m_pauseBreakBytesToSkip--; 93 | if(m_pauseBreakBytesToSkip == 0) { 94 | return 0x1ff; 95 | } 96 | continue; 97 | } 98 | 99 | switch(b) { 100 | case 0xf0: 101 | m_flags |= SCANCODE_BREAK; 102 | break; 103 | case 0xe0: 104 | m_flags |= SCANCODE_EXTENDED; 105 | break; 106 | case 0xe1: 107 | // skip over the mess that the pause/break key sends 108 | m_pauseBreakBytesToSkip = 7; 109 | break; 110 | default: 111 | // an actual scan code 112 | code = b; 113 | if(m_flags & SCANCODE_EXTENDED) { 114 | code |= 0x100; 115 | } 116 | 117 | if(!(m_flags & SCANCODE_BREAK)) { 118 | m_flags = 0; 119 | updatePressedKeys(code, true); 120 | return code; 121 | } else { 122 | m_flags = 0; 123 | updatePressedKeys(code, false); 124 | } 125 | } 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | 132 | void PS2Keyboard::updatePressedKeys(uint16_t code, bool isPressed) { 133 | uint8_t byteIndex = (uint8_t)(code >> 3); 134 | if(byteIndex >= sizeof(m_pressedKeys)) 135 | return; 136 | 137 | if(isPressed) { 138 | bitSet(m_pressedKeys[byteIndex], code & 0x07); 139 | } else { 140 | bitClear(m_pressedKeys[byteIndex], code & 0x07); 141 | } 142 | } 143 | 144 | 145 | bool PS2Keyboard::isKeyPressed(uint16_t code) const { 146 | uint8_t byteIndex = (uint8_t)(code >> 3); 147 | if(byteIndex >= sizeof(m_pressedKeys)) 148 | return false; 149 | return bitRead(m_pressedKeys[byteIndex], code & 0x07); 150 | } 151 | 152 | 153 | bool PS2Keyboard::isShiftPressed() const { 154 | return isKeyPressed(SCAN_CODE_LSHIFT) || isKeyPressed(SCAN_CODE_RSHIFT); 155 | } 156 | 157 | 158 | bool PS2Keyboard::isCtrlPressed() const { 159 | return isKeyPressed(SCAN_CODE_LCTRL) || isKeyPressed(SCAN_CODE_RCTRL); 160 | } 161 | 162 | 163 | bool PS2Keyboard::isAltPressed() const { 164 | return isKeyPressed(SCAN_CODE_LALT) || isKeyPressed(SCAN_CODE_RALT); 165 | } 166 | 167 | 168 | bool PS2Keyboard::isWinPressed() const { 169 | return isKeyPressed(SCAN_CODE_LWIN) || isKeyPressed(SCAN_CODE_RWIN); 170 | } 171 | -------------------------------------------------------------------------------- /src/AppleII_PS2_Keyboard/PS2Keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "PS2Interface.h" 5 | 6 | 7 | // Class to receive PS/2 keyboard scan codes from a PS/2 interface. 8 | // 9 | // The scan codes returned are slightly compressed to make table lookups easier. For scan 10 | // codes with a leading E0 byte, it is replaced with a 0x01 and placed in the MSB of the 11 | // uint16_t returned. So for example, the 'Delete' key with a scan code of E071 would return 12 | // a code value of 0x0171. 13 | class PS2Keyboard : private PS2Interface { 14 | public: 15 | // Scan code values of some keys 16 | enum { 17 | SCAN_CODE_LSHIFT = 0x012, 18 | SCAN_CODE_RSHIFT = 0x059, 19 | SCAN_CODE_LCTRL = 0x014, 20 | SCAN_CODE_RCTRL = 0x114, 21 | SCAN_CODE_LALT = 0x011, 22 | SCAN_CODE_RALT = 0x111, 23 | SCAN_CODE_LWIN = 0x11f, 24 | SCAN_CODE_RWIN = 0x127, 25 | SCAN_CODE_MAX = 0x200, 26 | }; 27 | 28 | PS2Keyboard(); 29 | 30 | using PS2Interface::setup; 31 | using PS2Interface::onClockFallingEdge; 32 | 33 | // Returns the keypress received from the keyboard or 0 if there is none. 34 | uint16_t getKeypress(); 35 | 36 | // Returns a boolean value indicating if a key with the given code is currently pressed. 37 | bool isKeyPressed(uint16_t code) const; 38 | 39 | // Returns a boolean value indicating if any shift key is pressed. 40 | bool isShiftPressed() const; 41 | 42 | // Returns a boolean value indicating if any ctrl key is pressed. 43 | bool isCtrlPressed() const; 44 | 45 | // Returns a boolean value indicating if any alt key is pressed. 46 | bool isAltPressed() const; 47 | 48 | // Returns a boolean value indicating if any Windows key is pressed. 49 | bool isWinPressed() const; 50 | 51 | private: 52 | void updatePressedKeys(uint16_t code, bool isPressed); 53 | 54 | // bit definitions for m_pressedModifierKeys 55 | enum { 56 | PRESSED_LSHIFT = 0x01, 57 | PRESSED_RSHIFT = 0x02, 58 | PRESSED_LCTRL = 0x04, 59 | PRESSED_RCTRL = 0x08, 60 | PRESSED_LALT = 0x10, 61 | PRESSED_RALT = 0x20, 62 | PRESSED_LWIN = 0x40, 63 | PRESSED_RWIN = 0x80, 64 | }; 65 | 66 | // bit definitions for m_flags 67 | enum { 68 | SCANCODE_BREAK = 0x01, // next scancode is for a key-break (key being released) 69 | SCANCODE_EXTENDED = 0x02, // next scancode is extended 70 | }; 71 | 72 | uint8_t m_flags; 73 | uint8_t m_pauseBreakBytesToSkip; 74 | uint8_t m_pressedKeys[(SCAN_CODE_MAX+7) / 8]; 75 | }; 76 | 77 | 78 | PS2Keyboard::PS2Keyboard() : m_flags(0), m_pauseBreakBytesToSkip(0) { 79 | memset(m_pressedKeys, 0, sizeof(m_pressedKeys)); 80 | } 81 | 82 | 83 | uint16_t PS2Keyboard::getKeypress() { 84 | uint16_t code; 85 | 86 | while(1) { 87 | uint8_t b = getDataByte(); 88 | if(b == 0) 89 | break; 90 | 91 | if(m_pauseBreakBytesToSkip > 0) { 92 | m_pauseBreakBytesToSkip--; 93 | if(m_pauseBreakBytesToSkip == 0) { 94 | return 0x1ff; 95 | } 96 | continue; 97 | } 98 | 99 | switch(b) { 100 | case 0xf0: 101 | m_flags |= SCANCODE_BREAK; 102 | break; 103 | case 0xe0: 104 | m_flags |= SCANCODE_EXTENDED; 105 | break; 106 | case 0xe1: 107 | // skip over the mess that the pause/break key sends 108 | m_pauseBreakBytesToSkip = 7; 109 | break; 110 | default: 111 | // an actual scan code 112 | code = b; 113 | if(m_flags & SCANCODE_EXTENDED) { 114 | code |= 0x100; 115 | } 116 | 117 | if(!(m_flags & SCANCODE_BREAK)) { 118 | m_flags = 0; 119 | updatePressedKeys(code, true); 120 | return code; 121 | } else { 122 | m_flags = 0; 123 | updatePressedKeys(code, false); 124 | } 125 | } 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | 132 | void PS2Keyboard::updatePressedKeys(uint16_t code, bool isPressed) { 133 | uint8_t byteIndex = (uint8_t)(code >> 3); 134 | if(byteIndex >= sizeof(m_pressedKeys)) 135 | return; 136 | 137 | if(isPressed) { 138 | bitSet(m_pressedKeys[byteIndex], code & 0x07); 139 | } else { 140 | bitClear(m_pressedKeys[byteIndex], code & 0x07); 141 | } 142 | } 143 | 144 | 145 | bool PS2Keyboard::isKeyPressed(uint16_t code) const { 146 | uint8_t byteIndex = (uint8_t)(code >> 3); 147 | if(byteIndex >= sizeof(m_pressedKeys)) 148 | return false; 149 | return bitRead(m_pressedKeys[byteIndex], code & 0x07); 150 | } 151 | 152 | 153 | bool PS2Keyboard::isShiftPressed() const { 154 | return isKeyPressed(SCAN_CODE_LSHIFT) || isKeyPressed(SCAN_CODE_RSHIFT); 155 | } 156 | 157 | 158 | bool PS2Keyboard::isCtrlPressed() const { 159 | return isKeyPressed(SCAN_CODE_LCTRL) || isKeyPressed(SCAN_CODE_RCTRL); 160 | } 161 | 162 | 163 | bool PS2Keyboard::isAltPressed() const { 164 | return isKeyPressed(SCAN_CODE_LALT) || isKeyPressed(SCAN_CODE_RALT); 165 | } 166 | 167 | 168 | bool PS2Keyboard::isWinPressed() const { 169 | return isKeyPressed(SCAN_CODE_LWIN) || isKeyPressed(SCAN_CODE_RWIN); 170 | } 171 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-F_Cu.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:28-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Copper,L1,Top*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:28* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | G04 Aperture macros list* 15 | %AMRoundRect* 16 | 0 Rectangle with rounded corners* 17 | 0 $1 Rounding radius* 18 | 0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners* 19 | 0 Add a 4 corners polygon primitive as box body* 20 | 4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0* 21 | 0 Add four circle primitives for the rounded corners* 22 | 1,1,$1+$1,$2,$3* 23 | 1,1,$1+$1,$4,$5* 24 | 1,1,$1+$1,$6,$7* 25 | 1,1,$1+$1,$8,$9* 26 | 0 Add four rect primitives between the rounded corners* 27 | 20,1,$1+$1,$2,$3,$4,$5,0* 28 | 20,1,$1+$1,$4,$5,$6,$7,0* 29 | 20,1,$1+$1,$6,$7,$8,$9,0* 30 | 20,1,$1+$1,$8,$9,$2,$3,0*% 31 | G04 Aperture macros list end* 32 | %TA.AperFunction,ComponentPad*% 33 | %ADD10C,1.600000*% 34 | %TD*% 35 | %TA.AperFunction,ComponentPad*% 36 | %ADD11RoundRect,0.250000X0.550000X0.550000X-0.550000X0.550000X-0.550000X-0.550000X0.550000X-0.550000X0*% 37 | %TD*% 38 | %TA.AperFunction,ComponentPad*% 39 | %ADD12R,1.700000X1.700000*% 40 | %TD*% 41 | %TA.AperFunction,ComponentPad*% 42 | %ADD13C,1.700000*% 43 | %TD*% 44 | %TA.AperFunction,ViaPad*% 45 | %ADD14C,0.600000*% 46 | %TD*% 47 | %TA.AperFunction,Conductor*% 48 | %ADD15C,0.400000*% 49 | %TD*% 50 | %TA.AperFunction,Conductor*% 51 | %ADD16C,0.200000*% 52 | %TD*% 53 | G04 APERTURE END LIST* 54 | D10* 55 | %TO.P,C1,1*% 56 | %TO.N,+5V*% 57 | X154940000Y-111125000D03* 58 | %TO.P,C1,2*% 59 | %TO.N,GND*% 60 | X147440000Y-111125000D03* 61 | %TD*% 62 | D11* 63 | %TO.P,J1,1,Pin_1*% 64 | %TO.N,+5V*% 65 | X151130000Y-107950000D03* 66 | D10* 67 | %TO.P,J1,2,Pin_2*% 68 | %TO.N,/STROBE*% 69 | X151130000Y-105410000D03* 70 | %TO.P,J1,3,Pin_3*% 71 | %TO.N,/~{RESET}*% 72 | X151130000Y-102870000D03* 73 | %TO.P,J1,4,Pin_4*% 74 | %TO.N,unconnected-(J1-Pin_4-Pad4)*% 75 | X151130000Y-100330000D03* 76 | %TO.P,J1,5,Pin_5*% 77 | %TO.N,/D5*% 78 | X151130000Y-97790000D03* 79 | %TO.P,J1,6,Pin_6*% 80 | %TO.N,/D4*% 81 | X151130000Y-95250000D03* 82 | %TO.P,J1,7,Pin_7*% 83 | %TO.N,/D6*% 84 | X151130000Y-92710000D03* 85 | %TO.P,J1,8,Pin_8*% 86 | %TO.N,GND*% 87 | X151130000Y-90170000D03* 88 | %TO.P,J1,9,Pin_9*% 89 | %TO.N,unconnected-(J1-Pin_9-Pad9)*% 90 | X143510000Y-90170000D03* 91 | %TO.P,J1,10,Pin_10*% 92 | %TO.N,/D2*% 93 | X143510000Y-92710000D03* 94 | %TO.P,J1,11,Pin_11*% 95 | %TO.N,/D3*% 96 | X143510000Y-95250000D03* 97 | %TO.P,J1,12,Pin_12*% 98 | %TO.N,/D0*% 99 | X143510000Y-97790000D03* 100 | %TO.P,J1,13,Pin_13*% 101 | %TO.N,/D1*% 102 | X143510000Y-100330000D03* 103 | %TO.P,J1,14,Pin_14*% 104 | %TO.N,unconnected-(J1-Pin_14-Pad14)*% 105 | X143510000Y-102870000D03* 106 | %TO.P,J1,15,Pin_15*% 107 | %TO.N,unconnected-(J1-Pin_15-Pad15)*% 108 | X143510000Y-105410000D03* 109 | %TO.P,J1,16,Pin_16*% 110 | %TO.N,unconnected-(J1-Pin_16-Pad16)*% 111 | X143510000Y-107950000D03* 112 | %TD*% 113 | D12* 114 | %TO.P,J2,1,Pin_1*% 115 | %TO.N,/PS2_CLK*% 116 | X153670000Y-80010000D03* 117 | D13* 118 | %TO.P,J2,2,Pin_2*% 119 | %TO.N,GND*% 120 | X153670000Y-82550000D03* 121 | %TO.P,J2,3,Pin_3*% 122 | %TO.N,unconnected-(J2-Pin_3-Pad3)*% 123 | X151130000Y-80010000D03* 124 | %TO.P,J2,4,Pin_4*% 125 | %TO.N,/PS2_DATA*% 126 | X151130000Y-82550000D03* 127 | %TO.P,J2,5,Pin_5*% 128 | %TO.N,unconnected-(J2-Pin_5-Pad5)*% 129 | X148590000Y-80010000D03* 130 | %TO.P,J2,6,Pin_6*% 131 | %TO.N,unconnected-(J2-Pin_6-Pad6)*% 132 | X148590000Y-82550000D03* 133 | %TO.P,J2,7,Pin_7*% 134 | %TO.N,unconnected-(J2-Pin_7-Pad7)*% 135 | X146050000Y-80010000D03* 136 | %TO.P,J2,8,Pin_8*% 137 | %TO.N,+5V*% 138 | X146050000Y-82550000D03* 139 | %TD*% 140 | D11* 141 | %TO.P,U1,1,VCC*% 142 | %TO.N,+5V*% 143 | X154940000Y-105410000D03* 144 | D10* 145 | %TO.P,U1,2,XTAL1/PB0*% 146 | %TO.N,/PS2_CLK*% 147 | X154940000Y-102870000D03* 148 | %TO.P,U1,3,XTAL2/PB1*% 149 | %TO.N,/PS2_DATA*% 150 | X154940000Y-100330000D03* 151 | %TO.P,U1,4,~{RESET}/PB3*% 152 | %TO.N,unconnected-(U1-~{RESET}{slash}PB3-Pad4)*% 153 | X154940000Y-97790000D03* 154 | %TO.P,U1,5,PB2*% 155 | %TO.N,/~{RESET}*% 156 | X154940000Y-95250000D03* 157 | %TO.P,U1,6,PA7*% 158 | %TO.N,/D4*% 159 | X154940000Y-92710000D03* 160 | %TO.P,U1,7,PA6*% 161 | %TO.N,/D6*% 162 | X154940000Y-90170000D03* 163 | %TO.P,U1,8,PA5*% 164 | %TO.N,/D2*% 165 | X147320000Y-90170000D03* 166 | %TO.P,U1,9,PA4*% 167 | %TO.N,/D3*% 168 | X147320000Y-92710000D03* 169 | %TO.P,U1,10,PA3*% 170 | %TO.N,/D0*% 171 | X147320000Y-95250000D03* 172 | %TO.P,U1,11,PA2*% 173 | %TO.N,/D5*% 174 | X147320000Y-97790000D03* 175 | %TO.P,U1,12,PA1*% 176 | %TO.N,/D1*% 177 | X147320000Y-100330000D03* 178 | %TO.P,U1,13,AREF/PA0*% 179 | %TO.N,/STROBE*% 180 | X147320000Y-102870000D03* 181 | %TO.P,U1,14,GND*% 182 | %TO.N,GND*% 183 | X147320000Y-105410000D03* 184 | %TD*% 185 | D14* 186 | %TO.N,/PS2_CLK*% 187 | X156845000Y-83185000D03* 188 | %TD*% 189 | D15* 190 | %TO.N,GND*% 191 | X147440000Y-111125000D02* 192 | X147440000Y-105530000D01* 193 | %TO.N,+5V*% 194 | X154940000Y-110490000D02* 195 | X154940000Y-107950000D01* 196 | X151130000Y-107950000D02* 197 | X154940000Y-107950000D01* 198 | X154940000Y-105410000D02* 199 | X154940000Y-107950000D01* 200 | D16* 201 | %TO.N,/D3*% 202 | X144145000Y-95250000D02* 203 | X146685000Y-92710000D01* 204 | %TO.N,/D0*% 205 | X144145000Y-97790000D02* 206 | X146685000Y-95250000D01* 207 | %TO.N,/D1*% 208 | X143510000Y-100330000D02* 209 | X147320000Y-100330000D01* 210 | %TO.N,/D5*% 211 | X147320000Y-97790000D02* 212 | X151130000Y-97790000D01* 213 | %TO.N,/D4*% 214 | X151765000Y-95250000D02* 215 | X154305000Y-92710000D01* 216 | %TO.N,/D6*% 217 | X151765000Y-92710000D02* 218 | X154305000Y-90170000D01* 219 | %TO.N,/~{RESET}*% 220 | X151130000Y-102870000D02* 221 | X153035000Y-100965000D01* 222 | X153035000Y-100965000D02* 223 | X153035000Y-97155000D01* 224 | X154940000Y-95250000D02* 225 | X153035000Y-97155000D01* 226 | %TO.N,/D2*% 227 | X144145000Y-92710000D02* 228 | X146685000Y-90170000D01* 229 | %TO.N,/PS2_DATA*% 230 | X156845000Y-98425000D02* 231 | X156845000Y-88265000D01* 232 | X151130000Y-82550000D02* 233 | X156845000Y-88265000D01* 234 | X154940000Y-100330000D02* 235 | X156845000Y-98425000D01* 236 | %TO.N,/PS2_CLK*% 237 | X158115000Y-99695000D02* 238 | X158115000Y-84455000D01* 239 | X154940000Y-102870000D02* 240 | X158115000Y-99695000D01* 241 | X156845000Y-83185000D02* 242 | X158115000Y-84455000D01* 243 | %TO.N,/STROBE*% 244 | X147955000Y-102870000D02* 245 | X150495000Y-105410000D01* 246 | %TD*% 247 | M02* 248 | -------------------------------------------------------------------------------- /src/AppleII_PS2_Keyboard/AppleIIKeyboardTranslation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "PS2Keyboard.h" 3 | 4 | // This file is generated from a script 5 | // DO NOT EDIT 6 | 7 | // Class to translate PS2 scan codes into Apple II keyboard codes. 8 | class AppleIIKeyboardTranslation { 9 | public: 10 | AppleIIKeyboardTranslation(PS2Keyboard& kbd) : m_kbd(kbd) {} 11 | 12 | // Fetches the next encoded key code, or 0 if there isn't one. 13 | uint8_t getKeyCode(); 14 | 15 | private: 16 | PS2Keyboard& m_kbd; 17 | 18 | enum { 19 | SCANCODE_SPAN1_START = 21, 20 | SCANCODE_SPAN1_SIZE = 98, 21 | SCANCODE_SPAN2_START = 363, 22 | SCANCODE_SPAN2_SIZE = 18, 23 | }; 24 | static const uint8_t scancode_span1[SCANCODE_SPAN1_SIZE][4] PROGMEM; 25 | static const uint8_t scancode_span2[SCANCODE_SPAN2_SIZE][4] PROGMEM; 26 | }; 27 | 28 | 29 | uint8_t AppleIIKeyboardTranslation::getKeyCode() { 30 | uint16_t scanCode = m_kbd.getKeypress(); 31 | 32 | uint8_t modifiers = 0; 33 | if(m_kbd.isShiftPressed()) { 34 | modifiers |= 0x1; 35 | } 36 | if(m_kbd.isCtrlPressed()) { 37 | modifiers |= 0x2; 38 | } 39 | 40 | if(scanCode < SCANCODE_SPAN1_START) { 41 | return 0; 42 | } else if(scanCode < SCANCODE_SPAN1_START+SCANCODE_SPAN1_SIZE) { 43 | return pgm_read_byte(&(scancode_span1[scanCode - SCANCODE_SPAN1_START][modifiers])); 44 | } 45 | 46 | if(scanCode < SCANCODE_SPAN2_START) { 47 | return 0; 48 | } else if(scanCode < SCANCODE_SPAN2_START+SCANCODE_SPAN2_SIZE) { 49 | return pgm_read_byte(&(scancode_span2[scanCode - SCANCODE_SPAN2_START][modifiers])); 50 | } 51 | return 0; 52 | } 53 | 54 | const uint8_t AppleIIKeyboardTranslation::scancode_span1[AppleIIKeyboardTranslation::SCANCODE_SPAN1_SIZE][4] = { 55 | // scan code, no modifier, SHIFT modifier, CTRL modifier, both modifiers 56 | /* 0x015 [Q] */ {0xd1, 0xd1, 0x91, 0x91}, 57 | /* 0x016 [1!] */ {0xb1, 0xa1, 0xb1, 0xa1}, 58 | /* 0x017 */ {}, 59 | /* 0x018 */ {}, 60 | /* 0x019 */ {}, 61 | /* 0x01a [Z] */ {0xda, 0xda, 0x9a, 0x9a}, 62 | /* 0x01b [S] */ {0xd3, 0xd3, 0x93, 0x93}, 63 | /* 0x01c [A] */ {0xc1, 0xc1, 0x81, 0x81}, 64 | /* 0x01d [W] */ {0xd7, 0xd7, 0x97, 0x97}, 65 | /* 0x01e [2@] */ {0xb2, 0xc0, 0xb2, 0xc0}, 66 | /* 0x01f */ {}, 67 | /* 0x020 */ {}, 68 | /* 0x021 [C] */ {0xc3, 0xc3, 0x83, 0x83}, 69 | /* 0x022 [X] */ {0xd8, 0xd8, 0x98, 0x98}, 70 | /* 0x023 [D] */ {0xc4, 0xc4, 0x84, 0x84}, 71 | /* 0x024 [E] */ {0xc5, 0xc5, 0x85, 0x85}, 72 | /* 0x025 [4$] */ {0xb4, 0xa4, 0xb4, 0xa4}, 73 | /* 0x026 [3#] */ {0xb3, 0xa3, 0xb3, 0xa3}, 74 | /* 0x027 */ {}, 75 | /* 0x028 */ {}, 76 | /* 0x029 [Space] */ {0xa0, 0xa0, 0xa0, 0xa0}, 77 | /* 0x02a [V] */ {0xd6, 0xd6, 0x96, 0x96}, 78 | /* 0x02b [F] */ {0xc6, 0xc6, 0x86, 0x86}, 79 | /* 0x02c [T] */ {0xd4, 0xd4, 0x94, 0x94}, 80 | /* 0x02d [R] */ {0xd2, 0xd2, 0x92, 0x92}, 81 | /* 0x02e [5%] */ {0xb5, 0xa5, 0xb5, 0xa5}, 82 | /* 0x02f */ {}, 83 | /* 0x030 */ {}, 84 | /* 0x031 [N] */ {0xce, 0xce, 0x8e, 0x9e}, 85 | /* 0x032 [B] */ {0xc2, 0xc2, 0x82, 0x82}, 86 | /* 0x033 [H] */ {0xc8, 0xc8, 0x88, 0x88}, 87 | /* 0x034 [G] */ {0xc7, 0xc7, 0x87, 0x87}, 88 | /* 0x035 [Y] */ {0xd9, 0xd9, 0x99, 0x99}, 89 | /* 0x036 [6^] */ {0xb6, 0xde, 0xb6, 0xde}, 90 | /* 0x037 */ {}, 91 | /* 0x038 */ {}, 92 | /* 0x039 */ {}, 93 | /* 0x03a [M] */ {0xcd, 0xcd, 0x8e, 0x9d}, 94 | /* 0x03b [J] */ {0xca, 0xca, 0x8a, 0x8a}, 95 | /* 0x03c [U] */ {0xd5, 0xd5, 0x95, 0x95}, 96 | /* 0x03d [7&] */ {0xb7, 0xa6, 0xb7, 0xa6}, 97 | /* 0x03e [8*] */ {0xb8, 0xaa, 0xb8, 0xaa}, 98 | /* 0x03f */ {}, 99 | /* 0x040 */ {}, 100 | /* 0x041 [,<] */ {0xac, 0xbc, 0xac, 0xbc}, 101 | /* 0x042 [K] */ {0xcb, 0xcb, 0x8b, 0x8b}, 102 | /* 0x043 [I] */ {0xc9, 0xc9, 0x89, 0x89}, 103 | /* 0x044 [O] */ {0xcf, 0xcf, 0x8f, 0x8f}, 104 | /* 0x045 [0)] */ {0xb0, 0xa9, 0xb0, 0xa9}, 105 | /* 0x046 [9(] */ {0xb9, 0xa8, 0xb9, 0xa8}, 106 | /* 0x047 */ {}, 107 | /* 0x048 */ {}, 108 | /* 0x049 [.>] */ {0xae, 0xbe, 0xae, 0xbe}, 109 | /* 0x04a [/?] */ {0xaf, 0xbf, 0xaf, 0xbf}, 110 | /* 0x04b [L] */ {0xcc, 0xcc, 0x8c, 0x8c}, 111 | /* 0x04c [;:] */ {0xbb, 0xba, 0xbb, 0xba}, 112 | /* 0x04d [P] */ {0xd0, 0xd0, 0x90, 0x80}, 113 | /* 0x04e [-_] */ {0xad, 0xad, 0xad, 0xad}, 114 | /* 0x04f */ {}, 115 | /* 0x050 */ {}, 116 | /* 0x051 */ {}, 117 | /* 0x052 ['"] */ {0xa7, 0xa2, 0xa7, 0xa2}, 118 | /* 0x053 */ {}, 119 | /* 0x054 */ {}, 120 | /* 0x055 [=+] */ {0xbd, 0xab, 0xbd, 0xab}, 121 | /* 0x056 */ {}, 122 | /* 0x057 */ {}, 123 | /* 0x058 */ {}, 124 | /* 0x059 */ {}, 125 | /* 0x05a [Enter] */ {0x8d, 0x8d, 0x8d, 0x8d}, 126 | /* 0x05b []}] */ {0xdd, 0xdd, 0xdd, 0xdd}, 127 | /* 0x05c */ {}, 128 | /* 0x05d */ {}, 129 | /* 0x05e */ {}, 130 | /* 0x05f */ {}, 131 | /* 0x060 */ {}, 132 | /* 0x061 */ {}, 133 | /* 0x062 */ {}, 134 | /* 0x063 */ {}, 135 | /* 0x064 */ {}, 136 | /* 0x065 */ {}, 137 | /* 0x066 */ {}, 138 | /* 0x067 */ {}, 139 | /* 0x068 */ {}, 140 | /* 0x069 */ {}, 141 | /* 0x06a */ {}, 142 | /* 0x06b */ {}, 143 | /* 0x06c */ {}, 144 | /* 0x06d */ {}, 145 | /* 0x06e */ {}, 146 | /* 0x06f */ {}, 147 | /* 0x070 */ {}, 148 | /* 0x071 */ {}, 149 | /* 0x072 */ {}, 150 | /* 0x073 */ {}, 151 | /* 0x074 */ {}, 152 | /* 0x075 */ {}, 153 | /* 0x076 [Escape] */ {0x9b, 0x9b, 0x9b, 0x9b}, 154 | }; 155 | 156 | const uint8_t AppleIIKeyboardTranslation::scancode_span2[AppleIIKeyboardTranslation::SCANCODE_SPAN2_SIZE][4] = { 157 | // scan code, no modifier, SHIFT modifier, CTRL modifier, both modifiers 158 | /* 0x16b [LeftArrow] */ {0x88, 0x88, 0x88, 0x88}, 159 | /* 0x16c */ {}, 160 | /* 0x16d */ {}, 161 | /* 0x16e */ {}, 162 | /* 0x16f */ {}, 163 | /* 0x170 */ {}, 164 | /* 0x171 */ {}, 165 | /* 0x172 */ {}, 166 | /* 0x173 */ {}, 167 | /* 0x174 [RightArrow] */ {0x95, 0x95, 0x95, 0x95}, 168 | /* 0x175 */ {}, 169 | /* 0x176 */ {}, 170 | /* 0x177 */ {}, 171 | /* 0x178 */ {}, 172 | /* 0x179 */ {}, 173 | /* 0x17a */ {}, 174 | /* 0x17b */ {}, 175 | /* 0x17c [PrtScr] */ {0x00, 0x00, 0xff, 0xff}, 176 | }; 177 | -------------------------------------------------------------------------------- /AppleII-Keyboard/Libraries/footprints/Connector_Project.pretty/DIP-14_W7.62mm_Socket.kicad_mod: -------------------------------------------------------------------------------- 1 | (footprint "DIP-14_W7.62mm_Socket" 2 | (version 20241229) 3 | (generator "pcbnew") 4 | (generator_version "9.0") 5 | (layer "F.Cu") 6 | (descr "14-lead though-hole mounted DIP package, row spacing 7.62mm (300 mils), Socket") 7 | (tags "THT DIP DIL PDIP 2.54mm 7.62mm 300mil Socket") 8 | (property "Reference" "REF**" 9 | (at 3.81 -2.33 0) 10 | (layer "F.SilkS") 11 | (uuid "eb03afee-7efe-4aee-b30c-e5b4acdd11a4") 12 | (effects 13 | (font 14 | (size 1 1) 15 | (thickness 0.15) 16 | ) 17 | ) 18 | ) 19 | (property "Value" "DIP-14_W7.62mm_Socket" 20 | (at 3.81 17.57 0) 21 | (layer "F.Fab") 22 | (uuid "1fa6fa97-7dfe-4da8-8e04-020b386088fc") 23 | (effects 24 | (font 25 | (size 1 1) 26 | (thickness 0.15) 27 | ) 28 | ) 29 | ) 30 | (property "Datasheet" "" 31 | (at 0 0 0) 32 | (layer "F.Fab") 33 | (hide yes) 34 | (uuid "82c816d9-aed4-478f-8a85-163cce0019cf") 35 | (effects 36 | (font 37 | (size 1.27 1.27) 38 | (thickness 0.15) 39 | ) 40 | ) 41 | ) 42 | (property "Description" "" 43 | (at 0 0 0) 44 | (layer "F.Fab") 45 | (hide yes) 46 | (uuid "8e1eb855-9a44-4c9f-88f6-33468404e28f") 47 | (effects 48 | (font 49 | (size 1.27 1.27) 50 | (thickness 0.15) 51 | ) 52 | ) 53 | ) 54 | (attr through_hole) 55 | (fp_line 56 | (start 1.16 -1.33) 57 | (end 1.16 16.57) 58 | (stroke 59 | (width 0.12) 60 | (type solid) 61 | ) 62 | (layer "F.SilkS") 63 | (uuid "f7907be0-80ca-488f-af36-33ef82d1929b") 64 | ) 65 | (fp_line 66 | (start 6.46 16.57) 67 | (end 6.46 -1.33) 68 | (stroke 69 | (width 0.12) 70 | (type solid) 71 | ) 72 | (layer "F.SilkS") 73 | (uuid "3b261256-2d2e-4768-9663-eab7f6cd9230") 74 | ) 75 | (fp_poly 76 | (pts 77 | (xy -0.762 -2.794) (xy 0 -1.778) (xy 0.762 -2.794) 78 | ) 79 | (stroke 80 | (width 0.1) 81 | (type solid) 82 | ) 83 | (fill yes) 84 | (layer "F.SilkS") 85 | (uuid "24834295-ef75-49c6-ae7f-35b0561da236") 86 | ) 87 | (fp_rect 88 | (start -1.52 -1.59) 89 | (end 9.14 16.82) 90 | (stroke 91 | (width 0.05) 92 | (type solid) 93 | ) 94 | (fill no) 95 | (layer "F.CrtYd") 96 | (uuid "9c7f6bc6-0379-4dda-9946-811ea0885d8e") 97 | ) 98 | (fp_line 99 | (start 0.635 -0.27) 100 | (end 1.635 -1.27) 101 | (stroke 102 | (width 0.1) 103 | (type solid) 104 | ) 105 | (layer "F.Fab") 106 | (uuid "696256de-caa9-44fd-bf37-5a61e7702e0c") 107 | ) 108 | (fp_line 109 | (start 0.635 16.51) 110 | (end 0.635 -0.27) 111 | (stroke 112 | (width 0.1) 113 | (type solid) 114 | ) 115 | (layer "F.Fab") 116 | (uuid "7cb3795f-7f4d-4e37-8811-07e9ab3b3129") 117 | ) 118 | (fp_line 119 | (start 1.635 -1.27) 120 | (end 6.985 -1.27) 121 | (stroke 122 | (width 0.1) 123 | (type solid) 124 | ) 125 | (layer "F.Fab") 126 | (uuid "41e4f246-d99b-4c6e-bc86-f38a15df02d0") 127 | ) 128 | (fp_line 129 | (start 6.985 -1.27) 130 | (end 6.985 16.51) 131 | (stroke 132 | (width 0.1) 133 | (type solid) 134 | ) 135 | (layer "F.Fab") 136 | (uuid "4b981ad8-5066-41e1-a3d9-966bc816db14") 137 | ) 138 | (fp_line 139 | (start 6.985 16.51) 140 | (end 0.635 16.51) 141 | (stroke 142 | (width 0.1) 143 | (type solid) 144 | ) 145 | (layer "F.Fab") 146 | (uuid "735878a2-ef4f-4ee1-bf5b-2ec394465a45") 147 | ) 148 | (fp_rect 149 | (start -1.27 -1.33) 150 | (end 8.89 16.57) 151 | (stroke 152 | (width 0.1) 153 | (type solid) 154 | ) 155 | (fill no) 156 | (layer "F.Fab") 157 | (uuid "fba3b167-9257-4c0a-9902-55294c6630a3") 158 | ) 159 | (fp_text user "${REFERENCE}" 160 | (at 3.81 7.62 90) 161 | (layer "F.Fab") 162 | (uuid "9909a5dd-61ea-4dd3-8de1-4bd056b9503e") 163 | (effects 164 | (font 165 | (size 1 1) 166 | (thickness 0.15) 167 | ) 168 | ) 169 | ) 170 | (pad "1" thru_hole roundrect 171 | (at 0 0) 172 | (size 1.6 1.6) 173 | (drill 0.8) 174 | (layers "*.Cu" "*.Mask") 175 | (remove_unused_layers no) 176 | (roundrect_rratio 0.15625) 177 | (uuid "a6d43d5f-1fbf-437c-90ce-53029b8c94db") 178 | ) 179 | (pad "2" thru_hole circle 180 | (at 0 2.54) 181 | (size 1.6 1.6) 182 | (drill 0.8) 183 | (layers "*.Cu" "*.Mask") 184 | (remove_unused_layers no) 185 | (uuid "cae4e772-31a8-4801-b5c1-8322776d4da6") 186 | ) 187 | (pad "3" thru_hole circle 188 | (at 0 5.08) 189 | (size 1.6 1.6) 190 | (drill 0.8) 191 | (layers "*.Cu" "*.Mask") 192 | (remove_unused_layers no) 193 | (uuid "20fd7e2a-b822-4538-9870-d4a9d67ecab9") 194 | ) 195 | (pad "4" thru_hole circle 196 | (at 0 7.62) 197 | (size 1.6 1.6) 198 | (drill 0.8) 199 | (layers "*.Cu" "*.Mask") 200 | (remove_unused_layers no) 201 | (uuid "610c9e07-b0f9-45ab-b597-006e26b10a2d") 202 | ) 203 | (pad "5" thru_hole circle 204 | (at 0 10.16) 205 | (size 1.6 1.6) 206 | (drill 0.8) 207 | (layers "*.Cu" "*.Mask") 208 | (remove_unused_layers no) 209 | (uuid "f4b794e0-6345-4a60-8a84-27624a05335b") 210 | ) 211 | (pad "6" thru_hole circle 212 | (at 0 12.7) 213 | (size 1.6 1.6) 214 | (drill 0.8) 215 | (layers "*.Cu" "*.Mask") 216 | (remove_unused_layers no) 217 | (uuid "39fc4732-71ac-4602-b0e5-c3dc3f244596") 218 | ) 219 | (pad "7" thru_hole circle 220 | (at 0 15.24) 221 | (size 1.6 1.6) 222 | (drill 0.8) 223 | (layers "*.Cu" "*.Mask") 224 | (remove_unused_layers no) 225 | (uuid "8e3f770a-90ea-4f16-91a6-585f722c682e") 226 | ) 227 | (pad "8" thru_hole circle 228 | (at 7.62 15.24) 229 | (size 1.6 1.6) 230 | (drill 0.8) 231 | (layers "*.Cu" "*.Mask") 232 | (remove_unused_layers no) 233 | (uuid "2198cb37-5aa9-4366-9530-7015bd18992b") 234 | ) 235 | (pad "9" thru_hole circle 236 | (at 7.62 12.7) 237 | (size 1.6 1.6) 238 | (drill 0.8) 239 | (layers "*.Cu" "*.Mask") 240 | (remove_unused_layers no) 241 | (uuid "1933f5b8-6e8f-4cd6-9970-cc5a26be37cc") 242 | ) 243 | (pad "10" thru_hole circle 244 | (at 7.62 10.16) 245 | (size 1.6 1.6) 246 | (drill 0.8) 247 | (layers "*.Cu" "*.Mask") 248 | (remove_unused_layers no) 249 | (uuid "8ac5b097-d1bf-473e-aa83-e81ec1e44681") 250 | ) 251 | (pad "11" thru_hole circle 252 | (at 7.62 7.62) 253 | (size 1.6 1.6) 254 | (drill 0.8) 255 | (layers "*.Cu" "*.Mask") 256 | (remove_unused_layers no) 257 | (uuid "8614eb2d-f6a0-4cf5-9a48-915fbe4ba9b6") 258 | ) 259 | (pad "12" thru_hole circle 260 | (at 7.62 5.08) 261 | (size 1.6 1.6) 262 | (drill 0.8) 263 | (layers "*.Cu" "*.Mask") 264 | (remove_unused_layers no) 265 | (uuid "b9bcaaf1-9cb3-4302-b00e-9a1381f68e95") 266 | ) 267 | (pad "13" thru_hole circle 268 | (at 7.62 2.54) 269 | (size 1.6 1.6) 270 | (drill 0.8) 271 | (layers "*.Cu" "*.Mask") 272 | (remove_unused_layers no) 273 | (uuid "83c05297-08d6-45cb-bac7-09ca4520fffa") 274 | ) 275 | (pad "14" thru_hole circle 276 | (at 7.62 0) 277 | (size 1.6 1.6) 278 | (drill 0.8) 279 | (layers "*.Cu" "*.Mask") 280 | (remove_unused_layers no) 281 | (uuid "8d9c64e8-03bb-44ad-af47-1c83fe50f2c7") 282 | ) 283 | (embedded_fonts no) 284 | (model "${KICAD9_3DMODEL_DIR}/Package_DIP.3dshapes/DIP-14_W7.62mm_Socket.step" 285 | (offset 286 | (xyz 0 0 0) 287 | ) 288 | (scale 289 | (xyz 1 1 1) 290 | ) 291 | (rotate 292 | (xyz 0 0 0) 293 | ) 294 | ) 295 | ) 296 | -------------------------------------------------------------------------------- /AppleII-Keyboard/Libraries/footprints/Connector_Project.pretty/DIP-16_W7.62mm_UndersidePins.kicad_mod: -------------------------------------------------------------------------------- 1 | (footprint "DIP-16_W7.62mm_UndersidePins" 2 | (version 20241229) 3 | (generator "pcbnew") 4 | (generator_version "9.0") 5 | (layer "F.Cu") 6 | (descr "Underside pins mounted in a DIP-16 pattern, row spacing 7.62mm (300 mils)") 7 | (tags "THT DIP DIL PDIP 2.54mm 7.62mm 300mil") 8 | (property "Reference" "REF**" 9 | (at 3.81 -2.33 0) 10 | (layer "F.SilkS") 11 | (uuid "ac44ce80-d9a2-46d4-a68d-0a7c7539f026") 12 | (effects 13 | (font 14 | (size 1 1) 15 | (thickness 0.15) 16 | ) 17 | ) 18 | ) 19 | (property "Value" "DIP-16_W7.62mm_UndersidePins" 20 | (at 3.81 20.11 0) 21 | (layer "F.Fab") 22 | (uuid "2efa30b6-50b2-48f4-97b2-f6e500671115") 23 | (effects 24 | (font 25 | (size 1 1) 26 | (thickness 0.15) 27 | ) 28 | ) 29 | ) 30 | (property "Datasheet" "" 31 | (at 0 0 0) 32 | (layer "F.Fab") 33 | (hide yes) 34 | (uuid "c908d517-c94d-4491-be44-cdfa9b526248") 35 | (effects 36 | (font 37 | (size 1.27 1.27) 38 | (thickness 0.15) 39 | ) 40 | ) 41 | ) 42 | (property "Description" "" 43 | (at 0 0 0) 44 | (layer "F.Fab") 45 | (hide yes) 46 | (uuid "d25855e2-3638-47e4-983e-e4a258a74f54") 47 | (effects 48 | (font 49 | (size 1.27 1.27) 50 | (thickness 0.15) 51 | ) 52 | ) 53 | ) 54 | (attr through_hole allow_missing_courtyard) 55 | (fp_line 56 | (start 1.16 -1.33) 57 | (end 1.16 19.11) 58 | (stroke 59 | (width 0.12) 60 | (type solid) 61 | ) 62 | (layer "F.SilkS") 63 | (uuid "7e4bc5d8-dfa0-4e2a-b6d8-b10ca2303a22") 64 | ) 65 | (fp_line 66 | (start 1.16 19.11) 67 | (end 6.46 19.11) 68 | (stroke 69 | (width 0.12) 70 | (type solid) 71 | ) 72 | (layer "F.SilkS") 73 | (uuid "a9143744-4687-4200-bf94-dde1ea8cf008") 74 | ) 75 | (fp_line 76 | (start 2.81 -1.33) 77 | (end 1.16 -1.33) 78 | (stroke 79 | (width 0.12) 80 | (type solid) 81 | ) 82 | (layer "F.SilkS") 83 | (uuid "7ccd329b-f5ce-40eb-b63f-8985aee02579") 84 | ) 85 | (fp_line 86 | (start 6.46 -1.33) 87 | (end 4.81 -1.33) 88 | (stroke 89 | (width 0.12) 90 | (type solid) 91 | ) 92 | (layer "F.SilkS") 93 | (uuid "0f9aec10-0dff-4ff9-b654-c219cde65166") 94 | ) 95 | (fp_line 96 | (start 6.46 19.11) 97 | (end 6.46 -1.33) 98 | (stroke 99 | (width 0.12) 100 | (type solid) 101 | ) 102 | (layer "F.SilkS") 103 | (uuid "b176a66c-804a-47ad-af4f-96184cc3be82") 104 | ) 105 | (fp_arc 106 | (start 4.81 -1.33) 107 | (mid 3.81 -0.33) 108 | (end 2.81 -1.33) 109 | (stroke 110 | (width 0.12) 111 | (type solid) 112 | ) 113 | (layer "F.SilkS") 114 | (uuid "88b6d4a2-c20c-4e15-9fcb-038f0a27c065") 115 | ) 116 | (fp_rect 117 | (start -1.06 -1.52) 118 | (end 8.67 19.3) 119 | (stroke 120 | (width 0.05) 121 | (type solid) 122 | ) 123 | (fill no) 124 | (layer "B.CrtYd") 125 | (uuid "c95712cd-1fb0-4b22-b689-5b0bacebd859") 126 | ) 127 | (fp_line 128 | (start 0.635 -0.27) 129 | (end 1.635 -1.27) 130 | (stroke 131 | (width 0.1) 132 | (type solid) 133 | ) 134 | (layer "F.Fab") 135 | (uuid "3c3b11c2-8e63-4f47-97d2-6c565478ec37") 136 | ) 137 | (fp_line 138 | (start 0.635 19.05) 139 | (end 0.635 -0.27) 140 | (stroke 141 | (width 0.1) 142 | (type solid) 143 | ) 144 | (layer "F.Fab") 145 | (uuid "e3a3e845-cc16-4b3e-bd64-6e4b2263713d") 146 | ) 147 | (fp_line 148 | (start 1.635 -1.27) 149 | (end 6.985 -1.27) 150 | (stroke 151 | (width 0.1) 152 | (type solid) 153 | ) 154 | (layer "F.Fab") 155 | (uuid "1df6b092-dea2-4fea-83dd-3ab7254bfe82") 156 | ) 157 | (fp_line 158 | (start 6.985 -1.27) 159 | (end 6.985 19.05) 160 | (stroke 161 | (width 0.1) 162 | (type solid) 163 | ) 164 | (layer "F.Fab") 165 | (uuid "0d88c5e4-bee6-4e1b-9756-11dbad5eeb1a") 166 | ) 167 | (fp_line 168 | (start 6.985 19.05) 169 | (end 0.635 19.05) 170 | (stroke 171 | (width 0.1) 172 | (type solid) 173 | ) 174 | (layer "F.Fab") 175 | (uuid "ef803d19-8a73-43e8-a84d-d9bff8c86e5e") 176 | ) 177 | (fp_text user "${REFERENCE}" 178 | (at 3.81 8.89 90) 179 | (layer "F.Fab") 180 | (uuid "f35a1992-f732-4107-a3ff-49a97fe5e410") 181 | (effects 182 | (font 183 | (size 1 1) 184 | (thickness 0.15) 185 | ) 186 | ) 187 | ) 188 | (pad "1" thru_hole roundrect 189 | (at 0 0) 190 | (size 1.6 1.6) 191 | (drill 0.8) 192 | (layers "*.Cu" "*.Mask") 193 | (remove_unused_layers no) 194 | (roundrect_rratio 0.15625) 195 | (uuid "bf2870c9-b74b-4d4f-9d33-90e294738c8f") 196 | ) 197 | (pad "2" thru_hole circle 198 | (at 0 2.54) 199 | (size 1.6 1.6) 200 | (drill 0.8) 201 | (layers "*.Cu" "*.Mask") 202 | (remove_unused_layers no) 203 | (uuid "f408e7d5-01e6-4556-a269-b70635261781") 204 | ) 205 | (pad "3" thru_hole circle 206 | (at 0 5.08) 207 | (size 1.6 1.6) 208 | (drill 0.8) 209 | (layers "*.Cu" "*.Mask") 210 | (remove_unused_layers no) 211 | (uuid "a314d97e-b87f-4173-ae58-0f495247af84") 212 | ) 213 | (pad "4" thru_hole circle 214 | (at 0 7.62) 215 | (size 1.6 1.6) 216 | (drill 0.8) 217 | (layers "*.Cu" "*.Mask") 218 | (remove_unused_layers no) 219 | (uuid "0498b90a-a685-411b-9eb3-81784a5b4af0") 220 | ) 221 | (pad "5" thru_hole circle 222 | (at 0 10.16) 223 | (size 1.6 1.6) 224 | (drill 0.8) 225 | (layers "*.Cu" "*.Mask") 226 | (remove_unused_layers no) 227 | (uuid "460ffaaf-62df-487c-bae6-e83b168be098") 228 | ) 229 | (pad "6" thru_hole circle 230 | (at 0 12.7) 231 | (size 1.6 1.6) 232 | (drill 0.8) 233 | (layers "*.Cu" "*.Mask") 234 | (remove_unused_layers no) 235 | (uuid "dde060bc-1111-4f81-beb3-bd646d207759") 236 | ) 237 | (pad "7" thru_hole circle 238 | (at 0 15.24) 239 | (size 1.6 1.6) 240 | (drill 0.8) 241 | (layers "*.Cu" "*.Mask") 242 | (remove_unused_layers no) 243 | (uuid "5e3df0f9-a5f8-411a-b83a-3c9be816b59d") 244 | ) 245 | (pad "8" thru_hole circle 246 | (at 0 17.78) 247 | (size 1.6 1.6) 248 | (drill 0.8) 249 | (layers "*.Cu" "*.Mask") 250 | (remove_unused_layers no) 251 | (uuid "cea67c44-7978-45e4-9a05-dac6a18860a9") 252 | ) 253 | (pad "9" thru_hole circle 254 | (at 7.62 17.78) 255 | (size 1.6 1.6) 256 | (drill 0.8) 257 | (layers "*.Cu" "*.Mask") 258 | (remove_unused_layers no) 259 | (uuid "76d3f4d4-0367-4ed6-ac81-9e9993882cd4") 260 | ) 261 | (pad "10" thru_hole circle 262 | (at 7.62 15.24) 263 | (size 1.6 1.6) 264 | (drill 0.8) 265 | (layers "*.Cu" "*.Mask") 266 | (remove_unused_layers no) 267 | (uuid "bd3059cb-e08c-45cf-a82d-831162394318") 268 | ) 269 | (pad "11" thru_hole circle 270 | (at 7.62 12.7) 271 | (size 1.6 1.6) 272 | (drill 0.8) 273 | (layers "*.Cu" "*.Mask") 274 | (remove_unused_layers no) 275 | (uuid "cf3f1c94-316d-40dd-9b43-9ca3c718fdc7") 276 | ) 277 | (pad "12" thru_hole circle 278 | (at 7.62 10.16) 279 | (size 1.6 1.6) 280 | (drill 0.8) 281 | (layers "*.Cu" "*.Mask") 282 | (remove_unused_layers no) 283 | (uuid "e38a1c24-1ca5-4131-930c-9d687006004a") 284 | ) 285 | (pad "13" thru_hole circle 286 | (at 7.62 7.62) 287 | (size 1.6 1.6) 288 | (drill 0.8) 289 | (layers "*.Cu" "*.Mask") 290 | (remove_unused_layers no) 291 | (uuid "119838a4-fa45-4093-ac62-cf52349705bd") 292 | ) 293 | (pad "14" thru_hole circle 294 | (at 7.62 5.08) 295 | (size 1.6 1.6) 296 | (drill 0.8) 297 | (layers "*.Cu" "*.Mask") 298 | (remove_unused_layers no) 299 | (uuid "79892084-13a2-4fc0-91af-5049fa16f6da") 300 | ) 301 | (pad "15" thru_hole circle 302 | (at 7.62 2.54) 303 | (size 1.6 1.6) 304 | (drill 0.8) 305 | (layers "*.Cu" "*.Mask") 306 | (remove_unused_layers no) 307 | (uuid "7fdbb6c9-18ca-4261-a724-8856ae401928") 308 | ) 309 | (pad "16" thru_hole circle 310 | (at 7.62 0) 311 | (size 1.6 1.6) 312 | (drill 0.8) 313 | (layers "*.Cu" "*.Mask") 314 | (remove_unused_layers no) 315 | (uuid "2fd33398-f3fe-4ebe-be78-36815c58f92e") 316 | ) 317 | (embedded_fonts no) 318 | ) 319 | -------------------------------------------------------------------------------- /AppleII-Keyboard/Libraries/symbols/Diode_Project.kicad_sym: -------------------------------------------------------------------------------- 1 | (kicad_symbol_lib 2 | (version 20241209) 3 | (generator "kicad_symbol_editor") 4 | (generator_version "9.0") 5 | (symbol "DT2042-04TS" 6 | (pin_names 7 | (hide yes) 8 | ) 9 | (exclude_from_sim no) 10 | (in_bom yes) 11 | (on_board yes) 12 | (property "Reference" "D" 13 | (at 7.62 2.54 0) 14 | (effects 15 | (font 16 | (size 1.27 1.27) 17 | ) 18 | (justify left) 19 | ) 20 | ) 21 | (property "Value" "DT2042-04TS" 22 | (at 7.62 0.635 0) 23 | (effects 24 | (font 25 | (size 1.27 1.27) 26 | ) 27 | (justify left) 28 | ) 29 | ) 30 | (property "Footprint" "Package_TO_SOT_SMD:TSOT-23-6_HandSoldering" 31 | (at 7.62 -1.27 0) 32 | (effects 33 | (font 34 | (size 1.27 1.27) 35 | ) 36 | (justify left) 37 | (hide yes) 38 | ) 39 | ) 40 | (property "Datasheet" "" 41 | (at 3.175 3.175 0) 42 | (effects 43 | (font 44 | (size 1.27 1.27) 45 | ) 46 | (hide yes) 47 | ) 48 | ) 49 | (property "Description" "TVS Diode Array, 5.5V Working, 4 Channels, TSOT-23-6 package" 50 | (at 0 0 0) 51 | (effects 52 | (font 53 | (size 1.27 1.27) 54 | ) 55 | (hide yes) 56 | ) 57 | ) 58 | (property "ki_keywords" "usb esd protection suppression transient" 59 | (at 0 0 0) 60 | (effects 61 | (font 62 | (size 1.27 1.27) 63 | ) 64 | (hide yes) 65 | ) 66 | ) 67 | (property "ki_fp_filters" "SOT?23*" 68 | (at 0 0 0) 69 | (effects 70 | (font 71 | (size 1.27 1.27) 72 | ) 73 | (hide yes) 74 | ) 75 | ) 76 | (symbol "DT2042-04TS_0_0" 77 | (pin passive line 78 | (at 0 -5.08 90) 79 | (length 2.54) 80 | (name "A" 81 | (effects 82 | (font 83 | (size 1.27 1.27) 84 | ) 85 | ) 86 | ) 87 | (number "2" 88 | (effects 89 | (font 90 | (size 1.27 1.27) 91 | ) 92 | ) 93 | ) 94 | ) 95 | ) 96 | (symbol "DT2042-04TS_0_1" 97 | (rectangle 98 | (start -4.445 2.54) 99 | (end 6.985 -2.54) 100 | (stroke 101 | (width 0.254) 102 | (type default) 103 | ) 104 | (fill 105 | (type background) 106 | ) 107 | ) 108 | (polyline 109 | (pts 110 | (xy -3.302 1.016) (xy -3.302 1.27) (xy -1.778 1.27) 111 | ) 112 | (stroke 113 | (width 0) 114 | (type default) 115 | ) 116 | (fill 117 | (type none) 118 | ) 119 | ) 120 | (polyline 121 | (pts 122 | (xy -2.54 2.54) (xy -2.54 1.27) 123 | ) 124 | (stroke 125 | (width 0) 126 | (type default) 127 | ) 128 | (fill 129 | (type none) 130 | ) 131 | ) 132 | (polyline 133 | (pts 134 | (xy -2.54 1.27) (xy -2.54 -1.27) (xy 2.54 -1.27) (xy 2.54 1.27) 135 | ) 136 | (stroke 137 | (width 0) 138 | (type default) 139 | ) 140 | (fill 141 | (type none) 142 | ) 143 | ) 144 | (polyline 145 | (pts 146 | (xy -2.54 1.27) (xy -1.905 0) (xy -3.175 0) (xy -2.54 1.27) 147 | ) 148 | (stroke 149 | (width 0) 150 | (type default) 151 | ) 152 | (fill 153 | (type none) 154 | ) 155 | ) 156 | (polyline 157 | (pts 158 | (xy 0 2.54) (xy 0 1.27) 159 | ) 160 | (stroke 161 | (width 0) 162 | (type default) 163 | ) 164 | (fill 165 | (type none) 166 | ) 167 | ) 168 | (polyline 169 | (pts 170 | (xy 0 -1.27) (xy 0 1.27) 171 | ) 172 | (stroke 173 | (width 0) 174 | (type default) 175 | ) 176 | (fill 177 | (type none) 178 | ) 179 | ) 180 | (polyline 181 | (pts 182 | (xy 0 -1.27) (xy 0 -2.54) 183 | ) 184 | (stroke 185 | (width 0) 186 | (type default) 187 | ) 188 | (fill 189 | (type none) 190 | ) 191 | ) 192 | (circle 193 | (center 0 -1.27) 194 | (radius 0.254) 195 | (stroke 196 | (width 0) 197 | (type default) 198 | ) 199 | (fill 200 | (type outline) 201 | ) 202 | ) 203 | (polyline 204 | (pts 205 | (xy 0.635 0) (xy -0.635 0) (xy 0 1.27) (xy 0.635 0) 206 | ) 207 | (stroke 208 | (width 0) 209 | (type default) 210 | ) 211 | (fill 212 | (type none) 213 | ) 214 | ) 215 | (polyline 216 | (pts 217 | (xy 0.762 1.27) (xy -0.762 1.27) (xy -0.762 1.016) 218 | ) 219 | (stroke 220 | (width 0) 221 | (type default) 222 | ) 223 | (fill 224 | (type none) 225 | ) 226 | ) 227 | (polyline 228 | (pts 229 | (xy 1.778 1.016) (xy 1.778 1.27) (xy 3.175 1.27) (xy 3.302 1.27) 230 | ) 231 | (stroke 232 | (width 0) 233 | (type default) 234 | ) 235 | (fill 236 | (type none) 237 | ) 238 | ) 239 | (polyline 240 | (pts 241 | (xy 2.54 2.54) (xy 2.54 1.27) 242 | ) 243 | (stroke 244 | (width 0) 245 | (type default) 246 | ) 247 | (fill 248 | (type none) 249 | ) 250 | ) 251 | (polyline 252 | (pts 253 | (xy 2.54 1.27) (xy 1.905 0) (xy 3.175 0) (xy 2.54 1.27) 254 | ) 255 | (stroke 256 | (width 0) 257 | (type default) 258 | ) 259 | (fill 260 | (type none) 261 | ) 262 | ) 263 | (circle 264 | (center 2.54 -1.27) 265 | (radius 0.254) 266 | (stroke 267 | (width 0) 268 | (type default) 269 | ) 270 | (fill 271 | (type outline) 272 | ) 273 | ) 274 | (polyline 275 | (pts 276 | (xy 4.318 1.016) (xy 4.318 1.27) (xy 5.715 1.27) (xy 5.842 1.27) 277 | ) 278 | (stroke 279 | (width 0) 280 | (type default) 281 | ) 282 | (fill 283 | (type none) 284 | ) 285 | ) 286 | (polyline 287 | (pts 288 | (xy 5.08 2.54) (xy 5.08 1.27) 289 | ) 290 | (stroke 291 | (width 0) 292 | (type default) 293 | ) 294 | (fill 295 | (type none) 296 | ) 297 | ) 298 | (polyline 299 | (pts 300 | (xy 5.08 1.27) (xy 5.08 -1.27) (xy 2.54 -1.27) 301 | ) 302 | (stroke 303 | (width 0) 304 | (type default) 305 | ) 306 | (fill 307 | (type none) 308 | ) 309 | ) 310 | (polyline 311 | (pts 312 | (xy 5.08 1.27) (xy 4.445 0) (xy 5.715 0) (xy 5.08 1.27) 313 | ) 314 | (stroke 315 | (width 0) 316 | (type default) 317 | ) 318 | (fill 319 | (type none) 320 | ) 321 | ) 322 | ) 323 | (symbol "DT2042-04TS_1_1" 324 | (pin no_connect line 325 | (at -3.81 -2.54 90) 326 | (length 2.54) 327 | (hide yes) 328 | (name "NC" 329 | (effects 330 | (font 331 | (size 1.27 1.27) 332 | ) 333 | ) 334 | ) 335 | (number "5" 336 | (effects 337 | (font 338 | (size 1.27 1.27) 339 | ) 340 | ) 341 | ) 342 | ) 343 | (pin passive line 344 | (at -2.54 5.08 270) 345 | (length 2.54) 346 | (name "K" 347 | (effects 348 | (font 349 | (size 1.27 1.27) 350 | ) 351 | ) 352 | ) 353 | (number "1" 354 | (effects 355 | (font 356 | (size 1.27 1.27) 357 | ) 358 | ) 359 | ) 360 | ) 361 | (pin passive line 362 | (at 0 5.08 270) 363 | (length 2.54) 364 | (name "K" 365 | (effects 366 | (font 367 | (size 1.27 1.27) 368 | ) 369 | ) 370 | ) 371 | (number "3" 372 | (effects 373 | (font 374 | (size 1.27 1.27) 375 | ) 376 | ) 377 | ) 378 | ) 379 | (pin passive line 380 | (at 2.54 5.08 270) 381 | (length 2.54) 382 | (name "K" 383 | (effects 384 | (font 385 | (size 1.27 1.27) 386 | ) 387 | ) 388 | ) 389 | (number "4" 390 | (effects 391 | (font 392 | (size 1.27 1.27) 393 | ) 394 | ) 395 | ) 396 | ) 397 | (pin passive line 398 | (at 5.08 5.08 270) 399 | (length 2.54) 400 | (name "K" 401 | (effects 402 | (font 403 | (size 1.27 1.27) 404 | ) 405 | ) 406 | ) 407 | (number "6" 408 | (effects 409 | (font 410 | (size 1.27 1.27) 411 | ) 412 | ) 413 | ) 414 | ) 415 | ) 416 | (embedded_fonts no) 417 | ) 418 | ) 419 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/Libraries/symbols/Connector_Project.kicad_sym: -------------------------------------------------------------------------------- 1 | (kicad_symbol_lib 2 | (version 20241209) 3 | (generator "kicad_symbol_editor") 4 | (generator_version "9.0") 5 | (symbol "Shielded-Mini-DIN-6" 6 | (pin_names 7 | (offset 1.016) 8 | ) 9 | (exclude_from_sim no) 10 | (in_bom yes) 11 | (on_board yes) 12 | (property "Reference" "J" 13 | (at 0 6.35 0) 14 | (effects 15 | (font 16 | (size 1.27 1.27) 17 | ) 18 | ) 19 | ) 20 | (property "Value" "Shielded-Mini-DIN-6" 21 | (at 0 -6.35 0) 22 | (effects 23 | (font 24 | (size 1.27 1.27) 25 | ) 26 | ) 27 | ) 28 | (property "Footprint" "Connector_Project:Mini_DIN_round_6_canned" 29 | (at 0 0 0) 30 | (effects 31 | (font 32 | (size 1.27 1.27) 33 | ) 34 | (hide yes) 35 | ) 36 | ) 37 | (property "Datasheet" "" 38 | (at 0 0 0) 39 | (effects 40 | (font 41 | (size 1.27 1.27) 42 | ) 43 | (hide yes) 44 | ) 45 | ) 46 | (property "Description" "Shielded 6-pin Mini-DIN connector" 47 | (at 0 0 0) 48 | (effects 49 | (font 50 | (size 1.27 1.27) 51 | ) 52 | (hide yes) 53 | ) 54 | ) 55 | (property "ki_keywords" "Mini-DIN" 56 | (at 0 0 0) 57 | (effects 58 | (font 59 | (size 1.27 1.27) 60 | ) 61 | (hide yes) 62 | ) 63 | ) 64 | (property "ki_fp_filters" "MINI?DIN*" 65 | (at 0 0 0) 66 | (effects 67 | (font 68 | (size 1.27 1.27) 69 | ) 70 | (hide yes) 71 | ) 72 | ) 73 | (symbol "Shielded-Mini-DIN-6_0_1" 74 | (polyline 75 | (pts 76 | (xy -4.318 -2.54) (xy -3.048 -2.54) (xy -3.048 -4.064) 77 | ) 78 | (stroke 79 | (width 0.254) 80 | (type default) 81 | ) 82 | (fill 83 | (type none) 84 | ) 85 | ) 86 | (polyline 87 | (pts 88 | (xy -3.81 0) (xy -5.08 0) 89 | ) 90 | (stroke 91 | (width 0) 92 | (type default) 93 | ) 94 | (fill 95 | (type none) 96 | ) 97 | ) 98 | (circle 99 | (center -3.302 0) 100 | (radius 0.508) 101 | (stroke 102 | (width 0) 103 | (type default) 104 | ) 105 | (fill 106 | (type none) 107 | ) 108 | ) 109 | (polyline 110 | (pts 111 | (xy -2.54 2.54) (xy -5.08 2.54) 112 | ) 113 | (stroke 114 | (width 0) 115 | (type default) 116 | ) 117 | (fill 118 | (type none) 119 | ) 120 | ) 121 | (circle 122 | (center -2.032 2.54) 123 | (radius 0.508) 124 | (stroke 125 | (width 0) 126 | (type default) 127 | ) 128 | (fill 129 | (type none) 130 | ) 131 | ) 132 | (circle 133 | (center -2.032 -2.54) 134 | (radius 0.508) 135 | (stroke 136 | (width 0) 137 | (type default) 138 | ) 139 | (fill 140 | (type none) 141 | ) 142 | ) 143 | (polyline 144 | (pts 145 | (xy -2.032 -3.048) (xy -2.032 -3.556) (xy -5.08 -3.556) (xy -5.08 -2.54) 146 | ) 147 | (stroke 148 | (width 0) 149 | (type default) 150 | ) 151 | (fill 152 | (type none) 153 | ) 154 | ) 155 | (polyline 156 | (pts 157 | (xy -1.016 5.08) (xy -1.016 4.064) (xy 1.016 4.064) (xy 1.016 5.08) 158 | ) 159 | (stroke 160 | (width 0.254) 161 | (type default) 162 | ) 163 | (fill 164 | (type none) 165 | ) 166 | ) 167 | (rectangle 168 | (start -0.762 2.54) 169 | (end 0.762 0) 170 | (stroke 171 | (width 0) 172 | (type default) 173 | ) 174 | (fill 175 | (type outline) 176 | ) 177 | ) 178 | (arc 179 | (start 3.048 -4.064) 180 | (mid 0 -5.08) 181 | (end -3.048 -4.064) 182 | (stroke 183 | (width 0.254) 184 | (type default) 185 | ) 186 | (fill 187 | (type none) 188 | ) 189 | ) 190 | (arc 191 | (start 1.016 5.08) 192 | (mid 4.6646 2.1356) 193 | (end 4.318 -2.54) 194 | (stroke 195 | (width 0.254) 196 | (type default) 197 | ) 198 | (fill 199 | (type none) 200 | ) 201 | ) 202 | (arc 203 | (start -4.318 -2.54) 204 | (mid -4.6241 2.1181) 205 | (end -1.016 5.08) 206 | (stroke 207 | (width 0.254) 208 | (type default) 209 | ) 210 | (fill 211 | (type none) 212 | ) 213 | ) 214 | (circle 215 | (center 2.032 -2.54) 216 | (radius 0.508) 217 | (stroke 218 | (width 0) 219 | (type default) 220 | ) 221 | (fill 222 | (type none) 223 | ) 224 | ) 225 | (polyline 226 | (pts 227 | (xy 2.032 -3.048) (xy 2.032 -3.556) (xy 5.08 -3.556) (xy 5.08 -2.54) 228 | ) 229 | (stroke 230 | (width 0) 231 | (type default) 232 | ) 233 | (fill 234 | (type none) 235 | ) 236 | ) 237 | (circle 238 | (center 2.286 2.54) 239 | (radius 0.508) 240 | (stroke 241 | (width 0) 242 | (type default) 243 | ) 244 | (fill 245 | (type none) 246 | ) 247 | ) 248 | (polyline 249 | (pts 250 | (xy 2.794 2.54) (xy 5.08 2.54) 251 | ) 252 | (stroke 253 | (width 0) 254 | (type default) 255 | ) 256 | (fill 257 | (type none) 258 | ) 259 | ) 260 | (circle 261 | (center 3.302 0) 262 | (radius 0.508) 263 | (stroke 264 | (width 0) 265 | (type default) 266 | ) 267 | (fill 268 | (type none) 269 | ) 270 | ) 271 | (polyline 272 | (pts 273 | (xy 4.318 -2.54) (xy 3.048 -2.54) (xy 3.048 -4.064) 274 | ) 275 | (stroke 276 | (width 0.254) 277 | (type default) 278 | ) 279 | (fill 280 | (type none) 281 | ) 282 | ) 283 | (polyline 284 | (pts 285 | (xy 5.08 0) (xy 3.81 0) 286 | ) 287 | (stroke 288 | (width 0) 289 | (type default) 290 | ) 291 | (fill 292 | (type none) 293 | ) 294 | ) 295 | ) 296 | (symbol "Shielded-Mini-DIN-6_1_1" 297 | (pin passive line 298 | (at -7.62 2.54 0) 299 | (length 2.54) 300 | (name "~" 301 | (effects 302 | (font 303 | (size 1.27 1.27) 304 | ) 305 | ) 306 | ) 307 | (number "6" 308 | (effects 309 | (font 310 | (size 1.27 1.27) 311 | ) 312 | ) 313 | ) 314 | ) 315 | (pin passive line 316 | (at -7.62 0 0) 317 | (length 2.54) 318 | (name "~" 319 | (effects 320 | (font 321 | (size 1.27 1.27) 322 | ) 323 | ) 324 | ) 325 | (number "4" 326 | (effects 327 | (font 328 | (size 1.27 1.27) 329 | ) 330 | ) 331 | ) 332 | ) 333 | (pin passive line 334 | (at -7.62 -2.54 0) 335 | (length 2.54) 336 | (name "~" 337 | (effects 338 | (font 339 | (size 1.27 1.27) 340 | ) 341 | ) 342 | ) 343 | (number "2" 344 | (effects 345 | (font 346 | (size 1.27 1.27) 347 | ) 348 | ) 349 | ) 350 | ) 351 | (pin passive line 352 | (at 0 -7.62 90) 353 | (length 2.54) 354 | (name "~" 355 | (effects 356 | (font 357 | (size 1.27 1.27) 358 | ) 359 | ) 360 | ) 361 | (number "SH" 362 | (effects 363 | (font 364 | (size 1.27 1.27) 365 | ) 366 | ) 367 | ) 368 | ) 369 | (pin passive line 370 | (at 7.62 2.54 180) 371 | (length 2.54) 372 | (name "~" 373 | (effects 374 | (font 375 | (size 1.27 1.27) 376 | ) 377 | ) 378 | ) 379 | (number "5" 380 | (effects 381 | (font 382 | (size 1.27 1.27) 383 | ) 384 | ) 385 | ) 386 | ) 387 | (pin passive line 388 | (at 7.62 0 180) 389 | (length 2.54) 390 | (name "~" 391 | (effects 392 | (font 393 | (size 1.27 1.27) 394 | ) 395 | ) 396 | ) 397 | (number "3" 398 | (effects 399 | (font 400 | (size 1.27 1.27) 401 | ) 402 | ) 403 | ) 404 | ) 405 | (pin passive line 406 | (at 7.62 -2.54 180) 407 | (length 2.54) 408 | (name "~" 409 | (effects 410 | (font 411 | (size 1.27 1.27) 412 | ) 413 | ) 414 | ) 415 | (number "1" 416 | (effects 417 | (font 418 | (size 1.27 1.27) 419 | ) 420 | ) 421 | ) 422 | ) 423 | ) 424 | (embedded_fonts no) 425 | ) 426 | ) 427 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apple II Keyboard Adapter 2 | 3 | This is a simple Arduino project to allow connecting a PS/2 keyboard to the 4 | 16 pin DIP keyboard connector on an Apple II. I've tested it on a 5 | ReactiveMicro reproduction Apple II+ RFI logic board and it works great. 6 | 7 | All keys are mapped to modern keyboard equivalents and the Apple can be 8 | reset with the Ctrl-PrtScrn key combo. 9 | 10 | I've built this project two different ways - the original prototype with a cheap Arduino Pro 11 | Micro clone, and a newer version that consolidates all the wiring onto a small PCB with an 12 | ATtiny24a microcontroller. This is very much a DIY project. 13 | 14 | ![Photos](docs/action_shots.jpg) 15 | 16 | 17 | ## ATtiny24a version 18 | 19 | ![Tiny Board Picture](docs/tiny_adapter_and_connector.jpg) 20 | 21 | This version of the keyboard adapter is pretty simple and also includes a footprint for optional 22 | ESD protection diodes to protect your Apple II from static discharges through the PS/2 interface. 23 | It will require an ATtiny ISP (In-system Programmer) like the XGecu T48 or similar, or an Arduino 24 | running the ArduinoISP sketch could also work. 25 | 26 | It's composed of two parts: an adapter board with a microcontroller for performing the 27 | translation logic and a connector board with the PS/2 keyboard connector that can be mounted 28 | separately. If you want to use a different type of PS/2 connector then you are free to wire 29 | up anything you need to the 8 pin header on the adapter board! For example, I can use an old 30 | PC screw-mounted PS/2 connector. 31 | 32 | 33 | ### Building 34 | 35 | This repo contains all the source files for building a Keyboard Adapter: 36 | * [KiCad project for the adapter board](./AppleII-Keyboard) 37 | * [KiCad project for a mountable PS/2 connector board](./AppleII-Keyboard-Connector) 38 | * [Source code for the microcontroller](./src/AppleII_PS2_Keyboard) 39 | 40 | All the output files are also included so you don't need to install KiCad or the Arduino IDE if 41 | you don't want to. 42 | * Schematics for the [adapter board](./AppleII-Keyboard/AppleII-Keyboard.pdf) and [connector board](./AppleII-Keyboard-Connector/AppleII-Keyboard-Connector.pdf) 43 | * Gerber files for the [adapter board](./AppleII-Keyboard/outputs/) and [connector board](./AppleII-Keyboard-Connector/outputs/) 44 | * [Pre-compiled ATtiny code](./src/AppleII_PS2_Keyboard/build/diy_attiny.avr.attiny24_diy/AppleII_PS2_Keyboard.ino.hex) to flash into the ATtiny 45 | 46 | 47 | #### Parts List 48 | 49 | Most of the parts are commodity and can be substituted for others, except for the ATtiny and the 50 | ESD protection diodes. The ESD diodes are OPTIONAL so can be omitted if you can't find them or have 51 | difficulty soldering the small surface-mount part. 52 | 53 | You'll need one of each PCB; one PCB for the adapter that plugs into the keyboard connector on the 54 | Apple II logic board and one PCB for the PS/2 mini-DIN connector board. 55 | 56 | 57 | | Qty | Value | Mfr | MfrPartNo | MouserPartNo | 58 | |-----|---------------------------|---------------------|--------------------|----------------------| 59 | | 1 | 1x16 Machine Pin Header | Samtec | TS-116-T-A | 200-TS116TA | 60 | | 1 | DIP-14 Socket | TE Connectivity | 1-2199298-3 | 571-1-2199298-3 | 61 | | 1 | ATtiny24a | Microchip | ATTINY24A-PU | 556-ATTINY24A-PU | 62 | | 1 | 0.1uF | Vishay | A104K15X7RF5TAA | 594-A104K15X7RF5TAA | 63 | | 1 | Breakaway 2x8 pin headers | Amphenol | 10129381-916001BLF | 649-1012938191601BLF | 64 | | 1 | ESD Protection Diodes | Diodes Incorporated | DT2042-04TS-7 | 621-DT2042-04TS-7 | 65 | | 1 | Mini-DIN-6 connector | Kycon | KMDGX-6S-BS | 806-KMDGX-6S-BS | 66 | | 2 | 2x4P IDC cable housing | Amphenol | 71600-008LF | 649-71600-008LF | 67 | 68 | In addition to these components you will also need some 8 conductor 1.27mm pitch ribbon cable for 69 | the cable between the adapter board and the connector board, as long as you need to reach wherever 70 | you'll be mounting the PS/2 connector. This type of ribbon cable can be scavenged from common internal 71 | cables that were used in old PCs. 72 | 73 | 74 | #### Assembling 75 | 76 | First, use a sharp thin knife on a solid surface (with protection) to split the 1x16 and 2x8 pin headers 77 | in half so you end up with 2 1x8 machine pin headers and 2 2x4 square pin heders. 78 | 79 | Then you can solder one of the 2x4 headers and the mini-DIN-6 connector to the connector board. 80 | 81 | Soldering together the adapter board is a little more involved: 82 | 1. If you have the ESD protection diode then carefully solder them on first. Pin 1 on the tiny package 83 | is marked with a dot that you may need a strong light and magnifying glass to see. This pin is marked 84 | on the PCB with a small triangle. After soldering on, check for shorts between any of the solder joints 85 | before continuing. 86 | 2. The two 8-machine-pin headers should be installed next on the **underside** of the board as the 87 | silkscreen is facing you. The board's silkscreen has an IC outline that the two pin headers will be 88 | installed around. Since the headers are on the underside of the board you will be soldering on the top 89 | of the board around that IC outline. 90 | 91 | It helps to keep the pin headers straight if you insert them into a solderless breadboard or protoboard 92 | and then rest the PCB on top while soldering them in place. 93 | 3. Install the DIP-14 IC socket on the top side of the board oriented so that pin 1 is pointed to by the 94 | triangle on the silkscreen. The IC sockets referenced in the part list will easily clear the solder 95 | joints of the pin headers from step 2 but if yours don't then you'll have to file a channel so they do. 96 | 97 | Half of the socket's pins will be between the two pin headers from step 2 so getting the soldering iron 98 | to them is a little tight. 99 | 4. Install the decoupling capacitor on the top side of the board and solder in place. 100 | 101 | To assemble the 8 pin ribbon cable just make sure that the same wire is entering the marked pin 1 position 102 | on both connector housings. The ribbon cable can enter either side of the housing as long as that wire lines 103 | up with the pin 1 position. 104 | 105 | 106 | #### Flashing the ATtiny 107 | 108 | These steps will vary depending on the programmer and software you use. I can confirm that the XGecu T48 109 | programmer works but I am sure there are many others. An Arduino running the ArduinoISP sketch should also 110 | work (though setting fuse values looks much more complicated). 111 | 112 | 1. Select the ATtiny24a device (DIP14 packaging if the different packages are listed) in your programming software. 113 | 2. Load [the .hex file](./src/AppleII_PS2_Keyboard/build/diy_attiny.avr.attiny24_diy/AppleII_PS2_Keyboard.ino.hex) 114 | into your programming software. Make sure to load it as a hex file and not as a binary file. 115 | 3. Find and open the tab or dialog box to set the ATtiny fuse values. In the Xgpro application these settings are 116 | on the "Config" tab. 117 | * clear CKDIV8=0 (to disable clock division by 8) 118 | 4. Program the ATtiny 119 | 120 | 121 | ## Arduino Pro Micro version 122 | 123 | #### Parts list 124 | 1. Arduino. I used a cheap Arduino Pro Micro clone from Amazon but 125 | you could probably adapt to use whatever you have on hand. 126 | 2. Female PS/2 connector 127 | 3. 2 8-pin male machine pin headers, or some other connector for the 128 | DIP-16 socket on the Apple II logic board. 129 | 130 | #### Assembling 131 | 132 | ![Hookup Diagram](docs/promicro_wiring_diagram.svg) 133 | 134 | _Warning_: The DIP-16 connector on the logic board does have some pins with 135 | higher voltages that will destroy your Arduino if you accidentally connect to 136 | them, so take care. 137 | 138 | The Arduino hole pattern is too wide for the DIP-16 socket so I used another 139 | PCB to hold the machine pins and then jumpered the Arduino to the pins on top. 140 | I also used a pin header to connect to a spare PS/2 connector from an old PC. 141 | 142 | It's not so pretty, but it's compact and cost almost nothing. 143 | 144 | ![Prototype Image](docs/prototype.jpg) 145 | -------------------------------------------------------------------------------- /src/scripts/generate_table.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import collections 4 | import json 5 | import itertools 6 | import logging 7 | import sys 8 | 9 | 10 | logging.basicConfig(level=logging.DEBUG, format='[%(levelname)s] %(message)s') 11 | 12 | logger = logging.getLogger(__name__) 13 | 14 | 15 | AppleKeyMapping = collections.namedtuple('AppleKeyMapping', 16 | ['plain', 'ctrl', 'shift', 'ctrl_shift', 'keycap']) 17 | 18 | 19 | # Create a map of relevant Apple II key combos to Apple II keyboard codes 20 | apple_keycodes = {} 21 | with open('appleii_asciicodes.txt') as fp: 22 | for line in fp: 23 | line = line.rstrip() 24 | keycap, plain_code, ctrled_code, shifted_code, ctrl_shifted_code = line.split(' ') 25 | plain_code = int(plain_code, 0) 26 | ctrled_code = int(ctrled_code, 0) 27 | shifted_code = int(shifted_code, 0) 28 | ctrl_shifted_code = int(ctrl_shifted_code, 0) 29 | 30 | if shifted_code != plain_code: 31 | assert len(keycap) == 2, "Expected two chars on the keycap [{}]".format(keycap) 32 | 33 | primary, secondary = keycap[0], keycap[1] 34 | apple_keycodes[primary] = plain_code 35 | apple_keycodes[secondary] = shifted_code 36 | 37 | if ctrled_code != plain_code: 38 | logger.debug("Ctrl modifier relevant for Apple II keycap [%s]", keycap) 39 | apple_keycodes['Ctrl+' + primary] = ctrled_code 40 | 41 | if ctrl_shifted_code != shifted_code: 42 | logger.debug("CtrlShift modifier relevant for Apple II keycap [%s]", keycap) 43 | apple_keycodes['CtrlShift+' + primary] = ctrl_shifted_code 44 | else: 45 | assert len(keycap) != 2, "Expected one char on the keycap [{}]".format(keycap) 46 | assert shifted_code == plain_code, "Expected no shift modifier effect" 47 | assert ctrl_shifted_code == ctrled_code, "Expected no shift modifier effect" 48 | 49 | apple_keycodes[keycap] = plain_code 50 | if ctrled_code != plain_code: 51 | logger.debug("Ctrl modifier relevant for Apple II keycap [%s]", keycap) 52 | apple_keycodes['Ctrl+' + keycap] = ctrled_code 53 | 54 | 55 | # For each PS/2 keyboard key, try to match it to a corresponding Apple II keyboard function 56 | ps2_mapping = {} 57 | with open('ps2_scancodes.txt') as fp: 58 | for line in fp: 59 | line = line.rstrip() 60 | scancode, keycap = line.split(' ') 61 | 62 | primary = keycap 63 | secondary = None 64 | if len(keycap) == 2: 65 | primary, secondary = keycap[0], keycap[1] 66 | 67 | plain_code = apple_keycodes.pop(primary, None) 68 | if plain_code is None: 69 | logger.info('PS/2 keycap [%s] does not map to an Apple II function', keycap) 70 | continue 71 | 72 | shifted_code = apple_keycodes.pop(secondary, plain_code) 73 | ctrled_code = apple_keycodes.pop('Ctrl+' + primary, plain_code) 74 | 75 | ctrl_shifted_code = apple_keycodes.pop('CtrlShift+' + primary, None) 76 | if ctrl_shifted_code is None: 77 | if shifted_code != plain_code: 78 | # This is primarily a shifted key 79 | ctrl_shifted_code = shifted_code 80 | elif ctrled_code != plain_code: 81 | # This is primarily a ctrl'd key 82 | ctrl_shifted_code = ctrled_code 83 | else: 84 | ctrl_shifted_code = plain_code 85 | 86 | ps2_mapping[scancode] = AppleKeyMapping(plain_code, ctrled_code, shifted_code, ctrl_shifted_code, keycap) 87 | 88 | 89 | # Check that all Apple II keys are representated in the mapping 90 | if len(apple_keycodes) != 0: 91 | logger.warning("Some Apple II keyboard keys are not represented:") 92 | for k in apple_keycodes: 93 | logger.warning(" - [%s]", k) 94 | sys.exit(1) 95 | 96 | 97 | #print(json.dumps(ps2_mapping, indent=' ')) 98 | 99 | def scancode_key(scancode): 100 | return "{0:02X}".format(scancode) if scancode < 0x100 \ 101 | else "E0{0:02X}".format(scancode % 0x100) 102 | 103 | # build a single lookup table of scancode to ASCII codes 104 | scancode_table = [ ps2_mapping.get(scancode_key(scancode), None) for scancode in range(512) ] 105 | 106 | 107 | # Split the table into two, removing the largest range of scan codes with no mapping 108 | def split_scancode_table(scancode_table): 109 | # First remove empty mappings from the end of the table 110 | while scancode_table and scancode_table[-1] is None: 111 | scancode_table = scancode_table[:-1] 112 | 113 | # Find the first non-empty mapping 114 | span1_start = 0 115 | for i in range(len(scancode_table)): 116 | if scancode_table[i] is not None: 117 | span1_start = i 118 | break 119 | 120 | # Find the largest span of empty mappings in the list to cut out 121 | range_start, range_size = 0, 0 122 | cut_start, cut_size = 0, 0 123 | for i in range(len(scancode_table)): 124 | if scancode_table[i] is None: 125 | if range_start + range_size == i: 126 | # empty mapping is part of the current span 127 | range_size += 1 128 | else: 129 | # start of a new empty mapping span 130 | range_start, range_size = i, 1 131 | else: 132 | # found the end of the current empty mapping span 133 | if range_size > cut_size: 134 | cut_start, cut_size = range_start, range_size 135 | 136 | # Cut out the range of empty mappings, returning the spans before & after it 137 | return span1_start, scancode_table[span1_start:cut_start], \ 138 | cut_start + cut_size, scancode_table[cut_start + cut_size:] 139 | 140 | 141 | span1_start, span1, span2_start, span2 = split_scancode_table(scancode_table) 142 | 143 | 144 | # Output a C++ class that maps PS/2 scan code & modifier keys (shift, ctrl) to the 145 | # Apple II keyboard code to emit. 146 | print(f"""#pragma once 147 | #include "PS2Keyboard.h" 148 | 149 | // This file is generated from a script 150 | // DO NOT EDIT 151 | 152 | // Class to translate PS2 scan codes into Apple II keyboard codes. 153 | class AppleIIKeyboardTranslation {{ 154 | public: 155 | AppleIIKeyboardTranslation(PS2Keyboard& kbd) : m_kbd(kbd) {{}} 156 | 157 | // Fetches the next encoded key code, or 0 if there isn't one. 158 | uint8_t getKeyCode(); 159 | 160 | private: 161 | PS2Keyboard& m_kbd; 162 | 163 | enum {{ 164 | SCANCODE_SPAN1_START = {span1_start}, 165 | SCANCODE_SPAN1_SIZE = {len(span1)}, 166 | SCANCODE_SPAN2_START = {span2_start}, 167 | SCANCODE_SPAN2_SIZE = {len(span2)}, 168 | }}; 169 | static const uint8_t scancode_span1[SCANCODE_SPAN1_SIZE][4] PROGMEM; 170 | static const uint8_t scancode_span2[SCANCODE_SPAN2_SIZE][4] PROGMEM; 171 | }}; 172 | """) 173 | 174 | print(""" 175 | uint8_t AppleIIKeyboardTranslation::getKeyCode() { 176 | uint16_t scanCode = m_kbd.getKeypress(); 177 | 178 | uint8_t modifiers = 0; 179 | if(m_kbd.isShiftPressed()) { 180 | modifiers |= 0x1; 181 | } 182 | if(m_kbd.isCtrlPressed()) { 183 | modifiers |= 0x2; 184 | } 185 | 186 | if(scanCode < SCANCODE_SPAN1_START) { 187 | return 0; 188 | } else if(scanCode < SCANCODE_SPAN1_START+SCANCODE_SPAN1_SIZE) { 189 | return pgm_read_byte(&(scancode_span1[scanCode - SCANCODE_SPAN1_START][modifiers])); 190 | } 191 | 192 | if(scanCode < SCANCODE_SPAN2_START) { 193 | return 0; 194 | } else if(scanCode < SCANCODE_SPAN2_START+SCANCODE_SPAN2_SIZE) { 195 | return pgm_read_byte(&(scancode_span2[scanCode - SCANCODE_SPAN2_START][modifiers])); 196 | } 197 | return 0; 198 | } 199 | """) 200 | 201 | 202 | print("const uint8_t AppleIIKeyboardTranslation::scancode_span1[AppleIIKeyboardTranslation::SCANCODE_SPAN1_SIZE][4] = {") 203 | print(" // scan code, no modifier, SHIFT modifier, CTRL modifier, both modifiers") 204 | for scancode, mapping in ((span1_start+i, span1[i]) for i in range(len(span1))): 205 | if mapping is not None: 206 | print(" /* {:#05x} {:>8} */ {{{:#04x}, {:#04x}, {:#04x}, {:#04x}}},".format( 207 | scancode, '[' + mapping.keycap + ']', mapping.plain, mapping.shift, 208 | mapping.ctrl, mapping.ctrl_shift)) 209 | else: 210 | print(" /* {:#05x} */ {{}},".format(scancode)) 211 | print("};\n") 212 | 213 | 214 | print("const uint8_t AppleIIKeyboardTranslation::scancode_span2[AppleIIKeyboardTranslation::SCANCODE_SPAN2_SIZE][4] = {") 215 | print(" // scan code, no modifier, SHIFT modifier, CTRL modifier, both modifiers") 216 | for scancode, mapping in ((span2_start+i, span2[i]) for i in range(len(span2))): 217 | if mapping is not None: 218 | print(" /* {:#05x} {:>8} */ {{{:#04x}, {:#04x}, {:#04x}, {:#04x}}},".format( 219 | scancode, '[' + mapping.keycap + ']', mapping.plain, mapping.shift, 220 | mapping.ctrl, mapping.ctrl_shift)) 221 | else: 222 | print(" /* {:#05x} */ {{}},".format(scancode)) 223 | print("};") 224 | -------------------------------------------------------------------------------- /AppleII-Keyboard/AppleII-Keyboard.kicad_pro: -------------------------------------------------------------------------------- 1 | { 2 | "board": { 3 | "3dviewports": [], 4 | "design_settings": { 5 | "defaults": { 6 | "apply_defaults_to_fp_fields": false, 7 | "apply_defaults_to_fp_shapes": false, 8 | "apply_defaults_to_fp_text": false, 9 | "board_outline_line_width": 0.05, 10 | "copper_line_width": 0.2, 11 | "copper_text_italic": false, 12 | "copper_text_size_h": 1.5, 13 | "copper_text_size_v": 1.5, 14 | "copper_text_thickness": 0.3, 15 | "copper_text_upright": false, 16 | "courtyard_line_width": 0.05, 17 | "dimension_precision": 4, 18 | "dimension_units": 3, 19 | "dimensions": { 20 | "arrow_length": 1270000, 21 | "extension_offset": 500000, 22 | "keep_text_aligned": true, 23 | "suppress_zeroes": true, 24 | "text_position": 0, 25 | "units_format": 0 26 | }, 27 | "fab_line_width": 0.1, 28 | "fab_text_italic": false, 29 | "fab_text_size_h": 1.0, 30 | "fab_text_size_v": 1.0, 31 | "fab_text_thickness": 0.15, 32 | "fab_text_upright": false, 33 | "other_line_width": 0.1, 34 | "other_text_italic": false, 35 | "other_text_size_h": 1.0, 36 | "other_text_size_v": 1.0, 37 | "other_text_thickness": 0.15, 38 | "other_text_upright": false, 39 | "pads": { 40 | "drill": 0.8, 41 | "height": 1.27, 42 | "width": 2.54 43 | }, 44 | "silk_line_width": 0.1, 45 | "silk_text_italic": false, 46 | "silk_text_size_h": 1.0, 47 | "silk_text_size_v": 1.0, 48 | "silk_text_thickness": 0.1, 49 | "silk_text_upright": false, 50 | "zones": { 51 | "min_clearance": 0.6 52 | } 53 | }, 54 | "diff_pair_dimensions": [ 55 | { 56 | "gap": 0.0, 57 | "via_gap": 0.0, 58 | "width": 0.0 59 | } 60 | ], 61 | "drc_exclusions": [], 62 | "meta": { 63 | "version": 2 64 | }, 65 | "rule_severities": { 66 | "annular_width": "error", 67 | "clearance": "error", 68 | "connection_width": "warning", 69 | "copper_edge_clearance": "error", 70 | "copper_sliver": "warning", 71 | "courtyards_overlap": "error", 72 | "creepage": "error", 73 | "diff_pair_gap_out_of_range": "error", 74 | "diff_pair_uncoupled_length_too_long": "error", 75 | "drill_out_of_range": "error", 76 | "duplicate_footprints": "warning", 77 | "extra_footprint": "warning", 78 | "footprint": "error", 79 | "footprint_filters_mismatch": "ignore", 80 | "footprint_symbol_mismatch": "warning", 81 | "footprint_type_mismatch": "ignore", 82 | "hole_clearance": "error", 83 | "hole_to_hole": "warning", 84 | "holes_co_located": "warning", 85 | "invalid_outline": "error", 86 | "isolated_copper": "warning", 87 | "item_on_disabled_layer": "error", 88 | "items_not_allowed": "error", 89 | "length_out_of_range": "error", 90 | "lib_footprint_issues": "warning", 91 | "lib_footprint_mismatch": "warning", 92 | "malformed_courtyard": "error", 93 | "microvia_drill_out_of_range": "error", 94 | "mirrored_text_on_front_layer": "warning", 95 | "missing_courtyard": "ignore", 96 | "missing_footprint": "warning", 97 | "net_conflict": "warning", 98 | "nonmirrored_text_on_back_layer": "warning", 99 | "npth_inside_courtyard": "ignore", 100 | "padstack": "warning", 101 | "pth_inside_courtyard": "ignore", 102 | "shorting_items": "error", 103 | "silk_edge_clearance": "warning", 104 | "silk_over_copper": "warning", 105 | "silk_overlap": "warning", 106 | "skew_out_of_range": "error", 107 | "solder_mask_bridge": "error", 108 | "starved_thermal": "error", 109 | "text_height": "warning", 110 | "text_on_edge_cuts": "error", 111 | "text_thickness": "warning", 112 | "through_hole_pad_without_hole": "error", 113 | "too_many_vias": "error", 114 | "track_angle": "error", 115 | "track_dangling": "warning", 116 | "track_segment_length": "error", 117 | "track_width": "error", 118 | "tracks_crossing": "error", 119 | "unconnected_items": "error", 120 | "unresolved_variable": "error", 121 | "via_dangling": "warning", 122 | "zones_intersect": "error" 123 | }, 124 | "rules": { 125 | "max_error": 0.005, 126 | "min_clearance": 0.1524, 127 | "min_connection": 0.1524, 128 | "min_copper_edge_clearance": 0.5, 129 | "min_groove_width": 0.0, 130 | "min_hole_clearance": 0.127, 131 | "min_hole_to_hole": 0.127, 132 | "min_microvia_diameter": 0.508, 133 | "min_microvia_drill": 0.254, 134 | "min_resolved_spokes": 1, 135 | "min_silk_clearance": 0.0, 136 | "min_text_height": 0.8, 137 | "min_text_thickness": 0.127, 138 | "min_through_hole_diameter": 0.3, 139 | "min_track_width": 0.1524, 140 | "min_via_annular_width": 0.127, 141 | "min_via_diameter": 0.508, 142 | "solder_mask_to_copper_clearance": 0.0, 143 | "use_height_for_length_calcs": true 144 | }, 145 | "teardrop_options": [ 146 | { 147 | "td_onpthpad": true, 148 | "td_onroundshapesonly": false, 149 | "td_onsmdpad": true, 150 | "td_ontrackend": false, 151 | "td_onvia": true 152 | } 153 | ], 154 | "teardrop_parameters": [ 155 | { 156 | "td_allow_use_two_tracks": true, 157 | "td_curve_segcount": 0, 158 | "td_height_ratio": 1.0, 159 | "td_length_ratio": 0.5, 160 | "td_maxheight": 2.0, 161 | "td_maxlen": 1.0, 162 | "td_on_pad_in_zone": false, 163 | "td_target_name": "td_round_shape", 164 | "td_width_to_size_filter_ratio": 0.9 165 | }, 166 | { 167 | "td_allow_use_two_tracks": true, 168 | "td_curve_segcount": 0, 169 | "td_height_ratio": 1.0, 170 | "td_length_ratio": 0.5, 171 | "td_maxheight": 2.0, 172 | "td_maxlen": 1.0, 173 | "td_on_pad_in_zone": false, 174 | "td_target_name": "td_rect_shape", 175 | "td_width_to_size_filter_ratio": 0.9 176 | }, 177 | { 178 | "td_allow_use_two_tracks": true, 179 | "td_curve_segcount": 0, 180 | "td_height_ratio": 1.0, 181 | "td_length_ratio": 0.5, 182 | "td_maxheight": 2.0, 183 | "td_maxlen": 1.0, 184 | "td_on_pad_in_zone": false, 185 | "td_target_name": "td_track_end", 186 | "td_width_to_size_filter_ratio": 0.9 187 | } 188 | ], 189 | "track_widths": [ 190 | 0.0 191 | ], 192 | "tuning_pattern_settings": { 193 | "diff_pair_defaults": { 194 | "corner_radius_percentage": 80, 195 | "corner_style": 1, 196 | "max_amplitude": 1.0, 197 | "min_amplitude": 0.2, 198 | "single_sided": false, 199 | "spacing": 1.0 200 | }, 201 | "diff_pair_skew_defaults": { 202 | "corner_radius_percentage": 80, 203 | "corner_style": 1, 204 | "max_amplitude": 1.0, 205 | "min_amplitude": 0.2, 206 | "single_sided": false, 207 | "spacing": 0.6 208 | }, 209 | "single_track_defaults": { 210 | "corner_radius_percentage": 80, 211 | "corner_style": 1, 212 | "max_amplitude": 1.0, 213 | "min_amplitude": 0.2, 214 | "single_sided": false, 215 | "spacing": 0.6 216 | } 217 | }, 218 | "via_dimensions": [ 219 | { 220 | "diameter": 0.0, 221 | "drill": 0.0 222 | } 223 | ], 224 | "zones_allow_external_fillets": false 225 | }, 226 | "ipc2581": { 227 | "dist": "", 228 | "distpn": "", 229 | "internal_id": "", 230 | "mfg": "", 231 | "mpn": "" 232 | }, 233 | "layer_pairs": [], 234 | "layer_presets": [], 235 | "viewports": [] 236 | }, 237 | "boards": [], 238 | "cvpcb": { 239 | "equivalence_files": [] 240 | }, 241 | "erc": { 242 | "erc_exclusions": [], 243 | "meta": { 244 | "version": 0 245 | }, 246 | "pin_map": [ 247 | [ 248 | 0, 249 | 0, 250 | 0, 251 | 0, 252 | 0, 253 | 0, 254 | 1, 255 | 0, 256 | 0, 257 | 0, 258 | 0, 259 | 2 260 | ], 261 | [ 262 | 0, 263 | 2, 264 | 0, 265 | 1, 266 | 0, 267 | 0, 268 | 1, 269 | 0, 270 | 2, 271 | 2, 272 | 2, 273 | 2 274 | ], 275 | [ 276 | 0, 277 | 0, 278 | 0, 279 | 0, 280 | 0, 281 | 0, 282 | 1, 283 | 0, 284 | 1, 285 | 0, 286 | 1, 287 | 2 288 | ], 289 | [ 290 | 0, 291 | 1, 292 | 0, 293 | 0, 294 | 0, 295 | 0, 296 | 1, 297 | 1, 298 | 2, 299 | 1, 300 | 1, 301 | 2 302 | ], 303 | [ 304 | 0, 305 | 0, 306 | 0, 307 | 0, 308 | 0, 309 | 0, 310 | 1, 311 | 0, 312 | 0, 313 | 0, 314 | 0, 315 | 2 316 | ], 317 | [ 318 | 0, 319 | 0, 320 | 0, 321 | 0, 322 | 0, 323 | 0, 324 | 0, 325 | 0, 326 | 0, 327 | 0, 328 | 0, 329 | 2 330 | ], 331 | [ 332 | 1, 333 | 1, 334 | 1, 335 | 1, 336 | 1, 337 | 0, 338 | 1, 339 | 1, 340 | 1, 341 | 1, 342 | 1, 343 | 2 344 | ], 345 | [ 346 | 0, 347 | 0, 348 | 0, 349 | 1, 350 | 0, 351 | 0, 352 | 1, 353 | 0, 354 | 0, 355 | 0, 356 | 0, 357 | 2 358 | ], 359 | [ 360 | 0, 361 | 2, 362 | 1, 363 | 2, 364 | 0, 365 | 0, 366 | 1, 367 | 0, 368 | 2, 369 | 2, 370 | 2, 371 | 2 372 | ], 373 | [ 374 | 0, 375 | 2, 376 | 0, 377 | 1, 378 | 0, 379 | 0, 380 | 1, 381 | 0, 382 | 2, 383 | 0, 384 | 0, 385 | 2 386 | ], 387 | [ 388 | 0, 389 | 2, 390 | 1, 391 | 1, 392 | 0, 393 | 0, 394 | 1, 395 | 0, 396 | 2, 397 | 0, 398 | 0, 399 | 2 400 | ], 401 | [ 402 | 2, 403 | 2, 404 | 2, 405 | 2, 406 | 2, 407 | 2, 408 | 2, 409 | 2, 410 | 2, 411 | 2, 412 | 2, 413 | 2 414 | ] 415 | ], 416 | "rule_severities": { 417 | "bus_definition_conflict": "error", 418 | "bus_entry_needed": "error", 419 | "bus_to_bus_conflict": "error", 420 | "bus_to_net_conflict": "error", 421 | "different_unit_footprint": "error", 422 | "different_unit_net": "error", 423 | "duplicate_reference": "error", 424 | "duplicate_sheet_names": "error", 425 | "endpoint_off_grid": "warning", 426 | "extra_units": "error", 427 | "footprint_filter": "ignore", 428 | "footprint_link_issues": "warning", 429 | "four_way_junction": "ignore", 430 | "global_label_dangling": "warning", 431 | "hier_label_mismatch": "error", 432 | "label_dangling": "error", 433 | "label_multiple_wires": "warning", 434 | "lib_symbol_issues": "warning", 435 | "lib_symbol_mismatch": "warning", 436 | "missing_bidi_pin": "warning", 437 | "missing_input_pin": "warning", 438 | "missing_power_pin": "error", 439 | "missing_unit": "warning", 440 | "multiple_net_names": "warning", 441 | "net_not_bus_member": "warning", 442 | "no_connect_connected": "warning", 443 | "no_connect_dangling": "warning", 444 | "pin_not_connected": "error", 445 | "pin_not_driven": "error", 446 | "pin_to_pin": "warning", 447 | "power_pin_not_driven": "error", 448 | "same_local_global_label": "warning", 449 | "similar_label_and_power": "warning", 450 | "similar_labels": "warning", 451 | "similar_power": "warning", 452 | "simulation_model_issue": "ignore", 453 | "single_global_label": "ignore", 454 | "unannotated": "error", 455 | "unconnected_wire_endpoint": "warning", 456 | "undefined_netclass": "error", 457 | "unit_value_mismatch": "error", 458 | "unresolved_variable": "error", 459 | "wire_dangling": "error" 460 | } 461 | }, 462 | "libraries": { 463 | "pinned_footprint_libs": [], 464 | "pinned_symbol_libs": [] 465 | }, 466 | "meta": { 467 | "filename": "AppleII-Keyboard.kicad_pro", 468 | "version": 3 469 | }, 470 | "net_settings": { 471 | "classes": [ 472 | { 473 | "bus_width": 12, 474 | "clearance": 0.2, 475 | "diff_pair_gap": 0.25, 476 | "diff_pair_via_gap": 0.25, 477 | "diff_pair_width": 0.2, 478 | "line_style": 0, 479 | "microvia_diameter": 0.3, 480 | "microvia_drill": 0.1, 481 | "name": "Default", 482 | "pcb_color": "rgba(0, 0, 0, 0.000)", 483 | "priority": 2147483647, 484 | "schematic_color": "rgba(0, 0, 0, 0.000)", 485 | "track_width": 0.2, 486 | "via_diameter": 0.6, 487 | "via_drill": 0.3, 488 | "wire_width": 6 489 | }, 490 | { 491 | "clearance": 0.2, 492 | "name": "Power", 493 | "pcb_color": "rgba(0, 0, 0, 0.000)", 494 | "priority": 0, 495 | "schematic_color": "rgba(0, 0, 0, 0.000)", 496 | "track_width": 0.4 497 | } 498 | ], 499 | "meta": { 500 | "version": 4 501 | }, 502 | "net_colors": null, 503 | "netclass_assignments": null, 504 | "netclass_patterns": [ 505 | { 506 | "netclass": "Power", 507 | "pattern": "GND|\\+5V" 508 | } 509 | ] 510 | }, 511 | "pcbnew": { 512 | "last_paths": { 513 | "gencad": "", 514 | "idf": "", 515 | "netlist": "", 516 | "plot": "outputs/", 517 | "pos_files": "", 518 | "specctra_dsn": "", 519 | "step": "", 520 | "svg": "", 521 | "vrml": "" 522 | }, 523 | "page_layout_descr_file": "" 524 | }, 525 | "schematic": { 526 | "annotate_start_num": 0, 527 | "bom_export_filename": "${PROJECTNAME}.csv", 528 | "bom_fmt_presets": [], 529 | "bom_fmt_settings": { 530 | "field_delimiter": ",", 531 | "keep_line_breaks": false, 532 | "keep_tabs": false, 533 | "name": "CSV", 534 | "ref_delimiter": ",", 535 | "ref_range_delimiter": "", 536 | "string_delimiter": "\"" 537 | }, 538 | "bom_presets": [], 539 | "bom_settings": { 540 | "exclude_dnp": false, 541 | "fields_ordered": [ 542 | { 543 | "group_by": false, 544 | "label": "Reference", 545 | "name": "Reference", 546 | "show": true 547 | }, 548 | { 549 | "group_by": false, 550 | "label": "Qty", 551 | "name": "${QUANTITY}", 552 | "show": true 553 | }, 554 | { 555 | "group_by": true, 556 | "label": "Value", 557 | "name": "Value", 558 | "show": true 559 | }, 560 | { 561 | "group_by": true, 562 | "label": "DNP", 563 | "name": "${DNP}", 564 | "show": true 565 | }, 566 | { 567 | "group_by": true, 568 | "label": "Exclude from BOM", 569 | "name": "${EXCLUDE_FROM_BOM}", 570 | "show": true 571 | }, 572 | { 573 | "group_by": true, 574 | "label": "Exclude from Board", 575 | "name": "${EXCLUDE_FROM_BOARD}", 576 | "show": true 577 | }, 578 | { 579 | "group_by": true, 580 | "label": "Footprint", 581 | "name": "Footprint", 582 | "show": true 583 | }, 584 | { 585 | "group_by": false, 586 | "label": "Datasheet", 587 | "name": "Datasheet", 588 | "show": true 589 | } 590 | ], 591 | "filter_string": "", 592 | "group_symbols": true, 593 | "include_excluded_from_bom": true, 594 | "name": "Default Editing", 595 | "sort_asc": true, 596 | "sort_field": "Reference" 597 | }, 598 | "connection_grid_size": 50.0, 599 | "drawing": { 600 | "dashed_lines_dash_length_ratio": 12.0, 601 | "dashed_lines_gap_length_ratio": 3.0, 602 | "default_line_thickness": 6.0, 603 | "default_text_size": 50.0, 604 | "field_names": [], 605 | "intersheets_ref_own_page": false, 606 | "intersheets_ref_prefix": "", 607 | "intersheets_ref_short": false, 608 | "intersheets_ref_show": false, 609 | "intersheets_ref_suffix": "", 610 | "junction_size_choice": 3, 611 | "label_size_ratio": 0.375, 612 | "operating_point_overlay_i_precision": 3, 613 | "operating_point_overlay_i_range": "~A", 614 | "operating_point_overlay_v_precision": 3, 615 | "operating_point_overlay_v_range": "~V", 616 | "overbar_offset_ratio": 1.23, 617 | "pin_symbol_size": 25.0, 618 | "text_offset_ratio": 0.15 619 | }, 620 | "legacy_lib_dir": "", 621 | "legacy_lib_list": [], 622 | "meta": { 623 | "version": 1 624 | }, 625 | "net_format_name": "", 626 | "page_layout_descr_file": "", 627 | "plot_directory": "", 628 | "space_save_all_events": true, 629 | "spice_current_sheet_as_root": false, 630 | "spice_external_command": "spice \"%I\"", 631 | "spice_model_current_sheet_as_root": true, 632 | "spice_save_all_currents": false, 633 | "spice_save_all_dissipations": false, 634 | "spice_save_all_voltages": false, 635 | "subpart_first_id": 65, 636 | "subpart_id_separator": 0 637 | }, 638 | "sheets": [ 639 | [ 640 | "06fe8fa8-72a3-4f27-9148-5a94695a4471", 641 | "Root" 642 | ] 643 | ], 644 | "text_variables": {} 645 | } 646 | -------------------------------------------------------------------------------- /AppleII-Keyboard-Connector/AppleII-Keyboard-Connector.kicad_pro: -------------------------------------------------------------------------------- 1 | { 2 | "board": { 3 | "3dviewports": [], 4 | "design_settings": { 5 | "defaults": { 6 | "apply_defaults_to_fp_fields": false, 7 | "apply_defaults_to_fp_shapes": false, 8 | "apply_defaults_to_fp_text": false, 9 | "board_outline_line_width": 0.05, 10 | "copper_line_width": 0.2, 11 | "copper_text_italic": false, 12 | "copper_text_size_h": 1.5, 13 | "copper_text_size_v": 1.5, 14 | "copper_text_thickness": 0.3, 15 | "copper_text_upright": false, 16 | "courtyard_line_width": 0.05, 17 | "dimension_precision": 4, 18 | "dimension_units": 3, 19 | "dimensions": { 20 | "arrow_length": 1270000, 21 | "extension_offset": 500000, 22 | "keep_text_aligned": true, 23 | "suppress_zeroes": true, 24 | "text_position": 0, 25 | "units_format": 0 26 | }, 27 | "fab_line_width": 0.1, 28 | "fab_text_italic": false, 29 | "fab_text_size_h": 1.0, 30 | "fab_text_size_v": 1.0, 31 | "fab_text_thickness": 0.15, 32 | "fab_text_upright": false, 33 | "other_line_width": 0.1, 34 | "other_text_italic": false, 35 | "other_text_size_h": 1.0, 36 | "other_text_size_v": 1.0, 37 | "other_text_thickness": 0.15, 38 | "other_text_upright": false, 39 | "pads": { 40 | "drill": 0.8, 41 | "height": 1.27, 42 | "width": 2.54 43 | }, 44 | "silk_line_width": 0.1, 45 | "silk_text_italic": false, 46 | "silk_text_size_h": 1.0, 47 | "silk_text_size_v": 1.0, 48 | "silk_text_thickness": 0.1, 49 | "silk_text_upright": false, 50 | "zones": { 51 | "min_clearance": 0.6 52 | } 53 | }, 54 | "diff_pair_dimensions": [ 55 | { 56 | "gap": 0.0, 57 | "via_gap": 0.0, 58 | "width": 0.0 59 | } 60 | ], 61 | "drc_exclusions": [], 62 | "meta": { 63 | "version": 2 64 | }, 65 | "rule_severities": { 66 | "annular_width": "error", 67 | "clearance": "error", 68 | "connection_width": "warning", 69 | "copper_edge_clearance": "error", 70 | "copper_sliver": "warning", 71 | "courtyards_overlap": "error", 72 | "creepage": "error", 73 | "diff_pair_gap_out_of_range": "error", 74 | "diff_pair_uncoupled_length_too_long": "error", 75 | "drill_out_of_range": "error", 76 | "duplicate_footprints": "warning", 77 | "extra_footprint": "warning", 78 | "footprint": "error", 79 | "footprint_filters_mismatch": "ignore", 80 | "footprint_symbol_mismatch": "warning", 81 | "footprint_type_mismatch": "ignore", 82 | "hole_clearance": "error", 83 | "hole_to_hole": "warning", 84 | "holes_co_located": "warning", 85 | "invalid_outline": "error", 86 | "isolated_copper": "warning", 87 | "item_on_disabled_layer": "error", 88 | "items_not_allowed": "error", 89 | "length_out_of_range": "error", 90 | "lib_footprint_issues": "warning", 91 | "lib_footprint_mismatch": "warning", 92 | "malformed_courtyard": "error", 93 | "microvia_drill_out_of_range": "error", 94 | "mirrored_text_on_front_layer": "warning", 95 | "missing_courtyard": "ignore", 96 | "missing_footprint": "warning", 97 | "net_conflict": "warning", 98 | "nonmirrored_text_on_back_layer": "warning", 99 | "npth_inside_courtyard": "ignore", 100 | "padstack": "warning", 101 | "pth_inside_courtyard": "ignore", 102 | "shorting_items": "error", 103 | "silk_edge_clearance": "warning", 104 | "silk_over_copper": "warning", 105 | "silk_overlap": "warning", 106 | "skew_out_of_range": "error", 107 | "solder_mask_bridge": "error", 108 | "starved_thermal": "error", 109 | "text_height": "warning", 110 | "text_on_edge_cuts": "error", 111 | "text_thickness": "warning", 112 | "through_hole_pad_without_hole": "error", 113 | "too_many_vias": "error", 114 | "track_angle": "error", 115 | "track_dangling": "warning", 116 | "track_segment_length": "error", 117 | "track_width": "error", 118 | "tracks_crossing": "error", 119 | "unconnected_items": "error", 120 | "unresolved_variable": "error", 121 | "via_dangling": "warning", 122 | "zones_intersect": "error" 123 | }, 124 | "rules": { 125 | "max_error": 0.005, 126 | "min_clearance": 0.1524, 127 | "min_connection": 0.1524, 128 | "min_copper_edge_clearance": 0.5, 129 | "min_groove_width": 0.0, 130 | "min_hole_clearance": 0.127, 131 | "min_hole_to_hole": 0.127, 132 | "min_microvia_diameter": 0.508, 133 | "min_microvia_drill": 0.254, 134 | "min_resolved_spokes": 1, 135 | "min_silk_clearance": 0.0, 136 | "min_text_height": 0.8, 137 | "min_text_thickness": 0.127, 138 | "min_through_hole_diameter": 0.3, 139 | "min_track_width": 0.1524, 140 | "min_via_annular_width": 0.127, 141 | "min_via_diameter": 0.508, 142 | "solder_mask_to_copper_clearance": 0.0, 143 | "use_height_for_length_calcs": true 144 | }, 145 | "teardrop_options": [ 146 | { 147 | "td_onpthpad": true, 148 | "td_onroundshapesonly": false, 149 | "td_onsmdpad": true, 150 | "td_ontrackend": false, 151 | "td_onvia": true 152 | } 153 | ], 154 | "teardrop_parameters": [ 155 | { 156 | "td_allow_use_two_tracks": true, 157 | "td_curve_segcount": 0, 158 | "td_height_ratio": 1.0, 159 | "td_length_ratio": 0.5, 160 | "td_maxheight": 2.0, 161 | "td_maxlen": 1.0, 162 | "td_on_pad_in_zone": false, 163 | "td_target_name": "td_round_shape", 164 | "td_width_to_size_filter_ratio": 0.9 165 | }, 166 | { 167 | "td_allow_use_two_tracks": true, 168 | "td_curve_segcount": 0, 169 | "td_height_ratio": 1.0, 170 | "td_length_ratio": 0.5, 171 | "td_maxheight": 2.0, 172 | "td_maxlen": 1.0, 173 | "td_on_pad_in_zone": false, 174 | "td_target_name": "td_rect_shape", 175 | "td_width_to_size_filter_ratio": 0.9 176 | }, 177 | { 178 | "td_allow_use_two_tracks": true, 179 | "td_curve_segcount": 0, 180 | "td_height_ratio": 1.0, 181 | "td_length_ratio": 0.5, 182 | "td_maxheight": 2.0, 183 | "td_maxlen": 1.0, 184 | "td_on_pad_in_zone": false, 185 | "td_target_name": "td_track_end", 186 | "td_width_to_size_filter_ratio": 0.9 187 | } 188 | ], 189 | "track_widths": [ 190 | 0.0 191 | ], 192 | "tuning_pattern_settings": { 193 | "diff_pair_defaults": { 194 | "corner_radius_percentage": 80, 195 | "corner_style": 1, 196 | "max_amplitude": 1.0, 197 | "min_amplitude": 0.2, 198 | "single_sided": false, 199 | "spacing": 1.0 200 | }, 201 | "diff_pair_skew_defaults": { 202 | "corner_radius_percentage": 80, 203 | "corner_style": 1, 204 | "max_amplitude": 1.0, 205 | "min_amplitude": 0.2, 206 | "single_sided": false, 207 | "spacing": 0.6 208 | }, 209 | "single_track_defaults": { 210 | "corner_radius_percentage": 80, 211 | "corner_style": 1, 212 | "max_amplitude": 1.0, 213 | "min_amplitude": 0.2, 214 | "single_sided": false, 215 | "spacing": 0.6 216 | } 217 | }, 218 | "via_dimensions": [ 219 | { 220 | "diameter": 0.0, 221 | "drill": 0.0 222 | } 223 | ], 224 | "zones_allow_external_fillets": false 225 | }, 226 | "ipc2581": { 227 | "dist": "", 228 | "distpn": "", 229 | "internal_id": "", 230 | "mfg": "", 231 | "mpn": "" 232 | }, 233 | "layer_pairs": [], 234 | "layer_presets": [], 235 | "viewports": [] 236 | }, 237 | "boards": [], 238 | "cvpcb": { 239 | "equivalence_files": [] 240 | }, 241 | "erc": { 242 | "erc_exclusions": [], 243 | "meta": { 244 | "version": 0 245 | }, 246 | "pin_map": [ 247 | [ 248 | 0, 249 | 0, 250 | 0, 251 | 0, 252 | 0, 253 | 0, 254 | 1, 255 | 0, 256 | 0, 257 | 0, 258 | 0, 259 | 2 260 | ], 261 | [ 262 | 0, 263 | 2, 264 | 0, 265 | 1, 266 | 0, 267 | 0, 268 | 1, 269 | 0, 270 | 2, 271 | 2, 272 | 2, 273 | 2 274 | ], 275 | [ 276 | 0, 277 | 0, 278 | 0, 279 | 0, 280 | 0, 281 | 0, 282 | 1, 283 | 0, 284 | 1, 285 | 0, 286 | 1, 287 | 2 288 | ], 289 | [ 290 | 0, 291 | 1, 292 | 0, 293 | 0, 294 | 0, 295 | 0, 296 | 1, 297 | 1, 298 | 2, 299 | 1, 300 | 1, 301 | 2 302 | ], 303 | [ 304 | 0, 305 | 0, 306 | 0, 307 | 0, 308 | 0, 309 | 0, 310 | 1, 311 | 0, 312 | 0, 313 | 0, 314 | 0, 315 | 2 316 | ], 317 | [ 318 | 0, 319 | 0, 320 | 0, 321 | 0, 322 | 0, 323 | 0, 324 | 0, 325 | 0, 326 | 0, 327 | 0, 328 | 0, 329 | 2 330 | ], 331 | [ 332 | 1, 333 | 1, 334 | 1, 335 | 1, 336 | 1, 337 | 0, 338 | 1, 339 | 1, 340 | 1, 341 | 1, 342 | 1, 343 | 2 344 | ], 345 | [ 346 | 0, 347 | 0, 348 | 0, 349 | 1, 350 | 0, 351 | 0, 352 | 1, 353 | 0, 354 | 0, 355 | 0, 356 | 0, 357 | 2 358 | ], 359 | [ 360 | 0, 361 | 2, 362 | 1, 363 | 2, 364 | 0, 365 | 0, 366 | 1, 367 | 0, 368 | 2, 369 | 2, 370 | 2, 371 | 2 372 | ], 373 | [ 374 | 0, 375 | 2, 376 | 0, 377 | 1, 378 | 0, 379 | 0, 380 | 1, 381 | 0, 382 | 2, 383 | 0, 384 | 0, 385 | 2 386 | ], 387 | [ 388 | 0, 389 | 2, 390 | 1, 391 | 1, 392 | 0, 393 | 0, 394 | 1, 395 | 0, 396 | 2, 397 | 0, 398 | 0, 399 | 2 400 | ], 401 | [ 402 | 2, 403 | 2, 404 | 2, 405 | 2, 406 | 2, 407 | 2, 408 | 2, 409 | 2, 410 | 2, 411 | 2, 412 | 2, 413 | 2 414 | ] 415 | ], 416 | "rule_severities": { 417 | "bus_definition_conflict": "error", 418 | "bus_entry_needed": "error", 419 | "bus_to_bus_conflict": "error", 420 | "bus_to_net_conflict": "error", 421 | "different_unit_footprint": "error", 422 | "different_unit_net": "error", 423 | "duplicate_reference": "error", 424 | "duplicate_sheet_names": "error", 425 | "endpoint_off_grid": "warning", 426 | "extra_units": "error", 427 | "footprint_filter": "ignore", 428 | "footprint_link_issues": "warning", 429 | "four_way_junction": "ignore", 430 | "global_label_dangling": "warning", 431 | "hier_label_mismatch": "error", 432 | "label_dangling": "error", 433 | "label_multiple_wires": "warning", 434 | "lib_symbol_issues": "warning", 435 | "lib_symbol_mismatch": "warning", 436 | "missing_bidi_pin": "warning", 437 | "missing_input_pin": "warning", 438 | "missing_power_pin": "error", 439 | "missing_unit": "warning", 440 | "multiple_net_names": "warning", 441 | "net_not_bus_member": "warning", 442 | "no_connect_connected": "warning", 443 | "no_connect_dangling": "warning", 444 | "pin_not_connected": "error", 445 | "pin_not_driven": "error", 446 | "pin_to_pin": "warning", 447 | "power_pin_not_driven": "error", 448 | "same_local_global_label": "warning", 449 | "similar_label_and_power": "warning", 450 | "similar_labels": "warning", 451 | "similar_power": "warning", 452 | "simulation_model_issue": "ignore", 453 | "single_global_label": "ignore", 454 | "unannotated": "error", 455 | "unconnected_wire_endpoint": "warning", 456 | "undefined_netclass": "error", 457 | "unit_value_mismatch": "error", 458 | "unresolved_variable": "error", 459 | "wire_dangling": "error" 460 | } 461 | }, 462 | "libraries": { 463 | "pinned_footprint_libs": [], 464 | "pinned_symbol_libs": [] 465 | }, 466 | "meta": { 467 | "filename": "AppleII-Keyboard-Connector.kicad_pro", 468 | "version": 3 469 | }, 470 | "net_settings": { 471 | "classes": [ 472 | { 473 | "bus_width": 12, 474 | "clearance": 0.2, 475 | "diff_pair_gap": 0.25, 476 | "diff_pair_via_gap": 0.25, 477 | "diff_pair_width": 0.2, 478 | "line_style": 0, 479 | "microvia_diameter": 0.3, 480 | "microvia_drill": 0.1, 481 | "name": "Default", 482 | "pcb_color": "rgba(0, 0, 0, 0.000)", 483 | "priority": 2147483647, 484 | "schematic_color": "rgba(0, 0, 0, 0.000)", 485 | "track_width": 0.2, 486 | "via_diameter": 0.6, 487 | "via_drill": 0.3, 488 | "wire_width": 6 489 | }, 490 | { 491 | "clearance": 0.2, 492 | "name": "Power", 493 | "pcb_color": "rgba(0, 0, 0, 0.000)", 494 | "priority": 0, 495 | "schematic_color": "rgba(0, 0, 0, 0.000)", 496 | "track_width": 0.4 497 | } 498 | ], 499 | "meta": { 500 | "version": 4 501 | }, 502 | "net_colors": null, 503 | "netclass_assignments": null, 504 | "netclass_patterns": [ 505 | { 506 | "netclass": "Power", 507 | "pattern": "/GND|/\\+5V" 508 | } 509 | ] 510 | }, 511 | "pcbnew": { 512 | "last_paths": { 513 | "gencad": "", 514 | "idf": "", 515 | "netlist": "", 516 | "plot": "outputs/", 517 | "pos_files": "", 518 | "specctra_dsn": "", 519 | "step": "", 520 | "svg": "", 521 | "vrml": "" 522 | }, 523 | "page_layout_descr_file": "" 524 | }, 525 | "schematic": { 526 | "annotate_start_num": 0, 527 | "bom_export_filename": "${PROJECTNAME}.csv", 528 | "bom_fmt_presets": [], 529 | "bom_fmt_settings": { 530 | "field_delimiter": ",", 531 | "keep_line_breaks": false, 532 | "keep_tabs": false, 533 | "name": "CSV", 534 | "ref_delimiter": ",", 535 | "ref_range_delimiter": "", 536 | "string_delimiter": "\"" 537 | }, 538 | "bom_presets": [], 539 | "bom_settings": { 540 | "exclude_dnp": false, 541 | "fields_ordered": [ 542 | { 543 | "group_by": false, 544 | "label": "Reference", 545 | "name": "Reference", 546 | "show": true 547 | }, 548 | { 549 | "group_by": false, 550 | "label": "Qty", 551 | "name": "${QUANTITY}", 552 | "show": true 553 | }, 554 | { 555 | "group_by": true, 556 | "label": "Value", 557 | "name": "Value", 558 | "show": true 559 | }, 560 | { 561 | "group_by": true, 562 | "label": "DNP", 563 | "name": "${DNP}", 564 | "show": true 565 | }, 566 | { 567 | "group_by": true, 568 | "label": "Exclude from BOM", 569 | "name": "${EXCLUDE_FROM_BOM}", 570 | "show": true 571 | }, 572 | { 573 | "group_by": true, 574 | "label": "Exclude from Board", 575 | "name": "${EXCLUDE_FROM_BOARD}", 576 | "show": true 577 | }, 578 | { 579 | "group_by": true, 580 | "label": "Footprint", 581 | "name": "Footprint", 582 | "show": true 583 | }, 584 | { 585 | "group_by": false, 586 | "label": "Datasheet", 587 | "name": "Datasheet", 588 | "show": true 589 | } 590 | ], 591 | "filter_string": "", 592 | "group_symbols": true, 593 | "include_excluded_from_bom": true, 594 | "name": "Default Editing", 595 | "sort_asc": true, 596 | "sort_field": "Reference" 597 | }, 598 | "connection_grid_size": 50.0, 599 | "drawing": { 600 | "dashed_lines_dash_length_ratio": 12.0, 601 | "dashed_lines_gap_length_ratio": 3.0, 602 | "default_line_thickness": 6.0, 603 | "default_text_size": 50.0, 604 | "field_names": [], 605 | "intersheets_ref_own_page": false, 606 | "intersheets_ref_prefix": "", 607 | "intersheets_ref_short": false, 608 | "intersheets_ref_show": false, 609 | "intersheets_ref_suffix": "", 610 | "junction_size_choice": 3, 611 | "label_size_ratio": 0.375, 612 | "operating_point_overlay_i_precision": 3, 613 | "operating_point_overlay_i_range": "~A", 614 | "operating_point_overlay_v_precision": 3, 615 | "operating_point_overlay_v_range": "~V", 616 | "overbar_offset_ratio": 1.23, 617 | "pin_symbol_size": 25.0, 618 | "text_offset_ratio": 0.15 619 | }, 620 | "legacy_lib_dir": "", 621 | "legacy_lib_list": [], 622 | "meta": { 623 | "version": 1 624 | }, 625 | "net_format_name": "", 626 | "page_layout_descr_file": "", 627 | "plot_directory": "", 628 | "space_save_all_events": true, 629 | "spice_current_sheet_as_root": false, 630 | "spice_external_command": "spice \"%I\"", 631 | "spice_model_current_sheet_as_root": true, 632 | "spice_save_all_currents": false, 633 | "spice_save_all_dissipations": false, 634 | "spice_save_all_voltages": false, 635 | "subpart_first_id": 65, 636 | "subpart_id_separator": 0 637 | }, 638 | "sheets": [ 639 | [ 640 | "06fe8fa8-72a3-4f27-9148-5a94695a4471", 641 | "Root" 642 | ] 643 | ], 644 | "text_variables": {} 645 | } 646 | -------------------------------------------------------------------------------- /AppleII-Keyboard/outputs/AppleII-Keyboard-F_Silkscreen.gbr: -------------------------------------------------------------------------------- 1 | %TF.GenerationSoftware,KiCad,Pcbnew,9.0.4*% 2 | %TF.CreationDate,2025-09-30T15:31:28-04:00*% 3 | %TF.ProjectId,AppleII-Keyboard,4170706c-6549-4492-9d4b-6579626f6172,B*% 4 | %TF.SameCoordinates,Original*% 5 | %TF.FileFunction,Legend,Top*% 6 | %TF.FilePolarity,Positive*% 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 9.0.4) date 2025-09-30 15:31:28* 10 | %MOMM*% 11 | %LPD*% 12 | G01* 13 | G04 APERTURE LIST* 14 | %ADD10C,0.100000*% 15 | %ADD11C,0.150000*% 16 | %ADD12C,0.120000*% 17 | G04 APERTURE END LIST* 18 | D10* 19 | X156845000Y-80645000D02* 20 | X155575000Y-80010000D01* 21 | X156845000Y-79375000D01* 22 | X156845000Y-80645000D01* 23 | G36* 24 | X156845000Y-80645000D02* 25 | G01* 26 | X155575000Y-80010000D01* 27 | X156845000Y-79375000D01* 28 | X156845000Y-80645000D01* 29 | G37* 30 | D11* 31 | X146317142Y-86326723D02* 32 | X146698095Y-86326723D01* 33 | X146240952Y-86555295D02* 34 | X146507619Y-85755295D01* 35 | X146507619Y-85755295D02* 36 | X146774285Y-86555295D01* 37 | X147040952Y-86021961D02* 38 | X147040952Y-86821961D01* 39 | X147040952Y-86060057D02* 40 | X147117142Y-86021961D01* 41 | X147117142Y-86021961D02* 42 | X147269523Y-86021961D01* 43 | X147269523Y-86021961D02* 44 | X147345714Y-86060057D01* 45 | X147345714Y-86060057D02* 46 | X147383809Y-86098152D01* 47 | X147383809Y-86098152D02* 48 | X147421904Y-86174342D01* 49 | X147421904Y-86174342D02* 50 | X147421904Y-86402914D01* 51 | X147421904Y-86402914D02* 52 | X147383809Y-86479104D01* 53 | X147383809Y-86479104D02* 54 | X147345714Y-86517200D01* 55 | X147345714Y-86517200D02* 56 | X147269523Y-86555295D01* 57 | X147269523Y-86555295D02* 58 | X147117142Y-86555295D01* 59 | X147117142Y-86555295D02* 60 | X147040952Y-86517200D01* 61 | X147764762Y-86021961D02* 62 | X147764762Y-86821961D01* 63 | X147764762Y-86060057D02* 64 | X147840952Y-86021961D01* 65 | X147840952Y-86021961D02* 66 | X147993333Y-86021961D01* 67 | X147993333Y-86021961D02* 68 | X148069524Y-86060057D01* 69 | X148069524Y-86060057D02* 70 | X148107619Y-86098152D01* 71 | X148107619Y-86098152D02* 72 | X148145714Y-86174342D01* 73 | X148145714Y-86174342D02* 74 | X148145714Y-86402914D01* 75 | X148145714Y-86402914D02* 76 | X148107619Y-86479104D01* 77 | X148107619Y-86479104D02* 78 | X148069524Y-86517200D01* 79 | X148069524Y-86517200D02* 80 | X147993333Y-86555295D01* 81 | X147993333Y-86555295D02* 82 | X147840952Y-86555295D01* 83 | X147840952Y-86555295D02* 84 | X147764762Y-86517200D01* 85 | X148602857Y-86555295D02* 86 | X148526667Y-86517200D01* 87 | X148526667Y-86517200D02* 88 | X148488572Y-86441009D01* 89 | X148488572Y-86441009D02* 90 | X148488572Y-85755295D01* 91 | X149212382Y-86517200D02* 92 | X149136191Y-86555295D01* 93 | X149136191Y-86555295D02* 94 | X148983810Y-86555295D01* 95 | X148983810Y-86555295D02* 96 | X148907620Y-86517200D01* 97 | X148907620Y-86517200D02* 98 | X148869524Y-86441009D01* 99 | X148869524Y-86441009D02* 100 | X148869524Y-86136247D01* 101 | X148869524Y-86136247D02* 102 | X148907620Y-86060057D01* 103 | X148907620Y-86060057D02* 104 | X148983810Y-86021961D01* 105 | X148983810Y-86021961D02* 106 | X149136191Y-86021961D01* 107 | X149136191Y-86021961D02* 108 | X149212382Y-86060057D01* 109 | X149212382Y-86060057D02* 110 | X149250477Y-86136247D01* 111 | X149250477Y-86136247D02* 112 | X149250477Y-86212438D01* 113 | X149250477Y-86212438D02* 114 | X148869524Y-86288628D01* 115 | X150202858Y-86555295D02* 116 | X150202858Y-85755295D01* 117 | X150583810Y-86555295D02* 118 | X150583810Y-85755295D01* 119 | X150964762Y-86250533D02* 120 | X151574286Y-86250533D01* 121 | X151269524Y-86555295D02* 122 | X151269524Y-85945771D01* 123 | X152450476Y-86021961D02* 124 | X152755238Y-86021961D01* 125 | X152564762Y-85755295D02* 126 | X152564762Y-86441009D01* 127 | X152564762Y-86441009D02* 128 | X152602857Y-86517200D01* 129 | X152602857Y-86517200D02* 130 | X152679047Y-86555295D01* 131 | X152679047Y-86555295D02* 132 | X152755238Y-86555295D01* 133 | X153136190Y-86555295D02* 134 | X153060000Y-86517200D01* 135 | X153060000Y-86517200D02* 136 | X153021905Y-86479104D01* 137 | X153021905Y-86479104D02* 138 | X152983809Y-86402914D01* 139 | X152983809Y-86402914D02* 140 | X152983809Y-86174342D01* 141 | X152983809Y-86174342D02* 142 | X153021905Y-86098152D01* 143 | X153021905Y-86098152D02* 144 | X153060000Y-86060057D01* 145 | X153060000Y-86060057D02* 146 | X153136190Y-86021961D01* 147 | X153136190Y-86021961D02* 148 | X153250476Y-86021961D01* 149 | X153250476Y-86021961D02* 150 | X153326667Y-86060057D01* 151 | X153326667Y-86060057D02* 152 | X153364762Y-86098152D01* 153 | X153364762Y-86098152D02* 154 | X153402857Y-86174342D01* 155 | X153402857Y-86174342D02* 156 | X153402857Y-86402914D01* 157 | X153402857Y-86402914D02* 158 | X153364762Y-86479104D01* 159 | X153364762Y-86479104D02* 160 | X153326667Y-86517200D01* 161 | X153326667Y-86517200D02* 162 | X153250476Y-86555295D01* 163 | X153250476Y-86555295D02* 164 | X153136190Y-86555295D01* 165 | X145421904Y-87843250D02* 166 | X145421904Y-87043250D01* 167 | X145421904Y-87043250D02* 168 | X145726666Y-87043250D01* 169 | X145726666Y-87043250D02* 170 | X145802856Y-87081345D01* 171 | X145802856Y-87081345D02* 172 | X145840951Y-87119440D01* 173 | X145840951Y-87119440D02* 174 | X145879047Y-87195631D01* 175 | X145879047Y-87195631D02* 176 | X145879047Y-87309916D01* 177 | X145879047Y-87309916D02* 178 | X145840951Y-87386107D01* 179 | X145840951Y-87386107D02* 180 | X145802856Y-87424202D01* 181 | X145802856Y-87424202D02* 182 | X145726666Y-87462297D01* 183 | X145726666Y-87462297D02* 184 | X145421904Y-87462297D01* 185 | X146183808Y-87805155D02* 186 | X146298094Y-87843250D01* 187 | X146298094Y-87843250D02* 188 | X146488570Y-87843250D01* 189 | X146488570Y-87843250D02* 190 | X146564761Y-87805155D01* 191 | X146564761Y-87805155D02* 192 | X146602856Y-87767059D01* 193 | X146602856Y-87767059D02* 194 | X146640951Y-87690869D01* 195 | X146640951Y-87690869D02* 196 | X146640951Y-87614678D01* 197 | X146640951Y-87614678D02* 198 | X146602856Y-87538488D01* 199 | X146602856Y-87538488D02* 200 | X146564761Y-87500393D01* 201 | X146564761Y-87500393D02* 202 | X146488570Y-87462297D01* 203 | X146488570Y-87462297D02* 204 | X146336189Y-87424202D01* 205 | X146336189Y-87424202D02* 206 | X146259999Y-87386107D01* 207 | X146259999Y-87386107D02* 208 | X146221904Y-87348012D01* 209 | X146221904Y-87348012D02* 210 | X146183808Y-87271821D01* 211 | X146183808Y-87271821D02* 212 | X146183808Y-87195631D01* 213 | X146183808Y-87195631D02* 214 | X146221904Y-87119440D01* 215 | X146221904Y-87119440D02* 216 | X146259999Y-87081345D01* 217 | X146259999Y-87081345D02* 218 | X146336189Y-87043250D01* 219 | X146336189Y-87043250D02* 220 | X146526666Y-87043250D01* 221 | X146526666Y-87043250D02* 222 | X146640951Y-87081345D01* 223 | X147555237Y-87005155D02* 224 | X146869523Y-88033726D01* 225 | X147783808Y-87119440D02* 226 | X147821904Y-87081345D01* 227 | X147821904Y-87081345D02* 228 | X147898094Y-87043250D01* 229 | X147898094Y-87043250D02* 230 | X148088570Y-87043250D01* 231 | X148088570Y-87043250D02* 232 | X148164761Y-87081345D01* 233 | X148164761Y-87081345D02* 234 | X148202856Y-87119440D01* 235 | X148202856Y-87119440D02* 236 | X148240951Y-87195631D01* 237 | X148240951Y-87195631D02* 238 | X148240951Y-87271821D01* 239 | X148240951Y-87271821D02* 240 | X148202856Y-87386107D01* 241 | X148202856Y-87386107D02* 242 | X147745713Y-87843250D01* 243 | X147745713Y-87843250D02* 244 | X148240951Y-87843250D01* 245 | X149193333Y-87843250D02* 246 | X149193333Y-87043250D01* 247 | X149650476Y-87843250D02* 248 | X149307618Y-87386107D01* 249 | X149650476Y-87043250D02* 250 | X149193333Y-87500393D01* 251 | X150298095Y-87805155D02* 252 | X150221904Y-87843250D01* 253 | X150221904Y-87843250D02* 254 | X150069523Y-87843250D01* 255 | X150069523Y-87843250D02* 256 | X149993333Y-87805155D01* 257 | X149993333Y-87805155D02* 258 | X149955237Y-87728964D01* 259 | X149955237Y-87728964D02* 260 | X149955237Y-87424202D01* 261 | X149955237Y-87424202D02* 262 | X149993333Y-87348012D01* 263 | X149993333Y-87348012D02* 264 | X150069523Y-87309916D01* 265 | X150069523Y-87309916D02* 266 | X150221904Y-87309916D01* 267 | X150221904Y-87309916D02* 268 | X150298095Y-87348012D01* 269 | X150298095Y-87348012D02* 270 | X150336190Y-87424202D01* 271 | X150336190Y-87424202D02* 272 | X150336190Y-87500393D01* 273 | X150336190Y-87500393D02* 274 | X149955237Y-87576583D01* 275 | X150602856Y-87309916D02* 276 | X150793332Y-87843250D01* 277 | X150983809Y-87309916D02* 278 | X150793332Y-87843250D01* 279 | X150793332Y-87843250D02* 280 | X150717142Y-88033726D01* 281 | X150717142Y-88033726D02* 282 | X150679047Y-88071821D01* 283 | X150679047Y-88071821D02* 284 | X150602856Y-88109916D01* 285 | X151288571Y-87843250D02* 286 | X151288571Y-87043250D01* 287 | X151288571Y-87348012D02* 288 | X151364761Y-87309916D01* 289 | X151364761Y-87309916D02* 290 | X151517142Y-87309916D01* 291 | X151517142Y-87309916D02* 292 | X151593333Y-87348012D01* 293 | X151593333Y-87348012D02* 294 | X151631428Y-87386107D01* 295 | X151631428Y-87386107D02* 296 | X151669523Y-87462297D01* 297 | X151669523Y-87462297D02* 298 | X151669523Y-87690869D01* 299 | X151669523Y-87690869D02* 300 | X151631428Y-87767059D01* 301 | X151631428Y-87767059D02* 302 | X151593333Y-87805155D01* 303 | X151593333Y-87805155D02* 304 | X151517142Y-87843250D01* 305 | X151517142Y-87843250D02* 306 | X151364761Y-87843250D01* 307 | X151364761Y-87843250D02* 308 | X151288571Y-87805155D01* 309 | X152126666Y-87843250D02* 310 | X152050476Y-87805155D01* 311 | X152050476Y-87805155D02* 312 | X152012381Y-87767059D01* 313 | X152012381Y-87767059D02* 314 | X151974285Y-87690869D01* 315 | X151974285Y-87690869D02* 316 | X151974285Y-87462297D01* 317 | X151974285Y-87462297D02* 318 | X152012381Y-87386107D01* 319 | X152012381Y-87386107D02* 320 | X152050476Y-87348012D01* 321 | X152050476Y-87348012D02* 322 | X152126666Y-87309916D01* 323 | X152126666Y-87309916D02* 324 | X152240952Y-87309916D01* 325 | X152240952Y-87309916D02* 326 | X152317143Y-87348012D01* 327 | X152317143Y-87348012D02* 328 | X152355238Y-87386107D01* 329 | X152355238Y-87386107D02* 330 | X152393333Y-87462297D01* 331 | X152393333Y-87462297D02* 332 | X152393333Y-87690869D01* 333 | X152393333Y-87690869D02* 334 | X152355238Y-87767059D01* 335 | X152355238Y-87767059D02* 336 | X152317143Y-87805155D01* 337 | X152317143Y-87805155D02* 338 | X152240952Y-87843250D01* 339 | X152240952Y-87843250D02* 340 | X152126666Y-87843250D01* 341 | X153079048Y-87843250D02* 342 | X153079048Y-87424202D01* 343 | X153079048Y-87424202D02* 344 | X153040953Y-87348012D01* 345 | X153040953Y-87348012D02* 346 | X152964762Y-87309916D01* 347 | X152964762Y-87309916D02* 348 | X152812381Y-87309916D01* 349 | X152812381Y-87309916D02* 350 | X152736191Y-87348012D01* 351 | X153079048Y-87805155D02* 352 | X153002857Y-87843250D01* 353 | X153002857Y-87843250D02* 354 | X152812381Y-87843250D01* 355 | X152812381Y-87843250D02* 356 | X152736191Y-87805155D01* 357 | X152736191Y-87805155D02* 358 | X152698095Y-87728964D01* 359 | X152698095Y-87728964D02* 360 | X152698095Y-87652774D01* 361 | X152698095Y-87652774D02* 362 | X152736191Y-87576583D01* 363 | X152736191Y-87576583D02* 364 | X152812381Y-87538488D01* 365 | X152812381Y-87538488D02* 366 | X153002857Y-87538488D01* 367 | X153002857Y-87538488D02* 368 | X153079048Y-87500393D01* 369 | X153460001Y-87843250D02* 370 | X153460001Y-87309916D01* 371 | X153460001Y-87462297D02* 372 | X153498096Y-87386107D01* 373 | X153498096Y-87386107D02* 374 | X153536191Y-87348012D01* 375 | X153536191Y-87348012D02* 376 | X153612382Y-87309916D01* 377 | X153612382Y-87309916D02* 378 | X153688572Y-87309916D01* 379 | X154298096Y-87843250D02* 380 | X154298096Y-87043250D01* 381 | X154298096Y-87805155D02* 382 | X154221905Y-87843250D01* 383 | X154221905Y-87843250D02* 384 | X154069524Y-87843250D01* 385 | X154069524Y-87843250D02* 386 | X153993334Y-87805155D01* 387 | X153993334Y-87805155D02* 388 | X153955239Y-87767059D01* 389 | X153955239Y-87767059D02* 390 | X153917143Y-87690869D01* 391 | X153917143Y-87690869D02* 392 | X153917143Y-87462297D01* 393 | X153917143Y-87462297D02* 394 | X153955239Y-87386107D01* 395 | X153955239Y-87386107D02* 396 | X153993334Y-87348012D01* 397 | X153993334Y-87348012D02* 398 | X154069524Y-87309916D01* 399 | X154069524Y-87309916D02* 400 | X154221905Y-87309916D01* 401 | X154221905Y-87309916D02* 402 | X154298096Y-87348012D01* 403 | X158130180Y-93813922D02* 404 | X158130180Y-94385350D01* 405 | X157130180Y-94099636D02* 406 | X158130180Y-94099636D01* 407 | X157130180Y-94861541D02* 408 | X157177800Y-94766303D01* 409 | X157177800Y-94766303D02* 410 | X157225419Y-94718684D01* 411 | X157225419Y-94718684D02* 412 | X157320657Y-94671065D01* 413 | X157320657Y-94671065D02* 414 | X157606371Y-94671065D01* 415 | X157606371Y-94671065D02* 416 | X157701609Y-94718684D01* 417 | X157701609Y-94718684D02* 418 | X157749228Y-94766303D01* 419 | X157749228Y-94766303D02* 420 | X157796847Y-94861541D01* 421 | X157796847Y-94861541D02* 422 | X157796847Y-95004398D01* 423 | X157796847Y-95004398D02* 424 | X157749228Y-95099636D01* 425 | X157749228Y-95099636D02* 426 | X157701609Y-95147255D01* 427 | X157701609Y-95147255D02* 428 | X157606371Y-95194874D01* 429 | X157606371Y-95194874D02* 430 | X157320657Y-95194874D01* 431 | X157320657Y-95194874D02* 432 | X157225419Y-95147255D01* 433 | X157225419Y-95147255D02* 434 | X157177800Y-95099636D01* 435 | X157177800Y-95099636D02* 436 | X157130180Y-95004398D01* 437 | X157130180Y-95004398D02* 438 | X157130180Y-94861541D01* 439 | X157796847Y-95528208D02* 440 | X157130180Y-95718684D01* 441 | X157130180Y-95718684D02* 442 | X157606371Y-95909160D01* 443 | X157606371Y-95909160D02* 444 | X157130180Y-96099636D01* 445 | X157130180Y-96099636D02* 446 | X157796847Y-96290112D01* 447 | X157130180Y-97099636D02* 448 | X157653990Y-97099636D01* 449 | X157653990Y-97099636D02* 450 | X157749228Y-97052017D01* 451 | X157749228Y-97052017D02* 452 | X157796847Y-96956779D01* 453 | X157796847Y-96956779D02* 454 | X157796847Y-96766303D01* 455 | X157796847Y-96766303D02* 456 | X157749228Y-96671065D01* 457 | X157177800Y-97099636D02* 458 | X157130180Y-97004398D01* 459 | X157130180Y-97004398D02* 460 | X157130180Y-96766303D01* 461 | X157130180Y-96766303D02* 462 | X157177800Y-96671065D01* 463 | X157177800Y-96671065D02* 464 | X157273038Y-96623446D01* 465 | X157273038Y-96623446D02* 466 | X157368276Y-96623446D01* 467 | X157368276Y-96623446D02* 468 | X157463514Y-96671065D01* 469 | X157463514Y-96671065D02* 470 | X157511133Y-96766303D01* 471 | X157511133Y-96766303D02* 472 | X157511133Y-97004398D01* 473 | X157511133Y-97004398D02* 474 | X157558752Y-97099636D01* 475 | X157130180Y-97575827D02* 476 | X157796847Y-97575827D01* 477 | X157606371Y-97575827D02* 478 | X157701609Y-97623446D01* 479 | X157701609Y-97623446D02* 480 | X157749228Y-97671065D01* 481 | X157749228Y-97671065D02* 482 | X157796847Y-97766303D01* 483 | X157796847Y-97766303D02* 484 | X157796847Y-97861541D01* 485 | X157130180Y-98623446D02* 486 | X158130180Y-98623446D01* 487 | X157177800Y-98623446D02* 488 | X157130180Y-98528208D01* 489 | X157130180Y-98528208D02* 490 | X157130180Y-98337732D01* 491 | X157130180Y-98337732D02* 492 | X157177800Y-98242494D01* 493 | X157177800Y-98242494D02* 494 | X157225419Y-98194875D01* 495 | X157225419Y-98194875D02* 496 | X157320657Y-98147256D01* 497 | X157320657Y-98147256D02* 498 | X157606371Y-98147256D01* 499 | X157606371Y-98147256D02* 500 | X157701609Y-98194875D01* 501 | X157701609Y-98194875D02* 502 | X157749228Y-98242494D01* 503 | X157749228Y-98242494D02* 504 | X157796847Y-98337732D01* 505 | X157796847Y-98337732D02* 506 | X157796847Y-98528208D01* 507 | X157796847Y-98528208D02* 508 | X157749228Y-98623446D01* 509 | X157653990Y-100194875D02* 510 | X157653990Y-99861542D01* 511 | X157130180Y-99861542D02* 512 | X158130180Y-99861542D01* 513 | X158130180Y-99861542D02* 514 | X158130180Y-100337732D01* 515 | X157130180Y-100718685D02* 516 | X157796847Y-100718685D01* 517 | X157606371Y-100718685D02* 518 | X157701609Y-100766304D01* 519 | X157701609Y-100766304D02* 520 | X157749228Y-100813923D01* 521 | X157749228Y-100813923D02* 522 | X157796847Y-100909161D01* 523 | X157796847Y-100909161D02* 524 | X157796847Y-101004399D01* 525 | X157130180Y-101480590D02* 526 | X157177800Y-101385352D01* 527 | X157177800Y-101385352D02* 528 | X157225419Y-101337733D01* 529 | X157225419Y-101337733D02* 530 | X157320657Y-101290114D01* 531 | X157320657Y-101290114D02* 532 | X157606371Y-101290114D01* 533 | X157606371Y-101290114D02* 534 | X157701609Y-101337733D01* 535 | X157701609Y-101337733D02* 536 | X157749228Y-101385352D01* 537 | X157749228Y-101385352D02* 538 | X157796847Y-101480590D01* 539 | X157796847Y-101480590D02* 540 | X157796847Y-101623447D01* 541 | X157796847Y-101623447D02* 542 | X157749228Y-101718685D01* 543 | X157749228Y-101718685D02* 544 | X157701609Y-101766304D01* 545 | X157701609Y-101766304D02* 546 | X157606371Y-101813923D01* 547 | X157606371Y-101813923D02* 548 | X157320657Y-101813923D01* 549 | X157320657Y-101813923D02* 550 | X157225419Y-101766304D01* 551 | X157225419Y-101766304D02* 552 | X157177800Y-101718685D01* 553 | X157177800Y-101718685D02* 554 | X157130180Y-101623447D01* 555 | X157130180Y-101623447D02* 556 | X157130180Y-101480590D01* 557 | X157796847Y-102242495D02* 558 | X157130180Y-102242495D01* 559 | X157701609Y-102242495D02* 560 | X157749228Y-102290114D01* 561 | X157749228Y-102290114D02* 562 | X157796847Y-102385352D01* 563 | X157796847Y-102385352D02* 564 | X157796847Y-102528209D01* 565 | X157796847Y-102528209D02* 566 | X157749228Y-102623447D01* 567 | X157749228Y-102623447D02* 568 | X157653990Y-102671066D01* 569 | X157653990Y-102671066D02* 570 | X157130180Y-102671066D01* 571 | X157796847Y-103004400D02* 572 | X157796847Y-103385352D01* 573 | X158130180Y-103147257D02* 574 | X157273038Y-103147257D01* 575 | X157273038Y-103147257D02* 576 | X157177800Y-103194876D01* 577 | X157177800Y-103194876D02* 578 | X157130180Y-103290114D01* 579 | X157130180Y-103290114D02* 580 | X157130180Y-103385352D01* 581 | X157511133Y-104480591D02* 582 | X157511133Y-105242496D01* 583 | X157796847Y-105718686D02* 584 | X157511133Y-106480591D01* 585 | X157511133Y-106480591D02* 586 | X157225419Y-105718686D01* 587 | D12* 588 | %TO.C,C1*% 589 | X148480000Y-111125000D02* 590 | X149170000Y-111125000D01* 591 | X153900000Y-111125000D02* 592 | X153210000Y-111125000D01* 593 | X153210000Y-112545000D02* 594 | X149170000Y-112545000D01* 595 | X149170000Y-109705000D01* 596 | X153210000Y-109705000D01* 597 | X153210000Y-112545000D01* 598 | %TO.C,J1*% 599 | X144670000Y-88840000D02* 600 | X144670000Y-109280000D01* 601 | X144670000Y-109280000D02* 602 | X146320000Y-109280000D01* 603 | X148320000Y-109280000D02* 604 | X149970000Y-109280000D01* 605 | X149970000Y-88840000D02* 606 | X144670000Y-88840000D01* 607 | X149970000Y-109280000D02* 608 | X149970000Y-88840000D01* 609 | X146320000Y-109280000D02* 610 | G75* 611 | G02* 612 | X148320000Y-109280000I1000000J0D01* 613 | G01* 614 | %TO.C,J2*% 615 | X144670000Y-78630000D02* 616 | X144670000Y-83930000D01* 617 | X152400000Y-78630000D02* 618 | X144670000Y-78630000D01* 619 | X152400000Y-78630000D02* 620 | X152400000Y-81280000D01* 621 | X152400000Y-81280000D02* 622 | X155050000Y-81280000D01* 623 | X153670000Y-78630000D02* 624 | X155050000Y-78630000D01* 625 | X155050000Y-78630000D02* 626 | X155050000Y-80010000D01* 627 | X155050000Y-81280000D02* 628 | X155050000Y-83930000D01* 629 | X155050000Y-83930000D02* 630 | X144670000Y-83930000D01* 631 | %TO.C,U1*% 632 | X148480000Y-88840000D02* 633 | X148480000Y-106740000D01* 634 | X153780000Y-106740000D02* 635 | X153780000Y-88840000D01* 636 | D10* 637 | X155702000Y-108204000D02* 638 | X154178000Y-108204000D01* 639 | X154940000Y-107188000D01* 640 | X155702000Y-108204000D01* 641 | G36* 642 | X155702000Y-108204000D02* 643 | G01* 644 | X154178000Y-108204000D01* 645 | X154940000Y-107188000D01* 646 | X155702000Y-108204000D01* 647 | G37* 648 | %TD*% 649 | M02* 650 | --------------------------------------------------------------------------------