UN TASTIERINO NUMERICO PER IL C-64

A NUMERIC KEYPAD FOR THE C-64

 

Dopo aver visto un articolo su una rivista del settore che spiegava come interfacciare un tastierino numerico (simile a quello di un telefono con 12 tasti) ad un PET Commodore tramite la User Port, mi venne l'idea di fare altrettanto con il mio Commodore 64: nacque così il mio primo (ed anche unico) progetto hardware per questa macchina. In realtà il progetto non era solo hardware, ma anche software perché bisognava realizzare una routine ovviamente in linguaggio macchina 6510, che ne permettesse il funzionamento e non interferisse con le normali operazioni della tastiera.

Il software, come specificato anche nell'articolo, dipendeva dal tipo di tastierino che si andava ad interfacciare, così tramite un mio amico che aveva (ed ha ancora) un'attività commerciale nel campo dei sistemi di pesatura mi procurai un tastierino (a matrice con righe e colonne) a 16 tasti di quelli usati nei primi registratori di cassa e feci fare le relative saldature ad un connettore femmina adatto alla User Port. Una cosa interessante fu il fatto che, a parte i tasti numerici da 0 a 9, gli altri 6 erano "liberi" nel senso che avevano un cappuccio trasparente removibile sotto il quale poteva essere messa una scritta che indicava la corrispondenza con il tasto: così quattro furono assegnati ai simboli  +    -     ●  e RETURN e gli altri due a KEY1 e KEY2 cosicché modificando con una istruzione POKE due locazioni opportune di memoria li si poteva programmare con il codice ASCII del carattere desiderato.

Il risultato finale, dopo averlo messo in un contenitore artigianale, è visibile nella foto a sinistra. Si possono vedere in basso i due tasti programmabili  KEY1 e KEY2 . La matrice dei tasti è composta da 4 righe e da 4 colonne, quindi vengono usati 8 fili che andranno a corrispondere ai piedini PB0 ... PB7 della User Port.

La programmazione si basa sul fatto che è possibile definire i vari piedini PB come ingressi o come uscite (tramite la locazione di memoria 56579 - $DD03) e che la pressione di un tasto attiva un segnale di riga e uno di colonna: così interrogando la locazione 56577 ($DD01) si può sapere con una serie di test quale tasto è stato premuto ed inviare così il relativo codice ASCII al buffer di tastiera del C-64. Per poter interrogare il dispositivo è poi necessario modificare la routine di interrupt che ogni sessantesimo di secondo interroga la tastiera. Nel nostro caso abbiamo definito PB0-PB3 come uscite (righe) e PB4-PB7 come ingressi (colonne) in questo modo:

R1 → 7,8,9,+           R2 →  4,5,6,-        R3 → 1,2,3,.            R4 →  0,KEY2,KEY1,RETURN

C1 → 8,5,2,KEY2    C2 → 7,4,1,0        C3 → 9,6,3,KEY1    C4 → +,-,.,RETURN

la corrispondenza con la User Port è la seguente:

  0   1    2   3 |   4    5   6   7
R4 R1 R2 R3 | C2 C1 C4 C3

Il programma in Macro Assembler, opportunamente commentato, è il seguente:
 

; gestione pad numerico con user Port
org    $c000
IOR    equ $dd01
LASTK  equ $0334
NUMCAR equ $c6
SETINT sei
       lda #$12   ; nuovo indirizzo di
       sta $0314  ; interrupt a $c012
       lda #$c0   ; (49170)
       sta $0315
       lda #$0f   ; setta la User Port
       sta IOR+2  ; con 4 ingressi e 4
                  ; uscite: PB0-PB3 sono
                  ; uscite, PB4-PB7 sono
                  ; ingressi
       cli
       rts
RIGA3  lda #$0e   ; gestione riga#3
       sta IOR
       lda IOR
       cmp #$fe   ; se IOR=254 salta a
       beq RIGA2  ; gestire la riga #2
CASO1  cmp #$de   ; premuto 1 ?
       bne CASO2  ; no, vai a testare 2
       lda #$31   ; si, ASCII di 1 (49)
       jmp METBUF
