English Amiga Board Amiga Lore


Go Back   English Amiga Board > Coders > Coders. Language > Coders. Blitz Basic

 
 
Thread Tools
Old 05 March 2017, 08:16   #1
earok
Moderator

 
Join Date: Dec 2013
Location: Auckland
Posts: 1,313
Detect CD32 pad connected in Blitz?

Is there an easy way to detect whether a CD32 pad is connected? (without using lowlevel.library etc which may not be present)
earok is offline  
AdSense AdSense  
Old 05 March 2017, 11:17   #2
Anakirob
Unregistered User
Anakirob's Avatar
 
Join Date: Nov 2005
Location: Tasmania
Age: 35
Posts: 785
I can't think of any way to automatically detect one, but you could manually detect one by requesting the user press one of the buttons not present on a standard joystick.

For example to prompt the user to press red or green. If red button is detected then it's a standard controller, if green then it's a cd32 pad.
Anakirob is offline  
Old 05 March 2017, 23:58   #3
Daedalus
Registered User

Daedalus's Avatar
 
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 1,528
You can do it by peeking and poking the if you're happy to do that? When being read, the CD32 sends a bitstream, with the first 7 bits representing the status of all the buttons other than the D-pad. If you keep reading though, the 8th bit is always 1 and the 9th bit is always 0. If you can detect those bits, you can be sure that it's a CD32 pad connected as no combination of button bashing can change those two bits.

I don't have the code to hand at the moment, but that's how I did the detection in a controller tester I wrote. When I'm at that machine again, I can dig up the code for you if that helps?
Daedalus is offline  
Old 19 March 2017, 03:50   #4
earok
Moderator

 
Join Date: Dec 2013
Location: Auckland
Posts: 1,313
Quote:
Originally Posted by Daedalus View Post
You can do it by peeking and poking the if you're happy to do that? When being read, the CD32 sends a bitstream, with the first 7 bits representing the status of all the buttons other than the D-pad. If you keep reading though, the 8th bit is always 1 and the 9th bit is always 0. If you can detect those bits, you can be sure that it's a CD32 pad connected as no combination of button bashing can change those two bits.

I don't have the code to hand at the moment, but that's how I did the detection in a controller tester I wrote. When I'm at that machine again, I can dig up the code for you if that helps?
Eeek, sorry for the delay writing back, yes that would be most useful.
earok is offline  
Old 19 March 2017, 14:14   #5
Daedalus
Registered User

Daedalus's Avatar
 
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 1,528
Quote:
Originally Posted by earok View Post
Eeek, sorry for the delay writing back, yes that would be most useful.
No bother Here you go - it's not the most beautiful code I've ever written, but it works well... It's my complete button reading code so it can probably be stripped down if you only want to detect the controller, but it can also be used as-is and only call it when you need to detect the pad.

The potgo_ functions are from the AmiBlitz3 potgo.include file, but the code in them is pretty simple and is just a wrapper for the OS calls. You can see it in the AmiBlitz3 code repository and download it to use in Blitz 2. It's probably not even strictly necessary if you're shutting down the OS - you could just bang the hardware directly without allocating the resource, but if anything else uses the port you'd get strange things happening.

Code:
; Setup code near the start of your program.
debug.b=True ; or false...

If potgo_Open{}=False Then NPrint "Can't open potgo.resource!":End

mask.w = %1111111100000001

allocmask.w = potgo_AllocPotBits{mask}

If debug Then NPrint "Allocating...",Right$(Bin$(mask),16)
If debug Then NPrint "and got......",Right$(Bin$(allocmask),16)

If allocmask & %0000111100000000
  If debug Then NPrint "Allocated port 0 bits successfully"
Else
  If debug Then NPrint "Unable to allocate port 0 bits!"
End If

If allocmask & %1111000000000000
  If debug Then NPrint "Allocated port 1 bits successfully"
Else
  If debug Then NPrint "Unable to allocate port 1 bits!"
End If

VWait 5 ; Let things settle down a little, you might not need this

; ...
; Other initialisation code here
; ...

Function.w cd32buttons{port.b}
SHARED allocmask, debug
result.w=0

; Define the pins needed for 
If port=1
  potgoon.w =%0010000000000000
  potgooff.w=%0011000000000000
  firepin.b=%10000000
  serbit.w=14
Else
  potgoon.w =%0000001000000000
  potgooff.w=%0000001100000000
  firepin.b=%01000000
  serbit.w=10
