Skip to content
Kanishk Sama
← Projects

Geometry Dash on MSPM0G3507

A Geometry Dash clone built from scratch on an MSPM0G3507 microcontroller — real-time LCD sprite rendering and 12-bit DAC audio driven by two independent interrupt sources, with analog and digital input handled entirely in C++.

Software
Period
Spring 2026
Role
2-person team with Arjun Bhardwaj
Stack
C++ · MSPM0G3507 · LCD · 12-bit DAC · TimerG12 · SysTick · ADC · GPIO
Demo
Watch
30 Hz
TimerG12 interrupt driving game-state updates
11 kHz
SysTick-driven DAC audio playback

The problem

A game engine on a microcontroller doesn’t get an operating system’s help with any of the things a PC game takes for granted — no scheduler, no audio driver, no display compositor. Rendering sprites to an LCD, playing audio, and reading player input all have to share one core, in real time, without any of them starving the others. Miss a beat on the audio timer and playback crackles; fall behind on the render timer and the game visibly stutters.

What we built

Working with Arjun Bhardwaj, I built a Geometry Dash clone in C++ on an MSPM0G3507, with real-time LCD sprite rendering, 12-bit DAC audio output, and a bilingual UI.

The core design decision was splitting the two real-time obligations onto two independent interrupt sources rather than one shared loop:

  • TimerG12 at 30 Hz drives game-state updates — physics, collision, scoring.
  • SysTick at 11 kHz drives DAC audio playback.

Separating them means a slow frame of game logic can’t stutter the audio, and vice versa — each runs on its own clock, and neither blocks the other.

I/O

Player input came through both analog and digital paths:

  • ADC slidepot sampling with noise filtering for continuous input.
  • GPIO switch debouncing, so a single physical press registers as a single logical press rather than a burst of them.

Both matter for the same reason the dual-ISR split does: physical I/O is noisy and asynchronous by nature, and a game that reads it naively will feel wrong to play even when the core logic is correct.

What I’d do next

  • Profile ISR headroom. The two interrupts don’t starve each other in practice; I never measured how much slack either one actually has.
  • Extend the bilingual UI. It currently covers the core game text — extending it to every screen would be the natural next step.