PS2 For FIRST

Hey, guys.
I’m now officially a FIRST mentor for Plainfield HS.
The kids have asked me to write the code so that they can use a PS2 controller with the Innovative FIRST robotics platform that they’re used to controlling their bots with.
The IFI controller doesn’t allow the users acess to its Syncronous Serial Ports, so I’m going to use a PIC16F877 that I’m learning on in my Microcomputers class.
I figure that, since my Microcomputers professor was the one who roped me into FIRST, then it’s only fair that I do it on the 877 and get bonus points for it.
:stuck_out_tongue:

Here’s the current code that I’ve got:
The only thing I have left to do is write a routine to ask for the button/joystick info from the PS2.
All the PS2 setup that’s in the ATOM tutorial is done just before Main.

Right now, all Main is doing is displaying the values of each recieved byte (though I didn’t write the code to recieve them) on 8 of the micro’s pins whenever an outside source changes an input pin.

Later, I’ll stick the code for what I have left to do in the interupt routine.
It’ll just do an algorithm to pick which register to save the bytes in.

[code];;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Programmer: Nick Reiser ;
; Date: 11-18-2006 ;
; Lab: 5 ;
; Title: SPI IFI PS2 ;
; Description: This code is written for adapting a Madcatz Wireless PS2 ;
; controller to an IFI platform. ;
; SPI pins are reserved on the IFI, so the 877 is a middleman. ;
; SPI communication between master 877 and slave PS2 controller ;
; occurs at FOSC/64 = 62,500 bits/s ;
; Communication to the IFI platform occurs whenever the IFI slaps ;
; the 877. ;
; When slapped, the 877 places a new byte on PORTD. ;
; These bytes rotate through the 7 bytes that the 877 gets from ;
; the PS2 controller. ;
; These bytes are updated continuously, so if the IFI slaps the ;
; 877 too slowly, it is possible to miss data. ;
; However, the benefit of this method is that the IFI will never ;
; fall behind a stack of data if something happens (i.e. an ;
; interupt) to slow down the IFI. ;
; Also, if the IFI should slap the 877 too fast, it’ll only be ;
; reading old data, which is no harm. ;
; All this will be running much faster than the user can press ;
; buttons, anyhow, so it should not matter. ;
; Another plus about this program is that it can be tested in real;
; time with LEDs, logic probe, etc. because the output on PORTD ;
; will only change when the tester changes the input on PORTC<0>. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Variable Declaration;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TempW equ 0x20 ;
PS2Mode equ 0x21 ;
PS2Buttons1 equ 0x22 ;
PS2Buttons2 equ 0x23 ;
PS2RJoystickX equ 0x24 ;
PS2RJoystickY equ 0x25 ;
PS2LJoystickX equ 0x26 ;
PS2LJoystickY equ 0x27 ;
ByteCounter equ 0x28 ;
RXByte equ 0x29 ;
TXByte equ 0x30 ;
SPICounter equ 0x31 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Processor Setup;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
list p=16f877 ;select processor ;
#include <p16f877.inc> ;register definition header ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Memory Vectors;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0x000 ;reset vector ;
goto Start ;
;
org 0x004 ;interupt vector ;
goto ISR ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Software Setup;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Start org 0x020 ;start ;
clrf TempW ;
;
SPIMasterSetup ;compiler has “label” error if banksel here ;
banksel TRISD ;
clrf TRISD ;PORTD output ;
bsf TRISC, 0 ;slap input ;
bcf TRISC, 1 ;alldone output ;
bcf TRISC, 2 ;attention output ;
bcf TRISC, 3 ;SCK output ;
bsf TRISC, 4 ;SDI input ;
bcf TRISC, 5 ;SDO output ;
banksel PORTC ;
clrf PORTC ;
clrf PORTD ;
clrf PS2Mode ;
clrf PS2Buttons1 ;
clrf PS2Buttons2 ;
clrf PS2RJoystickX ;
clrf PS2RJoystickY ;
clrf PS2LJoystickX ;
clrf PS2LJoystickY ;
clrf ByteCounter ;
clrf RXByte ;
clrf TXByte ;
clrf SPICounter ;
banksel SSPSTAT ;
movlw B’10000000’ ;
movwf SSPSTAT ;this processor is SPI master ;
banksel SSPBUF ;
clrf SSPBUF ;
banksel SSPCON ;
movlw B’11110010’ ;
movwf SSPCON ;SPI enable, CLK idle low, master, FOSC/16 ;
banksel OPTION_REG ;
movlw B’10000111’ ;
movwf OPTION_REG ;setup Timer0 with 256 prescalar ;
banksel INTCON ;
bsf INTCON, GIE ;enable global interupts ;
banksel PIE1 ;
bsf PIE1, SSPIE ;enable SSP interupts ;
;
PS2Setup bcf PORTC, 2 ;attention low ;
PS2ConfigEN movlw 0x01 ;
movwf TXByte ;1st byte sent ;
;
Loop1A movlw D’1’ ;
andwf SPICounter, W ;if SPICounter = 1, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop1A ;
movlw 0x42 ;
movwf TXByte ;2nd byte sent ;
;
Loop2A movlw D’2’ ;
andwf SPICounter, W ;if SPICounter = 2, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop2A ;
movlw 0x00 ;
movwf TXByte ;3rd byte sent ;
;
Loop3A movlw D’3’ ;
andwf SPICounter, W ;if SPICounter = 3, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop3A ;
movlw 0x01 ;
movwf TXByte ;4th byte sent ;
;
Loop4A movlw D’4’ ;
andwf SPICounter, W ;if SPICounter = 4, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop4A ;
movlw 0x00 ;
movwf TXByte ;5th byte sent ;
bsf PORTC, 2 ;attention high ;
;
PS2SetMode bcf PORTC, 2 ;attention low ;
;
Loop0B movlw D’5’ ;
andwf SPICounter, W ;if SPICounter = 5, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop0B ;
movlw 0x01 ;
movwf TXByte ;1st byte sent ;
;
Loop1B movlw D’6’ ;
andwf SPICounter, W ;if SPICounter = 6, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop1B ;
movlw 0x44 ;
movwf TXByte ;2nd byte sent ;
;
Loop2B movlw D’7’ ;
andwf SPICounter, W ;if SPICounter = 7, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop2B ;
movlw 0x00 ;
movwf TXByte ;3rd byte sent ;
;
Loop3B movlw D’8’ ;
andwf SPICounter, W ;if SPICounter = 8, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop3B ;
movlw 0x01 ;
movwf TXByte ;4th byte sent ;
;
Loop4B movlw D’9’ ;
andwf SPICounter, W ;if SPICounter = 9, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop4B ;
movlw 0x03 ;
movwf TXByte ;5th byte sent ;
;
Loop5B movlw D’10’ ;
andwf SPICounter, W ;if SPICounter = 10, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop5B ;
movlw 0x00 ;
movwf TXByte ;6th byte sent ;
;
Loop6B movlw D’11’ ;
andwf SPICounter, W ;if SPICounter = 11, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop6B ;
movlw 0x00 ;
movwf TXByte ;7th byte sent ;
;
Loop7B movlw D’12’ ;
andwf SPICounter, W ;if SPICounter = 12, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop7B ;
movlw 0x00 ;
movwf TXByte ;8th byte sent ;
;
Loop8B movlw D’13’ ;
andwf SPICounter, W ;if SPICounter = 13, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop8B ;
movlw 0x00 ;
movwf TXByte ;9th byte sent ;
bsf PORTC, 2 ;attention high ;
;
PS2VibrationEN bcf PORTC, 2 ;attention low ;
;
Loop0C movlw D’14’ ;
andwf SPICounter, W ;if SPICounter = 14, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop0C ;
movlw 0x01 ;
movwf TXByte ;1st byte sent ;
;
Loop1C movlw D’15’ ;
andwf SPICounter, W ;if SPICounter = 15, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop1C ;
movlw 0x4D ;
movwf TXByte ;2nd byte sent ;
;
Loop2C movlw D’16’ ;
andwf SPICounter, W ;if SPICounter = 16, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop2C ;
movlw 0x00 ;
movwf TXByte ;3rd byte sent ;
;
Loop3C movlw D’17’ ;
andwf SPICounter, W ;if SPICounter = 17, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop3C ;
movlw 0x00 ;
movwf TXByte ;4th byte sent ;
;
Loop4C movlw D’18’ ;
andwf SPICounter, W ;if SPICounter = 18, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop4C ;
movlw 0x01 ;
movwf TXByte ;5th byte sent ;
;
Loop5C movlw D’19’ ;
andwf SPICounter, W ;if SPICounter = 19, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop5C ;
movlw 0xFF ;
movwf TXByte ;6th byte sent ;
;
Loop6C movlw D’20’ ;
andwf SPICounter, W ;if SPICounter = 20, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop6C ;
movlw 0xFF ;
movwf TXByte ;7th byte sent ;
;
Loop7C movlw D’21’ ;
andwf SPICounter, W ;if SPICounter = 21, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop7C ;
movlw 0xFF ;
movwf TXByte ;8th byte sent ;
;
Loop8C movlw D’22’ ;
andwf SPICounter, W ;if SPICounter = 22, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop8C ;
movlw 0xFF ;
movwf TXByte ;9th byte sent ;
bsf PORTC, 2 ;attention high ;
;
PS2ConfigExit bcf PORTC, 2 ;attention low ;
;
Loop0D movlw D’23’ ;
andwf SPICounter, W ;if SPICounter = 23, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop0D ;
movlw 0x01 ;
movwf TXByte ;1st byte sent ;
;
Loop1D movlw D’24’ ;
andwf SPICounter, W ;if SPICounter = 24, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop1D ;
movlw 0x43 ;
movwf TXByte ;2nd byte sent ;
;
Loop2D movlw D’25’ ;
andwf SPICounter, W ;if SPICounter = 25, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop2D ;
movlw 0x00 ;
movwf TXByte ;3rd byte sent ;
;
Loop3D movlw D’26’ ;
andwf SPICounter, W ;if SPICounter = 26, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop3D ;
movlw 0x00 ;
movwf TXByte ;4th byte sent ;
;
Loop4D movlw D’27’ ;
andwf SPICounter, W ;if SPICounter = 27, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop4D ;
movlw 0x00 ;
movwf TXByte ;5th byte sent ;
;
Loop5D movlw D’28’ ;
andwf SPICounter, W ;if SPICounter = 28, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop5D ;
movlw 0x00 ;
movwf TXByte ;6th byte sent ;
;
Loop6D movlw D’29’ ;
andwf SPICounter, W ;if SPICounter = 29, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop6D ;
movlw 0x00 ;
movwf TXByte ;7th byte sent ;
;
Loop7D movlw D’30’ ;
andwf SPICounter, W ;if SPICounter = 30, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop7D ;
movlw 0x00 ;
movwf TXByte ;8th byte sent ;
;
Loop8D movlw D’31’ ;
andwf SPICounter, W ;if SPICounter = 31, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto Loop8D ;
movlw 0x00 ;
movwf TXByte ;9th byte sent ;
bsf PORTC, 2 ;attention high ;
;
banksel PORTD ;go back to bank 0 ;
goto Main ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Continuous Loop;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Main btfss PORTC, 0 ;check if slap bit clear ;
call EvenSlaps ;
btfsc PORTC, 0 ;check if slap bit set ;
call OddSlaps ;
goto Main ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Interupt Handlers;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ISR movwf TempW ;save W register ;
btfsc PIR1, SSPIF ;test for SPI/I2C flag ;
call SSPHandler ;
movfw TempW ;reload W register ;
retfie ;
;
SSPHandler incf SPICounter, F ;count how many times transmit occurs ;
movfw SSPBUF ;
movwf RXByte ;read from the SSP ;
movfw TXByte ;
movwf SSPBUF ;write to the SSP ;
bcf PIR1, SSPIF ;reset SPI/I2C flag ;
return ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Subroutines;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EvenSlaps btfss ByteCounter, 0 ;if set, then ByteCounter is odd, which ;
goto ExitEvenSlaps ;means IFI has slapped by changing RC0 ;
incf ByteCounter, F ;makes ByteCounter even & gets next byte rdy;
;RECAP: PORTD & ByteCounter now both even ;
movlw D’2’ ;
andwf ByteCounter, W ;if ByteCounter = 2, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto $+3 ;if not 0, skip the next 2 lines ;
movfw PS2Buttons1 ;load second controller byte ;
movwf PORTD ;send IFI a new byte ;
;
movlw D’4’ ;
andwf ByteCounter, W ;if ByteCounter = 4, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto $+3 ;if not 0, skip the next 2 lines ;
movfw PS2RJoystickX ;load fourth controller byte ;
movwf PORTD ;send IFI a new byte ;
;
movlw D’6’ ;
andwf ByteCounter, W ;if ByteCounter = 6, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto $+3 ;if not 0, skip the next 2 lines ;
movfw PS2LJoystickX ;load sixth controller byte ;
movwf PORTD ;send IFI a new byte ;
;
movlw D’8’ ;
andwf ByteCounter, W ;if Bytecounter = 8, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto ExitEvenSlaps ;flee the subroutine ;
bsf PORTC, 1 ;set alldone output when finished sending ;
clrf PORTD ;reset IFI outport ;
clrf ByteCounter ;reset byte counter ;
;
ExitEvenSlaps return ;RECAP: ByteCounter & PORTD still both even ;
;
OddSlaps btfsc ByteCounter, 0 ;if clear, then ByteCounter is even, which ;
goto ExitOddSlaps ;means IFI has slapped by changing RC0 ;
incf ByteCounter, F ;makes ByteCounter odd & gets next byte rdy ;
;RECAP: PORTD & ByteCounter now both odd ;
movlw D’1’ ;
andwf ByteCounter, W ;if ByteCounter = 1, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto $+4 ;if not 0, skip the next 3 lines ;
movfw PS2Mode ;load first controller byte ;
movwf PORTD ;send IFI a new byte ;
bcf PORTC, 1 ;clear alldone output when sending begins ;
;
movlw D’3’ ;
andwf ByteCounter, W ;if ByteCounter = 3, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto $+3 ;if not 0, skip the next 2 lines ;
movfw PS2Buttons2 ;load third controller byte ;
movwf PORTD ;send IFI a new byte ;
;
movlw D’5’ ;
andwf ByteCounter, W ;if ByteCounter = 5, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto $+3 ;if not 0, skip the next 2 lines ;
movfw PS2RJoystickY ;load fifth controller byte ;
movwf PORTD ;send IFI a new byte ;
;
movlw D’7’ ;
andwf ByteCounter, W ;if ByteCounter = 7, then W = 0 ;
btfss STATUS, Z ;W = 0? ;
goto ExitOddSlaps ;if not 0, flee the subroutine ;
movfw PS2LJoystickY ;load seventh controller byte ;
movwf PORTD ;send IFI a new byte ;
;
ExitOddSlaps return ;RECAP: ByteCounter & PORTD still both odd ;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		end                                 ;program never actually ends

