Understanding the PS2 reading / setup commands

I don’t have any problems with this working, I am connecting fine with my wireless controller and am able to use the buttons to control which sequence I play.
I’m just interested in understanding this bit a little more…

high CLK

low SEL
shiftout CMD,CLK,FASTLSBPRE,$1\8,$43\8,$0\8,$1\8,$0\8] ;CONFIG_MODE_ENTER
high SEL
pause 1

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$44\8,$00\8,$01\8,$03\8,$00\8,$00\8,$00\8,$00\8] ;SET_MODE_AND_LOCK
high SEL
pause 100

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$4F\8,$00\8,$FF\8,$FF\8,$03\8,$00\8,$00\8,$00\8] ;SET_DS2_NATIVE_MODE
high SEL
pause 1

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$4D\8,$00\8,$00\8,$01\8,$FF\8,$FF\8,$FF\8,$FF\8] ;VIBRATION_ENABLE
high SEL
pause 1

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$43\8,$00\8,$00\8,$5A\8,$5A\8,$5A\8,$5A\8,$5A\8] ;CONFIG_MODE_EXIT_DS2_NATIVE
high SEL
pause 1

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$43\8,$00\8,$00\8,$00\8,$00\8,$00\8,$00\8,$00\8] ;CONFIG_MODE_EXIT
high SEL
pause 1

Can anyone tell me what it all means? what each byte corresponds in the shiftout commands?
Thanks!

There are several sites that talk about how the PS2 control works. The one that I keep bookmarked and read when I am having problems getting it to work on different platforms is: curiousinventor.com/guides/ps2

The bytes correspond to commands to the PS2 which are mostly described in the above link.

Kurt

Would you be willing to share this code with others? I know it’s been a very popular question here on the forum. How do I use the PS2 to select sequences… What’s the project? Tell us more. :smiley:

yeah i don’t mind sharing the code –
it’s not very advanced compared to the pheonix v2 code - in fact, its very basic! But I am learning from the ground up and learning fast.
I am using a mrs-01 frame with atom pro, BB2 and ssc-32 with an srf08 ultrasonic sensor.

a link to an earlier video is:

youtube.com/watch?v=qqskMQo2hxc

since then i have added in multiple gaits, and a selection of turning or attacking upon close proximity to an object.

Anyway, it is a work in progress but here it is:

[code];CONFIGURATION

SDA Con P6 ;set up the Serial DAta pin for using the I2C bus
SCL Con P7 ;Set up the Serial Clock Line for using the I2C bus
SRF08 Con 0xE0 ;Set up the address of the sensor on the I2C bus

SSCpinout con P11 ;set up the serial out to pin 11
SSCpinin con P10 ;set up the serial in to pin 11
SSCbaud con i38400 ;set up the baud rate for communication between the SSC and the BB2

DAT con P12 ;set up the pin used for DATa with the ps2 controller communications
CMD con P13 ;set up the pin used for CoMmanD with the ps2 controller
SEL con P14 ;set up the pin used for SELect (signal goes low during transmission)
CLK con P15 ;Set up the pin used for the Clock - to keep in sync

ButtonDown con 0 ;used for when the user input was the on-board buttons
ButtonUp con 1 ;used for when the user input was the on-board buttons

CmdReg Con 0 ;Sonar Command register
LightReg Con 1 ;Sonar Light sensor register
RangeReg Con 2 ;Sonar 1st Range register

binarycount var byte ;Variable named binarycount - used for user input
seqnum var byte ;Variable named seqnum - copys the contents of binary input into here (selecting gaits)
Sequence var byte ;Variable named Seqence - used to store the sequence number required
Prevseq var byte ;Variable named Prevseq - used to compare current and last sequence
Speed var byte ;Variable named Speed - used to control the speed of the sequence
liftleg var byte
moveflag var bit ;Variable named moveflag - used to flag movement

Light var byte ’ Light sensor
Range var word ’ 16 bit variable for Range
PrevRange var word
turn var byte
attack var byte
prevattack var byte
Display var word

Prange10 var word
Prange9 var word
Prange8 var word
Prange7 var word
Prange6 var word

Prange5 var word
Prange4 var word
Prange3 var word
Prange2 var word
Prange1 var word
Prange var word

AvRange var word

prevattack = 0
attack = 0
Display = 0

;-----------------------------

index var byte ;Variable named index - used in a for - next loop to display ps2 readings in terminal
ps2 var byte(19) ;An array of bytes called ps2 (19 of them) - used to store information from the ps2
mode var byte ;Variable named mode - stores the mode of the ps2 controller

