Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Paddle Read Timing

146 views
Skip to first unread message

Oliver Schmidt

unread,
Jun 4, 2020, 3:17:32 PM6/4/20
to
Hi,

I need to read the two axis of a joystick for the "usual" case of generating digital left/right/up/down values. I learned that calling PDL($FB1E) two times in a row is a bad idea as the second readout may be influenced by the first readout.

As I on the other hand by no means need the 255 values resolution it seemed the "natural" approach to me to not call PDL at all but to read both axis at the same time with my own read function. It generally works as expected - so far so good.

Many times when reading about Apple II accelerators it was mentioned that they slow down to the stock Apple II speed for a certain amount of time/cycles on access to $C070. Therefore I thought I don't need to take special care of faster CPUs but can just always use my read function as-is.

However, now I tested my read function on a IIgs and it doesn't work as expected when the IIgs is set to fast speed. So my questions are:

1. Am I in general correct at all to presume that accelerators temporarily throttle for some time/cycles on $C070 access?

2. Is my conclusion correct that the IIgs does not slow down on $C070 access? I now presume it has a patched PDL function taking the system speed into account.

3. In case I'm correct in that I need to take the IIgs in fast speed into account. Is there a reason to favor one of the two approaches I imagine: a) Use different threshold values when I detect fast speed vs. b) slow down during paddle read.

4. Are there other (popular) setups I need to take into account? I'm of course especially thinking about the other faster Apple II coming from Apple - the //c Plus.

5. Given the ugliness of having to deal with different CPU speeds: Is there a nice way to use PDL to read two axis?

As always thanks for hints,
Oliver

John Brooks

unread,
Jun 5, 2020, 12:22:07 AM6/5/20
to

John Brooks

unread,
Jun 5, 2020, 12:33:17 AM6/5/20
to
In case I haven't posted this previously, here is a 6502 1MHz dual-paddle read routine:


1 *-------------------------------
2 * 6502 single-pass GetJoyXY
3 *
4 * 10/21/2018 by John Brooks
5 *-------------------------------
7
8 org $300
9
10 TestJoy
0300: 20 58 FC 11 jsr $fc58
12 :Loop
0303: A9 00 13 lda #0
0305: 85 24 14 sta $24
0307: 20 1A 03 15 jsr GetJoyXY
030A: 8A 16 txa
030B: 20 DA FD 17 jsr $fdda
030E: A9 AC 18 lda #","
0310: 20 ED FD 19 jsr $fded
0313: 98 20 tya
0314: 20 DA FD 21 jsr $fdda
0317: 4C 03 03 22 jmp :Loop
23
24 *-------------------------------
25 * Read JoyX,Y every 11cyc on avg
26 * Returns: X=JoyX, Y=JoyY
27 GetJoyXY
031A: 08 28 php ;Save interrupt enable
031B: 78 29 sei ;Disable interrupts
30
031C: 2C 70 C0 31 bit $C070 ;Start X,Y timers. 11c to 1st read
031F: A2 01 33 ldx #1 ;2: DualCtr=0+1=1. Wraps to 0 at 3*85=255 XY reads2 ,0002
0321: A0 7F 34 ldy #$7F ;2 2 ,0004
0323: 24 00 35 bit 0 ;3: wait 3 ,0007
36 :DualXY0 ;Inc X,Y 3x in 33 cycles (1st read counts twice)
0325: CC 64 C0 37 cpy $C064 ;4: Chk JoyX. 16c to DualXY14 ,0011
0328: 2C 65 C0 39 bit $C065 ;4: Chk JoyY 4 ,0004
032B: B0 2D 40 bcs :ToSoloY ;2/3 2',0006
032D: 10 1D 41 bpl :ToSoloX ;2/3 2',0008
032F: E8 42 inx ;2: Inc XY 2 ,0010
0330: E8 43 inx ;2 2 ,0012
44 :DualXY1
0331: CC 64 C0 45 cpy $C064 ;4: Chk JoyX. 17c to DualXY04 ,0016
0334: 2C 65 C0 47 bit $C065 ;4: Chk JoyY 4 ,0004
0337: B0 21 48 bcs :ToSoloY ;2/3 2',0006
0339: 10 11 49 bpl :ToSoloX ;2/3 2',0008
033B: E8 50 inx ;2: Inc XY 2 ,0010
033C: D0 E7 51 bne :DualXY0 ;2/3 2',0012
52
53 :DualXY2 ;256th read
033E: AD 64 C0 54 lda $C064 ;3: Chk JoyX 4 ,0016
0341: 2D 65 C0 55 and $C065 ;3: Chk JoyY 4 ,0020
0344: 30 01 56 bmi :SameXY ;3 2',0022
0346: CA 57 dex ;#$FE 2 ,0024
58 :SameXY 0347: CA 59 dex ;#$FF 2 ,0026
0348: 8A 60 txa 2 ,0028
0349: A8 61 tay 2 ,0030
034A: 28 62 plp 4 ,0034
034B: 60 63 rts 6 ,0040
64
65 :ToSoloX
034C: 8A 66 txa ;2 2 ,0042
034D: A8 67 tay ;2: Y = JoyY + 1 2 ,0044
68 :SoloX ;Read every 11 cycles
034E: 2C 64 C0 69 bit $C064 ;4: Chk JoyX 4 ,0048
0351: 10 04 70 bpl :SoloXDone ;2/3 2',0050
0353: E8 71 inx ;2 2 ,0052
0354: D0 F8 72 bne :SoloX ;2/3 2',0054
0356: CA 73 dex ;Clamp to 255 2 ,0056
74 :SoloXDone
0357: 88 75 dey ;2: Correct Dual ctr starting at 12 ,0058
0358: 28 76 plp 4 ,0062
0359: 60 77 rts 6 ,0068
78
79 :ToSoloY
035A: 10 EB 80 bpl :SameXY ;2/3 2',0070
035C: 8A 81 txa ;2: X = JoyX + 1 2 ,0072
035D: A8 82 tay ;2 2 ,0074
83 :SoloY ;Read every 11 cycles
035E: 2C 65 C0 84 bit $C065 ;4: Chk JoyY 4 ,0078
0361: 10 04 85 bpl :SoloYDone ;2/3 2',0080
0363: C8 86 iny ;2 2 ,0082
0364: D0 F8 87 bne :SoloY ;2/3 2',0084
0366: 88 88 dey ;Clamp to 255 2 ,0086
89 :SoloYDone
0367: CA 90 dex ;2: Correct Dual ctr starting at 12 ,0088
0368: 28 91 plp 4 ,0092
0369: 60 92 rts 6 ,0098
93


