Reading Touch Pad
Moderator: Moderators
Reading Touch Pad
I've resurrected a project that would use the Atari 2600's keypad controller. I found great pin out info at this site.
As compared to the Joystick pinout:
Pin Description
1 Up
2 Down
3 Left
4 Right
5 NC
6 Fire
7 NC
8 Ground
9 NC
Here's the Kids Controller (Touch Pad)
Pin #
# 5 9 6
1 1 2 3
2 4 5 6
3 7 8 9
4 * 0 #
7 +5v pulls pins 5 & 9 through 4.7k resistors
My table isn't aligned, but the idea is: pressing 3 on the keypad would be the same as holding the fire button and UP on a joystick simultaneously.
It uses the Paddle control pins too. When I do a straight read of locations 37151, 37152, 36872, 36873, I get a lot of "flickering" results (similar to paddle reads). Should I change the value of 37154 as if I am reading the joystick? I wanted to see if anyone has ideas. I'm still testing.
As compared to the Joystick pinout:
Pin Description
1 Up
2 Down
3 Left
4 Right
5 NC
6 Fire
7 NC
8 Ground
9 NC
Here's the Kids Controller (Touch Pad)
Pin #
# 5 9 6
1 1 2 3
2 4 5 6
3 7 8 9
4 * 0 #
7 +5v pulls pins 5 & 9 through 4.7k resistors
My table isn't aligned, but the idea is: pressing 3 on the keypad would be the same as holding the fire button and UP on a joystick simultaneously.
It uses the Paddle control pins too. When I do a straight read of locations 37151, 37152, 36872, 36873, I get a lot of "flickering" results (similar to paddle reads). Should I change the value of 37154 as if I am reading the joystick? I wanted to see if anyone has ideas. I'm still testing.
Here's this if it helps. I can't remember where I found it. It was a magazine article in RUN or something.
I think the key pad needs to be scanned like the keyboard.
Code: Select all
200 print"S... loading interface"
210 tm%=peek(51)+256*peek(52)-160:nh%=tm%/256:nl%=tm%-nh%*
256
220 poke51,nl%:poke55,nl%:poke52,nh%:poke56,nh%:clr
230 tm%=peek(51)+256*peek(52)
240 fori=0to159
250 readn%
260 ifn%=-1thenn%=peek(51)
270 ifn%=-2thenn%=peek(52)
280 poketm%+i,n%
290 next
300 systm%+143
320 end
330 data 240,12
350 rem place values for cntroller keys here...
390 data 55:rem s1=7
400 data 56:rem s2=8
410 data 57:rem s3=9
420 data 52:rem s4=4
430 data 53:rem s5=5
440 data 54:rem s6=6
450 data 49:rem s7=1
460 data 50:rem s8=2
470 data 51:rem s9=3
480 data 46:rem s10=,
490 data 48:rem s11=0
500 data 13:rem s12=cr
520 data160,1,169,195,45,17,145,141,17,145,169,127,141,32,145,141,34
,145
530 data173,19,145,41,195,133,254,162,3,169,2,133,203,6,203,165
540 data203,5,254,141,19,145,152,160,0,136,208,253,168,169,128,205
550 data9,144,144,32,200,205,8,144,144,26,200,173,17,145,41,32
560 data240,18,200,202,48,51,208,213,165,254,141,19,145,169,128,141
570 data34,145,208,210,196,251,240,20,132,251,200,173,20,3,133,245
580 data173,21,3,133,246,177,245,240,3,32,201,235,169,247,141,32
590 data145,169,255,141,34,145,76,191,234,169,255,133,251,208,237
,120
600 data169,-1,141,20,3,169,-2,141,21,3,169,255,133,251,88,96
Rob
Try this ..
Lee.
Code: Select all
; touch pad controller code for VIC 20
;
; the controller is a matrix of switches and is connected to the VIC 20 as follows ..
;
; joy 0 --> 1 2 3
; joy 1 --> 4 5 6
; joy 2 --> 7 8 9
; joy 3 --> * 0 #
; | | |
; pot y <---+ | |
; pot x <-----+ |
; fire <-------+
;
; The code works by sequentially making joy 0 to 3 output zero and reading pot y, pot x
; and fire
LAB_CB = $CB ; current row drive
LAB_F5 = $F5 ; keyboard matrix lookup table pointer low byte
LAB_F6 = $F6 ; keyboard matrix lookup table pointer high byte
LAB_FB = $FB ; last key number, $FF if no key pressed
LAB_FE = $FE ; temporary port direction mask
LAB_0314 = $0314 ; IRQ vector low byte
LAB_0315 = $0315 ; IRQ vector high byte
LAB_9008 = $9008 ; pot x
LAB_9009 = $9009 ; pot y
LAB_9111 = $9111 ; VIA 1 DRA
; bit function
; --- --------
; 7 serial ATN out
; 6 cassette switch
; 5 LP FIRE
; 4 joy 2 LEFT
; 3 joy 1 DOWN
; 2 joy 0 UP
; 1 serial DATA in
; 0 serial CLK in
LAB_9113 = $9113 ; VIA 1 DDRA
LAB_9120 = $9120 ; VIA 2 DRB, keyboard column drive
; bit function
; --- --------
; 7 joy 3 RIGHT
; 6-0 keyboard column drive
LAB_9122 = $9122 ; VIA 2 DDRB
LAB_EABF = $EABF ; VIC IRQ handler
LAB_EBC9 = $EBC9 ; save the key in A to the keyboard buffer
; this code is loaded by the BASIC program to the 160 bytes at the top of memory. In this
; case the code has been assembled for an unexpanded VIC but it will work, with only two
; bytes changed in the setup routine, at other addresses.
.ORG $1D60
; our IRQ routine for the touchpad
LAB_1D60
BEQ LAB_1D6E ; go do the code, branch always
; controller key definitions
;LAB_1D62
.byte '7' ; S1 = 7
.byte '8' ; S2 = 8
.byte '9' ; S3 = 9
.byte '4' ; S4 = 4
.byte '5' ; S5 = 5
.byte '6' ; S6 = 6
.byte '1' ; S7 = 1
.byte '2' ; S8 = 2
.byte '3' ; S9 = 3
.byte ',' ; S10 = ,
.byte '0' ; S11 = 0
.byte $0D ; S12 = [CR]
; touchpad IRQ code continues
LAB_1D6E
LDY #$01 ; set key 1
LDA #$C3 ; set mask xx00 00xx, fire button and joy pins
AND LAB_9111 ; mask VIA 1 DRA, clear the fire button and joy pins
STA LAB_9111 ; save VIA 1 DRA
LDA #$7F ; set joy3 bit to input, others to output
STA LAB_9120 ; save VIA 2 DRB, joy 3 to zero
STA LAB_9122 ; set VIA 2 DDRB, joy 3 to input
LDA LAB_9113 ; read VIA 1 DDRA
AND #$C3 ; AND with mask xx00 00xx, fire button and joy pins to
; inputs
STA LAB_FE ; save the port direction mask
LDX #$03 ; set the row count
LDA #$02 ; set the row drive to the first row - 1
STA LAB_CB ; save the row drive
LAB_1D8D
ASL LAB_CB ; shift the row drive left
LDA LAB_CB ; get the row drive
ORA LAB_FE ; OR in the port direction mask
STA LAB_9113 ; save VIA 1 DDRA, set just one of the joy pins to output
LAB_1D96
TYA ; save Y
; wait for a bit
LDY #$00 ; set for 256 loop delay
LAB_1D99
DEY ; decrement delay count
BNE LAB_1D99 ; loop if more to do
TAY ; restore Y
LDA #$80 ; set a half way value
CMP LAB_9009 ; compare the half way value with the pot y value
BCC LAB_1DC4 ; if the input is low go process it
INY ; increment the key number
CMP LAB_9008 ; compare the half way value with the pot x value
BCC LAB_1DC4 ; if the input is low go process it
INY ; increment the key number
LDA LAB_9111 ; read VIA 1 DRA
AND #$20 ; mask 00x0 0000, the fire button
BEQ LAB_1DC4 ; if the input is low go process it
INY ; increment the key number
DEX ; decrement the row count
BMI LAB_1DE9 ; if the count is negative no keys have been pressed so
; clear the last key pressed, tidy up and exit
BNE LAB_1D8D ; loop if not all of joy 0 to 2 done ..
; joy 0 to 2 done, now do joy 3
LDA LAB_FE ; get the port direction mask
STA LAB_9113 ; save VIA 1 DDRA, joy 0 to 2 and fire to inputs
LDA #$80 ; set joy 3 to output, data bit already set to 0
STA LAB_9122 ; save VIA 2 DDRB
BNE LAB_1D96 ; go scan the last row, branch always
; a column is low
LAB_1DC4
CPY LAB_FB ; compare the key number with the previous key number
BEQ LAB_1DDC ; if the same just restore the keyboard ports and exit
STY LAB_FB ; else save this key number as the last key number
INY ; increment the key number for the table index
LDA LAB_0314 ; get the start of out code pointer low byte
STA LAB_F5 ; save the keyboard pointer low byte
LDA LAB_0315 ; get the start of out code pointer high byte
STA LAB_F6 ; save the keyboard pointer high byte
LDA (LAB_F5),Y ; get the ASCII key code
BEQ LAB_1DDC ; if null skip the key save
JSR LAB_EBC9 ; save the key in A to the keyboard buffer
LAB_1DDC
LDA #$F7 ; set keyboard column c3 for [RUN/STOP]
STA LAB_9120 ; save VIA 2 DRB, keyboard column drive
LDA #$FF ; set all outputs
STA LAB_9122 ; save VIA 2 DDRB
JMP LAB_EABF ; go do the normal VIC IRQ handler
LAB_1DE9
LDA #$FF ; set A
STA LAB_FB ; clear the last key number
BNE LAB_1DDC ; restore the keyboard ports and go do the normal IRQ
; routine, branch always
; setup the interrupt, called using SYS tm% + 143
LAB_1DEF
SEI ; disable interrupts
LDA #>LAB_1D60 ; set our code start low byte
STA LAB_0314 ; save the IRQ vector low byte
LDA #<LAB_1D60 ; set our code start high byte
STA LAB_0315 ; save the IRQ vector high byte
LDA #$FF ; set A
STA LAB_FB ; clear the last key number
CLI ; enable interrupts
RTS
;; changing the above code as follows would make it able to be run from any address
;; without needing changes as the end of memory pointer contains the address needed
;
;; setup the interrupt, called using SYS tm% + 143
;
;LAB_37 = $37 ; end of memory low byte
;LAB_38 = $38 ; end of memory high byte
;
;LAB_1DEF
; SEI ; disable interrupts
; LDA LAB_37 ; get the end of memory low byte
; STA LAB_0314 ; save the IRQ vector low byte
; LDA LAB_38 ; get the end of memory high byte
; STA LAB_0315 ; save the IRQ vector high byte
; LDA #$FF ; set A
; STA LAB_FB ; clear the last key number
; CLI ; enable interrupts
; RTS
.END
@Leeeeee
Nice program!
Slight change though, this:
should be:
< = low byte
> = hi byte
Nice program!
Slight change though, this:
Code: Select all
LAB_1DEF
SEI ; disable interrupts
LDA #>LAB_1D60 ; set our code start low byte
STA LAB_0314 ; save the IRQ vector low byte
LDA #<LAB_1D60 ; set our code start high byte
STA LAB_0315 ; save the IRQ vector high byte
LDA #$FF ; set A
STA LAB_FB ; clear the last key number
CLI ; enable interrupts
RTS
Code: Select all
LAB_1DEF
SEI ; disable interrupts
LDA #<LAB_1D60 ; set our code start low byte
STA LAB_0314 ; save the IRQ vector low byte
LDA #>LAB_1D60 ; set our code start high byte
STA LAB_0315 ; save the IRQ vector high byte
LDA #$FF ; set A
STA LAB_FB ; clear the last key number
CLI ; enable interrupts
RTS
> = hi byte
Jeff, Your Basic programming skills are awesome - mabey it is time to 'Dip your toe' in the waters of ML. It's not that scary, just take your time and absorb everything before moving on. Usborne's Machine Code for Beginners (pdf is available at worldofspectrum) is a great place to start. It has simple examples that are designed so a programmer aged 12 can understand. Even if you don't end up writing any ML code, it's good to be able to de-cypher other programmers work to learn new tricks and techniquesJeff-20 wrote:Help! Can someone turn this Machine Code into BASIC, so that I can understand it?????
Android Tablet running Frodo 64 emulator running VIC 20 emulator....
- Mike
- Herr VC
- Posts: 4901
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
The ML routine runs in the interrupt, and accesses the same VIA ports which are also used to scan the normal keyboard.
Even if you do a 1:1 translation of the machine code to BASIC, it can't be run as an interrupt routine, only in the "foreground" (i.e. within the main program). Furthermore, exactly the keyscan routine in the IRQ will disturb a BASIC translation of the touch pad decode routine, as both access the same VIA registers, unless you disable interrupts - and then neither jiffy clock nor keyboard will work anymore.
Isn't it acceptable for you to use a working solution, just because it isn't written in BASIC?
Finally, as for an explanation of how it works, Lee did it in the last line of the introductory comments of the ML source code:
Even if you do a 1:1 translation of the machine code to BASIC, it can't be run as an interrupt routine, only in the "foreground" (i.e. within the main program). Furthermore, exactly the keyscan routine in the IRQ will disturb a BASIC translation of the touch pad decode routine, as both access the same VIA registers, unless you disable interrupts - and then neither jiffy clock nor keyboard will work anymore.
Isn't it acceptable for you to use a working solution, just because it isn't written in BASIC?
Finally, as for an explanation of how it works, Lee did it in the last line of the introductory comments of the ML source code:
Code: Select all
; touch pad controller code for VIC 20
;
; the controller is a matrix of switches and is connected to the VIC 20 as follows ..
;
; joy 0 --> 1 2 3
; joy 1 --> 4 5 6
; joy 2 --> 7 8 9
; joy 3 --> * 0 #
; | | |
; pot y <---+ | |
; pot x <-----+ |
; fire <-------+
Leeeeee wrote:The code works by sequentially making joy 0 to 3 output zero and reading pot y, pot x and fire
Now I see! This can't really be done in BASIC alone. Thanks for explaining. I would have to SYS a routine. I was running the BASIC code above, and nothing was happening. How would I get the input information from this routine to use in a BASIC program? To put it simple, I'm not sure how to interface.