3 were requested at 10 mS intervals. If it’s good enough
for Windows, it’s good enough for us. Here’s the
PIC32MX timer code:
//***********************************************
//* INITIALIZE THE IN REPORT TIMER
//***********************************************
void InitializeTimer(void)
{
T4CON = 0x0; //Stop and Init Timer
T4CON = 0x0050; //prescaler = 1:32 -
//internal clock
//Clear timer register
//Load period register -
//0.010 second period
TMR4 = 0;
PR4 = 0x61A8;
IPC4SET = 0x00000005;
// Set priority
//level=1
IFS0bits.T4IF = 0;
IEC0bits.T4IE = 1;
T4CONSET = 0x8000;
//Start Timer
}
The PR4 period register value is calculated as follows:
Timer Clock = 80 MHz
Prescaler = 1:32
Desired Interval = 0.010 seconds
PR4 =
1 raw timer tick time = 1/80000000 = 0.000000012
seconds
1 prescaled timer tick time = 32 0.000000012 =
0.000000400 seconds
PR4 = 0.010 / 0.000000400 = 25000 = 0x61A8
Every 10 mS, Timer4 will overflow and generate an
interrupt. The interrupt handler’s job is to place the
PIC32MX application in the proper state to retrieve a
report from the DualShock 3. The Timer4 interrupt handler
looks like this:
//*******************************************
//* IN REPORT TIMER INTERRUPT HANDLER
//*******************************************
#pragma interrupt _T4Interrupt ipl4 vector 16
void _T4Interrupt( void )
{
if (IFS0bits.T4IF)
{
IFS0bits.T4IF = 0;
//mPORTAToggleBits(BIT_0);
if(READY_TO_TX_RX_REPORT == PS3State)
{
PS3State = GET_INPUT_REPORT;
}
}
}
Digilent
chipKIT Max32
chipKIT Network Shield
www.digilentinc.com
Microchip
XC32 C Compiler
Microchip USB Stack
www.microchip.com
Ellisys
Ellisys USB Explorer 200
Protocol Analyzer
www.ellisys.com
Sony
PlayStation DualShock 3
Controller
www.sony.com
58
June 2013
I used the mPORTAToggleBits(BIT_0) function to
toggle the RA0 I/O pin. If you want to check my math,
uncomment the toggle bit function and put a scope to
RA0. As they say, numbers don’t lie.
TAKEOFF ROLL
The PIC32MX is supported by a number of libraries
that are designed to help the programmer get the most
out of the 32-bit silicon. With that, the first thing we will
do is code in some PIC32MX functions that will maximize
the microcontroller’s performance. The next bit of coding
will kick off the PIC32MX timing mechanisms and
interrupt engine. Finally, we will fire up the UART and set
it up to run at 115200 bps. All of this startup code can be
found in the init() function:
//*******************************************
//* INITIALIZE FUNCTION
//*******************************************
void init(void)
{
int value;
value = SYSTEMConfigWaitStatesAndPB(
GetSystemClock() );
// Enable the cache for the best performance
CheKseg0CacheOn();
// Enable Interrupts
INTEnableSystemMultiVectoredInt();
// Wait for PLL lock to stabilize
value = OSCCON;
while (!(value & 0x00000020))
{
value = OSCCON;
}
// Uncomment next 2 lines to check 10 mS
//timer on RA0
//mJTAGPortEnable(DEBUG_JTAGPORT_OFF);
//mPORTASetPinsDigitalOut(BIT_0);
//Initialize UART
setbuf(stdout,NULL); //UART1 REDIRECT
UARTConfigure(UART1, UART_ENABLE_PINS_
TX_RX_ONLY);
UARTSetFifoMode(UART1, UART_INTERRUPT_
ON_TX_NOT_FULL | UART_INTERRUPT_ON_
RX_NOT_EMPTY);
UARTSetLineControl(UART1, UART_DATA_
SIZE_8_BITS | UART_PARITY_NONE |
UART_STOP_BITS_1);
UARTSetDataRate(UART1, GetPeripheral
Clock(), 115200);
UARTEnable(UART1, UART_ENABLE_FLAGS
(UART_PERIPHERAL | UART_RX | UART_TX));
PS3State = DEVICE_NOT_CONNECTED;
}
This puppy is ready to fly.
GEAR UP
Let’s walk through the DualShock 3 client driver code
in sequence, beginning with the call to initialize the
hardware and USB engine: