sms/pad: new module to manage Megadrive controller in SMS

This commit is contained in:
Virgil Dupras 2019-07-02 09:02:19 -04:00
parent ca5bc07a75
commit 9eb80d5eac
2 changed files with 63 additions and 26 deletions

49
kernel/sms/pad.asm Normal file
View File

@ -0,0 +1,49 @@
; pad - read input from MD controller
;
; Conveniently expose an API to read the status of a MD pad. Moreover,
; implement a mechanism to input arbitrary characters from it. It goes as
; follow:
;
; * Direction pad select characters. Up/Down move by one, Left/Right move by 5\
; * Start acts like Return
; * A acts like Backspace
; * B changes "character class": lowercase, uppercase, numbers, special chars.
; The space character is the first among special chars.
; * C confirms letter selection
;
; *** Consts ***
;
.equ PAD_CTLPORT 0x3f
.equ PAD_D1PORT 0xdc
; *** Variables ***
;
; *** Code ***
; Put status for port A in register A. Bits, from MSB to LSB:
; Start - A - C - B - Right - Left - Down - Up
; Each bit is high when button is unpressed and low if button is pressed. For
; example, when no button is pressed, 0xff is returned.
padStatusA:
; This logic below is for the Genesis controller, which is modal. TH is
; an output pin that swiches the meaning of TL and TR. When TH is high
; (unselected), TL = Button B and TR = Button C. When TH is low
; (selected), TL = Button A and TR = Start.
push bc
ld a, 0b11111101 ; TH output, unselected
out (PAD_CTLPORT), a
in a, (PAD_D1PORT)
and 0x3f ; low 6 bits are good
ld b, a ; let's store them
; Start and A are returned when TH is selected, in bits 5 and 4. Well
; get them, left-shift them and integrate them to B.
ld a, 0b11011101 ; TH output, selected
out (PAD_CTLPORT), a
in a, (PAD_D1PORT)
and 0b00110000
sla a
sla a
or b
; we're good now!
pop bc
ret

View File

@ -1,11 +1,14 @@
di
im 1
jp main
.fill 0x66-$
retn
#include "sms/pad.asm"
main:
di
im 1
ld sp, 0xdff0
ld hl, VdpData
@ -60,45 +63,30 @@ mainloop:
; What we do here is simple. We go though all bits of port A controller
; increasing B each time. As soon as we get a hit, we display that
; letter. Pressed buttons go low.
; This logic below is for the Genesis controller, which is modal. TH is
; an output pin that swiches the meaning of TL and TR. When TH is high
; (unselected), TL = Button B and TR = Button C. When TH is low
; (selected), TL = Button A and TR = Start.
ld a, 0b11111101 ; TH output, unselected
out (0x3f), a
call padStatusA
ld b, 0x41 ; a
in a, (0xdc) ; I/O port
and 0b00100000 ; Port A Button C pressed
bit 5, a ; Port A Button C pressed
jr z, updateLetter
inc b ; b
in a, (0xdc)
and 0b00010000 ; Port A Button B pressed
bit 4, a ; Port A Button B pressed
jr z, updateLetter
inc b ; c
in a, (0xdc)
and 0b00001000 ; Port A Right pressed
bit 3, a ; Port A Right pressed
jr z, updateLetter
inc b ; d
in a, (0xdc)
and 0b00000100 ; Port A Left pressed
bit 2, a ; Port A Left pressed
jr z, updateLetter
inc b ; e
in a, (0xdc)
and 0b00000010 ; Port A Down pressed
bit 1, a ; Port A Down pressed
jr z, updateLetter
inc b ; f
in a, (0xdc)
and 0b00000001 ; Port A Up pressed
bit 0, a ; Port A Up pressed
jr z, updateLetter
ld a, 0b11011101 ; TH output, unselected
out (0x3f), a
inc b ; g
in a, (0xdc)
and 0b00010000 ; Port A Button A pressed
bit 6, a ; Port A Button A pressed
jr z, updateLetter
inc b ; h
in a, (0xdc)
and 0b00100000 ; Port A Start pressed
bit 7, a ; Port A Start pressed
jr z, allLetters ; when start is pressed, print all letters
; no button pressed on port A, continue to updateLetter