Small_Motor var byte ;Variable called Small_Motor - used for the vibration of the controller
Large_Motor var byte ;Variable called Small_Motor - used for the vibration of the controller

LastButton var Byte(2) ;Array of 2 bytes named LastButton - used to compare current and last ps2 button
LastButton(0) = 255 ;Set value to 255
LastButton(1) = 255 ;Set value to 255

bitA var bit ;Variable bit named bitA - used to store bit0 of binary count
bitB var bit ;Variable bit named bitB - used to store bit1 of binary count
bitC var bit ;Variable bit named bitC - used to store bit2 of binary count

ButtonA var bit ;Variable bit named ButtonA - used to store state of buttonA
ButtonB var bit ;Variable bit named ButtonB - used to store state of buttonB
ButtonC var bit ;Variable bit named ButtonC - used to store state of buttonC

PrevButA var bit ;Variable bit named PrevButA - used to store state of PrevButA
PrevButB var bit ;Variable bit named PrevButB - used to store state of PrevButB
PrevButC var bit ;Variable bit named PrevButC - used to store state of PrevButC

temp var word ;Large Variable named temp - used

bitA = 0 ;Set bitA to zero
bitB = 0 ;Set bitB to zero
bitC = 0 ;Set bitC to zero

ButtonA = 0 ;Set buttonA to zero
ButtonB = 0 ;Set buttonB to zero
ButtonC = 0 ;Set buttonC to zero

binarycount = 0 ;Set binarycount to zero
seqnum = 0 ;Set seqnum to zero
Prevseq = 0 ;Set Prevseq to zero
Sequence = 0 ;Set Sequence to zero
moveflag = 1 ;Set moveflag to one
turn = 0
attack = 0
;leftleg = 0

main

gosub ps2initialise
gosub change
Serout S_OUT, i9600, " before wakeup "]
gosub wakeup
Serout S_OUT, i9600, " after wakeup "]
loop

gosub ps2reading
gosub sensorreading
gosub AverageRange
gosub check

;;;;;;;;;;;;;;;;;;;;Check for user input;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;; Binary counter ;;;;;;;;;;;;;;;;;;;;;

IF (ps2(2).bit6 = 0) and LastButton(1).bit6 THEN	;Cross Button test
	binarycount = binarycount + 1
 	sound P9,[100\500]
 	low P9
ENDIF

 
IF (ps2(2).bit5 = 0) and LastButton(1).bit5 THEN	;Circle Button test
binarycount = binarycount - 1
sound P9,[100\1000]
low P9
ENDIF

IF (ps2(2).bit7 = 0) and LastButton(1).bit7 THEN	;Square Button test
	binarycount = 0
 	sound P9,[100\1500]
 	low P9
ENDIF

LastButton(0) = ps2(1)
LastButton(1) = ps2(2)

if (ButtonA = ButtonDown) AND (PrevButA = ButtonUp) then
	binarycount = binarycount + 1
	sound P9, [10\3000]
	low P9
endif

if (ButtonB = ButtonDown) AND (PrevButB = ButtonUp) then
	binarycount = binarycount - 1
	sound P9, [10\1000]		
	low P9
endif

if (ButtonC = ButtonDown) AND (PrevButC = ButtonUp) then
	binarycount = 0
	sound P9, [10\2000]
	low P9
endif

;;;;;;;;;;;;;;;Make the LEDs represent the number;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; in the binary counter ;;;;;;;;;;;;;;;;;;;;;;;;;;

bitA = binarycount.BIT0
bitB = binarycount.BIT1
bitC = binarycount.BIT2

;------------------read the binary counter and act------------------
;----------------- upon the number required ------------------------

if (bitA = 1) AND (bitB = 0) AND (bitC = 0) then

; sound P9, [100\1000]
binarycount = 1
endif

if (bitA = 0) AND (bitB = 1) AND (bitC = 0) then

; sound P9, [100\2000]
binarycount = 2
endif

if (bitA = 1) AND (bitB = 1) AND (bitC = 0) then

; sound P9, [100\3000]
binarycount = 3
endif

if (bitA = 0) AND (bitB = 0) AND (bitC = 1) then	

; sound P9, [100\4000]
binarycount = 4
endif

if (bitA = 1) AND (bitB = 0) AND (bitC = 1) then

; sound P9, [100\5000]
binarycount = 5
endif

if (bitA = 0) AND (bitB = 1) AND (bitC = 1) then

