NEVER MIND THE KEYPAD - HERE'S THE INTERRUPT ROUTINE
ZX Computing, June 1986

If you've got a 128 and are thinking about buying the add-on
keypad, then Toni Baker's program could save you #20!


The Spectrum 128 comes complete with a little hole in the front
right-hand corner for plugging in a specially designed add-on keypad,
available from Sinclair (or possibly Amstrad). The keypad contains all
the digits from 0 to 9, some calculator keys such as + and *, and a
whole new collection of editing keys. Now the numbers and symbols
aren't anything special - they're just the same keys as on the 128
keyboard, only in a different place. If you can make the effort to
hold down SYMBOL SHIFT while pressing 'K' you may come to the
conclusion that you don't really need a keypad after all - if only it
weren't for those new editing keys. This program will do something
about those too!


New keys

The new editing keys contain such functions as "Delete Right", "Move
Left to the Start of the next word", and so on. This program is a
relocatable interrupt routine which puts all of the new (and
previously unobtainable) editing keys back where they belong - on the
conventional Spectrum keyboard.

It makes use of two keys which on the standard Spectrum 128 are
unused: they are TRUE VIDEO and INV VIDEO. Except in 48K mode, these
keys are not used at all. My interrupt routine redefines them: now
they are SHIFT keys. On their own they are ignored, but may be used in
conjunction with other keys. "TRUE VIDEO" now means "Line", and "INV
VIDEO" now means "Word". Thus, if you hold down TRUE-VIDEO and press
CURSOR-RIGHT then the cursor will move rightward to the end of the
line. Similarly, if you hold down TRUE-VIDEO and press CURSOR-LEFT
then the cursor will move to the start of the line. TRUE-VIDEO with
the UP and DOWN cursor keys will move the cursor to the first and last
line of the program respectively.

INV-VIDEO moves the cursor by words. If you hold down INV-VIDEO and
press CURSOR-RIGHT then the cursor will move rightward to the start of
the next word (a "word" in this context is a sequence of anything
except space); INV-VIDEO with CURSOR-LEFT will move the cursor
leftward to the start of the next word. INV-VIDEO with UP and DOWN
will move the cursor up or down by ten lines.

SYMBOL SHIFT may now be used with the cursor keys. For this purpose,
SYMBOL-SHIFT may be taken to mean "Delete". Thus SYMBOL-SHIFT with
CURSOR-LEFT produces "Delete Left" - exactly the same as the ordinary
DELETE key. SYMBOL-SHIFT with CURSOR-RIGHT, however, produces "Delete
Right", which deletes the character at the cursor position.
SYMBOL-SHIFT may also be used in conjunction with either TRUE-VIDEO or
INV-VIDEO, so for instance, SYMBOL-SHIFT / TRUE-VIDEO / CURSOR-RIGHT
will delete everything on the current line to the right of the cursor
position, and SYMBOL-SHIFT / INV-VIDEO / CURSOR-LEFT will delete the
next word to the left of the cursor.


Toggle

There is one additional editing key which will appear on the new
keypad. It is called TOGGLE, and its purpose is to switch between the
upper screen and the lower screen, without having to go through the
SCREEN option on the menu. My program uses TRUE-VIDEO and INV-VIDEO
together as the Toggle key. Pressing both of these at the same time
will produce the toggle.

My program makes other improvements to the keyboard, apart from adding
new keys. The symbols (such as square-bracket and the weird-squiggle)
which were previously only attainable by going into E-mode, have now
been put back on the keys where they belong - directly. To obtain
Square-Left-Bracket now, all you have to press is SYMBOL-SHIFT/Y. Only
the Copyright Symbol has moved - this can now be obtained with
SYMBOL-SHIFT/I.

Graphics Mode, too, is improved. Previously, G-mode suffered from two
disadvantages: the cursor keys didn't work, and keys 'T' to 'Z'
produced some strange effects. My program changes all this. You can
now use both the original cursor keys, and the new editing keys, in
G-mode exactly as you would normally. (To get the inverse of graphics
1 to 8 you must now use SYMBOL-SHIFT, as CAPS-SHIFT with numbers will
not work).


Input

One final point - users of the Spectrum 128 may have noticed that the
new Full Screen Editor isn't used for INPUT. If you type INPUT A$ then
you'll find that all the keywords on SYMBOL-SHIFT actually come out as
keywords. Furthermore, in G-Mode keys 'T' to 'Z' will all come out as
keywords (with Graphic-T being SPECTRUM, and Graphic-U being PLAY). If
you have a keypad you'll find that your lovely new editing keys don't
work - and in fact come out as keywords. This program makes a special
check for INPUT, and temporarily deactivates itself during INPUT. This
means that the Spectrum behaves normally during INPUT. This is
necessary for two reasons: (i) it MUST be possible to obtain the
keyword STOP on SYMBOL-SHIFT/A to break out of an input; and (ii) the
new editing keys don't work during INPUT anyway.