[/code]

Hi Nick,

Have you succeeded in interfacing the PS2 controller to a PIC? I want to do the same. But I’ll be using an 18F4550 or '4620, and in HiTech C.

Alan KM6VV

This post is almost a year old,i really don’t think he will respond to your question,i havn’t seen him online for a year now.

Apparently I’m quite late to the party as well, but I’ll add what I think I know about FIRST that would make this illegal in case someone else is going to try it.

You can’t connect any externally powered devices to the joystick ports on the controller. So unless you can power both the PIC and the joystick from the 100 or so milliamp power pin on the joystick ports, it’s disallowed. The only thing you can connect powered devices to is the console port and this is incoming only.

I’m late to the thread too.

I’m not doing anything with a FIRST (whatever that is), I will be interfacing the PS2 (Lynx receiver) to a PIC (and/or an Atmen ARM7) processor(s).

The receiver will be powered from a 5v logic supply. The PIC will be powered from the supply as well. An SSC-32 will also be powered appropriately as well (although not involved with PS2).

What is missing/confusing is the SPI serial interface information. SPI speed, inverted/ receive data (?) MSB/LSB first, and the simultaneous xmit/receive that the PIC (and my ARM7) expect. The BASIC Stamp processors appear to do SHIFTIN/SHIFTOUT by bit-banging, (software simulation of a hardware device). I believe the BASIC Stamp modules use one of the PIC 16F877 family devices. Some PICs have built in SPI; BASIC Stamp may be using that hardware. Does anyone know?

