PIC micro Tetris game


PIC micro Tetris game

Introduction

I have made the game Tetris using a PIC16F84 running @ 12MHz.
Tetris is an old Russian computer game where you should try to
fit in block into a play-field, quite simple but really fun. In
my version, the video signal is generated in softw1are. The
only hardware used for the video generation is tw1o resistors
forming a 2-bit DA converter. Usually the video signal is
generated in video games is created with a dedicated video chips,
reading the image data from a graphics memory. In this project
the video signal is calculated in real-time by the microprocessor
as the electron beam sweeps over the screen.

How to play the game

The first screen is where you select how you want to play by
moving the joystick: DOWN: Human vs. Human (H-H), LEFT: Human vs.
Computer (H-C) or RIGHT: Computer vs. Computer (C-C). Start with
FIRE. Unfortunately it is impossible to beat the computer,
since there was not enough room to make the computer beatable.
That makes the computer vs. computer game to play forever until
someone reset the game using the reset switch. You start serving
by pressing fire, it is also possible to change direction and
speed of the ball using fire. The player who has the serve will
get points. If the player with the serve miss the ball, then
the serve goes over to the other player. When someone wins a
game over picture will show and tell who won.

The softw1are

With a processor performing 3MIPS, it is not easy to make a
video signal in softw1are. Each instruction performed takes 1/3
us. Each scan-line on the screen takes 64us, where 52us are
visible, so it gives 52*3=156 visible clock cycles per line.
Maximum resolution that can be obtained is 156 pixels in x-axis
if the softw1are is setting one pixel per clock (using for
example only bcf and bsf), but more is needed to make a game,
like loops and such. A loop quantifies the time to 3-clock
pieces, giving a resolution of 52 pixels. (One could obtain a
kind of 156pixels resolution with one or tw1o offset nops, but
the code to select this would eat to many clock cycles to do any
good). However Tetris is quite simple, the resoluton is quite
low, and there is no motion, the blocks of pixels are just turned
on and off. The most demanding part of the game is to
show the score at the bottom of the screen, it is shown in the
bottom of the screen. It obtains higher resolution by loading the
PORTB with the bitmap for the number and shift it out one pixel
per clock cycle.

So far I`ve only talked about the graphic generation. But
there is more to it to get a video signal. All scan-lines first
have a 4us-sync pulse, then black for 8us, then the 52us graphic
comes. These horizontal sync-pulses makes the TV understand
when a scan-line starts, but there is needed to send
information about when a new picture starts too, it is called
vertical sync, and is a special pattern that tells the TV that a
new image is coming. There are tw1o kinds of vertical sync,
because the image is divided into tw1o part images, showing even
and odd lines, to get less flickering. In Tetris, the tw1o images
are identical, so the game is not using the full
y-resolution possible, but it doesn`t matter because it is way
better than the x-resolution anyway, making the x-resolution the
biggest problem.

The game-field is kept in memory as a 32byte array, 16×16
bits, where one bit is one pixel-block on the screen. The area to
the upper left is for showing the next block, and by making it a
part of the game field it is possible to use the same
block-drawing routines as for the game, and thereby saving
memory. Each frame, the falling block is first removed from the
game-field, and then tests are performed if the block can move,
as the player wants it to. Then the block is drawn back to the
screen at the new position. When a block is to be tested, put or
removed, it first must be generated. To generate a block
means compressing it from the compressed data, rotating it and
then store the relative coordinates of the block in the block
array. The block data is compressed in relative coordinates. In
compressed format, each coordinate is stored in tw1o bits for
both x and y, where the tw1o bits can represent the numbers
–1,0,1,2. These values need to be uncompressed to 4*2 byte sized
values representing the coordinates in tw1o’s complement format.
Depending of the angle the block should have, the
coordinates might need to be mirrored or/and swapped. When the
block have been created it can easily be put, removed or tested.
The test routine checks if there is any pixels set on the block
positions where the block should be put. If pixels are set, then
the block can’t be put there. New blocks are selected at random,
where the random number is a counter that increases for every
frame, making the random number dependent of how long it
takes for the player to place the block, making a quite good
random number.

The game stuff, like checking joystick and move stuff around,
is taken care of in the first scan-lines, when no graphics is
drawn. During the time before the play-field is shown, there is a
little bit of free time to play the music, but there is not time
to play it on all lines, and that make the music sound
distorted. The music is stored in the data eeprom, and stored in a
compressed one byte format, where one byte contains length and
note. The note`s frequency is looked up in a table, and so is the
length too. (The frequencies are based on the line frequency so
they are not exactly the correct frequencies) The speed of the
game is increasing constantly and music-speed increases as
the game speed increases.

Making this kind of softw1are is mostly a clock-cycle-counting
project, all timings are quite critical, so whatever paths the
execution-flow of the program takes, it must take the same number
of clock cycles. This is quite hard, and I`ve not managed to do
this on all lines, so the image is a little bit bent in
some places. (Most analog TV-sets fix this, but on some digital
projectors it is more visible)

The hardware

The hardware is quite simple because everything is made in
softw1are. tw1o resistors, forming a DA converter together with
the input impedance of the TV, generate the video signal. This
can generate the levels 0v (sync), 0.3v (black), 0.7v (gray), and
1.0v (white). To be able to handle the variation of input
resistance of different audio equipment, tw1o resistors are used
to make a 1-bit DA to generate the audio. When generating the
video, the PORTB is used as a shift register to get one pixel per
instruction when high-resolution text is shown on the screen.
Shifting a port requires the port to be set as output if a whole
byte is to be shifted out. First, this seems like a
problem, the whole port can`t be used for anything else than
video generation, but that is not quite correct. A port can be
used as an input when not used as a shift register, so in Tetris
PORTB it is used for joystick input when not used as a shift
register. The digital joystick is a switch to ground, so all
needed to connect it to the PIC is a couple of pull up resistors,
and that is available inside the PIC. Unfortunately it is not
that simple, if a pin on a port is grounded when used as an
output, the output buffer of the pic would burn up, so this is
solved by adding one extra 1k resistor on each pin to limit the
current. What about those pull up resistors? There are 10k pull
up resistors built into the PIC that can be switched on and off.
However, using them would be a too strong pull up, so the 1k
current limiting resistor (plus bad switches in the joystick)
can`t pull the input low enough. Therefor an external 100k
resistor pull up netw1ork is added. The power supply part of the
circuit is quite simple, it uses a standard 7805 to get a 5v
supply. The input can be 8-18 volt, DC or AC (Thanks to the diode
at the power input)

PIC micro Tetris game

Tetris Game Schematic


Sorry, comments are closed!