; sound P9, [100\6000]
binarycount = 6
endif

if (bitA = 1) AND (bitB = 1) AND (bitC = 1) then

; sound P9, [100\7000]
binarycount = 7
endif

if (bitA = 0) AND (bitB = 0) AND (bitC = 0) then

; sound P9, [100\500]
binarycount = 0
endif

;------------------^^ makes sure the counter resets ---------------
;------------------ and can only be between 0 - 7 ----------------
;------------------ don’t need more than 8 variants --------------

seqnum = binarycount 

if(binarycount <=6) AND (binarycount<>0) then
	moveflag = 1


if(binarycount=0) then
	moveflag = 0
;	gosub all1500

;	liftflag = 1
endif

If(binarycount=7) then
serout SSCpinout, SSCbaud, “PL0”, 13]
moveflag = 0

serout SSCpinout, SSCbaud,"#0 p1500"]
	serout SSCpinout, SSCbaud,"#1 p1500"]
		serout SSCpinout, SSCbaud,"#2 p1500"]
		
serout SSCpinout, SSCbaud,"#4 p1500"]
	serout SSCpinout, SSCbaud,"#5 p1500"]
		serout SSCpinout, SSCbaud,"#6 p1500"]
		
serout SSCpinout, SSCbaud,"#8 p1500"]
	serout SSCpinout, SSCbaud,"#9 p1500"]
		serout SSCpinout, SSCbaud,"#10 p1500"]

serout SSCpinout, SSCbaud,"#16 p1500"]
	serout SSCpinout, SSCbaud,"#17 p1500"]
		serout SSCpinout, SSCbaud,"#18 p1500"]
		
serout SSCpinout, SSCbaud,"#20 p1500"]
	serout SSCpinout, SSCbaud,"#21 p1500"]
		serout SSCpinout, SSCbaud,"#22 p1500"]
		
serout SSCpinout, SSCbaud,"#24 p1500"]
	serout SSCpinout, SSCbaud,"#25 p1500"]
		serout SSCpinout, SSCbaud,"#26 p1500"]
		
serout SSCpinout, SSCbaud,"T800",13]

endif

serout s_out,i9600,"binarycount is ",DEC binarycount, 13]

;-------------- if in correct mode then goto walking sub -----------------

if (moveflag = 1) and (seqnum <> Prevseq) then
gosub walking
endif

; PrevButA = ButtonA
; PrevButB = ButtonB
; PrevButC = ButtonC

goto loop

;----------------------- Choose which gait to use -------------------
;----------------------- depending on user input --------------------

walking:

if (seqnum = 1) then

; leftleg = 1
Sequence = 4
Speed = 100
turn = 1
attack = 0
endif

if (seqnum = 2) then

; leftleg = 0
Sequence = 5
Speed = 100
turn = 1
attack = 0
endif

if (seqnum = 3) then

; leftleg = 1
Sequence = 6
Speed = 100
turn = 1
attack = 0
endif

if (seqnum = 4) then

; leftleg = 1
Sequence = 4
Speed = 100
turn = 0
attack = 1
endif

if (seqnum = 5) then

; leftleg = 0
Sequence = 5
Speed = 100
turn = 0
attack = 1
endif

if (seqnum = 6) then

; leftleg = 1
Sequence = 6
Speed = 100
turn = 0
attack = 1
endif

PrevSeq = seqnum

serout SSCpinout,SSCbaud,"PL0 SQ",dec Sequence," SM", dec Speed," IX0 PA0", 13]

; serout s_out,i9600,“should move leg…”,13]

return

;-----------------Initialise the ps2 controller---------------------
;-----------------set up communications and mode--------------------

ps2initialise:
high CLK

low SEL
shiftout CMD,CLK,FASTLSBPRE,$1\8,$43\8,$0\8,$1\8,$0\8] ;CONFIG_MODE_ENTER
high SEL
pause 1

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$44\8,$00\8,$01\8,$03\8,$00\8,$00\8,$00\8,$00\8] ;SET_MODE_AND_LOCK
high SEL
pause 100

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$4F\8,$00\8,$FF\8,$FF\8,$03\8,$00\8,$00\8,$00\8] ;SET_DS2_NATIVE_MODE
high SEL
pause 1

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$4D\8,$00\8,$00\8,$01\8,$FF\8,$FF\8,$FF\8,$FF\8] ;VIBRATION_ENABLE
high SEL
pause 1

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$43\8,$00\8,$00\8,$5A\8,$5A\8,$5A\8,$5A\8,$5A\8] ;CONFIG_MODE_EXIT_DS2_NATIVE
high SEL
pause 1