It’s nice that the BASIC Stamp (BASIC in general) and similar modules provide you with a lot of nice routines, but there’s no understanding of how things work “behind the curtain”. If I can get the PS2 receiver to “say something”; I can look at the data with a 'scope, and determine this. However If the BASIC Atom (w/stamp) is the “Master”, then it has to say something first.

PBP (PIC BASIC PRO) has these SHIFTIN/SHIFTOUT commands, and is supposed to be similar to BS2 code. If I have to, I’ll find out what they’re doing by examining the resultant ASM code. 'Scoping out a working PS2/BASIC Atom “connection” would also reveal the info, if none is forthcoming.

Having the interface data available to use the Lynx PS2 and receiver would probably increase sales. It appears to be a great combination for a lot of robot-type projects.

Alan KM6VV

The FIRST is a robot competition i believe,i have been in the FIRST lego mindstorms competition about 1 year ago.

usfirst.org/ Robot competition with many different levels of competition. The largest scale happens around Feb-March each year. Definitely a lot of fun.

If you’ve got the time to become a mentor, find a local school with a team or encourage one to start a team. It’s a great experience for everyone involved.

Yea,great fun :smiley: but it hurt my ears :laughing:

I never saw this post. I wonder if Nick will ever come back? I miss his hummor. :laughing:

I remeber this one topic,it was really funny :laughing:
I think it was called “Wheres Jim” or something like that :laughing:

EDIT : Its this topic right here :
lynxmotion.net/phpbb/viewtopic.php?t=184
Sry for hacking the thread :wink:

I haven’t seen nick for a while. :frowning: