

DuelTank
Duel Tanks is a real-time two-player artillery game built completely from scratch on the MSPM0G3507 microcontroller.
- Size
- 118 × 100 mm
- Copper layers
- 2
- Thickness
- 1.6 mm
- Parts
- 72
- Nets
- 64
- Pads
- 215
- Tracks, vias
- 449, 84
- Pours
- 4
- Routed
- Yes
- KiCad
- KiCad 9.0 (file 20241229)
- Created
- 6 Apr 2026
- Updated
- 25 Apr 2026
Overview
DuelTank is an open-source printed circuit board by SathvikY3533, from the SathvikY3533/DuelTanks repository on GitHub. It is a 2-layer board of 118 × 100 mm with 72 parts on 64 nets, routed with 449 tracks and 84 vias.
It is built around the ULN2003BD. Its parts include 21 resistors, 7 capacitors, 7 diodes, 7 connectors and 4 switches.
Main components
1README
README.mdDuel Tanks
Two-player real-time tank battle — ECE319H Spring 2026
Check out more of my work at sathvikyechuri.com
Demo
📺 Video coming soon
Screenshots
| Splash Screen | Tank Select | Gameplay |
|---|---|---|
| coming soon | coming soon | coming soon |
Overview
Duel Tanks is a real-time two-player artillery game built completely from scratch on the MSPM0G3507 microcontroller. Two players face off on separate boards connected by a UART link — shells fired off one screen physically cross over to the opponent's screen, with full parabolic physics preserved across the wire.
Everything — the graphics engine, sprite system, physics engine, UART protocol, sound system, and game state machine — was written from scratch in C++. No game engine, no external libraries.
Placed 3rd in the ECE319H Spring 2026 in-class competition.
How It Works
Each board runs the same firmware with a PLAYER_ID flag determining which side the player starts on. Missiles exit one screen, get encoded into a 5-byte UART packet, and spawn on the opponent's screen with matching velocity — making it feel like a single continuous battlefield split across two displays.
Board 1 (left) Board 2 (right)
┌──────────────┐ ┌──────────────┐
│ 🎯 >>> │──UART──│ >>> 💥 │
│ [Tank] │ │ [Tank] │
└──────────────┘ └──────────────┘
PA8 TX ──────────────► PA22 RX
PA22 RX ◄────────────── PA8 TX
GND ◄──────────────────► GNDFeatures
- Parabolic missile physics — fixed-point arithmetic, gravity simulation, arc trajectory
- Cross-screen projectiles — missiles exit your screen and appear on the opponent's via UART
- City background — night skyline with building silhouettes and window lighting
- Hilly terrain — multi-sine generated terrain profile, tanks ride the hills
- 3 playable tanks with unique abilities:
- 🔵 Brawler — Double Shot (fires two missiles spread ±5°)
- 🟢 Phantom — Speed Boost (2× movement speed for 1.5 sec)
- 🔴 Artillery — Ricochet (next shot bounces off terrain)
- Full game flow — splash → language select → rules → tank select → battle ready handshake → countdown → gameplay → end screen
- 2-minute match timer — compare lives at time's up for winner
- English / Spanish language support
- Sound effects — shoot, explosion, incoming warning, victory, defeat, and more
Hardware
| Component | Details |
|---|---|
| MCU | MSPM0G3507 LaunchPad |
| Display | ST7735R LCD (160×128, landscape) |
| Input | 4 tactile buttons + slide potentiometer |
| Audio | 5-bit R2R DAC → MCP34119P amplifier → speaker |
| Sync | Battle Ready GPIO handshake (PA17 / PA31) |
| Communication | UART at 115200 baud, board-to-board |
Pin Map
| Signal | Pin |
|---|---|
| LCD SPI | PB6, PB7, PB8, PB9, PB15, PA13 |
| Slide pot (ADC) | PB18 |
| 5-bit DAC | PB0 – PB4 |
| UART TX | PA8 (UART1) |
| UART RX | PA22 (UART2) |
| Battle Ready Out | PA17 (P1) / PA31 (P2) |
| Battle Ready In | PA31 (P1) / PA17 (P2) |
| Fire button | PB17 |
| Shield button | PB12 |
| Left button | PB16 |
| Right button | PA27 |
Software Architecture
main5.cpp
└── Game_Update() ← called every 33ms (30Hz)
├── Switch_Tick() ← edge detection for all 4 buttons
├── State machine ← SPLASH → LANGUAGE → RULES → TANK_SELECT
│ → WAITING → COUNTDOWN → GAMEPLAY → END
├── Physics engine ← fixed-point parabolic missile simulation
├── Sprite renderer ← transparent pixel-by-pixel draw, dirty-rect erase
├── GameUART ← 5-byte packets with 0xAA 0x55 sync header
└── Sound engine ← SysTick ISR at 11025Hz → R2R DAC outputUART Packet Format
[ 0xAA ][ 0x55 ][ TYPE ][ DATA1 ][ DATA2 ]
sync sync what payload payloadControls
| Input | Action |
|---|---|
| Left / Right buttons | Move tank |
| Slide pot | Aim angle (0° – 89°) |
| Hold Fire | Charge shot power |
| Release Fire | Shoot |
| Shield | Use tank ability |
| Fire + Left + Right (hold) | Force quit match |
Building
Open in Code Composer Studio with the ECE319H Lab 9 starter project. Add all .cpp / .h files. Before flashing:
- Set
#define PLAYER_ID 1inGame.hfor the left board - Set
#define PLAYER_ID 2inGame.hfor the right board - Connect boards: PA8→PA22, PA22→PA8, GND→GND
License
Built for ECE319H at UT Austin. All game logic, physics, graphics, and UART protocol written from scratch.
Parts
72| Qty | Value | Footprint | References |
|---|---|---|---|
| 7 | 300 | ECE319K:R_Axial_DIN0204_L3.6mm_D1.6mm_P7.62mm_Horizontal | R1, R4, R5, R6, R21, R22, R23 |
| 5 | 0.1uF | ECE319K:C_Axial_200mil | C3, C4, C5, C6, C7 |
| 5 | 1.5k | ECE319K:R_Axial_DIN0204_L3.6mm_D1.6mm_P7.62mm_Horizontal | R8, R9, R10, R11, R19 |
| 5 | 10k | ECE319K:R_Axial_DIN0204_L3.6mm_D1.6mm_P7.62mm_Horizontal | R12, R13, R14, R15, R20 |
| 4 | M.3 | MountingHole:MountingHole_3.2mm_M3_Pad_TopBottom | H1, H2, H3, H4 |
| 3 | 12k | ECE319K:R_Axial_DIN0204_L3.6mm_D1.6mm_P7.62mm_Horizontal | R16, R17, R18 |
| 2 | 1053131105 | nanofit_1x5:CONN_SD-105313-100_05_MOL | J3, J5 |
| 2 | LOGO | images:arrow | G***, G*** |
| 1 | 1uF | ECE319K:CP_Radial_Tantal200mil | C1 |
| 1 | 20k | ECE319K:R_Axial_DIN0204_L3.6mm_D1.6mm_P7.62mm_Horizontal | R7 |
| 1 | 3.3V | ECE319K:Testpoint_1x02_P2.54mm | TP1 |
| 1 | 4.7uF | ECE319K:CP_Radial_Tantal200mil | C2 |
| 1 | Conn_01x08 | Connector_PinHeader_2.54mm:PinHeader_1x08_P2.54mm_Vertical | J8 |
| 1 | DACOUT | TestPoint:TestPoint_Pad_D2.0mm | TP17 |
| 1 | DACOUT | ECE319K:Testpoint_1x02_P2.54mm | J7 |
| 1 | Divider1 | TestPoint:TestPoint_Pad_D2.0mm | TP10 |
| 1 | Divider2 | TestPoint:TestPoint_Pad_D2.0mm | TP11 |
| 1 | Divider3 | TestPoint:TestPoint_Pad_D2.0mm | TP12 |
| 1 | Divider4 | TestPoint:TestPoint_Pad_D2.0mm | TP13 |
| 1 | Divider5 | TestPoint:TestPoint_Pad_D2.0mm | TP14 |
| 1 | Fire | ECE319K:SW_PUSH_6mm | SW2 |
| 1 | Fire_SW | TestPoint:TestPoint_Pad_D2.0mm | TP5 |
| 1 | GND | ECE319K:Testpoint_1x02_P2.54mm | J6 |
| 1 | GREEN_LED1 | ECE319K:LED_D5.0mm | D2 |
| 1 | GREEN_LED2 | ECE319K:LED_D5.0mm | D3 |
| 1 | GREEN_LED3 | ECE319K:LED_D5.0mm | D5 |
| 1 | GREEN_LED4 | ECE319K:LED_D5.0mm | D10 |
| 1 | LOGO | LOGO | G*** |
| 1 | LOGO | images:shield | G*** |
| 1 | LOGO | images:fire | G*** |
| 1 | LP-MSPM0G3507 | ECE319K:ti_LP_MSPM0G3507 | U2 |
| 1 | Left | ECE319K:SW_PUSH_6mm | SW3 |
| 1 | Left_SW | TestPoint:TestPoint_Pad_D2.0mm | TP2 |
| 1 | MCP34119P | ECE319K:DIP-8_W7.62mm_LongPads | U3 |
| 1 | PTA2043 | ECE319K:PTA2043pot | RV1 |
| 1 | PWR_RED | ECE319K:LED_D5.0mm | D1 |
| 1 | Pot | ECE319K:Testpoint_1x02_P2.54mm | J4 |
| 1 | Right | ECE319K:SW_PUSH_6mm | SW4 |
| 1 | Right_SW | TestPoint:TestPoint_Pad_D2.0mm | TP4 |
| 1 | Shield | ECE319K:SW_PUSH_6mm | SW1 |
| 1 | Shield_SW | TestPoint:TestPoint_Pad_D2.0mm | TP3 |
| 1 | SlidePot | TestPoint:TestPoint_Pad_D2.0mm | TP16 |
| 1 | Speaker | ECE319K:PinHeader_1x02_P2.54mm_Vertical | J2 |
| 1 | TExaS | ECE319K:PinHeader_1x03_P2.54mm_Vertical | JP1 |
| 1 | ULN2003B | ECE319K:DIP-16_W7.62mm | U5 |
| 1 | YellowLED_RX | ECE319K:LED_D5.0mm | D9 |
| 1 | YellowLED_TX | ECE319K:LED_D5.0mm | D8 |
Similar boards
- 4 layers179.3 × 72.5 mm

