diff --git a/kernel/sms/pad.asm b/kernel/sms/pad.asm new file mode 100644 index 0000000..0530a35 --- /dev/null +++ b/kernel/sms/pad.asm @@ -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 diff --git a/recipes/sms/glue.asm b/recipes/sms/glue.asm index a5f08a7..7dc211d 100644 --- a/recipes/sms/glue.asm +++ b/recipes/sms/glue.asm @@ -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