In this project, we will build a pocket arcade machine using a Kypruino, a 1.8" colour LCD, a 0.91" OLED display, and the Kypruino's onboard buttons, NeoPixels and buzzer.
The Kypruino is held upright so that its four buttons form a cross that works like a game controller D-pad. The colour LCD is the main game screen, while the small OLED beside it acts as a live second screen showing your score, lives, gauges and short messages as you play. Twelve classic games fit on a single board, from Tetris and Snake to a rhythm game and a virtual pet.
This guide is written so that beginners can follow along. The wiring takes eight jumper wires and the code needs no extra libraries, so you can have the arcade running quickly and then explore how the games work at your own pace.
Project Resources: Source Code & 3D Printing Files.

The completed Kypruino mini arcade machine, with the colour LCD as the main screen and the OLED as a live second screen.
What the project does
When you switch the arcade on, it shows a short splash screen and opens a game menu. Pick a game with the buttons and play.
- Twelve games: Simon Says, Snake, Tetris, 2048, Breakout, Space Shooter, Lane Racer, Frogger, Flappy, Whack-a-Mole, Beat Lanes and Kypruino Pet
- Two screens: the colour LCD shows the game, and the OLED shows score, lives, gauges and reactions
- D-pad controls: the four onboard buttons act as UP, DOWN, LEFT and RIGHT
- Music and sound effects: the onboard buzzer plays tunes and game sounds
- Reactive lighting: the onboard NeoPixels flash and glow with the action
- Saved high scores: the best score for every game is kept even when the power is off
- Pause, sound switch and attract mode: pause any game, mute the buzzer, and the machine shows an animated title screen when left idle
The result is a real handheld games console that you built and programmed yourself.
Components needed
For this build, you will need:
- 1 × Kypruino board
- 1 × 1.8" TFT LCD display, 128×160, ST7735
- 1 × 0.91" OLED display, 128×32, I2C
- 8 × male-to-female DuPont wires
- 1 × USB-C cable
- Arduino IDE for programming
- Arcade case model, available in our GitHub repository
The project uses the Kypruino's built-in buttons, NeoPixels and buzzer, so no separate controller, LEDs or sound module are required.
How the system works
Two screens
The 1.8" colour LCD is mounted sideways (landscape) and shows the game itself. The 0.91" OLED is mounted upright (portrait) next to it and works as a scoreboard. While you play, it shows things like your score and best score, hearts for lives, a speedometer in Lane Racer, an altitude gauge in Flappy, or messages such as YUM!, HOP! and PERFECT.
The D-pad
With the USB-C connector facing down, the Kypruino's four buttons sit in a cross. The program reads them as directions: C = UP, A = DOWN, B = LEFT and D = RIGHT (labelled U, D, L , R).
Sound and light
The onboard buzzer plays background music and short sound effects such as coins, jumps and explosions. The three onboard NeoPixels react to the game, flashing on hits, glowing during the menu and turning into a rainbow when you set a new best score.
High scores
Each game has its own slot in the Kypruino's EEPROM, a small memory that keeps its contents without power. Your best scores, the sound setting and your virtual pet are all still there the next time you plug the arcade in.
The games
All twelve games use the same four buttons. The OLED shows different information for each one.
| Game | How to play | Second screen |
|---|---|---|
| Simon Says | Watch the four pads light up, then repeat the pattern with the matching buttons | Round, score, WATCH / YOUR TURN |
| Snake | Steer with the D-pad, eat the fruit, and do not bite your own tail | Length gauge, score |
| Tetris | LEFT/RIGHT move, UP rotates, DOWN drops, with the classic Korobeiniki tune | Level, lines cleared |
| 2048 | Slide the tiles and merge matching numbers until you reach 2048 | Highest tile, score |
| Breakout | LEFT/RIGHT move the paddle, UP launches the ball; five rows of bricks and three lives | Lives, level, score |
| Space Shooter | LEFT/RIGHT move, UP fires, DOWN uses a smart bomb against waves of aliens | Lives, wave, bomb status |
| Lane Racer | LEFT/RIGHT change lane, UP boosts, DOWN brakes | Speedometer, score |
| Frogger | Hop across the road and the river to reach the five homes | Lives, homes reached |
| Flappy | Press UP to flap through the gaps in the pipes | Altitude gauge, score |
| Whack-a-Mole | Press the button for the hole where the mole appears, and avoid the bombs | Reaction time in ms, lives |
| Beat Lanes | A rhythm game: press each lane's button as the note reaches the line | Combo, health, PERFECT / GOOD / MISS |
| Kypruino Pet | Feed, play with, clean and put your pet to sleep; it is saved between sessions | Four stat gauges, age, mood |

