Posts Tagged ‘Art Shiz’

PS2 Fiddling Part 2

Thursday, December 16th, 2010

Looking for trouble on the PS2 Controller

Getting the PS2 data to playback correctly took some doing. The first problem was getting the controller synced to the PS2, which was necessary to handle the configuration streams. “Modern” Ps2 controllers can be set up in lots of different ways — as a standard digital controller or all flavors of analog. You can tell them (if you’re a PS2 or l33t haXX0r) to send stick data, analog button pressure, to configure the vibration motor in different ways, etc etc. So, when the PS2 does this, our doppleganger controller has to respond correctly. The big PITA there is that the PS2 will send any number of “don’t care” digital reads before this happens. In the terminal above I’m counting polls before we switch over to analog and begin a pre-determined configuration routine which is similar from game to game.

The next problem was buffer overflow. I used to use these fancy Atmel Dataflash AT45DB642D parts to record data, and they ruled. They had onboard RAM buffers and generally took care of erasing and writing flash memory at the same time. Then every distributor ran out of them. [2011-07-06T12:42:33+00:00 — they’ve been back for awhile now, thankfully] So I made a daughterboard and used a “peoples’ flash memory” IC by SST. It was a lot more like “normal” [read: annoying] flash in that you had to handle buffering and sector erasing yourself and it was painfully slow. This coupled with the fact that when this one bowling game used the analog button pressure (O GOD WHY?) the controller was spitting like 20 bytes a read led to trouble. Specifically, I needed to buffer all the data coming off the controller while the erase happened and that could take seconds. I ended up with a 3-way ping-ponged buffer AND compressing the data so that it would only log CHANGES in controller readings. This did the trick. I felt smug.

Here’s the pretty pretty result:

Throw some dees on it

PS2 Fiddling Part I

Tuesday, December 14th, 2010

Mucking with the serial stream on the PS2 Controller

So I’ve been building a bunch of video game controller controllers (game TiVos we call them) for Cory Arcangel for a big Barbican show. It’s pretty much everything from the Odyssey / Atari 2600 to the PS2. Basically, their job is to play back (repeat) a played video game in an artsy way, and to talk to a host computer for file transfer, etc etc. Most of them work by snooping the active-low buttons during the recording, then pulling those buttons low during playback at the right time. There is NO WAY this stays in sync with the system, but that kinda wasn’t the point.

However, it turns out for the PS2, that some of the bowling (yes, bowling) games Cory wanted used the ANALOG BUTTON PRESSURE coming off the controller. I was already an advocate of reading and replaying the serial stream from the controller rather than messing with the switches, but it turns out to do these games you pretty much have to do that. So, here I am, learning PS2 serial protocol. There are tons of notes online on this, but I especially liked and used Andrew McCubbins’ “PSXCONT” notes (though I couldn’t find his source code). The UPCB project, as usual during this video game project, was very helpful. Micah Dowty’s notes were really helpful. Lastly, the curious inventor PS2 site rules.

There had to be a lot of bus turnaround kind of thing to both read and playback the PS2 stream, so I needed an external MUX which I made from a 74HC157.

Armed with all that, I hooked up the TiVo, wrote some test code, let her rip, and watched the serial stream for boo-boos using the Saleae Logic analyzer.

What the analyzer had to say

There were lots, and they had to do with non-deterministic boot times and the initialization sequence it takes to convince the PS2 that the controller is legit. More later.

Infinite Impulse Response, Art, Flatulence

Friday, June 25th, 2010

So I got back from Chicago on Monday, where I went to take care of this blighted piece of public art. “Remoc” is this big old green beast who I made with a sculptor buddy back in like 2005, at the behest of my old boss, for the UChicago Childrens’ Hospital. Theoretically he makes sick kids laugh. I’ve seen this. I know it happens sometimes. Usually when you pull his finger, as above. However it is hard not to see him as basically a monster whose job it is to complicate my life.

In some earlier posts I talk about some of the capacitive sensors I designed for him, to allow him to sense childrens’ touches. Well, they developed problems (spurious reads) and I had to head back to the midwest to have a look.

I knew his sensor circuits were pretty resolute, but I basically no-brainered his sensor code because I was too confident in my design. The day before I left to head back to the windy windy I re-wrote a bunch of his sensor handling code.

Mostly I changed how he crunches numbers. Sensor data ends up getting put into two different filters; one with a long time constant and one with a short one. His long term averages are generated by an IIR which divides by 8192, so it takes something like 73,000 readings to settle from 0 to 4096 (12-bit sensors). Sensors were updated in the main game loop, so the loop timing was “fast but indeterminite”. I’d have scoped it, if I had a scope and the hardware in the same place. In real life it took him five minutes or so to settle from any particularly messed up event (like unplugging a sensor).

The short term averages do the same thing over 32. I tried using an FIR (where you have an array and subtract an old member and add in a new one) for this but it ended up being more of a pain in the ass as I kept missing some stupid bug I was making where I wrote off the end of an array so I just made it an IIR since there were people watching and expecting results.