CASO2  cmp #$ee   ; premuto 2 ?
       bne CASO3  ; no, vai a testare 3
       lda #$32   ; si, ASCII di 2 (50)
       jmp METBUF
CASO3  cmp #$be   ; premuto 3 ?
       bne CASOP  ; no, vai a testare .
       lda #$33   ; si, ASCII di 3 (51)
       jmp METBUF
CASOP  cmp #$7e   ; premuto . ?
       bne FITTIZ ; no, nessun tasto
       lda #$2e   ; si, ASCII di . (46)
       jmp METBUF
FITTIZ jmp IRQ1   ; label fittizia
                  ; branch > 128
RIGA2  lda #$0d   ; gestione riga #2
       sta IOR
       lda IOR
       cmp #$fd   ; se IOR=253 salta a
       beq RIGA1  ; gestire la riga #1
CASO4  cmp #$dd   ; premuto 4 ?
       bne CASO5  ; no, vai a testare 5
       lda #$34   ; si, ASCII di 4 (52)
       jmp METBUF
CASO5  cmp #$ed   ; premuto 5 ?
       bne CASO6  ; no, vai a testare 6
       lda #$35   ; si, ASCII di 5 (53)
       jmp METBUF
CASO6  cmp #$bd   ; premuto 6 ?
       bne CASOM  ; no, vai a testare -
       lda #$36   ; si, ASCII di 6 (54)
       jmp METBUF
CASOM  cmp #$7d   ; premuto - ?
       bne IRQ1   ; no, nessun tasto
       lda #$2d   ; si, ASCII di - (45)
       jmp METBUF
RIGA1  lda #$0b   ; gestione riga#1
       sta IOR
       lda IOR
       cmp #$fb   ; se IOR=251 salta a
       beq RIGA4  ; gestire la riga #4
CASO7  cmp #$db   ; premuto 7 ?
       bne CAS08  ; no, vai a testare 8
       lda #$37   ; si, ASCII di 7 (55)
       jmp METBUF
CASO8  cmp #$eb   ; premuto 8 ?
       bne CAS09  ; no, vai a testare 9
       lda #$38   ; si, ASCII di 8 (56)
       jmp METBUF
CASO9  cmp #$bb   ; premuto 9 ?
       bne CASOQ  ; no, vai a testare +
       lda #$39   ; si, ASCII di 9 (57)
       jmp METBUF
CASOQ  cmp #$7b   ; premuto + ?
       bne IRQ1   ; no, nessun tasto
       lda #$2b   ; si, ASCII di + (43)
       jmp METBUF
RIGA4  lda #$07   ; gestione riga #4
       sta IOR
       lda IOR
       cmp #$f7   ; se IOR=247 salta
       bne IRQ1   ; all'usuale IRQ1
CASO0  cmp #$e7   ; premuto 0 ?
       bne CASOCR ; no,vai a testare CR
       lda #$30   ; si, ASCII di 0 (48)
       jmp METBUF
CASOCR cmp #$77   ; premuto CR ?
       bne CASOF1 ; no, vai a testare F1
       lda #$0d   ; si, ASCII di CR (13)
       jmp METBUF
CASOF1 cmp #$d7   ; premuto F1 ?
       bne CASOF2 ; no, vai a testare F2
       lda #$00   ; si, ASCII indefinito
       jmp METBUF
CASOF2 cmp #$b7   ; premuto F2 ?
       bne IRQ1   ; no, nessun tasto
       lda #$00   ; si, ASCII indefinito
METBUF cmp LASTK  ; tasto uguale prece-
                  ; dente ?
       beq IRQ    ; si, salta all'IRQ
       tay        ; memorizza il ca-
                  ; rattere ricevuto
       lda NUMCAR
       cmp #$0a   ; NUMCAR > 10 ?
       bpl IRQ    ; si, vai all'IRQ
       inc NUMCAR ; no, aumentalo di 1
       ldx NUMCAR
       tya        ; metti nel buffer il
       sta $0276,x; carattere ricevuto
       jmp MEMKEY
IRQ1   lda #$01   ; nessun tasto
MEMKEY sta $0334  ; memorizza il codice
                  ; del tasto premuto
IRQ    jmp $ea31  ; salta a gestire il
                  ; normale interrupt