--End assembly, 106 bytes, Errors: 0

Oliver Schmidt

unread,
Jun 5, 2020, 2:26:21 AM6/5/20
to
Hi John,
Thanks for the valuable hint :-)

Regards,
Oliver

Oliver Schmidt

unread,
Jun 5, 2020, 3:26:36 AM6/5/20
to

Hi John,

> In case I haven't posted this previously, here is a 6502 1MHz dual-paddle read routine: [...]

Thanks for sharing!

For the sake of completeness here's my routine. It's simple, short, doesn't care for high resolution. It always takes the same amount of time, no matter how the paddles are positioned.
- Call with joystick number (0 or 1) in A.
- Results are stored in value0 and value1.
- UPPER_THRESHOLD is the paddle value you want to consider as "right enough" / "down enough".


; Read both paddles simultaneously
asl ; Joystick number -> paddle number
tax
ldy #$00
sty value0
sty value1
lda PTRIG ; Trigger paddles
loop: lda PADDL0,x ; Read paddle (0 or 2)
bmi set0 ; Cycles: 2 3
nop ; Cycles: 2
bpl nop0 ; Cycles: 3
set0: sty value0 ; Cycles: 4
nop0: ; - -
; Cycles: 7 7
lda PADDL1,x ; Read paddle (1 or 3)
bmi set1 ; Cycles: 2 3
nop ; Cycles: 2
bpl nop1 ; Cycles: 3
set1: sty value1 ; Cycles: 4
nop1: ; - -
; Cycles: 7 7
iny
cpy #UPPER_THRESHOLD+1
bne loop

Regards,
Oliver

Andy McFadden

unread,
Jun 5, 2020, 5:08:19 PM6/5/20
to

John Brooks

unread,
Jun 6, 2020, 2:11:51 AM6/6/20
to
On Friday, June 5, 2020 at 2:08:19 PM UTC-7, Andy McFadden wrote:
> Now summarized here: https://retrocomputing.stackexchange.com/q/15093/56

BTW, the latency between reading $C064 and $C065 can cause the Y axis to be off by one, so ideally both I/O locations would be read back-to-back. The GS 65816 is great for this, reading both the X & Y axis in 2 cycles as a 16-bit word.

Here is a smaller 41-byte GS routine with 128-position precision (32-bytes if SEI and force-1MHz are removed). It uses a 22 cycle loop, so the joystick range and calibration match the 11-cycle ROM and fast GS routine posted above, but at half precision (0-254 step 2), like Sathers but with smaller code and a one-cycle latency between reading X & Y:

    1 *-------------------------------
    2 * IIGS single-pass GetJoyXY
    3 *
    4 * 10/23/2018 by John Brooks
    5 *-------------------------------
    6          lst   off
    7          xc
    8          xc
    9 
   10          org   $300
   11 
   12 TestJoy
   13          jsr   $fc58
   14 :Loop
   15          stz   $24
   16          clc
   17          xce
   18          rep   #$30
   19          jsr   GetJoyXY
   20          tax
   21          xba
   22          tay
   23          sec
   24          xce
   25 
   26          txa
   27          jsr   $fdda
   28          lda   #","
   29          jsr   $fded
   30          tya
   31          jsr   $fdda
   32          bra   :Loop
   33 
   34 *-------------------------------
   35 * Acc=X,Y
   36          mx    %00
   37 GetJoyXY
   38          phd
   39          lda   #$c000
   40          tcd
   41          php
   42          sei
   43          ldx   $36        ;Save CPU speed
   44          stz   $36        ;Force 1MHz
   45 
   46          bit   $70        ;Start X,Y timers. 22 cycles to X read
   47          cyc   on
   48          jsr   :Rts       ;6+6 wait
   49          stz   $3e        ;4 Init Y,X result
   50          ldy   #254/2     ;3 Init loop ctr
   51          cyc   on
   52 :Loop                     ;22 cycle read loop
   53          lda   $64        ;4 Read X,Y
   54          and   #$8080     ;3
   55          asl              ;2 Cvt to Y,X
   56          adc   $3e        ;4 Add Y,X
   57          sta   $3e        ;4
   58          dey              ;2
   59          bne   :Loop      ;3   60 
   61 :Exit
   62          stx   $36        ;Restore CPU speed
   63          plp              ;Restore interrupt state
   64          pld              ;Restore dpage
   65          asl              ;Cvt Y,X range from $7F to $FE
   66          xba              ;Acc=X,Y
   67 :Rts
   68          rts
   69 
   70          lst   off

-JB
0 new messages