low SEL
shiftout CMD,CLK,FASTLSBPRE,$01\8,$43\8,$00\8,$00\8,$00\8,$00\8,$00\8,$00\8,$00\8] ;CONFIG_MODE_EXIT
high SEL
pause 1

return

;-----------PS2 Mode----------

ps2reading:
low SEL

;--------------- ask the ps2 controller what “mode” it is in
shiftout CMD,CLK,FASTLSBPRE,$1\8]
;--------------- reading “mode” from PS2 controller
;--------------- 73(hex) is Digital button mode (dualshock1)
;--------------- 79(hex) is Analog button mode (dualshock2)
shiftin DAT,CLK,FASTLSBPOST,[mode\8]
high SEL
pause 1

;-----------PS2 Data----------
low SEL
;-------------------- asking for data from ps2 controller -------------------
shiftout CMD,CLK,FASTLSBPRE,$1\8,$42\8]
;------------------------- reading data from controller ----------------------
;------------------- can’t use a “for-next” loop, it’s too slow to read PS2 data)

shiftin DAT,CLK,FASTLSBPOST,[ps2(0)\8,ps2(1)\8,ps2(2)\8,ps2(3)\8,ps2(4)\8,ps2(5)\8,ps2(6)\8,ps2(7)\8,ps2(8)\8, |
ps2(9)\8,ps2(10)\8,ps2(11)\8,ps2(12)\8,ps2(13)\8,ps2(14)\8,ps2(15)\8,ps2(16)\8,ps2(17)\8,ps2(18)\8]
high SEL
pause 1

;-----------PS2 Vibration motors----------
Small_Motor = 1 - Temp(1).bit5 ; Numeric right arrow button (Small Motor on/off)
Large_Motor = Temp(8) ; Analog left arrow button (Large Motor speed)

low SEL
shiftout CMD,CLK,FASTLSBPRE,$1\8,$42\8,$0\8,Small_Motor\8,Large_Motor\8]
high SEL

;----------------------In the Basic Micro Studio Terminal--------------
;----------------------Show the ps2 controller mode (A/D)--------------
;----------------------And Display the bytes coming in ----------------
serout S_OUT,i57600,[13, hex2 mode\2]
for index = 1 to 18
;serout S_OUT,i57600," ", dec3 temp(index)\3]
next
return

;----------------------Play on Start up ----------------------------

wakeup:
pause 500
sound p9, [100\1000,100\2000,100\3000]
low p9
serout SSCpinout,SSCbaud,“PL0 SQ0 SM100 IX0 PA0 ONCE”, 13]
gosub CheckMotion
serout SSCpinout,SSCbaud,“PL0 SQ1 SM100 IX0 PA0 ONCE”, 13]
gosub CheckMotion
return

;----------------------Check to see if a sequence is being played --------------------------

CheckMotion:

SequenceNumber var byte
SequenceFromStep var byte
SequenceToStep var byte
SequenceRemainingTime var byte

;Wait for Servo Contrioller Player to complete sequence    

SequenceWait:
serout SSCpinout, SSCbaud, “QPL0”, 13]
serin SSCpinin, SSCbaud, [SequenceNumber, SequenceFromStep, SequenceToStep, SequenceRemainingTime]

IF (SequenceNumber<>255 | SequenceFromStep<>0 | SequenceToStep<>0 | SequenceRemainingTime<>0) THEN
  GOTO SequenceWait ;Continue waiting
ENDIF    

return

change:
Serout S_OUT, i9600, "start change "]
i2cout SDA, SCL, SRF08, [CmdReg, 0xA0]
Serout S_OUT, i9600, " hhhh "] ; Serout S_OUT, i9600, “after 1”] ’ Use terminal window
i2cout SDA, SCL,SRF08, [CmdReg, 0xAA]

i2cout   SDA, SCL,SRF08, [CmdReg, 0xA5]
i2cout   SDA, SCL,SRF08, [SRF08]

Serout S_OUT, i9600, " finish change "]
; Serout S_OUT, i9600, "change address "] ’ Use terminal window

return

;---------------- Act upon the readings from the sensor -----------------

check:

;---------------- if the turn flag is set then turn the robot right ------------

if (AvRange < 20) AND (Range <> PrevRange) AND (attack = 0) AND (turn = 1)then