The two were then compared via percentage difference. I also changed the way his serial monitor worked to make it easier to see all this data change in realtime (I’ve gotten really into sending ANSI clear-screen escape sequences to xterm. It’s hood, but it works).

What I learned from this was two of his ten sensors (the copper tape parts, installed in his bowels a million years ago, and also set on fire once or twice by the sculptor) have shifted positions — I could see this by looking at the readings and moving my hand around. So there was no fixing this (correctly) without cutting a lot of fiberglass. I asked the hospital folks whether they would be OK with cutting his arm off for a little while and surprisingly they said no. Which was just fine with me. I did what I could with the data coming out but it wasn’t much. You may have to womp on his cast really hard to trigger it now, but it won’t read spuriously.

While sensor-sensor interference may be a little bit of a problem, I could also could tell that there were bigger EMI problems, generated by switching the LEDs and PWM audio. Those sensors are relatively insensitive to LF noise, but not so much to HF, which I’d change in future sensor designs. For the nonce I changed when the sensors were polled in the game code and disregarded reads which happened during electrically noisy events.

You know, regular electronics stuff:-)
I’d love a chance to do him all over again, but until then, I’m _almost_ happy with how he is.

Here’s some of the code I used.
The following updates his averages/filters:

static void UpdateTouchsensorAverages()
// Work averaging magic on sensor readings.
// Capacitance is indicated by low readings.  When the readings increase it means a removed hand OR a temperature rise.
{
	unsigned int 
		temp,
		i;
	
	for(i=0;i<NUM_SENSORS;i++)
	{
		temp=adcResults[i]; 							

		// Update long term reading
		sensorLongTermAverages[i]-=(sensorLongTermAverages[i]/LONG_TERM_AVG_DIVISOR);		// Remove a chunk of the average.
		sensorLongTermAverages[i]+=temp;													// Add in our new sample into average.

		sensorShortTermAverages[i]-=(sensorShortTermAverages[i]/SHORT_TERM_AVG_ARRAY_SIZE);
		sensorShortTermAverages[i]+=temp;
	}
}

This next bit compares the two values and decides whether he is “touched”:

static unsigned int TouchsensorsToKeyStates()
// Take the touchsensor readings, look at thresholds, and make them into keypresses.
// Since there are no real keys in this application, this is straightforward.
// We will just pass this directly to keyStates.
{
	unsigned int
		i,
		tempMask;
	
	tempMask=0;									// Zero out "keys".

	for(i=0;i<NUM_SENSORS;i++)					// Make keys that correspond to all sensors.
	{
		if((sensorShortTermAverages[i]*SHORT_TERM_MULTIPLIER)+((sensorLongTermAverages[i]*sensorThresholdPercentage[i])/100)<=sensorLongTermAverages[i])		// Scale up the short term reading, add it to a determined percentage of the long term.  If the sum is less than the long term average, call it a touch.
		{
//			printf("TOUCH: %d\n",i);
			tempMask|=(1<<i);													// Mark this sensor as a pressed key.
		}
	}	

	return(tempMask);
}

and this last part spits out RS232 data when I tell it to so I can “see what he’s feeling” like a marriage counselor:

static void DisplayAdcValues(void)
// Monitors Adc Shizz.  Prints out variables and touch info.
{
	unsigned int
		i;
	unsigned char 
		inputChar;

	if(CheckTimer(TIMER_1))
	{
		ResetTimer(TIMER_1);

		SerialWriteByte(DEBUG_UART,'\e');	// ANSI clear screen.  Old skool!
		SerialWriteByte(DEBUG_UART,'[');
		SerialWriteByte(DEBUG_UART,'2');
		SerialWriteByte(DEBUG_UART,'J');

		printf("x to Exit\n");

		for(i=0;i<NUM_SENSORS;i++)
		{
			printf("S:#%d adc=%d L=%d S=%d DP= ",i,adcResults[i],sensorLongTermAverages[i],(sensorShortTermAverages[i]*SHORT_TERM_MULTIPLIER));	// Print the sensor number and its averages.

			if(sensorLongTermAverages[i]>(sensorShortTermAverages[i]*SHORT_TERM_MULTIPLIER))	// FIR is less than the IIR (this is how it should be when touched)
			{
				printf("-");
				printf("%d",((sensorLongTermAverages[i]-(sensorShortTermAverages[i]*SHORT_TERM_MULTIPLIER))*100)/sensorLongTermAverages[i]);	// Print percent difference the short term is from the long
			}
			else	// FIR is greater.
			{
				printf("+");
				printf("%d",(((sensorShortTermAverages[i]*SHORT_TERM_MULTIPLIER)-sensorLongTermAverages[i])*100)/sensorLongTermAverages[i]);	// Print percent difference the short term is from the long		
			}

			if(keyState&(1<<i))	// Touched?
			{
				printf(" ***\n");
			}
			else
			{
				printf("\n");			
			}
		}		

		printf("\n");
	}
	else if(SerialRxBytesWaiting(DEBUG_UART))		// Something in the buffer?
	{
		inputChar=SerialReadByte(DEBUG_UART);	// Get it.

		if(inputChar=='x')
		{
			printf("\nMonitor Done.  Hope you learned something.  Bye!\n");
			SetGameState(RemocTerminal);
			gameSubState=GSS_0;
		}
	}
}

