An interactive, gamified Morse code learning platform
Learn Morse code from scratch with adaptive timing, real-time feedback, and progress tracking.
- Features
- Screenshots
- Quick Start
- Project Structure
- How It Works
- Exercises
- Configuration
- Tech Stack
- Contributing
- License
- Netflix-style profiles — Multiple users can track their own progress independently
- Adaptive timing engine — The dot/dash threshold adjusts in real-time to match your speed, whether you're a beginner or an experienced operator
- Smart diagnostic feedback — Explains why your input was wrong in plain English (e.g. "you paused too long between taps" or "you held the 2nd tap too long — it became a dash")
- 50 exercises across 7 levels — From single letters (E, T) through the full alphabet, numbers, words, and sentences
- Audio feedback — Configurable sine-wave tone plays while keying
- Progress tracking — Accuracy, WPM, scores, and best scores stored per user
- Encouraging messages — Positive reinforcement that adapts to your performance
- Per-user settings — Customise timing threshold, audio pitch, volume, and hint visibility
- One-click database setup — Build all tables and seed exercises from the browser
- Fully responsive — Works on desktop, tablet, and mobile
- Docker support — Get running in seconds with
docker compose up
Coming soon — the app features a vibrant dark theme with neon accents, animated morse symbols, and glowing UI elements.
-
Clone into your web server's document root:
cd /path/to/www git clone https://github.com/edmozley/morse.git -
Configure your database credentials:
cp morse/dbconfig.sample.php morse/dbconfig.php
Edit
dbconfig.phpwith your MySQL username, password, and database name. -
Create the database (if it doesn't exist):
CREATE DATABASE morse;
-
Build tables — Navigate to
http://localhost/morse/db/and click Build Database Tables. This creates all tables and seeds 50 exercises. -
Start learning — Go to
http://localhost/morse/, create a profile, and begin!
git clone https://github.com/edmozley/morse.git
cd morse
docker compose up -dThen open http://localhost:8080/morse/ in your browser.
The Docker setup includes:
- PHP 8.3 + Apache
- MySQL 8.0 (pre-configured, no manual setup needed)
- Persistent data volume for the database
To stop:
docker compose downTo stop and remove all data:
docker compose down -vmorse/
├── index.php # Home — profile selection & dashboard
├── dbconfig.sample.php # Sample database config (copy to dbconfig.php)
├── Dockerfile # Docker image definition
├── docker-compose.yml # Multi-container Docker setup
│
├── css/
│ └── style.css # Dark theme with vibrant neon accents
│
├── js/
│ └── morse.js # Core engine: adaptive timing, audio, practice logic
│
├── includes/
│ ├── header.php # HTML head, session, shared variables
│ ├── navbar.php # Top navigation bar
│ └── footer.php # Footer and script includes
│
├── exercises/
│ └── index.php # Exercise browser & practice interface
│
├── settings/
│ └── index.php # Per-user settings (timing, audio, display)
│
├── db/
│ └── index.php # One-click database builder & seeder
│
├── api/
│ ├── profiles.php # Create, select, delete profiles
│ └── progress.php # Save & retrieve exercise progress
│
└── docker/
├── apache.conf # Apache virtual host config
└── dbconfig.docker.php # Pre-configured DB settings for Docker
The core challenge of Morse input: how do you tell a slow beginner's dot from a fast expert's dash?
Fixed thresholds don't work. A beginner might hold a dot for 300ms while an expert's dash is only 100ms. The system uses a rolling average approach:
- Starts with a configurable default threshold (default: 200ms)
- Every tap is classified as a dot (below threshold) or dash (above)
- Running averages for dot and dash durations are maintained
- The threshold is recalculated as the midpoint between average dot and average dash
- Letter-gap and word-gap timers scale proportionally to your actual dot speed
The result: the system adapts to your speed in real-time. Fast typists get snappy response; beginners get comfortable timing.
When you get an exercise wrong, the system doesn't just say "wrong." It analyses what went wrong:
| What happened | Feedback |
|---|---|
| Paused too long between taps (split a letter into two) | "You tapped the right pattern (..) but paused too long between taps. The letter I needs 2 quick taps without a long gap." |
| Held a dot too long (became a dash) | "The 1st tap should be a short DOT but you held it too long (it became a dash)." |
| Released a dash too early (became a dot) | "The 2nd tap should be a long DASH but you released too quickly." |
| Too few taps | "You only tapped 2 times, but it needs 3." |
| Extra taps | "You tapped 4 times, but it only needs 2." |
| Level | Name | Content | Points |
|---|---|---|---|
| 1 | First Steps | Single letters: E, T, I, A, M, N | 10 |
| 2 | Building Blocks | More letters: S, O, H, R, D, U, K, W | 15 |
| 3 | Full Alphabet | Remaining letters: G through Z | 15 |
| 4 | Numbers | Digits 0-9 | 20 |
| 5 | Short Words | IT, ME, AN, SOS, HI, THE | 25-30 |
| 6 | Common Words | HELLO, WORLD, MORSE, CODE, RADIO, SIGNAL | 35-40 |
| 7 | Sentences | HI THERE, SEND HELP, I LOVE MORSE CODE | 50-75 |
After creating a profile, visit Settings to customise:
| Setting | Description | Range |
|---|---|---|
| Dot/Dash Threshold | Starting point for adaptive timing | 80–500ms |
| Sound | Toggle audio feedback on/off | On/Off |
| Volume | Tone volume level | 0–100% |
| Tone Frequency | Pitch of the Morse tone | 200–1200Hz |
| Show Hints | Display target Morse pattern during exercises | On/Off |
- Backend: PHP 8.1+ with PDO (MySQL driver)
- Database: MySQL 8.0
- Frontend: Vanilla JavaScript (ES6+), CSS3 with custom properties
- Audio: Web Audio API for real-time tone generation
- Fonts: Orbitron (display) + Inter (body)
- Containerisation: Docker with Apache + MySQL
Contributions are welcome! Some ideas for future development:
- Games mode — Timed challenges, streak counters, leaderboards
- Decode mode — Listen to Morse audio and type the translation
- Random practice — Randomly generated letters/words at your level
- Multiplayer — Race against other users in real-time
- Mobile app — PWA support for offline practice
This project is licensed under the MIT License. See LICENSE for details.
·— ·· -·· ·— -·-·--
Built with enthusiasm and too many dots and dashes.