How the KEYPAD editor (BASIC front-end) works

← Voltmace Delta 14B Driver

The KEYPAD editor (BASIC front-end)

This describes the BBC BASIC program in voltmace-delta-14b-driver-keypad.bas — the user-facing half of the Voltmace Delta 14B KEYPAD software. Line numbers below refer to that program.

What it is for

The Delta 14B handset has a 12-key keypad. On its own the BBC Micro cannot tell those keys apart, so this program lets you define what each keypad key sends and then installs a small machine-code resident driver that makes the keypad behave like a set of extra keyboard keys.

You interact with an on-screen picture of the keypad: press a key on the handset to select it, then press the key on the BBC keyboard whose character (or control code, function key, cursor key, …) that keypad key should produce. Two handsets can be defined independently. When you finish, the program writes your definitions into the resident driver, installs it at &0A00, and erases its own program text, leaving the resident driver in place. The resident driver then scans the keypad on every 50 Hz vertical-sync event and feeds your characters into the keyboard buffer.

The companion machine code — the resident driver the editor configures and installs — is covered by the disassembly in voltmace-delta-14b-driver-keypad.asm.

Shape of the program

Lines Role
10–170 Startup, protection clean-up, OS check, intro screens
180–280 Main loop and error handling
290–410 PROCINIT — initialise hardware and read the configuration tables
420–510 Drawing the on-screen keypad
520–740 The interactive editor (select a key, assign a character)
750–840 PROCREADKP — scan the physical keypad matrix
850–1070 Screen furniture: headers, instructions, the intro slideshow
1080–1210 PROCMENU — the Sound / Auto / Edit / Finish options
1220–1340 PROCFIN — build, patch, and install the resident driver
1350–1370 Finish: wipe the editor and leave the resident driver running

Startup and protection (10–170)

Line 10 is a REM that only exists because of the load-time protection: its length byte is stored as zero in the file and repaired to &16 by the loader before the program can run.

Line 30 selects MODE 7, clears the status flags (Z%, E1%, E2%), and sets the error handler to line 220. Z% selects between the protected behaviour (Z%=0, which self-erases) and an unprotected/developer mode (Z%=1, which stops with the editor listable). Z% is a resident integer — BBC BASIC keeps @% and A%Z% at fixed page-&4 addresses (Z% at &468), so unlike ordinary variables it survives RUN and could in principle be preset by machine code. Here it isn't: line 30 sets it to 0, nothing assigns it again, and neither the loader nor the resident driver touches page &4. So Z% is 0 throughout, the Z%=1 branches are never taken, and the program always runs protected.

Line 60, when Z%=0, reprograms the BREAK key. A BBC Micro has no f10 key; soft key 10 (*KEY10) is the "break string" that a soft (single) BREAK types into the input as part of reset. Line 60 sets that string to a self-destruct — CLS, then a loop zeroing &C00&3A80, the region holding the just-relocated BASIC program. It only arms the trap (hence the "DO NOT PRESS BREAK" warning later); it does not run the wipe now, which would erase the running editor.

Lines 70–120 guard against an incompatible operating system: ?&E8AA is read as an OS signature (the expected value is &4F); on a mismatch the program displays "KEYPAD DRIVER WILL NOT WORK WITH OPERATING SYSTEM OS 0.1" (line 90) and stops. Line 130 issues *FX200,2 — OSBYTE 200 bit 1, "clear user memory on the next BREAK" — so a BREAK now wipes the program to the power-on state. It sets only bit 1, so ESCAPE (bit 0) stays enabled: the two exits are deliberately different, and the warnings say so — BREAK destroys the program, while ESCAPE raises the normal escape error (17), which the ONERROR handler catches to restart. Line 150 dimensions the arrays, and line 170 shows the intro (PROCINTRO) before switching to MODE 1 for the editor.

Main loop (180–280)

Line 180 draws the header (PROCH1), the instructions (PROCINS), and runs the editor (PROCEDIT). Line 190 then shows the options menu (PROCMENU), which returns a choice in Q$:

