Professional Documents
Culture Documents
Picstack Report
Picstack Report
Winter 2019
Worden Barr, Chris Comeau
Stacker Using
LED Matrices
ECE 230
Intro to Embedded Systems
Final Project
Winter 2019
Instructor: Dr. Michael Jo
Chris Comeau
Worden Barr
Table of Contents
Introduction 3
Overview of Project 3
Fulfilment of ECE230 Final Project Requirements 3
User Guide 5
Before You Start 5
To Begin 6
Gameplay 6
Scoring 8
Bill of Materials 20
Introduction
Overview of Project
Using the PIC16F887 Microcontroller, we created a game
modeled off the fairly well-know arcade game, Stacker. Initially, we
were indecisive which game to implement, narrowing down our
options to either Tetris, Stacker, or Snake, all games we were very
familiar with. In the end, we decided that Snake was not as replayable,
and Tetris was too difficult due to the algorithm needed to rotate the
falling tetrominos and handle collisions. Thus, we set our minds on
implementing Stacker. Our goal in creating this project was to
demonstrate our understanding of the PIC architecture, I/O devices,
interrupts, and timers which we learned over the course of our ECE230
class.
In our version of stacker, the player is presented with a 6-LED-wide block bouncing left and right
on the bottom row of the game display. The player’s goal is to stack the LED blocks as high as possible in
order to obtain as high a score as they can.
Some additional features of our project include an 8-ohm loudspeaker which indicates, with a
short note, when an LED block has been placed on the tower and also indicates, with a long descending
note, when the game has been lost. The project also implements a scoring system, displayed on the LCD,
that keeps track of both the player’s score as well as the number of perfectly placed LED blocks in a row.
Lastly, the game speed linearly increases in pace as the game goes on, making the game more difficult as
the player progresses farther in the game.
User Guide
To Begin
Upon connecting the circuit to power, using the provided wall to barrel power supply, the
LED matrix and LCD screen should initialize by lighting up. From here, you are ready to begin
play. In the event that the LED or LCD screen does not light up or appears to be in an error state,
press the black RESET button located just to the right of the LED matrix.
Gameplay
The game begins with a 6 LED wide block sliding back and forth on the bottom row of
the LED matrix. Upon a user pressing the red USER BUTTON to the left of the LCD, the sliding
block will stop where it was at the time of the button press, and a new sliding block will appear
on the row above. However, upon a button press, if a piece of the sliding block is overhanging
the block on the row beneath, that overhanging section of the block will be lost, and the new
sliding block that appears on the row above will be just as short as the cut-off block below. In
addition, the game speed will increase as the user progresses higher and higher on the LED
matrix. If the user reaches the top of the LED matrix with their tower, the display will reset, and
the game will continue as before with the sliding block again at the bottom of the display. If, at
any point, the user misplaces an entire sliding bar, the game will end displaying the final score
on the LCD and GAME OVER on the game board. The objective of the game is to achieve the
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
highest score possible by stacking the blocks of LEDs, one on top of the other, for as long as
possible.
Scoring
Each successfully placed LED on each row of the game display will increase the user’s
score by 10 points. We also implemented a streak bonus in order to incentivise perfect play. This
happens when the player lands their placement exactly aligned with the previous row with no
missing blocks. This will increase the score they get by 10 points per perfect placement.
Circuit Diagram
Implementation
Inputs
The only vital user input we had for our system was a pushbutton. This button, referred to
above as USER BUTTON, served as the sole form of control the user needed to play the game.
The button allowed the user to stop the sliding blocks of LEDs as well as restart the game
whenever the user lost. The push button was wired up in such a way as to make it active-low,
utilizing internal pull-up resistors.
We also had a few other inputs that helped the system run internally. One of these was an
8 MHz high speed (HS) external crystal resonator instead of using the internal clock oscillator to
achieve more accurate time-keeping. We also made use of one of the unwired Port B analog pins
by taking advantage of the floating state. This is used for random sampling in the code to
generate pseudo-random numbers from a seemingly unpredictable source.
Outputs
Unlike our inputs, our system had several user outputs. Our outputs consisted of an LCD
display, an 8 ohm loudspeaker, and four 8x8 LED matrices.
For the LCD, in order to save on I/O pin usage, we configured it in both hardware and
software to run in 4-bit mode rather than 8-bit mode, allowing us to interface with the device
using only six pins.
For the 8 ohm loudspeaker, since the PIC16F887 microcontroller pins cannot output
more than a few milliAmps, and since the loudspeaker needs on the order of 100 mA to produce
an audible tone, we used the BS170 N-channel switching MOSFET to switch the current through
the loudspeaker on and off at a specified rate to produce the desired tone.
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
Figure 3.2 Four MAX7219 Chips Interfaced with Four 8x8 LED Matrices Figure 3.3 MAX7219 Chip
Lastly, for the four 8x8 LED matrices, we acquired a single unit of four cascaded LED
modules (Figure 3.2) such that the outputs of the first module were the inputs of the second
module and so on. Rather than having each row and column of the, in total, 8x32 LED matrix
individually interfaced with a single pin on the PIC16F887, the device we obtained came with
four MAX7219 microcontrollers (Figure 3.3) pre-connected to the LED arrays, allowing us to
interface with the entire array using a method similar to SPI with only 5 input pins: VCC,
Ground, Data In, Clock, and Load.
Figure 3.4 Scope Capture of MAX7219 DataIn Port with Bottom Row of LED
Matrix Lit as Follows: 11111000
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
The software system flow is depicted by flowchart/state machine below. This is a very
high level overview of how the program functions. The specifics in each state will be clarified in
sections below.
Move Block
The move block section is also fairly simple in that it is only responsible for the
movement calculation and animation of the block back and forth. The block has a position
horizontally within the column as well as a direction. The game makes the calculation for where
the block should be and then displays this on the corresponding column using the binary
representation of the block to light up the LEDs in that column. This happens repeatedly while
constantly check for if the user has pressed the button. If the user does press the button, the game
will enter the placing state.
Place Block
The place block section of the code handles a few different functions at the same time.
This section is response for the animation of placing the block, the calculation for the size of the
block for the next row, the score incrementing, making the placement sound, and speeding up the
game. It first calculates the size of the next block by taking the intersection between the placed
row and the previous row. The horizontal position of the next block is also pseudo-randomly
calculated. This is used to display the animation for the block that was just placed by flashing the
calculated row on and off a few times, while also incrementing the score each flash for a
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
seemingly smoothly incrementing score. This also triggers the sound to begin by switching the
CCP1 mode to the “Compare with toggle output” mode. The interrupt plays a tone for a few
periods before stopping and disabling the interrupt by changing the CCP1 mode back to disabled.
Once this animation is done the game then speeds up by decreasing the time between each game
tick. The game then decides if it should go to Game Over if the player lost by missing their
placement, New Screen if they have reached the top, or simply movement again if nothing
special happened.
New Screen
If the player reaches the top of the screen, the game will perform actions to create a new
screen. These actions are very similar to the reset discussed earlier, with a few key differences.
The most important differences are that score is not reset, and the the stack partially carries over
from the top. This means that the game takes the last row placed on the top and puts it on the
bottom to allow the player to continue from where they were before the new screen. Other than
this, the functionality is almost identical to that in Reset.
Game Over
The Game Over state is reached when the player makes a placement that does not
intersect the previous row. This disables the normal movement or placement animation in favor
of full screen-length display of the words “GAME OVER” using the LEDs. This is accompanied
by a new sound that instead moves downwards and stabilizes before ending. The score remains
on the LCD for the user to view. The system then waits for user input while flipping between the
words. Once the button is pressed, the game then enters the Reset stage and start the game over.
This would be functionally equivalent to pressing the dedicated reset button.
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
Cycle Structure
Whenever the game performs calculations and then renders onto the display, the game
follows the same pattern almost without exception. This is so that the user input is the closest to
both what has been calculated and what has been displayed on the LED matrices. This makes the
game feel more responsive and less like the input is lagging behind the game. The structure also
allows us to separate and compartmentalize each section of code so that they are easy to expand
and modify in the future.
Matrix Communication
In order to drive the LED matrices, we had to interface with the MAX7219 chip. This
component took in three varying signals to convey the data required to control the LEDs. This is
depicted in the diagram above which shows how a signal is sent to the device. We managed to
accomplish communication such as this through the implementation of an existing Arduino
library onto the PIC16F887. This allowed us much easier interfacing with the LED matrices and
allowed us to do much more powerful operations in a shorter development timeframe. This saved
us a ton of time in the long run because it helped create the base for our project to work from and
is cited in the Resources and Acknowledgements section. This code was readily scalable and
versatile so that we could use it in any way we needed. It also clarified some questions we had
about the control protocol and how messages are sent to multiple instances of the device in series
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
with each other. We also pulled code from Arduino directly in the form of the shift out function,
which allowed us to use a pin with a clock to send a series of data bits easily.
Our testing procedure was mostly iterative and was best tested through gameplay,
especially in the later stages of the project.
Speed Bumps
One of the larger issues we ran into during the project that had been persistent since
almost the start of the project was an apparent disjoint between the calculations and the display.
This had been arising due to the fact that we were using interrupts to drive our game ticking.
They would trigger every X ticks and do the main calculations for the game. We could not have
the display code within these interrupts as they bog down the interrupt due to the sending of the
data to the LED matrix taking a considerable amount of time compared to everything else. This
forced us to separate these so that the calculations alone executed in the interrupt. While this
worked in the beginning, as we added sections within the game tick in the interrupt, we noticed a
larger and larger discrepancy between what was calculated and what was displayed. This became
hard to play due to the user using feedback that did not correlate with what was happening to
play the game. Our solution to this issue was to pull the calculations out of the interrupt and
instead have game execute in a main loop that happens every game tick. This made the
calculation and the display happened almost together which made the game easier to play.
Another strange issue arose when we attempted to create the sound for the placement of
each row. We attempted to create the short pulse sound by enabling the CCP1 interrupt when we
wanted to make the noise and disabling it when we did not. This succeeded in creating the
desired sound effect, but also created a periodic, low frequency ticking noise. This was a difficult
issue to debug as it was hard to trace where exactly the noise was generated. The root of this
issue was actually due to the fact that despite the interrupt being disabled, the toggle on the
CCP1 pin still happens once every full clock cycle without calling our interrupt handler function.
This meant that we needed a different solution besides disabling the interrupts. The solution that
we arrived at after advice from classmates was to instead reconfigure the CCP1 module to a
disabled mode when we did not need to create sound.
Overall, we implemented a complete game that is both fun and simple to play which
creates a positive player experience. We could have added additional features such as a scrolling
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
new game or scrolling game over, but felt that it would not enhance the game enough to warrant
them and instead we implemented other features during our limited time.
Bill of Materials
1 PIC16F887 Used to run the game and for all inputs/outputs $0.00*
1 4 in 1 8x8 LED Matrix Used as game pixels for main gameplay display $10.95
Total $10.95
* Already possessed piece for no additional cost
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
Special thank you to Dr. Michael Jo and the Rose-Hulman ECE Department for guiding
us through any issues we had and providing the resources to make this project possible by giving
us a knowledge base to use in the future. Also, thank you to our fellow ECE230 classmates for
input and feedback on the game as well as playing it.