A few of the twelve games running on the colour LCD.
The Kypruino
The Kypruino acts as the brain and the controller of the arcade. It reads the buttons, runs the game logic and drives both screens, the buzzer and the lights.
Like a standard Arduino-compatible board, it can read inputs and control outputs. The Kypruino also includes several useful components directly on the board, including:
- Four general-purpose buttons
- NeoPixel LEDs
- Onboard buzzer
- A dedicated I2C/OLED port
- USB-C programming and power
Because the buttons, lights, buzzer and OLED port are already built in, only the colour LCD needs to be wired by hand.
The 1.8" colour LCD
The main screen is a 1.8" TFT LCD with a resolution of 128×160 pixels, controlled by an ST7735 chip. It talks to the Kypruino over SPI, a fast connection that uses separate wires for the clock and the data.
Typical features of the display include:
- Resolution: 128×160 pixels, used here as 160×128 in landscape
- Colours: 65,536 (16-bit RGB565 colour)
- Interface: SPI, running at 8 MHz in this project
- Backlight: LED, powered through the module's LED pin
The 0.91" OLED display
The second screen is a 0.91" OLED with a resolution of 128×32 pixels, controlled by an SSD1306 chip. It uses I2C, which needs only two signal wires and plugs straight into the Kypruino's dedicated OLED port.
In this project the OLED is turned on its side, so it becomes a tall, narrow screen 32 pixels wide and 128 pixels high. That shape works well for stacked numbers, vertical gauges and short words.
The arcade also works without the OLED connected, so you can test the LCD on its own first.
Designing and 3D printing the case
The case was designed to turn the Kypruino and both displays into a comfortable handheld.
- The Kypruino is held upright with the USB-C port facing down, so the four buttons line up as a D-pad and the cable leaves from the bottom.
- The colour LCD is mounted landscape as the main screen.
- The OLED is mounted portrait beside the LCD, close to where the player is already looking.
You can download the case model from the project GitHub repository.

3D render of the project's enclosure.
Choosing the filament
Any colour of PLA or PETG works for this build, since no light needs to shine through the case. A bright colour or a two-colour print gives it a proper arcade look. A clear translucent filament was used for the slot above the Kypruino's on-board LEDs, enabling it to be illuminated by them.
Preparing the printed parts
After printing:
- Remove any supports and loose material
- Check that both screens fit in their openings
- Check that all four Kypruino buttons can be pressed comfortably through the case
- Check that the USB-C cable reaches the board
- Check that the case closes
Wiring the project
Make sure the Kypruino's onboard NeoPixel and buzzer switches are enabled.
Connect the colour LCD using eight male-to-female DuPont wires.
| LCD Pin | Connects to Kypruino |
|---|---|
| VCC | 5V |
| GND | GND |
| SCK / CLK | D13 |
| SDA / MOSI | D11 |
| CS | D10 |
| A0 / DC | D5 |
| RESET | D3 |
| LED | 5V |
Pin labels differ slightly between LCD modules: SDA on the LCD is the SPI data line (MOSI), and A0 is the data/command (DC) pin. Some modules are designed for 3.3V only, so check your module's markings before connecting VCC and LED to 5V.
The OLED plugs directly into the Kypruino's I2C/OLED port (VCC, GND, SDA, SCL). It uses I2C address 0x3C.
| Onboard part | Kypruino pin |
|---|---|
| Button C (UP) | D4 |
| Button A (DOWN) | D7 |
| Button B (LEFT) | D6 |
| Button D (RIGHT) | D2 |
| NeoPixels | D8 |
| Buzzer | D9 |
The onboard parts are connected internally, so no wiring is needed for them.

