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

4 Practice Games

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

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. Four 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: --- 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.

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

Two ways to get the firmware onto a new device. All files are at github.com/Hex4rts/Morsetrainer.

Option A -- Compile from Source

For those who want to build from the source code 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.

Option B -- Flash a Pre-compiled Firmware

If someone provides you with a compiled .bin file, you can flash it without Arduino IDE.

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.

Updating the Firmware via SD Card

Once the firmware is installed with the correct partition scheme, you can update it without a USB cable.

Get the new firmware binary. If you compiled it yourself, use Sketch > Export Compiled Binary in Arduino IDE. Otherwise, download the .bin from the GitHub releases page.

Copy the file to the root of your SD card and rename it to exactly firmware.bin.

Insert the SD card and power on the device. Every time the device boots, it checks for a file called firmware.bin on the SD card. If it finds one, it flashes the update automatically, renames the file to firmware.done so it won't re-flash next time, and reboots into the new version.

NOTE

OTA updates require the device to already have been flashed with the custom partition scheme. If your initial install used "Huge APP", you'll need to re-flash via USB once with the correct partition before SD card updates will work.

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