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 |