MORSE
TRAINER

Standalone CW Practice Device
-- --- .-. ... .   - .-. .- .. -. . .-.
GITHUB REPOSITORY
73 de VE2HXR

What is it

MorseTrainer is a standalone Morse code practice device built on the Waveshare ESP32-S3-Touch-LCD-2.8. Connect your CW paddle or straight key and start practicing - no computer, no phone, no internet required.

Source code and releases: github.com/Hex4rts/Morsetrainer

3 Keyer Modes

Iambic A, Iambic B, and adaptive Straight Key that learns your personal timing

5 Practice Games

Falling Letters, Callsign Rush, Morse Trace with LEARN mode, QSO Simulator, and CW Essentials

Touchscreen UI

5-tab interface on a 320x240 IPS display with dark theme

OTA Updates

Drop a firmware file on the SD card, reboot, done

Hardware

ComponentDetail
BoardWaveshare ESP32-S3-Touch-LCD-2.8 (16MB flash, OPI PSRAM)
Dit paddleGPIO 15 - active LOW, internal pullup
Dah paddleGPIO 18 - active LOW, internal pullup
NeoPixels20x WS2812 on GPIO 43
AudioI2S DAC (BCLK=48, LRC=38, DOUT=47)
SD card4-bit SDMMC - stores scores, progress, and settings backup

The Interface

The screen is divided into five tabs along the bottom: HOME, KEY, OPS, CFG, and NET. Tap any tab to switch screens.

HOME

This is your main operating screen. As you key, colored bars appear at the top showing each dit and dah in real time. In Iambic mode, dits are blue and dahs are amber. In Straight Key mode, all bars are green with their width matching exactly how long you held the key.

Below the bars, a large text area displays the decoded characters as you send them. A CLR button lets you clear the text.

At the bottom of the screen, three cards show your current WPM speed, keyer mode, and callsign at a glance.

DECODED CLR CQ CQ CQ DE VE2HXR VE2HXR K WPM 20 MODE IAM-B CALL VE2HXR HOME KEY OPS CFG NET

KEY

This is where you choose your keyer mode and adjust your sending speed. The current WPM is shown in large text along with the dit duration in milliseconds. Use the + and - buttons to adjust speed from 5 to 60 WPM.

Three mode buttons let you switch between Iambic A, Iambic B, and Straight Key. The active mode is highlighted. A paddle swap button at the bottom lets you reverse which paddle is dit and which is dah.

SPEED (WPM) 20 dot = 60 ms - + KEYER MODE IAMBIC A IAMBIC B STRAIGHT PADDLE ASSIGNMENT DIT=LEFT DAH=RIGHT HOME KEY OPS CFG NET

OPS

The games menu. Five game cards show the name, a short description, and your best score. Tap a card to start playing.

A RESET SCORES button at the bottom clears all high scores and LEARN mode progress. It requires a confirmation tap to prevent accidents.

v Falling Letters Destroy before landing Best: 1240 C Callsign Rush Send callsigns fast Best: --- A Morse Trace Learn & practice Best: 890 Q QSO Simulator Practice CW contacts Best: --- CW Essentials Best: --- RESET SCORES HOME KEY OPS CFG NET

CFG

All device settings in a scrollable list. Each row has a label and a control - sliders, switches, dropdowns, or buttons.

CALL VE2HXR VOLUME 80% TONE 700Hz LIGHT FLIP LED BREATHE LEDs - 20 + KEY BRT BG BRT COLOR BACKUP RESTORE RESET HOME KEY OPS CFG NET
SettingWhat it does
CALLYour callsign. Tap to edit with on-screen keyboard.
VOLUMESidetone volume
TONESidetone frequency (200-1200 Hz)
LIGHTScreen backlight brightness
FLIPRotate the display 180 degrees for upside-down mounting
LEDChoose the LED effect mode (8 options)
LEDsNumber of NeoPixels in your strip (1-60). Use + and - to match your hardware.
KEY BRTBrightness for key-press LED flashes
BG BRTBrightness for background LED animations
COLORPick the color used by LED modes (7 presets)
BACKUPSave all settings to the SD card
RESTORELoad settings from SD card backup
RESETFactory reset - all settings back to defaults
SCREEN FLIP RECOVERY

If flipping makes touch unusable, hold both paddles while powering on to force normal orientation.

NET

WiFi settings for future features. Enter your network SSID and password. Credentials are stored on the SD card.

Practice Games

All games have an EXIT button to return to the menu at any time. Scores are saved to the SD card.

Falling Letters

