DEV-SNIP #1 - Input

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
sirmorris
Posts: 2811
Joined: Thu May 08, 2008 5:45 pm

DEV-SNIP #1 - Input

Post by sirmorris »

All programs need input. All zeddies have a keyboard. Great! With the availability of peripherals with joystick connections then the world of user input is looking richer than ever. With great richness comes great complexity however.

Here is my humble submission in the category of a nice general purpose input routine, where input from a number of devices is focused into a few simple values which can tell you whether an input is:

* just activated
* held
* just released
* not activated

It's currently specialised for ZXpand but it's easily updated to work with, for example, Chroma or (I still don't believe they exist) Kempston ;) :lol:
sirmorris
Posts: 2811
Joined: Thu May 08, 2008 5:45 pm

Re: DEV-SNIP #1 - Input

Post by sirmorris »

Code for BRASS assembler.

Code: Select all

readinput:
    call    $1ffe               ; get the joystick bits by calling ZXpand ROM function - this will crash with no ZXpand present
    ;        UDLRF---
    or      %00000111
    ld      (LAST_J),a

    ld      de,kbin             ; read the keyboard, building a table at (de)
    ld      c,$fe
    ld      b,8

-:  ld      a,c                 ; read each of the 8 half rows
    in      a,($fe)
    ld      (de),a
    rlc     c
    inc     de
    djnz    {-}

    ; point at first input state block
    ;
    ld      hl,inputstates

    call    updateinputstate ; (up)
    call    updateinputstate ; (down)
    call    updateinputstate ;  etc.
    call    updateinputstate ;
    call    updateinputstate
    call    updateinputstate

    ; fall into here for last input - quit

updateinputstate:
    ld      a,(hl)          ; input info table
    ld      (uibittest),a   ; get opcode for j/s bit test

    inc     hl
    ld      a,(hl)          ; half-row index
    inc     hl
    ld      de,kbin         ; keyboard bits table pointer - 8 byte aligned
    or      e
    ld      e,a             ; add offset to table
    ld      a,(de)          ; get key input bits
    and     (hl)            ; result will be a=0 if required key is down
    inc     hl
    jr      z,{+}           ; skip joystick read if pressed

    ld      a,(LAST_J)

+:  sla     (hl)            ; (key & 3) = 0 - not pressed, 1 - just pressed, 2 - just released and >3 - held

uibittest = $+1
    and	0             ; if a key was already detected a will be 0 so this test succeeds
    jr      nz,{+}          ; otherwise joystick bit is tested - skip if bit = 1 (not pressed)

    set     0,(hl)          ; signify impulse

+:  inc     hl              ; ready for next input in table
    ret


    .align  8
kbin:
    .byte	0,0,0,0,0,0,0,0		; storage for keyboard half-rows

LAST_J:
	.byte	0			; storage for last joystick value

; -----  4  3  2  1  0
;                       
; $FE -  V, C, X, Z, SH   0
; $FD -  G, F, D, S, A    1
; $FB -  T, R, E, W, Q    2
; $F7 -  5, 4, 3, 2, 1    3
; $EF -  6, 7, 8, 9, 0    4
; $DF -  Y, U, I, O, P    5
; $BF -  H, J, K, L, NL   6
; $7F -  B, N, M, ., SP   7
;
; joystick bit, or $ff/%11111111 for no joy
; key row offset 0-7,
; key mask,
; input impulse

inputstates:
    .byte	%10000000,2,%00000001,0        ; up      (Q)
    .byte	%01000000,1,%00000001,0        ; down    (A)
    .byte	%00100000,7,%00001000,0        ; left    (N)
    .byte	%00010000,7,%00000100,0        ; right   (M)
    .byte	%00001000,7,%00000001,0        ; fire    (SP)
    .byte	%11111111,3,%00000001,0        ; advance (1)
    .byte	%11111111,0,$00000101,0        ; quit    (SH+X)

; calculate actual input impulse addresses
up = inputstates + 3
down = inputstates + 7
left = inputstates + 11
right = inputstates + 15
fire = inputstates + 19
advance = inputstates + 23
quit = inputstates + 27

sirmorris
Posts: 2811
Joined: Thu May 08, 2008 5:45 pm

Re: DEV-SNIP #1 - Input

Post by sirmorris »

How it's used.

From the main program call readinput once per frame. The variables declared at the end of the code snippet point to bytes in memory where the current control state may be read.

If the value is 0, then no control is active.
If the value is 1, then a control associated with the trigger have just activated.
If the value is 3, then the controls associated with the trigger are still activated.
If the value is 2, then the controls associated with the trigger are just deactivated.

Code: Select all

	;  do something if UP pressed
	ld	a,(up)
	or	a
	jr	nz,up
	
	; fire only when fire button first pressed
	ld	a,(fire)
	cp	1
	jr	z,dofire
How it works.

Each trigger can have a joystick direction and key associated with it. The current input state is represented by bit 0 of the trigger value. The previous state is represented by the value of bit 1.

The state of a key is determined by specifying a half-row index and a bit mask. These correspond to the keyboard matrix and the table of keys and their values are shown in the table in the comment in the code. Columns show the bit number to test in the half-row, which are labelled in the diagram's rows.

The joystick direction is determined by specifying a bit mask used in some self modifying code that tests a bit in the joystick value.

The settings for an input are specified in the 'inputstates' structure like so:

Code: Select all

    .byte	%10000000,2,%00000001,0        ; up      (Q)
Here is the 'up' trigger. It's associated with bit 7 of the joystick value. It is also available by pressing Q - which appears in half-row 2, at bit 0:

Code: Select all

; -----  4  3  2  1  0
;                       
; $FE -  V, C, X, Z, SH   0
; $FD -  G, F, D, S, A    1
; $FB -  T, R, E, W, Q    2
...
The beauty of setting things up like this is that:

* input is all in one place
* redefining input is fairly simple, change the definition table
* different phases of the input can be detected easily so no external logic for one-shots is required

... and probably other stuff too.

I hope this code is useful.
User avatar
1024MAK
Posts: 5087
Joined: Mon Sep 26, 2011 10:56 am
Location: Looking forward to summer in Somerset, UK...

Re: DEV-SNIP #1 - Input

Post by 1024MAK »

sirmorris wrote: Tue Nov 14, 2017 12:21 pmIt's currently specialised for ZXpand but it's easily updated to work with, for example, Chroma or (I still don't believe they exist) Kempston ;)
Before finding this forum, I didn't think any users of ZX81's existed anymore.... :roll:
Let alone that there was new software and hardware being developed :shock:

(Maybe I should go looking for some fairies at the bottom of the garden now that the "nights are drawing in"... well, after a few pints...)

Kempston joystick interfaces (or compatible interfaces) is, I presume, what is being referred to. Kempston joystick interfaces that have a ZX81 sized edge-connector and which fit AND work do exist.

It's most likely that they were not made or marketed for the ZX81, but that ZX81 sized edge-connectors were a bit cheaper than ZX Spectrum sized edge-connectors...

Of course, the cheapest joystick "interface",is to wire up a 9 way D-connector to the keyboard matrix via soldering wires to the solder connections on the keyboard sockets...

Mark
ZX81 Variations
ZX81 Chip Pin-outs
ZX81 Video Transistor Buffer Amp

:!: Standby alert :!:
There are four lights!
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :!:
Looking forward to summer later in the year.
sirmorris
Posts: 2811
Joined: Thu May 08, 2008 5:45 pm

Re: DEV-SNIP #1 - Input

Post by sirmorris »

:D Glad to see my trap worked first time Mark :lol:

If anyone wants to donate an interface for testing purposes..! ;)
User avatar
mrtinb
Posts: 1905
Joined: Fri Nov 06, 2015 5:44 pm
Location: Denmark
Contact:

Re: DEV-SNIP #1 - Input

Post by mrtinb »

sirmorris wrote: Tue Nov 14, 2017 12:21 pm Here is my humble submission in the category of a nice general purpose input routine, where input from a number of devices is focused into a few simple values which can tell you whether an input is:
Is this a routine that gets both a joystick direction and a key back?
Can it be used for plain keyboard read, or is it only for joystick read?
Will it work for simple keybord read on hardware that is not ZXpand, or is it ZXpand specific ports?
Martin
https://zx.rtin.be
ZX81, Lambda 8300, Commodore 64, Mac G4 Cube
User avatar
Andy Rea
Posts: 1606
Joined: Fri May 09, 2008 2:48 pm
Location: Planet Earth
Contact:

Re: DEV-SNIP #1 - Input

Post by Andy Rea »

Cool, very cool...

Cheers Andy
what's that Smell.... smells like fresh flux and solder fumes...
sirmorris
Posts: 2811
Joined: Thu May 08, 2008 5:45 pm

Re: DEV-SNIP #1 - Input

Post by sirmorris »

mrtinb wrote: Tue Nov 14, 2017 1:37 pmIs this a routine that gets both a joystick direction and a key back? Can it be used for plain keyboard read, or is it only for joystick read?
Hi Martin. It is for game-style input, where a control/trigger is attached to a particular key and/or joystick direction. It can be used for keys only, or joystick only if desired. Specify $ff/%11111111 for either of the masks. In the example there are 2 keys which don't have a joystick equivalent.
mrtinb wrote: Tue Nov 14, 2017 1:37 pmWill it work for simple keybord read on hardware that is not ZXpand, or is it ZXpand specific ports?
Only the joystick is ZXpand specific. The keyboard reading is Sinclair standard. No specific hardware required :D
Andy Rea wrote: Tue Nov 14, 2017 1:53 pmCool, very cool...
Whaythenkyew 8-)
Moggy
Posts: 3222
Joined: Wed Jun 18, 2008 2:00 pm

Re: DEV-SNIP #1 - Input

Post by Moggy »

@Charlie

If you genuinely need a j/stk interface I have a pukka Kempston speccy one and a no-name ZX81 interface with ZX81 edge connector, you can have with my blessings.
Never used them so have to guess they are ok.
Last edited by Moggy on Tue Nov 14, 2017 3:13 pm, edited 3 times in total.
User avatar
mrtinb
Posts: 1905
Joined: Fri Nov 06, 2015 5:44 pm
Location: Denmark
Contact:

Re: DEV-SNIP #1 - Input

Post by mrtinb »

sirmorris wrote: Tue Nov 14, 2017 2:42 pm
mrtinb wrote: Tue Nov 14, 2017 1:37 pmWill it work for simple keybord read on hardware that is not ZXpand, or is it ZXpand specific ports?
Only the joystick is ZXpand specific. The keyboard reading is Sinclair standard. No specific hardware required :D
So if I use this routine in my program without ZXpand it will crash because I don't have ZXpand?
Martin
https://zx.rtin.be
ZX81, Lambda 8300, Commodore 64, Mac G4 Cube
Post Reply