mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-17 06:08:05 +11:00
recipes/rc2014/ps2: drive a shell with ps/2 kbd!
This commit is contained in:
parent
3cdb25bfda
commit
e44ebb08b2
81
kernel/kbd.asm
Normal file
81
kernel/kbd.asm
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
; kbd - implement GetC for PS/2 keyboard
|
||||||
|
;
|
||||||
|
; Status: Work in progress. See recipes/rc2014/ps2
|
||||||
|
;
|
||||||
|
; *** Defines ***
|
||||||
|
; The port of the device where we read scan codes. See recipe rc2014/ps2.
|
||||||
|
; KBD_PORT
|
||||||
|
|
||||||
|
; *** Variables ***
|
||||||
|
.equ KBD_SKIP_NEXT KBD_RAMSTART
|
||||||
|
.equ KBD_RAMEND KBD_SKIP_NEXT+1
|
||||||
|
|
||||||
|
kbdInit:
|
||||||
|
xor a
|
||||||
|
ld (KBD_SKIP_NEXT), a
|
||||||
|
ret
|
||||||
|
|
||||||
|
kbdGetC:
|
||||||
|
in a, (KBD_PORT)
|
||||||
|
or a ; cp 0
|
||||||
|
ret z
|
||||||
|
; scan code not zero, maybe we have something.
|
||||||
|
; Do we need to skip it?
|
||||||
|
push af ; <|
|
||||||
|
ld a, (KBD_SKIP_NEXT) ;|
|
||||||
|
or a ; |
|
||||||
|
jr nz, .skip ; |
|
||||||
|
pop af ; <|
|
||||||
|
cp 0x80
|
||||||
|
jr nc, .outOfBounds
|
||||||
|
; No need to skip, code within bounds, we have something! Let's see if
|
||||||
|
; there's a ASCII code associated to it.
|
||||||
|
push hl ; <|
|
||||||
|
ld hl, kbdScanCodes ; |
|
||||||
|
call addHL ; |
|
||||||
|
ld a, (hl) ; |
|
||||||
|
pop hl ; <|
|
||||||
|
or a ; cp 0
|
||||||
|
jp z, unsetZ ; no code. Keep A at 0, but unset Z
|
||||||
|
; We have something!
|
||||||
|
cp a ; ensure Z
|
||||||
|
ret
|
||||||
|
.outOfBounds:
|
||||||
|
; A scan code over 0x80 is out of bounds. Ignore.
|
||||||
|
; If F0 (break code) or E0 (extended code), we also skip the next code
|
||||||
|
cp 0xf0
|
||||||
|
jr z, .skipNext
|
||||||
|
cp 0xe0
|
||||||
|
jr z, .skipNext
|
||||||
|
xor a
|
||||||
|
jp unsetZ
|
||||||
|
.skipNext:
|
||||||
|
ld (KBD_SKIP_NEXT), a
|
||||||
|
xor a
|
||||||
|
jp unsetZ
|
||||||
|
.skip:
|
||||||
|
pop af ; equilibrate stack
|
||||||
|
xor a
|
||||||
|
ld (KBD_SKIP_NEXT), a
|
||||||
|
jp unsetZ
|
||||||
|
|
||||||
|
; A list of the value associated with the 0x80 possible scan codes of the set
|
||||||
|
; 2 of the PS/2 keyboard specs. 0 means no value. That value is a character than
|
||||||
|
; can be read in a GetC routine. No make code in the PS/2 set 2 reaches 0x80.
|
||||||
|
kbdScanCodes:
|
||||||
|
; 0x00 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||||
|
.db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,'`', 0
|
||||||
|
; 0x10 9 = TAB
|
||||||
|
.db 0, 0, 0, 0, 0,'Q','1', 0, 0, 0,'Z','S','A','W','2', 0
|
||||||
|
; 0x20 32 = SPACE
|
||||||
|
.db 0,'C','X','D','E','4','3', 0, 0, 32,'V','F','T','R','5', 0
|
||||||
|
; 0x30
|
||||||
|
.db 0,'N','B','H','G','Y','6', 0, 0, 0,'M','J','U','7','8', 0
|
||||||
|
; 0x40 59 = ;
|
||||||
|
.db 0,',','K','I','O','0','9', 0, 0,'.','/','L', 59,'P','-', 0
|
||||||
|
; 0x50 13 = RETURN 39 = '
|
||||||
|
.db 0, 0, 39, 0,'[','=', 0, 0, 0, 0, 13,']', 0,'\', 0, 0
|
||||||
|
; 0x60 8 = BKSP
|
||||||
|
.db 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
; 0x70 27 = ESC
|
||||||
|
.db 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
2
recipes/.gitignore
vendored
2
recipes/.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
*.bin
|
*.bin
|
||||||
*.cfs
|
*.cfs
|
||||||
|
*.hex
|
||||||
|
*.obj
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
PROGNAME = ps2ctl
|
PROGNAME = ps2ctl
|
||||||
AVRDUDEMCU ?= t45
|
AVRDUDEMCU ?= t45
|
||||||
AVRDUDEARGS ?= -c usbtiny -P usb
|
AVRDUDEARGS ?= -c usbtiny -P usb
|
||||||
TARGETS = $(PROGNAME).hex
|
TARGETS = $(PROGNAME).hex os.bin
|
||||||
|
ZASM = ../../../tools/zasm.sh
|
||||||
|
KERNEL = ../../../kernel
|
||||||
|
|
||||||
# Rules
|
# Rules
|
||||||
|
|
||||||
@ -14,9 +16,10 @@ send: $(PROGNAME).hex
|
|||||||
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$<
|
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$<
|
||||||
|
|
||||||
$(PROGNAME).hex: $(PROGNAME).asm
|
$(PROGNAME).hex: $(PROGNAME).asm
|
||||||
$(TARGETS):
|
|
||||||
avra -o $@ $<
|
avra -o $@ $<
|
||||||
|
|
||||||
clean:
|
os.bin: glue.asm
|
||||||
rm -f $(TARGETS) *.eep.hex *.obj
|
$(ZASM) $(KERNEL) < $< > $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGETS) *.eep.hex *.obj os.bin
|
||||||
|
@ -36,16 +36,15 @@ address selection + `IORQ` + `RO`
|
|||||||
|
|
||||||
## Using the PS/2 interface
|
## Using the PS/2 interface
|
||||||
|
|
||||||
As of now, the interface is incomplete and can only be queried through the
|
After having built and flashed the `glue.asm` supplied with this recipe, you end
|
||||||
shell's `iord`. I've set my device up for addr `8` (that is, I wired `A3`
|
up with a shell driven by the PS/2 keyboard (but it still outputs to ACIA).
|
||||||
through the inverter, the rest through diodes, and hooked this pudding to `OE`).
|
|
||||||
|
|
||||||
When doing `iord 8` in the shell, I get the scan code of the last key I pressed,
|
You will see, by typing on the keyboard, that it kinda works, but in a very
|
||||||
unless the 595 was "busy" with another code. For example, if I press `A`, my
|
basic and glitchy way. You will get double letters sometimes, and at some point,
|
||||||
next `iord 8` will yield `1C` (the "make" code for "A" in the PS/2 protocol).
|
communications are likely to become "corrupted" (you reliably get the wrong
|
||||||
|
letters). That's because parity checks, timeouts and reset procedures aren't
|
||||||
|
implemented yet.
|
||||||
|
|
||||||
Doing a second `iord 8` right after a first will yield `0`, indicating that the
|
But still, it kinda works!
|
||||||
device properly detect the first reading attempt and properly flushes the value
|
|
||||||
from the 595.
|
|
||||||
|
|
||||||
[avra]: https://github.com/hsoft/avra
|
[avra]: https://github.com/hsoft/avra
|
||||||
|
42
recipes/rc2014/ps2/glue.asm
Normal file
42
recipes/rc2014/ps2/glue.asm
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
.equ RAMSTART 0x8000
|
||||||
|
.equ RAMEND 0xffff
|
||||||
|
.equ ACIA_CTL 0x80 ; Control and status. RS off.
|
||||||
|
.equ ACIA_IO 0x81 ; Transmit. RS on.
|
||||||
|
.equ KBD_PORT 0x08
|
||||||
|
|
||||||
|
jp init
|
||||||
|
|
||||||
|
; interrupt hook
|
||||||
|
.fill 0x38-$
|
||||||
|
jp aciaInt
|
||||||
|
|
||||||
|
#include "err.h"
|
||||||
|
#include "core.asm"
|
||||||
|
#include "parse.asm"
|
||||||
|
.equ ACIA_RAMSTART RAMSTART
|
||||||
|
#include "acia.asm"
|
||||||
|
|
||||||
|
.equ KBD_RAMSTART ACIA_RAMEND
|
||||||
|
#include "kbd.asm"
|
||||||
|
|
||||||
|
.equ STDIO_RAMSTART KBD_RAMEND
|
||||||
|
#include "stdio.asm"
|
||||||
|
|
||||||
|
.equ SHELL_RAMSTART STDIO_RAMEND
|
||||||
|
.equ SHELL_EXTRA_CMD_COUNT 0
|
||||||
|
#include "shell.asm"
|
||||||
|
|
||||||
|
init:
|
||||||
|
di
|
||||||
|
; setup stack
|
||||||
|
ld hl, RAMEND
|
||||||
|
ld sp, hl
|
||||||
|
im 1
|
||||||
|
|
||||||
|
call aciaInit
|
||||||
|
ld hl, kbdGetC
|
||||||
|
ld de, aciaPutC
|
||||||
|
call stdioInit
|
||||||
|
call shellInit
|
||||||
|
ei
|
||||||
|
jp shellLoop
|
@ -233,16 +233,27 @@ sendTo595Loop:
|
|||||||
dec r16
|
dec r16
|
||||||
brne sendTo595Loop ; not zero yet? loop
|
brne sendTo595Loop ; not zero yet? loop
|
||||||
|
|
||||||
; toggle RCLK
|
; We're finished sending our data to the 595 and we're ready to go back
|
||||||
sbi PORTB, RCLK
|
; to business as usual. However, timing is important here. The z80 is
|
||||||
cbi PORTB, RCLK
|
; very fast and constantly hammers our 595 with polls. While this
|
||||||
|
; routine was running, it was getting zeroes, which is fine, but as soon
|
||||||
|
; as we trigger RCLK, the z80 is going to fetch that value. What we want
|
||||||
|
; to do is to enable back the interrupts as soon as RCLK is triggered
|
||||||
|
; so that the z80 doesn't have enough time to poll twice. If it did, we
|
||||||
|
; would return a double character. This is why RCLK triggering is the
|
||||||
|
; last operation.
|
||||||
|
|
||||||
; release PS/2
|
; release PS/2
|
||||||
cbi DDRB, DATA
|
cbi DDRB, DATA
|
||||||
|
|
||||||
; Set R2 to "595 is busy"
|
; Set R2 to "595 is busy"
|
||||||
inc r2
|
inc r2
|
||||||
|
|
||||||
|
; toggle RCLK
|
||||||
|
sbi PORTB, RCLK
|
||||||
|
cbi PORTB, RCLK
|
||||||
sei
|
sei
|
||||||
|
|
||||||
rjmp loop
|
rjmp loop
|
||||||
|
|
||||||
; Check that Y is within bounds, reset to SRAM_START if not.
|
; Check that Y is within bounds, reset to SRAM_START if not.
|
||||||
|
Loading…
Reference in New Issue
Block a user