This is all C code (duh) which is compiled with GCC for an M68k target.
In this case, as in so many when I am lost in the programming weeds, my buddy Todd Squires gave me tons of useful pointers.

It is also worth noting that a more positive analysis might paint Remoc as an excuse to spend a weekend in my old hometown drinking beer on the Metra tracks and eating the worlds finest tacos, which exist in Chicago, and which pretty much grow on trees.

xo
TMB

Dancing Stands Get All ED-209

Monday, June 7th, 2010

So, because it isn’t actually in a show yet I can’t talk about what this new dancing stand is for, but it may or may not be capable of beating up Robocop. Suffice it to say, the old gearmotor has been removed from this stand and replaced with a two-pound tank which comes as a separate synchronous motor and gearhead.

This also continues the fascinating if slightly worriesome Spring 2010 trend of my clients viewing me as a one stop for assembly language and abrasives, but things are slow so I’ll take it.

The new gearmotor was similar in size to the old one, but not so similar that it didn’t mean cutting out a big piece of the steel doghouse, making some aluminum mounts to hold the motor, drilling out the timing pulleys to fit the new motor shaft, and putting a detent in said shaft to seat the set screw. I also got my first set of metric taps, so that I could use M4 screws in this guy and the hardware I put in would match the hardware from the factory. This, O art world, is the attention to detail you get when you hire C Programmers to get their thread-cutting on.

Here she is all buttoned up.

Though I have a sneaking feeling Cory doesn’t really care about what the bottom of these things look like, I kinda do. Plus I figure the dust cover, you know, keeps dust out. Plus I had just gotten these really cool carbide burs and I was excited about cutting more holes in stuff.

Perhaps one day, one of these things will have a stepper motor or optical encoder or SOMETHING with silicon in it and everything will come full circle.

Bent 2010 / Video Mess Tool / Color Me Baddly Breakdown

Wednesday, April 28th, 2010

So, Bent 2010 is over, and as such my arbitrary deadline and excuse for spending time and cheddar on this particular device has been pulled. The above are the final circuits I presented with at the lecture.

The thing on the left is “Color Me Baddly” from the Gerbers below. It’s a color video synth (based on PLLs) which takes a CV in for the color generators (which is peculiar about its input range, to be sure). It also takes a CMOS level input which can invert the color carrier phase by 180 degrees. On the output side it spits standard composite video as well as a CMOS level color carrier (with no sync, blanking, or burst).

The PLL color tracking is pretty good! But not perfect. The PLL keeps lock over a range of a few volts in, and tracks as high as 30+ kHz, which is better than I’d hoped. It took a lot of fudging the loop filter, although the RC calculations weren’t very hard. The invert is a cool input, which originally I just made for the proto because I needed it to to get 360 degrees of color. But in general (not suprisingly) I’m finding that the more inputs you have to things like this the more weird interactions you can get between modulating signals. So I think the invert is here to stay.

The thing on the right is the “Video Mess Tool”. The circuit is different than I originally intended w/r/t the clamping circuits, which had to be made active. The crap you see over in the far right side in the proto area is that new clamp. The clamp ranges changed a little, too. The LT1203 and AD828 and AD8561 are all pretty great ICs and basically do EXACTLY what you’d expect. Even using the opamps in unity gain for the clamps (not recommended) worked without any hitches.

I think this circuit would look a lot cooler with a window comparator — something which muxed many different mess or non mess signals and was smarter about selecting when, and which had a _still_ better series of clamps for restricting signal range. A HSYNC+burst specific monostable following the comparator would also probably not be amiss, although some of the glitchiness would be eliminated. This could be selectable — “sloppy sync” vs “Teutonic Sync” or the like.

The thing in the back is a color synth I made for Christams 2009. It uses varactor diodes instead of a PLL and is its own weird animal. There are pics of that here.

So before finally throwing these guys into the mothballs for who knows what/how long, I made a couple more videos. They showcase some of the more complicated waveforms that can be generated. Neither has any audio involved; both use input from function generators. The above uses the mess tool to mux in a rainbow from the color synth into golf. The lower one is basically two synths being muxed together and inverted all around multiples of 60 Hz, which makes the trippy horizontal band.

Naturally, all this stuff looks better in person; taping an LCD screen with a webcam is not exaclty the height of majesty. And there’s a couple more tech notes on the Narrat1ve youtube channel.

This might be it for this project for awhile, so feel free to write to me or get on the forum if there’s anything else you’d like to know about!

[NOTE: Collin Cunningham of MAKE took a pretty kickass video of my lecture at Bent, and one day I’ll put it up here. Thanks, Collin!]

Xoxo, TB