Letters fall from the top of the screen. Key the correct Morse code to destroy each letter before it hits the danger zone at the bottom. The speed increases with each level. The game uses the full A-Z alphabet. If two identical letters are on screen, keying always destroys the one closest to the bottom first.

Beginner: the letter and its Morse code hint are both shown. Expert: only the letter - you need to know the code.

Callsign Rush

A random callsign appears on screen. Send it back in Morse as fast as you can. Callsigns use realistic prefixes from around the world.

Beginner: callsign shown with visual and audio, no time limit - practice at your own pace. Intermediate: callsign shown with audio, 12-second timer. Expert: audio only, 12-second timer.

Morse Trace

The device presents a letter (visually, audibly, or both depending on difficulty). You key it back. The device compares your timing to the correct pattern. Four difficulty levels: LEARN, Beginner, Intermediate, and Expert.

QSO Simulator

Practice realistic CW contacts. The device plays an incoming transmission and you respond with the appropriate reply. Three difficulty levels combined with three complexity levels (simple exchange, RST report, and full QSO) give you 9 combinations to master.

CW Essentials

Three practice modes in one game:

MY CALLSIGN: Builds your callsign progressively, letter by letter. First you practice just the first letter. Get it right 3 times in a row and the second letter is added. Then 3 more correct to add the third, and so on until you can send your full callsign from muscle memory. Your full callsign is shown faintly as a reference so you always know where you're headed.

PHRASES - GUIDED: A random CW phrase appears with its meaning (for example "QSL" with "Acknowledged / Confirmed" underneath). The device plays it in Morse first so you can hear it, then you key it back. Great for learning what each abbreviation sounds like and what it means at the same time.

PHRASES - PRACTICE: Same phrases and meanings shown on screen, but no audio. You key them from memory.

The phrase pool covers Q-codes (QSL, QRT, QRS, QRZ, QTH, QRM, QRN, QSB), prosigns (AR, SK, BT, K), common exchanges (CQ, DE, 73, 88, TU, R, RST), and greetings (GM, GA, GE). Every phrase is shown with its meaning so you learn what you're sending, not just the pattern.

LEARN Mode

The LEARN option inside Morse Trace is designed to teach Morse code from scratch. It introduces one letter at a time and uses a drill-and-recall cycle to build your memory.

Learning order: E T I A N M S U R W D K G O H V F L P J B X C Z Y Q 0-9

First, you drill each new letter with full guidance - the letter is shown, the sound is played, and visual bars show the pattern. You copy what you see and hear. After you've learned your first 3 letters, the system starts testing you with recall rounds: the letter appears but there's no sound and no bars. You have to key it from memory.

You get 3 tries per recall. If you fail all 3, the letter goes back to the drill queue. After 3 correct recalls in a row, the next new letter is introduced. The system alternates between drilling new letters and testing learned ones, making sure you don't forget what you've already practiced.

Your progress saves automatically to the SD card. You can turn off the device and pick up exactly where you left off.

Keyer Modes

Iambic A

Hold both paddles and the keyer produces alternating dits and dahs. Release both paddles and it stops after the current element finishes. Dit and dah lengths are determined by your WPM setting.

Iambic B

Same as Iambic A, but if you release a paddle during an element, the opposite element still plays. This is the "squeeze and release" technique preferred by many experienced CW operators.

Straight Key

Either paddle works as a simple on/off key. The device listens to your timing and figures out your speed automatically - you don't need to set a WPM for input. It learns the difference between your dits and dahs, detects character boundaries, and inserts spaces, all based on how you actually key.

The WPM setting only controls playback speed in games when the device sends Morse to you.

LED Modes

The device has a strip of 20 NeoPixel LEDs with 8 selectable modes. Two separate brightness sliders let you control how bright the key-press flashes are versus how bright the background animation is.

ModeWhat it does
OFFCompletely dark. No response to key presses or game events.
KEY FLASHDark when idle. Flashes briefly each time you press a key.
WPM METERShows your current speed as a bar graph across the strip.
STEADYSolid glow in your chosen color.
BREATHEYour chosen color gently pulses up and down.
STARFIELDRandom pixels twinkle and fade independently, like stars.
CHASEA bright tail of light runs continuously around the strip.
RAINBOWA continuous rainbow cycles across all the LEDs.

Every mode except OFF also flashes when you press a key. The flash briefly overrides the background animation, then the background resumes. You can pick your color from 7 presets in the CFG tab - it affects Steady, Breathe, Starfield, and Chase.

Installation Guide