serout SSCpinout, SSCbaud,"PL0 SQ3 SM200 IX0 PA0 ONCE", 13]
	gosub CheckMotion	
		serout SSCpinout, SSCbaud,"PL0 SQ3 SM200 IX0 PA0 ONCE", 13]
			gosub CheckMotion	
				serout SSCpinout, SSCbaud,"PL0 SQ3 SM200 IX0 PA0 ONCE", 13]
					gosub CheckMotion	
						serout SSCpinout, SSCbaud,"PL0 SQ3 SM200 IX0 PA0 ONCE", 13]
							gosub CheckMotion	
								serout SSCpinout, SSCbaud,"PL0 SQ3 SM200 IX0 PA0 ONCE", 13]
									gosub CheckMotion	
										serout SSCpinout, SSCbaud,"PL0 SQ3 SM200 IX0 PA0 ONCE", 13]
											gosub CheckMotion	
												serout SSCpinout, SSCbaud,"PL0 SQ3 SM200 IX0 PA0 ONCE", 13]

Serout   S_OUT, i9600, "turn"] ' Use terminal window

endif

if (AvRange < 20) AND (Range <> PrevRange) AND (attack = 1)AND (turn = 0)then
attack = 2
serout SSCpinout, SSCbaud,“PL0 SQ2 SM100 IX6 PA0 ONCE”, 13]
Serout S_OUT, i9600, “attack”] ’ Use terminal window
; serout cSCCout, cSCCbaud,"#1 p1250",13]
endif
prevattack = attack
PrevRange = Range

return

;----------------------filter out erratic sensor readings-----------------
;----------------------by taking an average of the last 13 readings-------

AverageRange:

Prange10 = Prange9
Prange9 = Prange8
Prange8 = Prange7
Prange7 = Prange6
Prange6 = Prange5

Prange5 = Prange4
Prange4 = Prange3
Prange3 = Prange2
Prange2 = Prange1
Prange1 = Prange
Prange = PrevRange
PrevRange = Range

AvRange = (Prange10 + Prange9 + Prange8 + Prange7 + Prange6 + Prange5 + Prange4 + Prange3 + Prange2 + Prange1 + Prange + PrevRange + Range) / 13
return

sensorreading:
Serout S_OUT, i9600, “start sensor”]
i2cout SDA, SCL, SRF08, [CmdReg,81] ; third param is the I2c device address
Serout S_OUT, i9600, " ranging "] ; Serout S_OUT, i9600, " gsdyaghhs "] ’ Use terminal window
pause 66
i2cout SDA, SCL, SRF08, [RangeReg] ; Do a write to the I2c Saying we want this variable
; Serout S_OUT, i9600, “after 2”] ’ Use terminal window

i2cin   SDA, SCL,SRF08, [Range.HighByte, Range.LowByte]

; Serout S_OUT, i9600, “after 3”] ’ Use terminal window

i2cout   SDA, SCL, SRF08, [Lightreg]    ; Do a write to the I2c Saying we want this variable

; Serout S_OUT, i9600, “after 2”] ’ Use terminal window

i2cin   SDA, SCL,SRF08, [Light]

; Serout S_OUT, i9600, “after 3”] ’ Use terminal window

Display = Display + 1
if (Display = 30) then
Serout S_OUT, i9600, "Light1 = ", dec Light, ", Range = ", DEC Range, " cm, AvRange = ", dec AvRange] ’ Use terminal window
; Serout S_OUT, i9600, “after 4”] ’ Use terminal window
Display = 0
endif

return[/code]

There are a lot of serouts i used to follow the flow of the program - they are for troubleshooting and just ignore them,
also there are a few parts from my older program where i used the buttons on the BB2 to select the gait rather than the ps2 controller so ignore that too!

as i said its a work in progress so be nice :stuck_out_tongue:
it needs tidying up but ill get round to that!

i forgot to say - the whole purpose of this project is so that the robot is autonomous - only having user input to select gaits and action to take upon seeing an object.
I am currently working on a code that changes the speed of the sequence playback by pressing r1 and l1 on the ps2 controller - i don’t think it will be too hard!

It’s probably best to use the file attachment function for code this long… I know I read every post on the forum, and my scrolling finger is worn out! :stuck_out_tongue: The code box function is truly meant for short programs or snippets.

That is why I use the new forum profile :wink: . It puts all of these in smaller scrollable controls. I also like the select all.

Kurt

sorry! there is always the click and drag of the scroll bar down the side…

Or your prospective reader could just skip the message…

Alan KM6VV