This program is completely relocatable. It may be placed in memory
anywhere you like (but see warning below). To activate it you must
store an interrupt vector (a pointer to the start of the routine) at
an address whose low part is FF. The I register must contain the high
part of the address of this vector, and finally IM 2 must be selected.
To deactivate the routine simply select IM 1.


A word of warning

On the Spectrum 128, Interrupt Vectors may only be placed between 80FF
and BEFF inclusive. An interrupt routine itself must exist wholly
between 400 and BFFF. This is because address C000 to FFFF are
pageable, and should an interrupt occur whilst the wrong 16K RAM is
paged in you will invariably get a crash. The ROM area is also
constantly pageing between the two ROMs so you can't use this as a
vector either. The (new) ROM constantly uses RAM page 7 - the normal
page selected by BASIC is RAM page 0. If an interrupt vector or
routine exists between C000 and FFFF in RAM page 0, and an interrupt
occurs whilst RAM page 7 is paged in, the results will be
catastrophic. Be warned.

That said, I'll leave you to type the routine in and SAVE it. It's
well worth doing. I for one have found the new editing keys extremely
useful indeed. See you soon, and Blessed be.


Stop press ...
Since Amstrad's take-over of Sinclair Research, development of components
such as the 128 keypad is under review, so this program could prove very
valuable to 128 owners until the keypad's future is decided.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;[I wrote START and STOP to set the interrupt routine at the highest possible]
;[location. See KEYPAD.TXT for instructions on relocating the code.      JimG]

