1
0
mirror of https://github.com/fruit-bat/pico-zxspectrum.git synced 2025-04-19 00:04:01 +03:00

PS/2 keyboard support

This commit is contained in:
Phil 2022-07-10 14:24:38 +01:00
parent 75bac822f5
commit 41eb8a6aaa
9 changed files with 83 additions and 3 deletions

View File

@ -12,6 +12,7 @@ Uses [Wren's Amazing PicoDVI](https://github.com/Wren6991/PicoDVI) and [CarlK's
* LCD support (ST7789 320x240)
* VGA video (RGB332, RGB222, RGBY1111)
* USB Keyboard & Joysticks
* PS/2 Keyboard
* PWM sound for ear, mic and AY-3-8912
* 12 quick save slots
* Load from .z80 snapshot files
@ -32,6 +33,7 @@ Uses [Wren's Amazing PicoDVI](https://github.com/Wren6991/PicoDVI) and [CarlK's
## Updates
* 27/06/22 - Added basic support for PS/2 keyboards
* 27/06/22 - Added support for RGB222 and RGBY1111 over VGA
* 22/06/22 - Even better sound with 4 pin audio output (HDMI version only)
* 18/06/22 - Dont't freeze if SD card missing
@ -67,6 +69,9 @@ Uses [Wren's Amazing PicoDVI](https://github.com/Wren6991/PicoDVI) and [CarlK's
| GP21 | | 21 | 27 | | | | Buzzer audio out |
| GP26 | | 26 | 31 | | | | PWM audio out |
| GP27 | | 26 | 32 | | | | PWM audio out |
| GP6 | | 6 | 9 | | | | PS/2 keyboard data |
| GP7 | | 7 | 10 | | | | PS/2 keyboard clock |
### Audio pins
Audio output comes in 3 variants 1, 2 and 4 pin:
@ -124,6 +129,19 @@ See this [CMakeLists.txt](src/picomputer/picomputer_vga_zx/CMakeLists.txt) for a
See this [CMakeLists.txt](src/picomputer/picomputer_vga/CMakeLists.txt) for an example configuration.
### PS/2 Keyboards
The emulator can accept input from a PS/2 keyboard wired to GP6 and GP7.
A suggested circuit is shown below:
![image](docs/ps2_interface_mk1.png)
The resistors and Zeners are there in case the keyboard contains a pull-up resistor to 5v on either the data or clock lines;
the data and clock lines are, in theory, open-collector with no pull-up.
I'm told most PS/2 keyboards can be run at 3.3v and the the extra components become redundant... but I've not tried with mine.
You may find the Pico struggles to deliver enough power at 3.3v for the SD card writes and running a keyboard.
Currently there is no toggling on the lock keys (caps/num lock) and the indicator leds are not used.
## Components
<a href="https://shop.pimoroni.com/products/raspberry-pi-pico">
<img src="https://cdn.shopify.com/s/files/1/0174/1800/products/PICOBOARDWHITEANGLE2_768x768.jpg" width="200"/>
@ -359,4 +377,4 @@ tio -m ODELBS /dev/ttyUSB0
[USB HID 1.1](https://www.usb.org/sites/default/files/hid1_11.pdf)<br/>
[ST7789 LCD driver reference](docs/ST7789_Datasheet.pdf)<br/>
[RGB for 128k ZX Spectrum](docs/128_rgb.pdf)<br/>
[PS/2 vs HID keyboard codes](docs/ps2-hid.pdf)<br/>

BIN
docs/ps2-hid.pdf Normal file

Binary file not shown.

BIN
docs/ps2_interface_mk1.cddx Normal file

Binary file not shown.

BIN
docs/ps2_interface_mk1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Circuit Diagram, cdlibrary.dll 4.0.0.0 -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" width="480" height="220" xmlns="http://www.w3.org/2000/svg">
<text x="270" y="150" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 270, 150)">2x 3.3v Zenner 1W</text>
<text x="398" y="190" style="font-family:Arial;font-size:12px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 398, 190)">PS/2 GND</text>
<line x1="350" y1="190" x2="387" y2="190" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="390" cy="190" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="398" y="110" style="font-family:Arial;font-size:12px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 398, 110)">PS/2 CLK</text>
<line x1="350" y1="110" x2="387" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="390" cy="110" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="398" y="70" style="font-family:Arial;font-size:12px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 398, 70)">PS/2 DAT</text>
<line x1="350" y1="70" x2="387" y2="70" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="390" cy="70" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="398" y="30" style="font-family:Arial;font-size:12px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 398, 30)">PS/2 VCC</text>
<line x1="350" y1="30" x2="387" y2="30" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="390" cy="30" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<line x1="250" y1="70" x2="250" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="210" y1="110" x2="210" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="210" y1="30" x2="350" y2="30" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="330" y1="110" x2="350" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="330" y1="70" x2="350" y2="70" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="210" y1="70" x2="280" y2="70" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="210" y1="110" x2="280" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="250" y1="170" x2="250" y2="190" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="210" y1="180" x2="210" y2="190" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="210" y1="170" x2="210" y2="180" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="210" y1="190" x2="350" y2="190" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="250" y1="170" x2="250" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<path d="M 250,143 M 242,143 L 258,143 M 250,143 L 258,158 L 242,158 L 250,143" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="259" y1="143" x2="259" y2="148" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="210" y1="170" x2="210" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<path d="M 210,143 M 202,143 L 218,143 M 210,143 L 218,158 L 202,158 L 210,143" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="219" y1="143" x2="219" y2="148" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="280" y1="110" x2="285" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="325" y1="110" x2="330" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<rect x="285" y="102" width="40" height="16" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="305" y="96" style="font-family:Arial;font-size:11px;text-anchor:middle" dominant-baseline="baseline" transform="rotate(0, 305, 96)">330 Ω</text>
<line x1="280" y1="70" x2="285" y2="70" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<line x1="325" y1="70" x2="330" y2="70" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<rect x="285" y="62" width="40" height="16" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="305" y="56" style="font-family:Arial;font-size:11px;text-anchor:middle" dominant-baseline="baseline" transform="rotate(0, 305, 56)">330 Ω</text>
<text x="152" y="30" style="font-family:Arial;font-size:12px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 152, 30)">Pico pin 40 (VBUS 5v)</text>
<line x1="163" y1="30" x2="210" y2="30" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="160" cy="30" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="152" y="190" style="font-family:Arial;font-size:12px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 152, 190)">Pico pin 38 (GND 0v)</text>
<line x1="163" y1="190" x2="210" y2="190" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="160" cy="190" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="152" y="110" style="font-family:Arial;font-size:12px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 152, 110)">Pico pin 10 (GP7 clk)</text>
<line x1="163" y1="110" x2="210" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="160" cy="110" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<text x="152" y="70" style="font-family:Arial;font-size:12px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 152, 70)">Pico pin 9 (GP6 data)</text>
<line x1="163" y1="70" x2="210" y2="70" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
<ellipse cx="160" cy="70" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<ellipse cx="250" cy="70" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<ellipse cx="210" cy="110" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<ellipse cx="250" cy="190" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
<ellipse cx="210" cy="190" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
</svg>

View File

@ -119,9 +119,12 @@ extern "C" void __not_in_flash_func(process_kbd_unmount)(uint8_t dev_addr, uint
}
extern "C" void __not_in_flash_func(process_kbd_report)(hid_keyboard_report_t const *report, hid_keyboard_report_t const *prev_report) {
printf("CURR ");print(report);
#if 0
// Some help debugging keyboard input/drivers
printf("PREV ");print(prev_report);
printf("CURR ");print(report);
#endif
int r;
if (showMenu) {
r = picoWinHidKeyboard.processHidReport(report, prev_report);