Wiring overview showing the eight LCD connections and the OLED on the Kypruino's I2C port.
Installing the Arduino libraries
This project does not need any extra libraries.
The drivers for the LCD, the OLED, the NeoPixels and the sound are all written inside the sketch itself. Writing small, purpose-built drivers instead of using general-purpose libraries is what allows twelve games to fit into the Kypruino's 32 KB of memory.
Uploading the code
Download the KypruinoArcade folder from our GitHub repository and open KypruinoArcade.ino in the Arduino IDE. The other files in the folder open automatically as tabs.
Connect the Kypruino to your computer using the USB-C cable. Select Arduino UNO as the board, choose the correct port, then upload.
The four buttons are mapped to directions in Config.h:
#define BTN_UP_PIN 4 // button C
#define BTN_DOWN_PIN 7 // button A
#define BTN_LEFT_PIN 6 // button B
#define BTN_RIGHT_PIN 2 // button D
The LCD control pins are set in the same file:
#define LCD_CS_PIN 10
#define LCD_DC_PIN 5
#define LCD_RST_PIN 3
The onboard NeoPixels and buzzer are connected internally to:
#define PIXEL_PIN 8
#define BUZZER_PIN 9
Getting the screens right
Display modules vary slightly, so Config.h includes a few settings to match yours:
- Buttons feel wrong? Run Button test from the menu, then swap the pin numbers above until the D-pad matches.
-
LCD upside down? Change
LCD_ROTATIONfrom 1 to 3. -
Red and blue swapped? Set
LCD_BGRto 0. -
Noisy strip along one edge of the LCD? Set
LCD_COL_OFFSETto 2 andLCD_ROW_OFFSETto 1. -
OLED text upside down? Toggle
OLED_FLIPbetween 1 and 0. -
NeoPixels too bright? Lower
PIXEL_BRIGHTNESS(0–255).
Understanding the program
1. The menu
After the splash screen, the LCD shows a list of games. UP and DOWN move through the list and RIGHT starts the selected game. While you browse, the OLED shows a short description of the game and its best score. The menu also contains a Button test and a Sound ON/OFF switch.
2. The game loop
Every game is updated 40 times per second. On each update, the program reads the buttons, moves the game forward by one step, updates the sound and lights, and redraws whatever changed. Using a fixed rate keeps the games running at the same speed no matter how much there is to draw.
3. Drawing without a screen buffer
A full copy of the colour screen would need 40 KB of memory, but the Kypruino has only 2 KB. Instead of keeping a copy, each game draws directly to the LCD and only redraws the parts that moved, such as the snake's head and tail or a falling Tetris piece.
The small OLED is different: its full picture needs only 512 bytes, so the program keeps a copy in memory and sends it over I2C only when something has changed.
4. Music without slowing the games
The buzzer is driven by one of the Kypruino's hardware timers. Once a note starts, the timer keeps it playing on its own, so music and sound effects cost almost no processing time and the games stay smooth.
5. Pause, game over and high scores
Holding LEFT and RIGHT together pauses the game. From the pause screen, UP resumes and DOWN returns to the menu.
When a game ends, the program compares your score with the best score saved in EEPROM. If you beat it, the new score is saved, the screens show NEW BEST! and the NeoPixels play a rainbow.
6. Attract mode
If no button is pressed for 40 seconds, the arcade switches to an animated title screen, just like real arcade cabinets do to attract players. Pressing any button returns to the menu.
Fitting twelve games into 32 KB
The Kypruino's ATmega328P microcontroller has 32 KB of program memory and 2 KB of working memory. Each game uses between 1 and 3 KB of program memory, and the full set of twelve compiles to about 29.9 KB, or around 92% of the space available.
A few techniques make this possible:
- Custom display, sound and lighting drivers instead of large general-purpose libraries
- Text, music and graphics stored in program memory (
PROGMEM) instead of working memory - One shared 300-byte memory area that each game uses while it is running
- Drawing only what changed instead of redrawing the whole screen
If you add your own game and the sketch becomes too big, you can leave out any game by setting its switch to 0 at the bottom of Config.h:
#define GAME_FLAPPY 0
Assembling the arcade
Once the circuit and code are working correctly, install the electronics inside the printed case.
- Place the Kypruino in the case upright, with the USB-C port facing down
- Fit the colour LCD into the main screen opening
- Connect the LCD to the Kypruino using the wiring table above
- Plug the OLED into the Kypruino's I2C/OLED port and fit it beside the LCD
- Turn on the Kypruino's NeoPixel and buzzer switches
- Route the USB-C cable through the bottom opening
- Secure the boards and loose wires, then close the case
Keep the LCD wires short and tidy so they do not press against the back of the screen or get pinched when the case closes.
Testing the project
After assembly, connect the USB-C cable.
- Check that the splash screen appears on the LCD and the OLED says hello
- Listen for the start-up sound and watch for the rainbow on the NeoPixels
- Open Button test from the menu and press each button to confirm the D-pad directions
- Start a game and check that the OLED shows the score and lives
- Hold LEFT and RIGHT together to check that the game pauses
- Finish a game and confirm that your best score is shown the next time you select it
If the LCD stays white or blank, check the SCK, SDA, CS, A0 and RESET wires. If the picture is upside down or the colours look wrong, use the settings in Getting the screens right above.
What students can learn
This project introduces several useful STEM concepts:
- Reading buttons as game controls
- SPI and I2C communication with two different displays
- Drawing graphics with pixels, colours and coordinates
- Game loops and fixed frame rates
- Collision detection, scoring and levels
- Random numbers in games
- Playing music and sound effects with a buzzer
- Saving data to EEPROM so it survives power loss
- Working within tight memory limits
- Organising a larger program into separate files
- 3D-printing enclosures for electronics
It also demonstrates an important engineering idea: careful design matters most when resources are limited. Classic arcade machines and early consoles ran their games on hardware not much more powerful than the Kypruino, using the same tricks this project uses.
Possible extensions
- Design your own game: copy GameSimon.cpp, which shows the three functions every game needs, and follow the steps in the project README
- Change the colours, speeds or difficulty of an existing game
- Write new music or sound effects for your favourite game
- Add a rechargeable battery pack to make the arcade cordless
- Design a larger case with arcade-style buttons wired to the same pins
- Add new moods, stats or animations to the Kypruino Pet
- Create a two-player game where players take turns and compare scores
Final thoughts
This project combines 3D printing, electronics and programming to turn a single Kypruino into a complete handheld games console.
Using only a Kypruino, two small displays and a printed case, the build delivers twelve games, a live second screen, music, lighting and saved high scores, with no extra libraries.
It is beginner-friendly to build, fun to play, and offers plenty of room to grow: once you understand how one game works, you can start writing your own.

Mid-game, with the OLED showing the live score and other stats.