Monday, September 20, 2010

UVOG Arcade Machine

Umpqua Valley Opensource Group is building a classic-style Arcade machine (with a few innovations.) I am in charge of drawing the sprites for one of the games, so I spent the weekend studying 8-bit video game palettes.

I settled on using limitations similar to the 8-bit NES. The NES itself only had around 54 possible colors on the system palette (technically there were 64 color indexes, but 10 of them were black and two were white!) There were also many additional limitations on how many colors could be used at a time on the screen as well as how many could be used per tile or sprite.

I am using the same basic ideas to restrict the artwork for this game, but I have created an expanded palette using a full range of 64 different colors. I also hand-tuned the choice of colors, and re-ordered the palette in a more sensible way.

Because the Arcade Machine is an Open Source Project, my palette is Open Source as well. I am calling it the UVPALETTE. It is available as a GPL (GIMP PaLette; which is usable in mtPaint also, and is basically a text file with a list of RGB values) at the following address:

I also have a demo of the palette here is a PNG file:

In order to make discussing and working with the palette easier, I have prescribed a canonical name for each color:

Names of colors on the first row (0x00 - 0x0F) Black, Dark Blue, Dark Cerulean, Dark Mint, Dark Green, Dark Lime, Dark Yellow, Dark Tan, Dark Orange, Dark Red, Dark Rose, Dark Orchid, Dark Violet, Dark Indigo, Forest, Charcoal.

Names of colors on the second row (0x10 - 0x1F) Gray, Blue, Cerulean, Mint, Green, Lime, Yellow, Tan, Orange, Red, Rose, Orchid, Violet, Indigo, Brown, Slate.

Names of colors on the third row (0x20 - 0x2F) Silver, Light Blue, Light Cerulean, Light Mint, Light Green, Light Lime, Light Yellow, Light Tan, Light Orange, Light Red, Light Rose, Light Orchid, Light Violet, Light Indigo, Jade, Chalk.

Names of colors on the fourth row (0x30 - 0x3F) Pale White, Pale Blue, Pale Cerulean, Pale Mint, Pale Green, Pale Lime, Pale Yellow, Pale Tan, Pale Orange, Pale Red, Pale Rose, Pale Orchid, Pale Violet, Pale Indigo, Gold, White.

Here is another version of the palette demo with the prescribed color names listed for quick reference:


Friday, September 3, 2010

Robot Logic, Part 1

UVOG has decided to make a robot as a club project. It will consist of Open Hardware and Open Software, and be easy for people to make at home on the cheap by repeating our steps.
My specialty is the software. So far, we have decided to use a handful of ATtiny2313 chips to control the various appendages and modules of the robot. The ATtiny2313's will be hooked up to a root controller of a type that is yet to be determined. So, I'm going to be learning AVR assembler to program the ATtiny2313 chip, but for now, I've been doing my experimenting with C. Assembler actually looks easier to use in this case, since I am so interested in direct pin manipulations and our memory space is so limited (2k program memory plus 256 bytes of SRAM and 256 bytes of EEPROM.)

One of my eventual goals is to learn the self-programming functions of the AVR instruction set so that I can reprogram any chip in the robot in place without any additional wiring other than that which we are using to send instructions from the root controller to the sub-controllers, but for now (until I have taught the chip how to do this), I have to use an external programmer.

Programming the Microcontroller

I've used three different programming boards for the 2313 so far. The first one was a hand-made parallel port programmer, which pulled its current from a USB connector. The second one is a board from Evil Mad Scientist which connects to the PC entirely with USB, through an adapter. Both of these were ok, except I kept having to pull the IC from the programming board, and put it on my breadboard for testing, then after failing (it is inevitable), pulling it again and returning it to the programming board. The third programmer is also a hand-made one, but this time it has two female headers running the length of the chip that I can plug test wires into. It also has a six-pin connector to attach or detach the parallel cable, which is a lot easier than running around behind the computer every time.

My debugging process now looks like this:

Plug the IC into the programming board. Plug the USB and Parallel into the PC, and plug the other end of the Parallel into the programming board. I will leave the IC , the USB and the Parallel (on the PC side) plugged in the entire time I'm working. The only cable I will unplug during the debug process is the programming board side of the parallel cable.

So far, I have not been using the UCSK, MISO, MOSI, or RESET pins (a.k.a., pins 1, 17, 18, or 19) in my actual experiment, so I can leave the IC on the test board, and hook up my other components by jumping a wire from the headers to the breadboard.

I unplug the single wire going from GND (pin 10) to the breadboard's ground bus, and I plug in the six-pin parallel connector, then run "make", and my toolchain compiles and automatically uploads the compiled code into the chip. Next, I plug the wire from pin the breadboard's ground bus back into pin 10 (GND) on the header, and I unplug the six pin connector, which releases the RESET pin causing the chip to boot up and run my code.

When I want to test again, I simply unplug GND and plug the six pins back in.

If I simply need to reset the chip to test the boot sequence again without reprogramming it, I can either apply a GND lead to the reset pin, or plug the 6-pin parallel connector in momentarily to accomplish the same thing.

How I Plan to Use the Chip

The 2313 has a nice amount of general purpose input/output pins. They have given names to the pins to indicate how they are treated internally as "ports." Along the "left side" of the chip, we have RESET (which doubles as PA2), then we have PD0, PD1, PA1, PA0, PD2, PD3, PD4, PD5, and GND. And going up the right side of the chip we have PD6, PB0 through 7, and VCC (our voltage source.)

For most of the chips in this project, I plan to use them in the following way:

Pin 1, 10, and 20 are keeping their purposes as RESET, GND, and VCC. Although repurposing RESET is possible, it is dangerous because it disables the programmability of the chip (RESET is normally held low while the chip is flashed.)

All the other pins down the left side are going to be used as inputs, in addition to pin 11 (the bottom pin on the right side.) This gives us a total of nine input pins which are known internally as PORTA and PORTD (with the exception of PORTA bit 2, which is reset.) When used as inputs, the values are actually read from the ports called PINA and PIND. All of the remaining pins on the right side will be used for outputs, which is known internally as PORTB.

Quick Review:
Input: 2 bits of PORTA and all 7 bits of PORTD. (actually PINA and PIND)
Output: All 8 bits of PORTB.

Some of our inputs have special functionality that we will be interested in, so we need to be careful to reserve those for the purposes we intend to use. Specifically, pin 6 and 7, a.k.a., PORTD2 and PORTD3 are the lines used to raise INT0 and INT1. INT0 is interesting to us, because it is the only regular user-definable interrupt that can raise the micro-controller out of its power-saver or sleep condition. (I don't remember exactly the term used for this particular sleep mode at the moment.)

I plan to use INT0 and INT1 to "talk to the chip" from the root controller.

This leaves us with the following general purpose inputs, which I would tend to utilize in the following manner:

Most Significant - - - - - Least Significant
PD6, PD5, PD4, PA1, PA0, PD1, PD0

If I care to get this into a single byte (sans the high bit), I think I can do so by performing the following bitwise operation:

MyInput = ((PIND & 0x73) | ((PINA & 0x03) <<>

Because the ATtiny2313 uses internal pull-up resistors, the default state of all the pins will read as high values (1). To toggle a pin, we must apply ground to it, which will lower it to zero. In other words, when we are dealing with inputs, "low means active." We might, therefore, want to inverse the value of all bits of input, so that we can logically use 1 to indicate active and 0 to indicate inactive.

Gotta run, I will post more on this later.