End If

Disable_ ; The pot pins get messed with during interrupts, so they need to be disabled

Poke.b $BFE201,(Peek.b($BFE201)|firepin) ; Joystick fire to output

Poke.b $BFE001,(Peek.b($BFE001) & NOT firepin) ; Output low

savepotgo.w=Peek.w($DFF016) ; So we can restore it later

Poke.w $DFF034,potgoon ; Set the relevant pin 5 to enable CD32 mode on the controller

; Ugly delay loop to give the pot lines time to stabilise
For i.w=1 To 5 
  mybytes.w=Peek.w($DFF016)
Next i

If port=1
  For i.w=14 To 6 Step -1
    Poke.b $BFE001,(Peek.b($BFE001)|firepin) ; Output high
    bytes.w=Peek.w($DFF016)
    Poke.b $BFE001,(Peek.b($BFE001) & NOT firepin) ; Output low
    result=result | ((bytes & (1 LSL 14)) LSR i) ; %0100000000000000
  Next i
Else ; Port 0
  For i.w=10 To 2 Step -1
    Poke.b $BFE001,(Peek.b($BFE001)|firepin) ; Output high
    bytes.w=Peek.w($DFF016)
    Poke.b $BFE001,(Peek.b($BFE001) & NOT firepin) ; Output low
    result=result | ((bytes & (1 LSL 10)) LSR i) ; %0000010000000000
  Next i
End If

; Put things back the way they were so you don't upset other functions
Poke.w $DFF034,potgooff

Poke.b $BFE001,(Peek.b($BFE001)|firepin) ; Output high
Poke.b $BFE201,(Peek.b($BFE201) & NOT firepin) ; Joystick fire to input

Poke.w $DFF034,savepotgo

; Another ugly delay loop
For i.w=1 To 50
  mybytes.w=Peek.w($DFF016)
Next i

Enable_ ; Turn interrupts back on

Function Return result
End Function

; ...
; More code here
; ...

; Detect controller on port 1
game.w=cd32buttons{1}
If (game & %10000000) AND (game & %100000000)=False
  NPrint "CD32 Controller Found on Port 1! "
Else
  NPrint "Standard Controller on Port 1!"
End If

; ...
; And more code...
; ...

; Free the potgo resource when you're finished
potgo_FreePotBits{allocmask}
This function will give you a binary word with the lower 9 bits related to the controller specified with the port parameter (0 or 1). Bits 0-6 correspond to the 7 buttons (0=blue, 1=red, 2=yellow, 3=green, 4=FFW, 5=rew, 6=play/pause). Bit 7 is always 1 and bit 8 is always 0 when a CD32 controller is connected, so this can be used to detect the presence of a controller automatically.

I hope it makes sense, but let me know if you need a hand with it.

Edit: Added extra code at the end to demonstrate the actual detection.

Last edited by Daedalus; 19 March 2017 at 14:23.
Daedalus is offline  
Old 19 March 2017, 19:50   #6
witchmaster
Registered User
witchmaster's Avatar
 
Join Date: Oct 2008
Location: Finland
Posts: 102
I started experimenting with inline assembly in Blitz Basic 2. Here is an alternative joystick / CD32 gamepad routine written in assembly. You can use it like a normal function, usage example included in code. This function will also read the joystick directions so it can replace all joyx joyy joyb calls, I have no idea if this is any faster though, I haven't tested.

EDIT1: There is a bug somewhere in this routine that causes problems on hardware, port 1 is working fine but not port 2. So I advice you not to use this until I find the bug... Can anybody see the problem? Probably a wrong address or something.

EDIT2: Ok, I found the bug. I had a MOVEQ instead of a MOVE.w instruction and another interesting problem was that when reading both ports, the second port would always return a pressed blue button status. This is because the capacitors used for pins on the joystick ports are so big so it takes up to 300Ás for the pin mode change to take effect. Instead of resetting the pins after each port read, I created a macro that resets both ports after reading them, so this macro needs to be called once after reading one or both joystick ports. The code is now updated, I have tested it on my stock A500 and A1200 with cd32 pad + mouse, joystick + mouse, cd32 pad + joystick and cd32 pad + cd32 pad.

EDIT3: Edited the code one more time, POTGO value is now restored to it's previous state after reading joystick port(s). I made a JoyTester program, you can download it below if interested (bootable adf image, tested on A500 and A1200, source included):
http://www.gamephase.net/files/JoyTesterv10.zip