BDA2 01B3BD   START     LD   BC,#BDB3    
BDA5 ED43FFBE           LD   (#BEFF),BC  
BDA9 3EBE               LD   A,#BE       
BDAB ED47               LD   I,A         
BDAD ED5E               IM   2           
BDAF C9                 RET              
BDB0 ED56     STOP      IM   1           
BDB2 C9                 RET              

BDB3 F5       INT_BEGIN PUSH AF            ;Stack all registers except DE
BDB4 C5                 PUSH BC            ;(which is not used by this routine)
BDB5 E5                 PUSH HL          
BDB6 DDE5               PUSH IX          
BDB8 FDE5               PUSH IY          
BDBA FD213A5C           LD   IY,#5C3A      ;Restore IY to its normal value
BDBE CD1C5B             CALL RET           ;Get the current value of the program
BDC1 3B       INT_PC    DEC  SP            ;counter onto the stack
BDC2 3B                 DEC  SP          
BDC3 DDE1               POP  IX            ;IX= address of label INT_PC
BDC5 01E900             LD   BC,#00E9    
BDC8 DD09               ADD  IX,BC         ;IX points to label INT_EXIT
BDCA FDCB376E           BIT  5,(FLAGX)  
BDCE 2805               JR   Z,INT_EDIT    ;Jump unless INPUTting
BDD0 CD3800             CALL MASK_INT      ;Treat this interrupt as normal
                                           ;(Note: The call address may be
                                           ;changed to vector the interrupt
                                           ;handling elsewhere)
BDD3 DDE9               JP   (IX)          ;Now jump to exit routine
BDD5 FDCB0746 INT_EDIT  BIT  0,(MODE)  
BDD9 2808               JR   Z,INT_LCG     ;Jump unless in E-mode
BDDB DD7E0B             LD   A,(INT_MODE)  
BDDE 32415C             LD   (MODE),A      ;Restore mode to previous value
BDE1 1806               JR   INT_LCEG
BDE3 3A415C   INT_LCG   LD   A,(MODE)   
BDE6 DD770B             LD   (INT_MODE),A  ;Store mode for later retrieval
BDE9 3A085C   INT_LCEG  LD   A,(LAST_K)    ;A= last key accepted, possibly
                                           ;altered by this interrupt routine
BDEC DDE5               PUSH IX          
BDEE E1                 POP  HL          
BDEF 015400             LD   BC,#0054    
BDF2 09                 ADD  HL,BC         ;HL points to label INT_T2END
BDF3 060B               LD   B,#0B         ;Eleven key changes to consider
BDF5 2B       INTDECODE DEC  HL          
BDF6 BE                 CP   (HL)        
BDF7 2B                 DEC  HL          
BDF8 2001               JR   NZ,INT_DEC2   ;Jump unless last key was encoded
BDFA 7E                 LD   A,(HL)        ;A= original (decoded) key value
BDFB 10F8     INT_DEC2  DJNZ INTDECODE     ;Repeat for all eleven possibilities
BDFD 32085C             LD   (LAST_K),A    ;Store decoded value
BE00 DDE5               PUSH IX          
BE02 E1                 POP  HL          
BE03 010C00             LD   BC,#000C    
BE06 09                 ADD  HL,BC         ;HL points to label INTTABLE1
BE07 01FEFE             LD   BC,#FEFE    
BE0A ED78     INT_KSCAN IN   A,(C)         ;A= keyboard scan of next keyrow
BE0C A6                 AND  (HL)        
BE0D BE                 CP   (HL)        
BE0E 2075               JR   NZ,INTNORMAL  ;Jump unless all reqd. bits are set
                                           ;(ie. jump if any keys other than
                                           ;TRUE VIDEO, INV VIDEO, SYM SHIFT and
                                           ;the cursor keys are pressed)
BE10 23                 INC  HL          
BE11 CB00               RLC  B           
BE13 38F5               JR   C,INT_KSCAN   ;Repeat to test all lines
BE15 ED78               IN   A,(C)         ;A= keyscan from line zero
BE17 1F                 RRA              
BE18 386B               JR   C,INTNORMAL   ;Jump unless CAPSHIFT assumed active
BE1A 3EF7               LD   A,#F7       
BE1C DBFE               IN   A,(#FE)     
BE1E 17                 RLA              
BE1F E638               AND  #38         
BE21 4F                 LD   C,A           ;C= scan of TRUE/INV VIDEO and LEFT
BE22 3EEF               LD   A,#EF       
BE24 DBFE               IN   A,(#FE)     
BE26 1F                 RRA              
BE27 1F                 RRA              
BE28 E607               AND  #07         
BE2A B1                 OR   C             ;Include scan of UP, DOWN and RIGHT
BE2B 4F                 LD   C,A         
BE2C 3E7F               LD   A,#7F       
BE2E DBFE               IN   A,(#FE)     
BE30 1F                 RRA              
BE31 1F                 RRA              
BE32 3002               JR   NC,INT_SS
BE34 CBF1               SET  6,C           ;Also include scan of SYM SHIFT   
BE36 79       INT_SS    LD   A,C           ;A= scan of all required keys
BE37 01FF15             LD   BC,#15FF    
BE3A BE       INT_NEW   CP   (HL)        
BE3B 23                 INC  HL          
BE3C 2001               JR   NZ,INT_NEW2
BE3E 4E                 LD   C,(HL)        ;Collect key value or code from table
BE3F 23       INT_NEW2  INC  HL            
;[The next line was printed incorrectly as 10FB in the magazine.  JimG]
BE40 10F8               DJNZ INT_NEW       ;Repeat for all required tests
BE42 79                 LD   A,C           ;A will now contain either a new key
                                           ;value (as per the keypad),  or FD
                                           ;(conventional cursor keys), FE
                                           ;(TRUE VIDEO or INV VIDEO alone), 
                                           ;or FF (anything else)
BE43 FEFD               CP   #FD         
BE45 381B               JR   C,INT_EDKEY   ;Jump if a new editing key found
BE47 DD7E09             LD   A,(INT_COUNT)  
BE4A A7                 AND  A           
BE4B 2809               JR   Z,INTMODIFY   ;Jump if more than five frames have
                                           ;passed since last new key detected
BE4D DD3509             DEC  (INT_COUNT)    
BE50 2804               JR   Z,INTMODIFY   ;Jump if exactly five frames passed
BE52 DD360AFF           LD   (INT_KEY),#FF ;Cancel last new key
BE56 0C       INTMODIFY INC  C           
BE57 282C               JR   Z,INTNORMAL   ;If new key not detected then jump to
                                           ;deal with as normal
BE59 0C                 INC  C           
BE5A 2819               JR   Z,INT_INCFR   ;Jump with TRUE VID or INV VID alone
                                           ;(to ignore them)
BE5C FD360700           LD   (MODE),#00    ;If cursor key detected then signal
                                           ;L/C mode
BE60 1823               JR   INTNORMAL     ;And thence deal with as normal
BE62 DDBE0A   INT_EDKEY CP   (INT_KEY)    
BE65 DD770A             LD   (INT_KEY),A   ;Store new editing key in variable
BE68 DD360905           LD   (INT_COUNT),#05  ;Restore from count to five
BE6C 2807               JR   Z,INT_INCFR   ;Jump unless key has changed
BE6E 32085C             LD   (LAST_K),A    ;Store new key
BE71 FDCB01EE           SET  5,(FLAGS)     ;Signal "New key detected"
BE75 2A785C   INT_INCFR LD   HL,(FRAMES)  
BE78 23                 INC  HL          
BE79 22785C             LD   (FRAMES),HL   ;Increment FRAMES variable
BE7C 7C                 LD   A,H         
BE7D B5                 OR   L           
BE7E 202A               JR   NZ,INT_EXIT   
BE80 FD3440             INC  (FRAMES)hi
BE83 1825               JR   INT_EXIT
BE85 CD3800   INTNORMAL CALL MASK_INT      ;Now carry out normal interrupt
                                           ;functions (Note: The call address
                                           ;may be changed to vector the
                                           ;interrupt handling elsewhere)
BE88 DD7E0B             LD   A,(INT_MODE)  
BE8B 32415C             LD   (MODE),A      ;Restore the mode correctly
BE8E 3A085C             LD   A,(LAST_K)    ;A= key value of key just detected
                                           ;(if any)
BE91 FEA3               CP   #A3         
BE93 3815               JR   C,INT_EXIT    ;Jump if key value is OK
BE95 DDE5               PUSH IX          
BE97 E1                 POP  HL          
BE98 013E00             LD   BC,#003E    
BE9B 09                 ADD  HL,BC         ;HL points to label INTTABLE2
BE9C 01FF0B             LD   BC,#0BFF    
BE9F BE       INTENCODE CP   (HL)        
BEA0 23                 INC  HL          
BEA1 2001               JR   NZ,INT_ENC2
BEA3 4E                 LD   C,(HL)        ;C= encoded key value
BEA4 23       INT_ENC2  INC  HL          
BEA5 10F8               DJNZ INTENCODE     ;Repeat to encode all eleven allowed
                                           ;values
BEA7 FD71CE             LD   (LAST_K),C    ;Store encoded value as last key
BEAA FDE1     INT_EXIT  POP  IY          
BEAC DDE1               POP  IX          
BEAE E1                 POP  HL          
BEAF C1                 POP  BC          
BEB0 F1                 POP  AF          
BEB1 FB                 EI               
BEB2 C9                 RET              

BEB3 00       INT_COUNT DEFB #00
BEB4 FF       INT_KEY   DEFB #FF
BEB5 00       INT_MODE  DEFB #00

;The remainder of the routine consists of data, as follows:

INTTABLE1
BEB6 1E1F1F03031F1F1D
BEBE 77FE6FFE6DAD6BAC
BEC6 4FAF6EAE75A673A5
BECE 57A876A71F0C3EAA
BED6 0FB42EB317B136B0
BEDE 67A95FFD7EFD7DFD
BEE6 7BFD

INTTABLE2
BEE8 C65BC55DE27EC37C
BEF0 CD5CCC7BCB7DAC7F
BEF8 C78CC88FC989

INT_T2END
BEFE 00                 DEFB #00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[Letter from Toni Baker in ZX Computing, November 1986]

Keypad not required

In the June issue of ZX Computing there was a program ! wrote for a
machine code interrupt routine which put all of the new keys from the
not yet available plug-in keypad for the Spectrum 128 in sensible
positions on the Spectrum 128 keyboard.

An interrupt routine, however, is not necessary at all! All of the
keypad keys are already on the standard Spectrum 128 keyboard,
although in rather peculiar positions. The diagram accompanying this
letter [KEYPAD.GIF] shows exactly where these new keys are. All of the
symbols from the keypad are visible in the diagram, and by each symbol
is a coloured square containing a letter or number (or in one case
DELETE). The colours tell you which combination of shift key and
extend mode is required with the letter or number in question. For
instance, the symbol [two underlined down arrows] (which means CURSOR
DOWN TO END OF PROGRAM) is accompanied by the letter T in a green
square and the letter V in a black square. A glance at the key will
tell you that a green square means EXTEND MODE FOLLOWED BY; therefore,
pressing EXTEND MODE followed by T will move the cursor down to the
end of the program. Similarly, since a black square means GRAPHIC
MODE, it follows that pressing GRAPH followed by V (followed by GRAPH
again to exit graphic mode) will have the same effect.

If you wish to make use of the new editing keys, but can't be bothered
to load in and set up an interrupt routine program each time you
switch the machine on, just cut the diagram out of the magazine (or
re-do your own copy) and stick it somewhere near your Spectrum 128 so
that you can refer to it whenever your Speccy is in use.

Of course, perfectionists who don't like the idea of having editing
keys all over the place with strange combinations of shifts, would
probably prefer to use the interrupt program, since that locates all
of the new keys in sensible positions (on the cursor keys in
conjunction with TRU VID and INV VID) so you don't need a table to
remember everything.

Toni Baker
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
