Posts Tagged ‘C Programming’

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

WTPA Firmware Rev 3 Released!

Thursday, April 1st, 2010

OK. I finished shoe-horning necessary functions into this beast. Somebody tell me something that needs to change or this beta becomes legit by tomorrow.
There are a whopping 12 bytes left in memory, and the OS has had a lot of fat trimmed.

Here’s beta 4 (final):
http://www.narrat1ve.com/WTPA_Firmware_0x03.tar.gz

And here’s the R3 changelog, so if you don’t know, now you know:

Firmware Version 0x03:
==============================================================================
Wed Sep 2 09:37:49 CDT 2009

Done:
— Hardcoded explicit bank start address variables into define statements. They are constants in our current system; this will prevent them from being overwritten, save us some RAM and some cycles.
— Sample Start / Window / Endpoint editing, realtime adjustment. Samples with will reverse when the start point is put after the endpoint.
— Separated the “bail” command for FX and loop adjustments in MIDI
— Re-number MIDI CCs
— Added MIDI option to edit samples with wide range or tighter resolution (editing pot is an 8-bit value, MIDI is 7)
— Added “edit mode” which sucks. But allows you to stop holding down three buttons while you edit a sample.
— Removed some un- or underused softclock (timer) and Uart functions — we’re running low on flash memory.
— Divided AudioHandler routines into bank-specific routines for ISR speed BUT
–> this means we are way over memory. So, got rid of intro sequence, debug mode, all sawtooth stuff, removed some timer functions, changed MIDI handling (don’t recognize bytes we don’t use anyway), changed LED blink functions (all blink times the same)
–> Also kilt the random number init code. Changed pinning in multiply-output mode.

xo
TB

“Video Game TiVo” Revised for Production

Monday, January 4th, 2010

So over the last couple years I’ve been building different variations on this thing for my client/buddy Cory. It’s had many names but the one we tended to call it the most often was the “Video Game TiVo”. It’s basically an AVR with a ton of Atmel Dataflash as well as some Vregs, level translators, and RS-232 chips.

The idea with these guys is that they sit around on a video game controller and log what the user is doing, and then spit that biz back out when you tell them to. The original ones simply hung out watching or asserting the actual switch lines using WPUs and the like, and as time went by they began to actually replace the controller interface entirely and deal exclusively with serial. Depending on the game system, they can sometimes play a game back deterministically, but mostly not because of RNG and/or timing issues. Either way, they’ll record MONTHS of game and can loop arbitrarily, etc etc. They also have a fancy terminal built in for communicating with a PC and recognizing different video game consoles.

Cory wanted them so he could throw infinite gutterballs in Playstation Bowling games. They do that just fine :-)

This one was tested on a PS1 and the canonical bowling.
This January I had geared up to finally make a TON of them so Cory could just have them handy and not need to call me when he needed one, and this was the final test run before we went into production.

Varactor Based Video Synth Prototype

Saturday, December 5th, 2009

My first winter in Brooklyn I made this biz. It’s a video synth that I put together on a little Narrat1ve-specific protoboard (or as I call it, the Narrat1ve Big Wizard). It’s different than the last one in lots of important ways. It’s NTSC, and generates all its own sync and blanking pulses in software (that mess is coded in C for the AVR). I spend a lot of time looking at Bruce Land’s stuff, as well as the always-on-point Owen Osborn.

More importantly I figured out how to get a continuously variable phase shift of the color carrier (analog color!) using varactor diodes! This was a big step in making stuff that looked cool. Varactors are not ideal in a lot of ways, but they are sure simple.

I slapped this guy together for a talk I gave at La Superette that I got asked to do by the inimitable Kyle and Tali from Lovid. They were really cool about this talk and I had a great time!

This really beautiful and simple proto has since been deprecated by the monsters II’ve made since and is hanging around in some drawer or other. Sad, really. Ask Too $hort about it.

xo
TB

WTPA Gets Iced; Version 2 Firmware Out!

Monday, July 6th, 2009

Happy Birthday America!


Wait — no: Happy Birtday WTPA!

It’s a little bogus to use the above fuzzy-wuzzy pictures, but given the current state of fireworks in my neighborhood and the celebratory announcement of the NEW FIRMWARE, I feel justified in using hazy party pics. The above was actually a totally kickass surprise party (peep the cake made by my girl Julianna Luther) in May to celebrate the WTPA launch here in Chicago; why my friends decided to start beef between me and Dre I’ll never know.

So anyway, we’ll pretend it’s a birthday party for the NEW FIRMWARE! As of today the version 2 firmware is now the most current, and will ship with all WTPAs ordered.

Changes From Rev1 To Rev2 Firmware:

  • The original firmware did not take into account settling time for the ADC when changing channels, and as a result, the last result from the control pot often ended up being logged as the first (or first several) samples. This resulted in a loud click at the beginning of a sampled phrase when the control pot was set to certain positions. The sampling routine now throws out the first few samples until the ADC has settled, eliminating the click.
  • The firmware now allows for playing a “single shot” sample when the sample is backwards masked.
  • The firmware now sets the DAC to midscale at powerup. This eliminates the loud bump that would happen the first time a user triggered any audio interrupt (including recording) after powerup.

The current firmware is now posted on the site (the old version of the source code is also included in the firmware download, and you’re welcome to compile and use that if you want to be retro for some weird reason). Those of you who already have WTPAs can update to the new firmware using any old avr programmer with a 6-pin ISP connector. I like the Atmel STK500, but I’d be remiss in not mentioning the fine programmers available for cheap at Adafruit Industries who pretty much have this whole kit game on lock.

Information on how to update your firmware is available in lots of AVR-specific places on the net:

  • The GNU Tool Chain for AVR — Very nerdy and complete and useful. It’s where I go.
  • Winavr — A Windows port of that toolchain.
  • AVRfreaks — The biggest and most complete AVR user community.
  • AVR Studio — Atmel’s IDE. I can’t stand this but you might like it.
  • WTPA User Forum — If and when there are WTPA specific questions about this, the answers will be here.

In other news, Narrat1ve has not one but THREE new products in the pipe. One smaller than WTPA, one bigger, and one A LOT bigger. And no, one of them is not a “real website”. I’m excited. Stay tuned.

Xoxoxo,

TMB