Playstation 2 Logic Analysis

Back for a bit to the world of prototyping peculiar Near Future kinds of things. I’m still working through this anti-game controller, game controller to do some experiments in alternative sorts of mobile interfaces for traditional game devices.

First, there are two other posts on the Logicport and related stuff, and I’ll just flag them here:

Logicport and I2C
Logicport Overview

I did some quick experiments with the Logicport to get my head around its operating features. (My previous brief analysis is here.) I was mostly motivated to work with a logic analyzer because many of the prototyping sketches I do require some sort of communication between devices using protocols like I2C/TWI, SPI or standard serial communication. If you can get these protocols to work right the first time, then you’re golden. Sometimes though, something goes wrong and debugging can be a pain. I’m the kind of guy who likes to see what’s going on rather than guess, and tools like a digital scope and logic analyzer are indispensable for me. It’s just a preference I have to invest in some pro gear, within a reasonable budget. Seeing as I was trying to get this PSX project done and had trouble debugging it, I figured this was as good a reason as any to go ahead and get it and figure out how to use it.

The Logicport is pretty reasonable for a 34 channel (plus 2 dedicated clock channels) logic analyzer because it offloads a lot of the heavy lifting to your PC — $389 with everything you need except the computer. I told myself I’d get one when I had some trouble debugging what should’ve been a fairly straightforward interface — hooking up a microcontroller to a Playstation 2 to make the PS2 think the microcontroller was the normal Playstation controller. This got a bit tricky to debug with just a digital scope that had only two channels with which to analyze essentially a protocol that was using five channels.