Code:
; CD32 GAMEPAD ROUTINE FOR BLITZ BASIC 2

#JOY_UP        = 8
#JOY_DOWN      = 4
#JOY_LEFT      = 2
#JOY_RIGHT     = 1
#JOY_BUTTON1   = 2048
#JOY_BUTTON2   = 4096
#CD32_RED      = 2048
#CD32_BLUE     = 4096
#CD32_GREEN    = 512
#CD32_YELLOW   = 1024
#CD32_LTRIGGER = 128
#CD32_RTRIGGER = 256
#CD32_PLAY     = 64
#CD32_GAMEPAD  = 16

DEFTYPE .w

Function.w ReadJoy{n}

  UNLK    a4              ; Must be at the top of an assembly procedure (a4 is used as local variable base)
  
  BTST    #0,d0           ; Test if d0=1 by testing bit 0 (Z=0 if bit 0 is 1)
  BNE.b   joy1            ; Branch to joy1 if Z=0
  
; ---------------------------------------------------
; Joy0
  MOVEQ   #6,d3           ; Button 1 bit (bit 6 (/FIR0) at address $BFE001 which is CIAA PRA)
                          ; also bit 6 of $BFE201 which is CIAA DDRA (data direction of joy0 pin 6)
  MOVE.w  #10,d4          ; Button 2 bit (joy0 pin 9, POTGOR)
  MOVE.w  #$f600,d5       ; Used to set POTGO (joy0 pin 5 output low) was f600
  MOVEA.l #$dff00a,a0     ; Joystick 0 data address (joy0dat)
  BRA     directions

; ---------------------------------------------------
joy1:
  MOVEQ   #7,d3           ; Button 1 bit (bit 7 (/FIR1) at address $BFE001 which is CIAA PRA)
                          ; also bit 7 of $BFE201 which is CIAA DDRA (data direction of joy1 pin 6)
  MOVE.w  #14,d4          ; Button 2 bit for Joy1 (joy1 pin 9, POTGOR)
  MOVE.w  #$6f00,d5       ; Used to set POTGO (joy1 pin 5 output low) was 6f00
  MOVEA.l #$dff00c,a0     ; Joystick 1 data address (joy1dat) 
  
  MOVEQ   #0,d0           ; Set d0 to 0 
  MOVE.w  #0,d6           ; Set d6 to 0 

; ---------------------------------------------------
directions: 
  MOVE.w  (a0),d0         ; Read joy0dat or joy1dat to d0 
  
  MOVE.w  d0,d1           ; Copy d0 to d1
  LSR.w   #1,d1           ; Shift d1 one bit to the right
  EOR.w   d0,d1           ; Exclusive OR d0 and d1 and store in d1

  BTST    #8,d1           ; Check joystick up (test bit 8 and set Z to 1 if bit is 0)
  SNE     d6              ; Set first byte of d7 to %11111111 if Z bit is set
  ADD.w   d6,d6           ; Add d7 to itself

  BTST    #0,d1           ; Check joystick down (test bit 0... read above)
  SNE     d6
  ADD.w   d6,d6

  BTST    #9,d0           ; Check joystick left (test bit 9... read above)
  SNE     d6
  ADD.w   d6,d6

  BTST    #1,d0           ; Check joystick right (test bit 1... read above)
  SNE     d6
  ADD.w   d6,d6
  
  LSR.w   #8,d6           ; Shift d6 8 steps to the right (logical)
  ANDI.b  #%1111,d6       ; Save only bits 0-3 of d6

; ---------------------------------------------------
; Normal buttons
  BTST    d3,$bfe001      ; Check button 1 bit at CIAA PRA
  BNE.b   button2         ; Branch to button2 if button1 is not pressed
  BSET    #11,d6          ; If button1 is pressed, set bit 13 of d6

button2:
  BTST    d4,$dff016      ; Check button 2 bit at POTGOR (aka. POTINP)
  BNE.b   cd32            ; Branch to cd32 if button2 is not pressed
  BSET    #12,d6          ; If button2 is pressed, set bit 13 of d6
  
