A tiny game console based on Attiny85
I had some Attiny85 chips lying around my desk and a few free days, so I went looking for projects. I found that Daniel Champagne had already created several games for this chip. His schematics were missing some resistor values, but he replied quickly when I emailed him.
This isn’t a retro gaming device. You can’t play 8-bit Nintendo games on an Attiny85. But you can play games specifically written for it, or write your own.
The OLED Problem
The project uses an SSD1306-based I2C OLED screen. I had a few of these in my lab. I compiled Daniel’s code using the ssd1306xled library from Github. It compiled fine. Nothing appeared on screen.
I tried several different OLED screens. None worked. I tested them with the Adafruit library. They all worked fine. The screens weren’t the problem.
The Github library is a port of the AVR TinuSaur project, and the original is hosted on BitBucket. Searching led me to a Tinusaur article describing compatibility issues. Most OLED screens from China claim to use SSD1306 but sometimes use SSD1315 or SSH1306 instead.
I cloned the original repository and modified it for my Attiny85. Still nothing. Digging into the code, I concluded the I2C implementation itself was broken. You can follow my debugging journey in this issue thread.
The Fix
The Attiny85 has 8KB of flash memory. The game uses about 6KB, leaving 2KB for the OLED driver. Libraries like Adafruit’s or Tiny4kOled would push the program over 8KB. I needed the lightweight ssd1306xled library to work.
I took the latest SSD1306XLED library and replaced its I2C implementation with the working one from TinyI2C. That fixed it.
My working fork is on Github.
The Schematic
While researching the OLED issue, I found a modified version of Daniel’s project by Dave on the element14 community. Dave optimized the Attiny85 pin usage. If you’re interested in this project, watch his video.
PCB Design
The goal was simple: make it as small as possible using SMD components. I used 0805 resistors. They’re small but still solderable by hand.
For quick projects I use EasyEDA instead of Altium. Here are the components I used:
| Quantity | Manufacturer Part Number | Manufacturer Name | Notes |
|---|---|---|---|
| 1.0 | ATTINY85-20PU | MICROCHIP | Attiny85 IC |
| 5.0 | SKQGAFE010 | ALPS ALPINE | Push button |
| 2.0 | MCWR08X2001FTL | MULTICOMP PRO | 2K resistor |
| 2.0 | WR08X1002FTL | WALSIN | 10K resistor |
| 1.0 | MCPWR05FTEW8201 | MULTICOMP PRO | 8.2K (8K2) resistor |
| 1.0 | ERJ6GEYJ392V | PANASONIC | 3.9K (3K9) resistor |
| 1.0 | MCWR08X1802FTL | MULTICOMP PRO | 18K resistor |
| 1.0 | MCABT-458-RC | MULTICOMP PRO | Speaker |
| 1.0 | 796136-1 | TE CONNECTIVITY | CR2032 battery holder |
| 1.0 | JS102011SAQN | C & K COMPONENTS | Power switch |
| 1.0 | SSD1306 | 0.96 inch white OLED screen |
Using Dave’s schematic as a reference, I created my PCB:
Another OLED Mistake
I ordered the PCB, then noticed a problem during the week-long wait. Look at the pin order: VCC-GND-SCL-SDA. Some OLED screens have the first two pins swapped.
You can fix this with trace cuts and jumpers, but I made a second design with configurable pads:
The first two pins are labeled 1 and 2 with a 4-pad box for configuration. If your screen is VCC-GND, connect PIN1 to VCC and PIN2 to GND. If it’s GND-VCC, reverse them.
I call these Design A (specific to VCC-GND-SCL-SDA screens) and Design B (works with either pin order).
Assembly
After a week, the PCB and components arrived.
Calibrating the Controls
The directional buttons connect to PIN 2 (A3) of the Attiny85. The code uses analogRead to determine which button is pressed, but the exact values depend on your resistors and wiring. Use this code to find your values:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void setup() {
_delay_ms(40);
SSD1306.ssd1306_init();
}
void loop() {
_delay_ms(500);
SSD1306.ssd1306_fillscreen(0);
int value = analogRead(A3);
if(value > 0) {
char buf[20];
sprintf(buf, "value: %d", value);
SSD1306.ssd1306_setpos(0, 1);
SSD1306.ssd1306_string_font6x8(buf);
}
}
My values:
- UP: 180-250
- DOWN: 300-400
- LEFT: 90-110
- RIGHT: >400
Update these in the game’s loop function, compile, and burn to the Attiny85. You can use an Arduino as ISP or a USBasp programmer.
Thanks to Daniel and Dave for the original work.
Downloads