The PIC Tetris game (PICtris) spawned from a recent question by RetroBrad in the forum. He wanted to know how to manipulate LEDs and draw 2D graphics. I'm more of a practical kind of guy and in the past, graphics were never an area of concern. I was intrigued to delve into the world of 2D to find out how things tick.

The 64 LEDs and four buttons are controlled by a single PIC (18LF4520) and two AA batteries. The source code operates very efficiently, and the program is extremely responsive. I was worried about the latter as I was determined to use algorithm based graphic rotations as compared to predefined constants. From here I could use a similar approach to create other interactive games!{nomultithumb}

NOTE: Tetris was developed for Swordfish Basic; the source code will compile under the free Swordfish Special Edition version.

Before I press on, here is a video of the completed Tetris game

As always, new features are a must! Since the above video, I have added the following:

A splash screen that displays "TETRIS" when the game starts.

High scores - your efforts are recorded in the EEPROM.

High power darlington driver to brighten up the display.

All of the above features are incorporated in the source code (found below).

Also, here is a recently completed version of the game - with audio! (Big thanks to DomS from Digital DIY for this project video)

Enrico Castellani also made a version of the PICTris board, and has been kind enough to share the Eagle PCB layout files. You can find the files and a video demonstration in the comments below.

Creating 2D Graphics

In the Tetris game, graphics are treated as 8x16 pixel objects. To ease the overhead of graphic design, I made an Excel spreadsheet that does all of the hard work for you.

There's an 8x16 field where you can place an "x" for each block of the object. Any block with a "x" will be formatted to look as it does below (I found that approach easier to interpret compared to scattered x's). The spreadsheet will calculate and display the Swordfish code required for the graphic! Simple. Here's a screen shot:

Create & Display Text

The spreadsheet can be used to create any object, including text. I recently wanted to add a small feature - a splash-screen. Using the graphic designer made it extremely easy to do.

I put an "x" in all the spots that would make up the word TETRIS on the 8x16 display. I had to get a little creative and split the word into two columns as shown on the right.

If you'd like to look at how I used the object as a text - browse through the source code (listed below), there will be a routine there called "SplashScreen".

Graphics on a PIC

There are several avenues to take when working with 2D graphics. I explored the mathematics behind two approaches: trigonometry (rotating Cartesian coordinates) and 2D affine matrix transformation. Both of them sound like you need a university degree to understand, though they are really quite simple in application. I originally used trigonometry to rotate the objects, though affine matrix transformation was much simpler and more importantly, faster.

What's going on? The array pSource contains graphic information for the object. Each byte represents a column of pixels, which can be referred to in X,Y format like so:

pObject(X).Bits(Y)

pObject is of type Word. This means that each index has 16 bits (two bytes). This allows two 8x8 displays to be joined and form a single 8x16 display. Consider any object in the display:

Keeping in mind that the top left hand corner is pixel 0,0: There are only four pixels that are enabled, they are:

X = 3, Y = 2

X = 4, Y = 2

X = 5, Y = 2

X = 4, Y = 3

The above information can be placed into pObject quite easily:

pObject(3).Bits(2)

pObject(4).Bits(2)

pObject(5).Bits(2)

pObject(4).Bits(3)

Now we have an array of pixel information that can be used anyway we want to.

Rotating Pixels

In the Tetris game, I was originally rotating objects CCW, though it has now changed to CW. As this example was written before that change, it will focus on turning an object CCW. If you want to spin an object the other way, then check the source code - both formulas are included. CCW Rotation Formula

X2 = (Y1 + PX - PY)Y2 = (PX + PY - X1 - Q)

Step 1

Define the origin (PX,PY)

The origin is the pixel which the object is to rotate around. For the above object, it would be wise to choose pixel (4,2). Why? because that coordinate will ensure the object remains at the same location as it spins around (consider what would happen if you spun a circle around anywhere else but the centre..)

Step 2

Define the object length/width (Q)

We are working in a single pixel by pixel environment. This means that the length and width (Q) of each pixel is always 0. I have included this step for use with other conditions.

Schematic

Some considerations with this schematic:

I have used two 8x8 common cathode LED matrix. I haven't included any pinout into for them as the pinout varies so much between manufacturers. You will need to check the datasheet for your specific matrix.

The Y connections are the positive side of the LEDs.

The X connections are the negative side of the LEDs.

Resistors could be any value under 200ohms (lower until you have the desired brightness - I used 80ohms).

Please try a "blinky" program on the PIC should your circuit not fire up and work the first time. I can guarantee you that this layout works; I used the netlist from this very schyematic to develop my PCB.

The symbol of a triangle with a line through it signifies Vdd (5V). Such ULN2803 Pin 10.

Other tips:

For common anode LED type displays; you will need to modify the source code. You will have to change the ULN2803 for a 8-Channel Source Driver such as UDN2803A.

Click to enarlge the image. Note: I have used the low voltage variant of the above PIC Micro, its part number is 18LF4520.

The PCB

Due to popular request, I'm also sharing the Gerber files for the PCB shown below:

Thanks for sharing this with us all. I'm looking forward to making this with my son as his first micro project.

As we have heaps of them, we will be using LED's instead of LED matrix's, I'm trying to work out the polarity of the ones used in your schematic, do the Y's represent the Anodes or Cathodes of the LED's please?

The devices I was using were common cathode types. 16-bits of row (Y) data are shifted in and then the appropriate column (X) is enabled. With that said, it is extremely easy to use either common anode/cathode devices - just a couple of minor edits.

Thanks for clearing that up Graham, by the looks you aren't using the dual color mode? So i'll make a pcb with our mini-cnc to use 128 x 5mm LED's instead. This way the code doesn't need to be changed as i'll make the 128 LED's appear the same electrically as 2 x 8x8 LED Matrixes.

Be more than happy too! To cut down on wear and breakages on the bits (which cost us a bundle), we use isolation routing, so it's quite a big job to create th NC files from the vector graphic layout. I've just finished the LED portion of the board, after sorting out how to get the Cathode columns lined up vertically while connecting the Anodes horizontally.

When we're done, assuming it actually works, I'll post a vid of the cnc in action making the board (computer controlled router = COOL!), and put up the NC files and my drawings to make it easier for those wanting to replicate it.

I see you have a debouncedelay constant defined, so i'm guessing we can safely put in a reset switch from the Pos power input?

Hi Graham, i managed to make an Eagle layout for your project, and tweaked it a bit, adding a power supply section using a LM7805 (to use a 9v battery).
The led matrix i used is made by LITE-ON, the model is "LTP-14088A-03"
I produced a master ready to be printed and used to etch a pcb.