This is a project I used for learning how to use simple SMT(Surface Mountable Technology) parts. The part with the closest pin spacing is a ULN2803 transistor array for driving the LEDs. The rest are 1206 resistors and capacitors. The processor is still in DIL package, this made routing much easier and allows the use a single sided PCB. For the power supply and connectors I used non-SMT parts, too.
You can click on one of the images to see a bigger picture.
This picture shows a breakout from the top side at the start of a game. The
connector on the right side is for the speaker, the ones on the left side
are for controller and power. The 5 single pins are used to program the
processor in circuit.
Here you can see the solder side: Driver array, current limiting resistors
and other supporting SMT parts.
This is the controller I built for my breakout.
After power-on breakout displays the title screen: the last score alternating with a scrolling "BREAKOUT" text. To start a game at any time just press the button. Press the button again to release a ball from the top left side.
While playing you control the the bouncing pad with the controller. Use the pad to bounce the ball to the top until all bricks of the wall are torn down. You have to hit every brick twice until it shatters. After you destroyed all bricks a new wall appears. If you miss a ball the game is over and the number of walls you destroyed so far will be shown.
Due to the small display size it is not possible to reach all positions by following the rules of physics exactly. So I added a random component when the ball hits the front part of the pad as seen from the ball's movement. Most times the ball bounces back just as dictated by the laws of physics, but sometimes he bounces from the rear part of the pad. This is illustrated in the following graphics:
To set the parameters press and hold the button while turning on breakout. The screen is filled from the top and a sound is played. Release the button after the screen is completely filled and the sound has stopped.
The number you can see is the speed of the game, smaller numbers are faster. A good value for starters is between 30 and 40. Change the speed with the controller and press the button to store the new value.
The next parameter is the controller sensitivity. It controls how many pulses have to come from the controller until the pad moves one step. For most quadrature-encoders this will be 1. A good value for the original Amiga 2000 mouse is 4. Press the button to store the new sensitivity and you reach the title screen.
The power supply is a simple 7805 linear regulator behind a bridge rectifier. So you can use any power supply brick rated over 9 V DC / 6 V AC at 200 mA. It is safe to use up to 30 V DC / 20 V AC, but the 7805 will get very hot.
Breakout uses an incremental quadrature encoder as controller. This is basically a rotating knob which has no stop. While the encoder is rotated it generates two pulse streams. The direction is encoded into the phase between these two streams. This sounds more complicated than it really is, see below for the explanation of the source code which reads the controller.
Every mechanical mouse has two of these encoders, so one of the possible controller types is an Amiga mouse. A mouse for Atari ST needs a small adapter, the pinout is different. I have built my own controller from an encoder with 30 steps per revolution with an integrated push function, so that I don't need an extra button. It is also possible to use the Atari Driving Controllers with an adapter, but they have a very low impulse rate, you need nearly a full revolution to move from one end to the other.
The ATmega8 processor is a powerful microcontroller with 8 KBytes program flash ROM, 1 KByte RAM and 512 Bytes EEPROM. In breakout it runs with its maximum clock of 16 MHz.
The power, clock and reset pins are connected as recommended by Atmel in their datasheets and application notes. I have even filtered the AVCC supply although this is only necessary when using the ADC. You can replace the 10 µH coil with a piece of wire and leave out the 100 nF capacitor on the AVCC pin. The 1N4148 diode on the reset pin prevents the AVR from entering parallel programming mode. I use the in-circuit serial programming mode for program download. The necessary connections are available on 1 mm pins.
The LED array is multiplexed, one row after the other is active, the others are turned off. The processor can only drive one LED at once, so I use a ULN2803 transistor array for the rows, 8 NPN darlington transistors with a common emitter pin. Every transistor can switch up to 500 mA which is enough for all 5 LEDs in a row.
For the lines I use a normal port pin with 33 Ohms resistors as current limiters. This leads to 25-30 mA per LED: The AVR delivers 4 V at 30 mA, the ULN2803 loses 1 V, the LED takes 2 V, this leaves 1 V for the resistor, so for 30 mA a 33 Ohms resistor is the right one.
I could drive the LEDs with a much higher current, but they are not much brighter and I would have to use drivers for the lines, too.
The speaker is connected by the same driver array as the LEDs to a PWM output. The output volume depends the the type of speaker and can be adjusted by changing the 180 Ohms resistor.
I have created a single sided PCB layout for breakout. The processor, power supply and LED array are normal through-hole parts, the rest are SMD, but nothing really small. The smallest pin spacing is still 1.27 mm, only half as wide as most normal ICs. If you don't want to etch your own board, you can use the schematic to build breakout on a piece of veroboard fully in through-hole technology.
If you want to use my layout you need to etch you own PCB. You can find more information on how to do this at the Homebrew PCB mailing list. I have included Gerber, PDF and 600 dpi PNG files of the layout inside the archive, use whatever format you can handle best.
The placement info is on pages 2 and 3 of the PDF file. I suggest that you start soldering with the SMD parts because once you add parts on the top side the PCB is no longer flat. Tin the pads with a minimal amount of solder first. Put the part onto the pads and solder one pad after the other. Remove any solder bridges with solder wick. Be careful with the 1N4148, it has a tendency to roll away. The value of the capacitors is not marked, so don't confuse them.
Once the SMD parts are finished you can solder in the through-hole parts. Start with the jumper wire, it is easy to forget. I used sockets for the microcontroller and the LED array. Mount the heat sink on the 7805 before soldering it in. The connector for the speaker is the same as on most PC speakers, a 4 pin 2.54 mm connector with the two inner pins missing. The 5 single pins are for the ISP connection needed for programming.
I have built my own controller using a quadrature-encoder with integrated button-press. You can also use any mouse with encoder outputs. The connector is wired for an Amiga mouse, but you can also use Atari ST mice with an adapter or the Atari Driving Controllers for the VCS 2600.
Before you can play breakout you need to program the ATmega8 processor with my software. This is done via the 5 single pins, a small interface to the parallel port of a PC and a piece of software. There are several different ISP software solutions and interfaces available, I use Uisp. The programming interface and the controller interface have pins in common, so don't connect a controller while programming. First you need to set the fuses to activate the external quartz and configure the brown-out and reset circuit. The low fuse needs to be set to 0xde, the high fuse to 0xc1. Then you can download the breakout.elf or breakout.srec file depending on your ISP software. After that you can remove the interface, connect the controller and start to play.
I wrote the software for breakout in the computer language C. I used the AVR target of the GCC compiler suite, see my main AVR page for links to more information and download. I used binutils 2.15, gcc 3.4.3 and avr-libc 1.2.3 for development.
The display is handled by the timer 0 interrupt running at 7.8 KHz. There are seven rows and every row is brightness controlled by 4 modes, so a full display cycle happens 280 times per second. The brightness control is limited to 2 different values. The lower brightness is displayed 4 times as long as the higher brightness. Due to the non-linear relation between current and brightness the other possible values don't look much different.
The data to show on the display is stored in the
Led0 is displayed in the first
Led1 is displayed in the other 3 cycles.
After a full display cycle is finished the global variable
Sync is set to 1. This is used as a stable time base by the
rest of the program, just like most console and PC games
use the VSYNC signal.
Another thing happening at the timer 0 interrupt is the reading of
the controller. First the controller pins are debounced. Most controllers
are mechanical and the switches take some time until the signal is stable.
Once the signal is debounced the relative movement is stored in
Mx. The button presses are checked outside the interrupt by a
small state engine called
runbuttonfsa() which uses the
debounced pin data.
The sound is generated by a PWM output from
timer 1. I don't use the PWM as a
DAC replacement, the output is a digital signal with a
fixed pulse to pause relation of 50% with a varying frequency. A tone is
playsound(). After the supplied length is over the
timer 0 interrupt turns the sound off again. There can only be one
tone active at a time.