; ---------------------------------------------------
; CD32 buttons
cd32:
  BSET    d3,$bfe201      ; Set ciaa ddr port a high (configure /fire0 as output) 6=joyport0, 7=joyport1
  BCLR    d3,$bfe001      ; Set /fire0 low

  MOVE.w  d5,$dff034      ; Set pin 5 as output low (write to potgo)

  MOVEQ   #0,d0           ; Set d0 to 0
  MOVEQ   #8,d1           ; Set d1 to 9, this will be used for the button read loop
  BRA     in              ; jump to in

loop: 
  TST.b   $bfe001         ; Read CIAA PRA multiple times to create a delay so a reliable button status
  TST.b   $bfe001         ; can be read.
in:   
  TST.b   $bfe001
  TST.b   $bfe001
  TST.b   $bfe001
  TST.b   $bfe001
  TST.b   $bfe001
  TST.b   $bfe001

  MOVE.w  $dff016,d2      ; Read POTGOR to d2

  BSET    d3,$bfe001      ; Set /fire0 high (clock pulse for shift register)
  BCLR    d3,$bfe001      ; Set /fire0 low

  BTST    d4,d2           ; Test bit 10 or 14 of POTGOR (pin 9, CD32 gamepad button data)
  BNE.b   readnext        ; Branch to readnext if pin 9 is 1 (0 means button is pressed)

  BSET    d1,d0           ; Set bit d1 of d0 if button is pressed

readnext:
  DBF     d1,loop         ; Decrement d1 and jump to loop if d1 > 0

  BSET    d3,$bfe001      ; Set button1 high
  BCLR    d3,$bfe201      ; Set ciaa ddr port as input
  
  MOVE.b  d0,d1           ; Copy first byte of d0 to d1
  ANDI.b  #%11,d1         ; Save the lowest two bits of d1
  CMPI.b  #%01,d1         ; Check if lowest bits equal %01 (cd32 gamepad signature)
  BEQ.b   cd32ok          ; If cd32 signature is ok, branch to cd32ok
  MOVE.b  #0,d0           ; Clear low byte of d0 since cd32 button readings are wrong
  
cd32ok:
  LSL.w   #4,d0           ; Shift d0 four steps to the left
  OR.l    d6,d0           ; Combine d0 with d6 by using bitwise OR
  
  RTS

End Function

Macro ReadPotgo
  potgo.w = Peek.w($dff016)
End Macro

Macro RestorePotgo
  Poke.w $dff034,potgo
End Macro

BLITZ ; Go into blitz mode
BitMap 0, 320, DispHeight, 5 ; Create a bitmap
PalRGB 0,1,15,15,15
BitMapOutput 0
Slice 0,42,5
Use Palette 0
Show 0, 0, 0

joystick = 0
Repeat
  VWait
  
  ; Read joy1 (0 for joy0)
  !SavePotgo ; Save the POTGO register, do this once before reading joystick port(s)
  joystick = ReadJoy{1}
  ; Reset POTGO register, call this macro after reading ports 0 and 1
  ; So if reading both ports, do that above and then call this macro once
  !RestorePotgo
  
  ; Print joystick variable
  Locate 0,0 : Print Bin$(joystick)
  
  ; CD32 gamepad check
  Locate 0,1
  If joystick & #CD32_GAMEPAD
    Print "CD32 Gamepad Connected!   "
  Else
    Print "Normal joystick connected!"
  EndIf
  
  ; Direction check
  Locate 0,2
  If joystick & #JOY_UP
    Print "Going up!"
  Else
    Print "         "
  EndIf
  
  ; Button check
  Locate 0,3
  If joystick & #CD32_PLAY
    Print "Play is pressed!"
  Else
    Print "                "
  EndIf
  
Until Joyb(0)>0

Last edited by witchmaster; 20 March 2017 at 22:39. Reason: Bug fixes, read post
witchmaster is online now  
AdSense AdSense  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Using CD32 pad on A1200 running CD32 games issue RetroPaul support.Games 23 14 October 2013 23:51
Using a six-button Megadrive pad as a CD32 pad StarEye support.Hardware 22 09 September 2013 03:51
jit or 2x1200 speed break cd32 detect cd turrican3 support.WinUAE 4 20 April 2013 17:51
PSX pad for CD32 cd32.co.uk MarketPlace 27 30 September 2008 17:31
The Quest To Make The Comp Pro CD32 Pad My Favourite Pad StarEye support.Hardware 0 02 December 2007 22:21

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 13:05.


Powered by vBulletin® Version 3.8.8 Beta 1
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Page generated in 0.18702 seconds with 14 queries