Lines 220–280 are the error handlers, including the "SYSTEM ERROR" report (line 250) and the ESCAPE-driven restart (error 17).

Initialisation and the configuration tables (290–410)

PROCINIT (line 290) enables the cursor-key/*FX4 mode, then (line 300) sets the User VIA data-direction register ?&FE62=&F0 (top nibble outputs for the column strobes and handset select, bottom nibble inputs for the rows) and clears the working variables.

The DATA statements are read straight into the editor's arrays:

Drawing the keypad (420–510)

PROCKEYPAD (line 420) draws all 15 keys and the copyright line. PROCBKKEY (430) draws a key in its unselected colour, PROCWTKEY (440) draws the currently selected key highlighted and shows its assigned character. The workhorse is PROCkey (450–500): it positions itself from KPOS%(), prints the label from KCHR$(N%,KP%), and special-cases key 13, which shows REAR or SIDE (the handset's two fire buttons) rather than a character.

The interactive editor (520–740)

PROCEDIT (line 520) is the core loop:

  1. Draw the keypad and take the current selection N%=CURKEY% (530).
  2. Highlight it (PROCWTKEY, 540) and scan the physical keypad (PROCREADKP, 550).
  3. If a different keypad key is now pressed (line 560), move the highlight to it and beep.
  4. Read a BBC keyboard key with K%=INKEY(5) (570). Lines 580–590 handle the flashing highlight and the CTRL Q (K%=17) exit.
  5. CTRL A (K%=1, lines 600–610) toggles between the two handsets (KP%) and redraws.
  6. Otherwise (line 620) PROCCONV turns the pressed key into a display string, PROCYEL stores it, PROCSND beeps, and the loop repeats.

Supporting routines:

Scanning the physical keypad (750–840)

PROCREADKP reads the handset matrix directly through User VIA port B (&FE60), exactly as the resident driver does. Line 750 selects the handset by writing KP%*&80 (bit 7 drives the 74LS157 multiplexer) and checks for "no key". The nested loops (780–830) strobe each column (?&FE60=COL%(X%)+&80*KP%) and test each row (?&FE60 AND ROW%(Y%)); a pressed cell yields CURKEY%=3*CURROW%+CURCOL%.

Screens and presentation (850–1070)

These procedures build the MODE-1/MODE-7 screens: PROCH1/PROCHEAD/PROCBIG (double-height banners), PROCA1/PROCA2 (text windows), PROCWARN (the "DO NOT PRESS BREAK" line), PROCINS (the how-to-use instructions, 890–900), and PROCINTRO (910–1010), the copyright-and-explanation slideshow shown at startup. PROCCONT (1050–1070) is the "PRESS SPACE-BAR TO CONTINUE" pause. The intro text explains that the resident driver installs at &A00–&AFF and runs under EVENT 4 (vertical sync), which the resident driver enables itself (lines 950–960).

The options menu (1080–1210)

PROCMENU offers four choices keyed S / A / E / F: Sound (beep on keypad press, toggled by B%, PROCONOFF), Auto repeat (A%, PROCAUTO), re-Edit, and Finish. Lines 1130–1180 read the choice into Q$ and return it to the main loop.

Building and installing the resident driver (1220–1340)

PROCFIN turns the on-screen definitions into a working resident driver:

Finishing (1350–1370)

Reached on finish whenever Z%=0 — which is always, in the shipped program. Line 1350 wipes the BASIC program (FOR N%=PAGE TO PAGE+&1C00 STEP4:!N%=0), leaves an empty program (!PAGE=&FF0D), and redefines the BREAK key from its self-destruct to *KEY10 CALL&A00 — so a subsequent soft BREAK now re-installs the driver instead of wiping — then prints "KEYPAD OPERATIONAL". Line 1360 restores *FX200,0 (memory preserved across BREAK) on OS versions whose signature isn't &4F; line 1370 resets PAGE and ENDs, leaving only the now-configured resident driver in memory.