light_mode dark_mode

Cookies & Things

Navigation
Home Blog Resume
External Links
GitHub open_in_new Twitter open_in_new

Coding Tetris from Scratch on an AVR Microcontroller

For the final project in Professor Tony Givargis’ embedded systems course, we were given the vague task to “do something interesting.” So, I made a version of Tetris on an ATMEGA32.


For all previous projects, we had only used a 20x4 character LCD and a 4x4 matrix keypad for human interface. This was the first thing I wanted to change. Instead of a boring character LCD, I decided to instead use a 128x64 dot-matrix LCD. The communication was very similar (it could even emulate a character LCD) but it allowed for pixel-by-pixel control, which was perfect for Tetris. Second, I decided to scrap the number keypad for a Nintendo NES Controller. This would make it feel more “gamelike,”

Unfortunately, these decisions came with the need to write the drivers from scratch for both the LCD and the controller since I couldn’t use the code I wrote on the last projects, but that was a challenge I was open to facing.

First, the LCD. After reading documentation and understanding how the memory layout is mapped to the screen, I wrote code that would update certain parts of the screen at once. Because the layout is a bit funny, and I wanted to have the screen in portrait rather than landscape, I wrote functions to abstract away the memory arrangement in favor of straightforward X and Y coordinates using some simple math. From there, it was pretty easy to modify pixels on the screen. The only final issue was that I had to modify 16 pixels in a vertical line at once. While I could have made code that read the memory and then updated certain pixels and wrote them back, that seemed inefficient and I decided to instead work around it in my game design, cleverly lining game and block borders up with these 16px lines so that drawing would be much faster.

Next, the Nintendo controller. This was pretty easy, as the controller functions using a parallel-in serial-out shift register. All I needed to do was latch the data, then cycle the clock pin while reading the data pin each time.

Lastly, to put it all together, I had to write the actual game logic. This turned out to be the hardest part, as there are a lot more edge cases in Tetris than I though, especially when it comes to piece rotation and bumping a piece if it would fit somewhere other than its current location when rotated. Regardless, I figured that out as well, and used some randomness created by how long it takes the user to start the game from power on to change the piece set each time. Randomness in embedded systems is incredibly hard to do if you want true random numbers (especially when it comes to cryptography) but for the purposes of a game, this was an acceptable approach to me.

Finally, below is a demonstration of it all working together! Here’s the C Source Code on GitHub as well.

Thank you for reading!