- 2 layers114.3 × 88.9 mm

CrickHit PCB
devanshjoshi08/CrickHit
Real-time cricket batting game on the TI MSPM0G3507 (ARM Cortex-M0+) with triple-ISR architecture, custom KiCad PCB, 5-bit DAC audio, and 3D-printed enclosure. Built for ECE 319H at UT Austin.
54 parts1 - 2 layers132.5 × 83 mm

- 2 layers114.3 × 88.9 mm

- 2 layers114.3 × 88.9 mm

Jc224364
se1yu/BlockBlast
Using knowledge from ECE 319H at UT Austin (Intro to Embedded Systems) to build a custom video game console and to program Block Blast from scratch.
54 parts - 2 layers114.3 × 88.9 mm

MVM833
SiddharthaG09/319KFinalProject
For our final project, we recreated Space Invaders in C, using a custom-designed PCB and an MSPM0G3507 microcontroller.
46 partsMIT - 2 layers140.8 × 66.4 mm

- 2 layers50 × 90 mm

Hackholidays
hackclub/OnBoard
💡 Join 1,000 teenagers and make your first PCB with a $100 grant!
72 parts915
Questions
How big is the DuelTank PCB?
It measures 118 × 100 mm and has 2 copper layers, 1.6 mm thick.
What parts does the DuelTank use?
72 parts, built around the ULN2003BD. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
Where can I download the DuelTank KiCad files?
From the SathvikY3533/DuelTanks repository on GitHub, at the commit this page was made from: the board is DuelTank/DuelTank.kicad_pcb and its schematic DuelTank/DuelTank.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Can I use the DuelTank design in my own project?
Its repository states no licence, so its author keeps all rights: ask SathvikY3533 before reusing the design.