From 236640867916512c9db8afdd7799dfc23d421ced Mon Sep 17 00:00:00 2001 From: Daniele Verducci su MatissePenguin Date: Wed, 3 Feb 2021 21:31:13 +0100 Subject: [PATCH] WIP PS/2 keyboard driver --- .../z80-assembly/os/drivers/ps2_keyboard.asm | 51 +++++-- .../os/drivers/ps2_keyboard_scancodeset2.asm | 137 ++++++++++++++++++ .../software/z80-assembly/os/main.asm | 8 +- .../pal_adapter/pal_adapter.ino | 67 --------- 4 files changed, 178 insertions(+), 85 deletions(-) delete mode 100644 prototiping-with-arduino/pal_adapter/pal_adapter.ino diff --git a/pat80-computer/software/z80-assembly/os/drivers/ps2_keyboard.asm b/pat80-computer/software/z80-assembly/os/drivers/ps2_keyboard.asm index 3d60168..be469d6 100644 --- a/pat80-computer/software/z80-assembly/os/drivers/ps2_keyboard.asm +++ b/pat80-computer/software/z80-assembly/os/drivers/ps2_keyboard.asm @@ -20,32 +20,53 @@ ; behave strangely (will drop next pressed key). This is not a problem, as the computer, once completed, will ; have a 60% keyboard, without any of the unusable keys. -include "ps2_keyboard_scancodeset2.asm" ; PS/2 Scan Codeset 2 mappings +include 'ps2_keyboard_scancodeset2.asm' ; PS/2 Scan Codeset 2 mappings ; config (IO port 1) -PS2KEYB_CLEAR_REG: EQU IO_1 -PS2KEYB_DATA_REG: EQU IO_1 + 1 +PS2KEYB_CLEAR_REG: EQU IO_2 +PS2KEYB_DATA_REG: EQU IO_2 + 1 + +PS2KEYB_TRANSMISSION_DURATION: EQU 86 ;@ 100khz ; The time needed for the keyboard to transmit all the 11 bits of data, in CPU clock cycles PS2KEYB_BREAK: EQU 0xF0 - %10000000 ; The MSB is dropped: see NOTE on intro above -; Reads a single character. 0s are ignored (can be used with keyboard). -; Doesn't check DATA_AVAILABLE register of parallel port, because a 0 byte -; is ignored anyway (it represents the ASCII NUL control char). +; Reads a single character and returns an ascii code when a valid key is pressed. Blocking. ; @return A The read character PS2Keyb_readc: in a, (PS2KEYB_DATA_REG) ; reads a character add a, 0 jp z, Term_readc ; if char is 0 (NULL), user didn't press any key: wait for character - ; check if code is a Break Code (0xF0). If it is, discard next key as it is a released key - ld b, a ; save a - cp 0xF0 ; compare a with Break Code - jp z, ps2keyb_readc_discard + ; we found something, allow the keyboard to complete data transmission + ld a, PS2KEYB_TRANSMISSION_DURATION/5 ; every cycle is 5 CPU cycles + ps2keyb_readc_waitloop: + sub 1 + jr nz, ps2keyb_readc_waitloop + ; data transmission should now be complete. + ; check if code is a Break Code. If it is, discard next key as it is a released key + ld c, a ; save a + cp PS2KEYB_BREAK ; compare a with Break Code + jp z, ps2keyb_readc_discard ; if it is a Break Code, jump to discarder routine ; we read a valid character: clean key registers in a, PS2KEYB_CLEAR_REG - ; TODO: Interpretare keycode con lo scan code set - ;ld a, b ; restore a + ; now we will convert keycode in c to ASCII code + ld hl, PS2KEYB_SCANCODESET_ASCII_MAP ; load start of codeset to ascii map + ld b, 0 ; reset b, as we are going to do a sum with bc (where c contains the read scancode) + add hl, bc ; add scancode value to map start addr (we are using it as offset) + ld a, (hl) ; load the corresponding ascii code in a for return ret ; returns in the a register ps2keyb_readc_discard: - ; waits for next non-0 keycode and discards it - ; TODO - jp PS2Keyb_readc ; go back and wait for another keycode + ; clean key registers + in a, PS2KEYB_CLEAR_REG + ps2keyb_readc_discard_waitfordata: + ; wait for next non-0 keycode and discards it (it is the code of the released key) + in a, (PS2KEYB_DATA_REG) ; reads a character + add a, 0 + jp z, ps2keyb_readc_discard_waitfordata ; if char is 0 (NULL), wait + ; we found something, allow the keyboard to complete data transmission + ld a, PS2KEYB_TRANSMISSION_DURATION/5 ; every cycle is 5 CPU cycles + ps2keyb_readc_discard_waitloop: + sub 1 + jr nz, ps2keyb_readc_discard_waitloop + ; data transmission should now be complete, throw away key code + in a, PS2KEYB_CLEAR_REG + jp PS2Keyb_readc ; go back and wait for another keycode diff --git a/pat80-computer/software/z80-assembly/os/drivers/ps2_keyboard_scancodeset2.asm b/pat80-computer/software/z80-assembly/os/drivers/ps2_keyboard_scancodeset2.asm index e69de29..c5ead3e 100644 --- a/pat80-computer/software/z80-assembly/os/drivers/ps2_keyboard_scancodeset2.asm +++ b/pat80-computer/software/z80-assembly/os/drivers/ps2_keyboard_scancodeset2.asm @@ -0,0 +1,137 @@ +; PS/2 Keycode Mode 2 to ASCII mapping table +; +; Keycodes 0 to 83 + +.db PS2KEYB_SCANCODESET_ASCII_MAP: .db 0 ; (Unused) +.db 0 ; F9 +.db 0 ; (Control key) +.db 0 ; F5 +.db 0 ; F3 +.db 0 ; F1 +.db 0 ; F2 +.db 0 ; F12 +.db 0 ; (Control key) +.db 0 ; F10 +.db 0 ; F8 +.db 0 ; F6 +.db 0 ; F4 +.db 9 ; TAB +.db 96 ; ` +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; L ALT +.db 0 ; L SHFT +.db 0 ; (Control key) +.db 0 ; L CTRL +.db 1 ; Q +.db 2 ; 1 +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 3 ; Z +.db 4 ; S +.db 65 ; A +.db 66 ; W +.db 67 ; 2 +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 68 ; C +.db 69 ; X +.db 70 ; D +.db 71 ; E +.db 72 ; 4 +.db 73 ; 3 +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 32 ; SPACE +.db 33 ; V +.db 34 ; F +.db 35 ; T +.db 36 ; R +.db 37 ; 5 +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 38 ; N +.db 39 ; B +.db 40 ; H +.db 41 ; G +.db 42 ; Y +.db 43 ; 6 +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 44 ; M +.db 45 ; J +.db 46 ; U +.db 47 ; 7 +.db 48 ; 8 +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 44 ; , +.db 45 ; K +.db 46 ; I +.db 47 ; O +.db 48 ; 0 +.db 49 ; 9 +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 46 ; . +.db 47 ; / +.db 48 ; L +.db 59 ; ; +.db 60 ; P +.db 45 ; - +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 39 ; ' +.db 0 ; (Unused) +.db 91 ; [ +.db 61 ; = +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; CAPS +.db 0 ; R SHFT +.db 10 ; ENTER +.db 93 ; ] +.db 0 ; (Unused) +.db 92 ; \ +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 8 ; BKSP +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 9 ; KP 1 +.db 0 ; (Unused) +.db 10 ; KP 4 -- NOTE: shadowed by break code (see the NOTE in ps2_keyboard.asm) +.db 11 ; KP 7 +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 0 ; (Unused) +.db 48 ; KP 0 +.db 46 ; KP . +.db 47 ; KP 2 +.db 48 ; KP 5 +.db 49 ; KP 6 +.db 50 ; KP 8 +.db 27 ; ESC +.db 0 ; NUM +.db 0 ; F11 +.db 43 ; KP + +.db 44 ; KP 3 +; The following codes are unrecognized by PAT80, as it uses only 7 bits (see the NOTE in ps2_keyboard.asm) +; .db 45 ; KP - +; .db 42 ; KP * +; .db 43 ; KP 9 +; .db 0 ; SCROLL +; .db 0 ; (Control key) +; .db 0 ; (Control key) +; .db 0 ; (Control key) +; .db 0 ; (Control key) +; .db 0 ; F7 \ No newline at end of file diff --git a/pat80-computer/software/z80-assembly/os/main.asm b/pat80-computer/software/z80-assembly/os/main.asm index afcf954..3ef0ea5 100644 --- a/pat80-computer/software/z80-assembly/os/main.asm +++ b/pat80-computer/software/z80-assembly/os/main.asm @@ -10,9 +10,9 @@ jp Sysinit ; Startup vector: DO NOT MOVE! Must be the first instruction ; DRIVERS VAR SPACE: 0x9000 - 0x9FFF (4kb) ; APPLICATION VAR SPACE: 0xA000 - 0xFFFF (24kb) ; I/O MAP -; I/O 0 (0x00 - 0x1F) Parallel terminal (uses addr 0x00 only) +; I/O 0 (0x00 - 0x1F) Parallel terminal (uses addr 0x00 and 0x01) ; I/O 1 (0x20 - 0x3F) Sound card (uses addr 0x20 only) -; I/O 2 (0x40 - 0x5F) +; I/O 2 (0x40 - 0x5F) PS2 Keyboard (uses 0x40 and 0x41) ; I/O 3 (0x60 - 0x7F) ; I/O 4 (0x80 - 0x9F) ; I/O 5 (0xA0 - 0xBF) @@ -56,7 +56,8 @@ Sys_Printc: ; Reads a single character ; @return A The read character Sys_Readc: - jp Term_readc + ;jp Term_readc + jp PS2Keyb_readc ; Reads a line ; @return BC The pointer to a null-terminated read string @@ -91,6 +92,7 @@ IO_7: EQU 0xE0 ;include 'drivers/hd44780.asm' ;include 'drivers/keyboard.asm' +include 'drivers/ps2_keyboard.asm' include 'drivers/arduino_terminal.asm' include 'drivers/sn76489.asm' include 'monitor.asm' diff --git a/prototiping-with-arduino/pal_adapter/pal_adapter.ino b/prototiping-with-arduino/pal_adapter/pal_adapter.ino deleted file mode 100644 index a09ff03..0000000 --- a/prototiping-with-arduino/pal_adapter/pal_adapter.ino +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -TVout TV; - -// Pins -#define RS 5 -#define EN 4 -const byte DATA [] = {A5, A4, A3, A2, 13, 12, 11, 10}; - - -bool clkState = false; - -void setup() { - Serial.begin(57600); - Serial.println("PAL debugger"); - - // Init comm pins - pinMode(EN, INPUT); - pinMode(RS, INPUT); - for(int pin = 0; pin < 8; pin++) { - pinMode(DATA[pin], INPUT); - } - - // Init VGA - TV.begin(PAL,120,96); - TV.select_font(font4x6); - - TV.println("TV init"); -} - -void loop() { - bool newClkState = digitalRead(EN); - if (newClkState == false && clkState == true) { - // Falling edge: read data from bus - onClk(); - } - clkState = newClkState; -} - -void onClk() { - bool isCommand = digitalRead(RS); - if (isCommand) { - //onCommandReceived(); - onDataReceived(); - } else { - onDataReceived(); - } -} - -void onCommandReceived() { - -} - -void onDataReceived() { - char ch = readByte(); - TV.print(ch); - Serial.println(ch); -} - -byte readByte() { - unsigned int data = 0; - for(int pin=0; pin < 8; pin++) { - byte b = digitalRead(DATA[pin]) ? 1 : 0; - data = (data << 1) + b; // Shifta di 1 e aggiunge il bit corrente. Serve per ricostruire il numero da binario - } - return data; -}