Four ways to get firmware onto your MorseTrainer, from easiest to most technical. All files live at github.com/Hex4rts/Morsetrainer.

Option A - Web Flasher EASIEST

Flash a brand-new ESP32-S3 directly from your browser. No Python, no Arduino IDE, no command line.

> WEB_FLASHER LAST UPDATE: checking…
BROWSER NOT SUPPORTED - USE CHROME, EDGE, OR OPERA ON DESKTOP HTTPS REQUIRED FOR WEB SERIAL
Browser Requirements
BROWSER

Works: Chrome, Edge, Opera (desktop). Won't work: Firefox, Safari, any mobile browser. The Web Serial API is only supported in Chromium-based desktop browsers.

DATA USB CABLE

Many USB-C cables are charge-only. Use one you know transmits data, or the board simply won't enumerate.

DRIVERS

Auto-installed on most systems. On Windows, if no COM port shows up, install CP210x or CH340 depending on your board's USB-to-serial chip.

How to use

Click FLASH MORSETRAINER above.

Select your ESP32-S3's serial port in the browser popup.

Wait ~30 seconds. Don't unplug during flashing. The device reboots into MorseTrainer automatically when done.

BOARD NOT DETECTED?

Hold the BOOT button while plugging in USB, wait a second, then release and click Flash again. Most ESP32-S3 boards auto-enter download mode, but some need this manual step.

Option B - OTA Update via SD Card FOR EXISTING DEVICES

Already running MorseTrainer and want the latest version? Download the firmware, drop it on your SD card, reboot - no computer needed.

> OTA_FIRMWARE LAST UPDATE: checking…
How to use

Click DOWNLOAD firmware.bin above. Keep the filename exactly firmware.bin - don't rename it.

Copy the file to the root of your SD card (not inside any folder).

Insert the SD card, power on the device. Every boot it checks for firmware.bin, flashes it, and renames it to firmware.done so it won't re-flash next time.

Device reboots into the new version. Total time ~20 seconds.

NOTE

OTA updates only work if the device was initially installed with the custom partition scheme. Option A above uses it automatically. If your first install used "Huge APP", re-flash once via Option A before OTA will work.

Option C - Manual Flash with esptool

For power users who prefer the command line, or for scripted/batch flashing.

Install esptool (requires Python):

pip install esptool

With a merged binary (single file, simplest):

esptool.py --chip esp32s3 --port COM3 --baud 921600 \ write_flash 0x0 MorseTrainer.ino.merged.bin

Replace COM3 with your actual port (on Linux, usually /dev/ttyACM0).

With separate files:

esptool.py --chip esp32s3 --port COM3 --baud 921600 \ write_flash \ 0x0000 bootloader.bin \ 0xe000 boot_app0.bin \ 0x8000 MorseTrainer_ino_partitions.bin \ 0x10000 MorseTrainer_ino.bin

If the board isn't detected, hold the BOOT button while plugging in USB, then release.

Option D - Compile from Source

For those who want to build from source or make modifications.

Install Arduino IDE and add ESP32 board support (esp32 by Espressif Systems from Board Manager).

Install libraries: LVGL 9.x and Adafruit NeoPixel via Library Manager.

Copy lv_conf.h from the project into your Arduino libraries folder. It must sit next to the lvgl folder, not inside it:

Arduino/libraries/lvgl/ ← from Library Manager Arduino/libraries/lv_conf.h ← copy here

Extract all project files into a folder called MorseTrainer inside your Arduino sketch folder. The .ino file, all .h/.cpp files, and the partitions.csv file must all be in the same folder.

Configure board settings in the Tools menu:

Board: ESP32S3 Dev Module Flash Size: 16 MB (128Mb) PSRAM: OPI PSRAM Partition Scheme: Custom ← NOT "Huge APP" USB CDC On Boot: Enabled CPU Frequency: 240MHz

Connect the board via USB and upload.

PARTITION SCHEME MUST BE "CUSTOM"

The included partitions.csv creates two app partitions, which is required for OTA updates to work. If you select "Huge APP", the firmware will compile and run, but you won't be able to update via SD card later. You'd have to re-flash via USB to fix it.

SD Card Files

The device creates these files as needed. Deleting any of them just resets that data.

FilePurpose
/firmware.binFirmware update - consumed on boot, renamed to .done
/mt_settings.txtSettings backup (from the BACKUP button in CFG)
/mt_wifi.txtWiFi network name and password
/trainer2.txtLEARN mode progress
/koch.txtKoch lesson progress
/scores/*.txtHigh scores for each game (falling, callrush, trace, qso, phrases)