Sunday, 19 December 2010

Battlezone With Lasers Part 2

Still an ongoing project to play Atari Battlezone via a laser projector (for no other reason than I like a challenge :)).

I stumbled for a long time over pushing data fast enough to a microcontroller, with a USB serial port proving too slow and a USB isosynchronous device being very complicated to program. Now I am using an mbed microcontroller board (with a decent amount of RAM and fast clock) to receive data and drive the DACs, and with the ethernet support of the mbed, I am able to send data over a TCP socket, which seems to be plenty fast enough.

The mbed's speed and RAM also allowed me to do a lot of the number crunching on the microcontroller (in particular the plotting of lines) so all I need is to push the lists of vertices to the mbed and it will generate "in between" points along a line (required so that the laser galvos can be moved a bit more incrementally - and with less probems of intertia -than just throwing them at the raw vertices. Also means I can keep plotting a frame while the next one arrives.

The "hard bit" - the actual Battlezone game - is actually easy, since I am using the wonderful open-source MAME emulator and was simply able to locate the vector display emulation code and hook my stuff into it. Luckily Battlezone does output vectors with decent continuity (i.e. where lines join up they tend to be sent consecutively, which saved me sorting list into some kind of optimised plot order). So basically my hooks in the MAME vector code just convert the floating point vector coordinates into 12 bit integer values (for my ADC) and flag "move" vs "draw" actions. Then the list can be dumped to the TCP socket at the end of the refresh cycle. At the moment I am only outputting every 10th frame to let the microcontroller breathe.

On the mbed side I am using a MCP4922 12-bit dual Digital to Analog Converter (DAC) with SPI serial interface, which can easily be driven from the mbed. The DACs drive a 20kpps Galvo set purchased from ebay (about £100 including PSU and drivers). I also have a 6N139 opto isolator driving the TTL blanking for the laser (a 50mW green DPSS module from Aixiz).

I am still working on the mbed code... at the moment I use a kind of double buffering with 2x16kb buffers, one of which can receive the frame buffer from TCP/IP socket while the mbed is plotting the other. Between plots the mbed checks if the receive frame is complete and switches the buffers if this is the case.

The frame rate I can plot is too slow, and I need to work out how to make it better.  I need to force delays during plotting to allow the mechanical galvos to catch up with the driver signal. These are all <1ms but they add up and reduce the frame rate. Also the lines are "plotted" with "in-between" point calculation to try to keep galvo movement rate reasonable. I need to work out the best combination of delays and divisions to get the best plot with the best framerate. I am also thinking about recognising the text at the top of the display (status text and scanner) and missing them out of the plot (text kills the plot rate)

Still a work in progress, but fun!