[ad#ad-4]

The Playstation 2 interfaces to its controllers using a protocol that is basically SPI (Serial Peripheral Interface). The protocol for SPI is fairly straightforward. There’s a clock (SCK) to synchronize bits of data across two channels: Master Out, Slave In (MOSI); Master In, Slave Out (MISO). MOSI bits are data moving from the master device to a slave device. MISO bits are data moving from the slave out to the master. It’s like a two lane highway of data, with each data bit synchronized by the clock. Additionally, there’s a “slave select” (SS) channel — one per slave device — that tells the slave whether or not it is “active” and should listen to data bits coming across the MOSI channel, or send data bits across the MISO channel. (Reasonably, only one slave device should be active at a time.)

So, that’s four channels. The Playstation 2 actually uses this plus an additional line that is not specifically part of the SPI protocol — an “Acknowledge” (ACK) line. This is used to “acknowledge” to the Playstation 2 console each “frame” of data. That’s just the way it works, and the one feature that is a bit outside of the SPI protocol. (I fabbed-up a simple splice along the Playstation 2 controller cable to watch the protocol and try and figure it out. The splice has a simple IDC-style connector that I can use to plug into to either read the channels or, eventually, connect to a microcontroller.)

There are a few pages online describing the specifics of how a Playstation 2 controller works, including ways to interface the controller itself (the joystick) to microcontrollers.

What I’m trying to do is that, but a bit more, which is to interface a microcontroller that behaves like a Playstation 2 controller to the Playstation 2 console. To do this, the microcontroller needs to respond as a (kinda) SPI slave device, just as the Playstation 2 controller does.

To start this whole business, I tried first writing code “blind” — just looking at descriptions people had put up of how they did this, especially Marcus Post’s work, which has some PIC code to look through. I ported this as best as I could to the Atmel platform (running on a 16MHz Atmega168 on an Arduino), but was having some “hiccups” where quite often the Atmega168 seemed to loosethe protocol. Why? It was hard for me to figure out.

So, two things going on here. One — verify the console-to-controller protocol that the Playstation 2 uses. Two — figure out how to use the Logicport. I’m going to leave two for later, and first show the analyzer crunching on the PS2 console-to-controller communication.

Okay, first thing I did was connect up six of the Logicport’s 34 channels as if we’re analyzing a SPI protocol which, basically, we’re doing. We need MOSI, MISO, SCK (clock), SS (slave select), plus the ACK channel. We also need a ground line to have a common electrical reference. These signals are analogous to the one’s the PS2 uses, only with somewhat different names — they are CMD (MOSI), DATA (MISO), CLOCK (SCK), ATT (SS) and ACK in PS2 speak.

The Logicport breaks up its 34 channels into 4 groups of 9 channels (that’s 36, but two of them are dedicated clock channels), with each group color coded by a bit of heat shrink tubing on the end of a colored wire. This makes it easy to figure out which channel is being represented in the software display. (Here’s a plug module that pops into the Logicport. These are convenient cause you can have one semi-permanently connected to individual projects so you’re not always re-wiring. Just save the Logicport file for each project with the same channels and pop the plug module into the main Logicport box.)

So, I just took the “white” group and connected the MOSI, MISO, SCK, SS and ACK channels from the Playstation 2 “splice” cable. I used yellow for MOSI/CMD, black for SCK/CLOCK, red for SS/ATT, brown for ACK, and green for MISO/DATA. With these signals connected from my “splice” cable to the Logicport, I should be able to start seeing the acquisition. (I’ll go over setting up Triggers and Interpreters in a later post. For now, let’s just see what a little fussing gets us.)

The Playstation 2 protocol is pretty straightforward. It starts out with the console activating the SS/slave-select line (channel D2, red/white) to indicate to the controller to start paying attention. SS is active low, so the channel drops from high to low to indicate “pay attention now.” Following this is a 0x01h byte of data along MOSI/CMD — channel D4, yellow/white. You can also see how the Interpreter can represent the data across a specific channel by aggregating bits and turning them into something useful, like a hex number. (You can also fold up these groups of channels if you don’t want to stare at individual bits.)

So, this is the basic preamble for communicating between the console and the controller. After the 0x01 the console sends the command 0x42, which basically means — send all your data. Simultaneously, the controller sends back a specific ID to indicate which type of controller it is. In this case, the controller ID is 0x79. Following this the controller sends a 0x5A to sort of say — data is coming.

The data that follows is basically the state of all the controller’s buttons and the analog controls’ positioning. For this controller, there are six subsequent bytes of data. For this particular controller, they’re like this (Here’s a more complete table for other kinds of controllers.):

Analogue Controller in Red Mode
BYTE    CMND    DATA
01     0x01   idle
02     0x42   0x79
03     idle    0x5A    Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7
04     idle    data    SLCT JOYR JOYL STRT UP   RGHT DOWN LEFT
05     idle    data    L2   R2   L1   R1   /   O    X    |_|
06     idle    data    Right Joy 0x00 = Left  0xFF = Right
07     idle    data    Right Joy 0x00 = Up    0xFF = Down
08     idle    data    Left Joy  0x00 = Left  0xFF = Right
09     idle    data    Left Joy  0x00 = Up    0xFF = Down

All Buttons active low.

For example, the acquisition image at top shows the “LEFT” arrow button being pushed down on the controller. Huh? Yeah, see — the right most bit in the white trace? It’s actually low — a little hard to tell cause of the angle, but it is. The PS2 spits out data least significant bit first, which means that bit 0 comes before (in time) bit 7, so the 0 at the end is bit 7, and bit 7 in byte 4 indicates whether the LEFT arrow is pressed, and everything is active low here, so a 0 means — pressed. (As I understand it the SPI protocol normally is the other way around, but luckily with the Logicport you can specific the bit ordering.)

Byte 5 is for the other buttons. This image shows bit 4 activated (low) indicating that the triangle button has been pressed. The bytes that follow are the the joysticks to indicate their positioning along their two (left/right, up/down) axes, running between 0x00 and 0xFF, with their “nominal” (centered) value being about 0x8C-ish, depending on how sticky they are and other things — they’re analog potentiometers which have a little bit of tolerance for variation for mechanical reasons and such.

Here’s an overall view of the entire transaction — the three bytes of preamble, followed by six bytes of controller state data starting around the 100uS. (Those bytes are near the bottom, staggered, in green. Next time I’ll explain how I set that view up.)

(Note that the acquisition shows that the console actually holds the SS/ATT signal for the equivalent of another six bytes of data. I’m not 100% sure why, but perhaps there could be additional data bytes for this sort of controller that I’m not getting. In any case, both the console and the controller send nothing back and forth. It’s just clocked nulls for another six bytes. So, off to the right of this image is lots of clock signals, and ACKS, but no meaningful data, until the SS pulls back high. Also notice the ACKS in the fifth channel (green) — these are acknowledge signals sent from the controller back to the console to verify that it’s alive and so forth. Evidently, these are necessary for the communication to work, but not strictly part of the SPI protocol. (Also, I am calling this SPI because it’s close enough, and provides a bit of a context for describing the communication and taking advantage of the Logicport’s SPI Interpreter. Technically I suppose it isn’t SPI.)

What’s next? Well, a brief overview of how I configured the Logicport to acquire the protocol data. And, now that I can actually see what’s happening and have a better understanding of the SPI-like console-to-controller communication, I should be all set to make a microcontroller behave like a Playstation 2 controller so I can spoof the PS2 and control it from other kinds of things.

[ad#ad-1]

I2C Logic Analysis

20080527_17-42-21

I’ve been doing a bit of business trying to clean up my sometimes wonky skills with I2C communication. It took a bit to figure it out, but I managed to get a few different kinds of devices to the Atmel microcontrollers I usually use — things like a real-time clock, an LIS3LV02DQ accelerometer, these EEPROM devices. Often enough, the first time I connect something new, I confuse some part of the protocol.

Being someone who prefers to see what’s going on rather than poke around and check for what might be a loose connection somewhere, I finally decided to get a logic analyzer. That way, I could take a bit of guesswork out of what was (not) going on. (Sometimes I’ve used my digital oscilloscope, which does the trick too for tracing signals, but then you have to do a bunch of counting bits on the scope — I get confused with such things, especially late at night.)

There are two other posts about this Logicport device, which you may be interested in.

Logicport Overview
PS2 Logic Analysis

(Click the image to try out Cabel Maxfield Sasser’s FancyZoom thingie, pluginifized by Stephen Granade. A new Near Future Laboratory feature!)

20080527_17-39-51

I recently got a hold of one of these Logicport devices from Intronix. It costs $384, and I got a bunch of these nifty “XKM” grabber hook things which are pretty essentially for fastening to small leads or the ends of wires. It’s got 34 channels that it can sample at 500MHz (200MHz if using an external clock..not 100% sure why its slower with an external clock, but okay..), plus built in “interpreters” for some protocols I’m bound to come across, like I2C, SPI, CAN and RS232. The instrument itself connects to your PC (a “PC” PC, not any old personal computer) where the GUI runs. So, unlike a mega-expensive benchtop logic analyzer, you can use a somewhat junker PC and have a decent logic analysis set up for less than $1000. (Or, run Parallels on your Mac and do it there — seems to work just fine.)

Here’s an Arduino that’s being used to control a MAX6953. The connection to the Arduino and the Logicport is pretty straightforward. Basically, I run an additional wire in parallel to Arduino analog in 4 and 5 which are the I2C lines SDA and SCL respectively. But, you could connect directly to the Atmega168 pins 28 and 27 right there on the chip just as easily if you’re using those useful XKM grabber things.

I mostly got this thing because I end up doing lots of I2C connected device kinda projects, where I’ll have some microcontroller like a PIC or Atmega communicating with some I2C digital potentiometer or display driver, etc. (Ultimately though I was _really_ motivated to get it while trying to get my Playstation 2 to allow itself to be controlled by an Atmega. It should work in theory, but there may be some timing related issues that were proving intractable to debug with just a normal oscilloscope. Hopefully this thing will help.)

I jump in whole-hog..my first Flavonoid prototype had several I2C devices on a single board and I just sort of “hoped” it all would work..This board has three I2C components on it. A DS1307 real-time clock, some EEPROM device there and a MXC6202J accelerometer. (I stopped using the MEMSIC accelerometers, which work perfectly fine, only they’re designed to use these little heaters inside to do their micro-electronic heat convection technique, and that seemed a little squirrely to me. But, that’s just me.)

Here’s basically what you see when you put the Logicport software into I2C interpretation mode. I tell it which of its 34 wires are connected to the two I2C lines (SDA and SCL), start up my development hardware and then click the little start acquisition button.

The I2C protocol is fairly straightforward. Essentially it allows one to use two wires to communicate with up to 127 other devices, each with its own address. The protocol is serial-based, so one of those two wires, called SCL, acts as a clock, while the other one, SDA, serializes data down the wire, one bit at a time. The “other devices” down the wire are slave devices that are under the control of a master, maybe some kind of microcontroller. So long as everything on the wire is well-behaved, they’ll listen for data sent to their unique address and handle commands and data appropriately.

There are safeguards built into the protocol to handle miscommunications, changing over roles between slave and master, multiple masters, etc. The simplest set up — the one I tend to stick with — is one always-and-forever master (a microcontroller, like an Atmega324) and one or several slave devices. There are also contingencies for situations where you want more than one slave of a specific chip. So, for example, here’s a board where I have two DS1803
digital potentiometers. Now, they’re the exact same part number — DS1803 010 (10k digital potentiometer) — and each has factory-burned in the same I2C address. To work around this situation, the part has a three extra pins that you can tie high or low in order to uniquely identify up to 8 of these on one I2C wire.

The Logicport and its software begins hunting for the protocol transitions and, hopefully, it’ll find a “start” sequence. In I2C land that’s the master device transitioning SDA from logic high to low while the clock, SCL, remains logic high. So, in that little picture above (click it to blow it up) you can see the mnemonic “S” in the trace indicating the start condition in the top line, where below it the protocol start conditions (SDA high to low, SCL high) are represented. Following that, the I2C protocol expects a sequence of 8 bits representing the slave device address. In this case, I’m testing a MAX6953 which has an address of 0x50h, so all’s good so far. After the end of the slave address is the an “A” which represents the protocol standard “acknowledge” — SDA low while the clock ticks a period. Then there’s this gap followed by another sequence of data which, in this case, is one of several commands I can use to instruct the MAX6953. In this case, the command is represented by a number “0x07h” that is actually an address to a register within the chip.

(It’s a bit confusing, muddling a command code number as a register address — just a bit of memory inside the device — but that can be helpful to think about because many chips using I2C allow you to continue to pump data bytes with the implication that you write the subsequent data to incremental memory addresses, which I describe a bit below.)

According to the MAX6953 specification sheet, allows me to put the display into either “test” mode (all LEDs on) or take it out of “test” mode. By adding an additional parameter to the command, I can control whether it goes into or out of test mode. That parameter is the data that follows the command. In this case, you can see the “acknowledge” and then another sequence of data which happens to be 0x00h — zero. This means that at this point I’m taking the MAX6953 out of test mode and preparing for normal operation. (If I had sent a 0x01h, it would put the MAX6953 into test mode and it would illuminate all of the LEDs in the matrix, useful for testing your wiring and making sure all of the LEDs actually work.)

After all that business — the completion of a command and its parameter, in this case — there’s a final sign-off sequence which is the “stop” in which the clock goes high and then the SDA line goes high and, that’s that. Most of the I2C devices I’ve worked with have some features that allow you to continue sending data before the stop with the following bytes of data going to incremental “addresses.” So, for example, in this case I wrote first to address 0x07, which is a register that lives at address “7” inside the chip. Like this:

If I wanted to write to the next register, I could just send another byte of data, rather than having to start all over again with a new command/address, data, etc. This can save clock cycles, when clock cycles matter. In this case, for a few such writes or reads, it’s not a big deal. In other cases, writing to Flash memory, for example, where you’re writing large blocks of data, it can be really useful and tightens things up nicely.

In the PCB below are three I2C components. On the bottom right is a DS1307 I2C Real-Time Clock (you can see the cylindrical crystal used to drive the clock to its right). On the top right is an AT24C1024 1k byte EEPROM chip controlled over I2C. In the kinda top middle is a Memsic I2C two axis accelerometer. By “control” I mean that you can send commands to these to do useful things, depending on what they do. So, for the EEPROM, you can tell it to write data to an address, or read data from an address and send it back across the I2C bus to the master device. The DS1307 can be told to set the day of the month, for example, or say what hour it is.

(A brief design notes about I2C chips. There are lots of them. Often you can find a chip within a family that does the exact same stuff with important variations, like operating voltage differences — 5v versus 3.3v — chip packages — DIP versus surface mount, etc. The useful thing here is that you can swap around as you move from prototyping with an Arduino, for example, which typically wants 5v to run and so the logic rail is 5v for logic high, or a DIP package for easier breadboarding. After all that mess, you can go to smaller, more refined and finished packaging to minimize the footprint.)

Flavonoid v.01s (I2C)

(Flickr)

Doing I2C logic analysis with the USB Oscilloscope gives you an image like the one below. It basically shows you the relationship between the clock (SCL) and the serial data line (SDA) and allows you to hunt down gremlins or other problems. How has it saved me? Mostly by saving me time and putting a quick end to real headscratchers.

I have to say, working with I2C has always worked. Eventually. There are two main problems I’ve had.

Number One Problem that I personally have had? Getting the device address wrong, usually by shifting the byte address over in my head by one bit.

Number Two Problem that I personally have had? Forgetting to put pull-up resistors on SDA and SCL. Without pull-ups, the logic levels float too erratically to get a clean and consistent data stream. The logic analyzer will show you stuff, but it won’t make sense and you’ll look at your code and it seems just fine, but the clock and data lines are just floating willy-nilly. So, like..pull-ups. Check that they’re there.

I’ve also tried this USB Oscilloscope thing awhile ago from Hobby Lab. It was relatively cheap — $170 or so, so half as much as the Logicport. (Relative in comparison to the Logicport, and also normal, lab-bench stuff which can run you 100 times as much, easily.) What this sort of device does is offload all the processing and display gymnastics to your PC .

The “box” essentially captures the data, maybe compresses it, and then funnels it across the USB to your PC to figure out how to display it, handling triggering on specific events, etc. The USB Oscilloscope has a digital scope — it comes with a couple of probes like you’d get with a regular scope. But, it also adds a bunch of additional digital channels for sampling up to 16 channels of regular digital data logic analysis, has logic generator feature, so you can pump out sequences of digital data for debugging stuff. I mostly got it for the the logic analysis feature, to help debug I2C and SPI communication when the going go tough.

Here’s a screen shot from a little I2C wrestling using the USB Oscilloscope.

I2C MXC62020J Logic Analysis

There were a few simple analysis features that I believe shouldn’t be too difficult to integrate into the software, but it may turn out that they are not so easy. For example, I want to be able to trigger on certain I2C addresses for example, but I guess that’d be like looking in the future. (It seems to me that you could just buffer a bunch, look for the I2C address following an I2C start and then trigger on this condition. But, I’m not the expert.) There are work-arounds to such things, such as having the Logicport trigger from another unused output pin on the device, and toggling that pin right before the “sequence of interest.” I also find it peculiar that the analysis can continue over and over again — there must be some way of stopping it after a certain number of I2C “frames” have been captured. Must be.

Additional Resources:

Arduino I2C Wire Library

I2C on Wikipedia

Logic Analyzer on Wikipedia

Stuff here at the Near Future Laboratory on I2C

Code to control a MAX6953 from an Arduino, changes the LED matrix to show a number from 0-9 depending on the relative value of a potentiometer connected to Analog In Pin 2 on the Arduino.


#include <Wire.h>

// Using the Wire library (created by Nicholas Zambetti)
// http://wiring.org.co/reference/libraries/Wire/index.html
// On the Arduino board, Analog In 4 is SDA, Analog In 5 is SCL
// These correspond to pin 27 (PC4/ADC4/SDA) and pin 28 (PC5/ADC5/SCL)
on the Atmega8
// The Wire class handles the TWI transactions, abstracting the
nittygritty to make
// prototyping easy.

byte i;
int potPin = 2;
int val = 0;
int ledPin = 13;

void setup()
{
Serial.begin(9600);
Wire.begin(); // join i2c bus (address optional for master)
Wire.beginTransmission(0x50);
Wire.send(0x07); // Display Test
Wire.send(0x00); // Normal Operation
Wire.endTransmission();

Wire.beginTransmission(0x50);
Wire.send(0x01); // Intensity16
Wire.send(0x0F); // Full
Wire.endTransmission();

Wire.beginTransmission(0x50);
Wire.send(0x04); // configuration register
Wire.send(0x01); // disable shutdown mode
Wire.endTransmission();
}

void setCharacter(char c)
{
// if(c >= 0x20 && c <= 0x7F) {
Wire.beginTransmission(0x50);
Wire.send(0x20); // Digit 0 Plane 0
Wire.send(c); // N
Wire.endTransmission();
// }
}

void loop()
{
val = analogRead(potPin);

setCharacter(val/100+‘0’);
delay(300);
}


syntax highlighted by Code2HTML, v. 0.9.1