··  ·−−  ·−−−−  ·−·  −−  −−     IW1RMM  ·  73 de Mauri  ·  Savona, Italy

Firmware v7.1.5  ·  ESP32 CYD  ·  Open Source

A complete
CW Keyer
in your hand.

The IW1RMM CW Encoder turns a €10 ESP32 touchscreen board into a full-featured Morse code keyer — all keying modes, speed control, preset messages, SD card playback, Bluetooth wireless control, and much more. Plug in your paddle and key.

Developed by Mauri IW1RMM, 2025–2026  ·  Based on original firmware by VK2IDL  ·  GPL v3

IW1RMM CW ENCODER v7.1.5
ModeIAMBIC B
Speed22 WPM
Tone650 Hz
Volume3 / 4
BLECONNECTED
Touch calOK ✓
▶  CQ CQ CQ DE IW1RMM IW1RMM K
MORSE 1
MORSE 2
SD
SETTINGS
SPARE
Overview

CW Encoder ESP32 CYD

Questo progetto implementa un encoder CW (codice Morse) basato su ESP32 CYD con interfaccia web. È progettato per radioamatori, test RF e sperimentazione digitale.

The project implements a CW (Morse code) encoder based on ESP32 CYD with a web interface, designed for ham radio operators, RF testing and digital experimentation.


What it does

Built around the paddle.

Everything starts with a paddle and a key output. The IW1RMM CW Encoder is first and foremost a high-quality Morse keyer — then a touchscreen interface, a message player, a beacon, and a contest tool.

🖐

All Keying Modes

Iambic A, Iambic B, Manual (straight key), Auto (electronic bug), Ultimatic. Switch modes in one tap. Each transmitted character is decoded in real time and shown on the scrolling display — even in manual mode.

⚙️

Precise Speed & Timing Control

5 to 100 WPM on screen. Full control over DAH ratio (2.0–4.5×), inter-element spacing weight, and Farnsworth character spacing for training. All values saved to non-volatile memory and restored on every boot.

📺

LVGL Touchscreen Interface

A clean, responsive 5-tab graphical UI on the 2.8" ILI9341 display. Scrolling text bars show transmitted characters live. Interactive 4-point touch calibration on first boot, stored permanently in NVS. NEW v7.1.5

💬

6 Editable Preset Messages

CQ, Name, Test, Ant/Rig, RST, Free — send any message with a single tap. Edit directly on screen with the virtual keyboard. Stored permanently in NVS flash. Messages can be sent individually or chained automatically.

📁

SD Card Text Player

Load any .txt file from MicroSD and transmit it in Morse at any speed. Full PLAY / PAUSE / STOP control. Text scrolls live on the display as it is transmitted. Ideal for long-text practice or automated operation.

📡

Wireless BLE Control

Built-in Bluetooth Low Energy (Nordic UART) lets you control the keyer from any Android phone or PC. Send text, change speed, play memories, query status. Always available regardless of operating mode. FIX v7.1.3

More features

🔁 Beacon Mode

Automatic CQ at configurable intervals (10–600 s). Ideal for propagation tests and unattended beacons.

🏆 Contest Mode

Auto-incrementing serial number per transmission. Counter saved to NVS and survives reboots.

📻 Sidetone DAC

Internal ESP32 DAC generates clean sidetone, 300–1200 Hz adjustable. Four volume levels. No external audio chip needed.

⚡ HSCW

High Speed CW (60–100+ WPM) for meteor scatter and aurora contacts.

🔬 QRSS

Ultra-slow CW (3s, 6s, 10s, 30s per DIT) for low-power propagation experiments and QRSS grabbers.

✦ Prosign Support

Full prosign set: <AR> <SK> <BT> <KN> <AS> <SN> — sent without inter-character space, per ITU standard.

🕐 Clock

Built-in digital clock on display. Optional DS3231 RTC for persistent timekeeping across reboots.

💾 SD Logging

All transmitted characters logged to CSV with timestamp, WPM, frequency and session metadata.

🔌 Paddle Swap

Swap DIT and DAH in one tap. For left-handed operators or reversed cables.

🔗 WinKey WK3

Full WinKey 2.3 binary protocol at 1200 baud for N1MM+, Win-Test, DXLog and other logging software.

⌨️ K3NG Serial

K3NG ASCII command set at 115200 baud via USB serial and BLE. Backslash commands for full control.

🛠️ FreeRTOS

morseTask on Core 0, LVGL on Core 1. 1 kHz hardware timer for sub-millisecond keying accuracy.


Hardware

The ESP32-2432S028R (CYD)

Everything you need in a single €10 board. No external display, no extra MCU, no separate audio chip.

ComponentDetail
MCUESP32-D0WD dual-core 240 MHz · 520 KB RAM · 4 MB flash
DisplayILI9341 2.8" TFT 320×240 · SPI (VSPI)
TouchXPT2046 resistive · SPI (HSPI) · 4-point calibrated
KEY / PTT outputGPIO 27 · shared pin · HIGH = active
SidetoneGPIO 25 DAC · 300–1200 Hz adjustable
Left paddle (DIT)GPIO 35
Right paddle (DAH)GPIO 22
SD cardHSPI · GPIO 18 / 19 / 23 / 5
PowerUSB-C 5V · no external supply needed
WirelessBLE 4.2 integrated · Wi-Fi available for future use

Changelog

Version History

VersionChanges
v7.1.5 Code comments optimised, reduced code lines. Minor text adjustments.
v7.1.4 Interactive 4-point touch calibration. Separate NVS namespace touch_cal. Serial escape, timeout and fallback protection. New K3NG commands \J \Y \X \E. LATEST
v7.1.3BLE fix: device name now visible on Android BLE scan. Name set in primary advertising payload; service UUID moved to scan response.
v7.1.2MANUAL mode fix: characters now displayed on text bars. mySet[] extended to 121 elements (full ITU punctuation + prosigns). Prosign display: <AR> <BT> <SK> etc.
v7.1.1FreeRTOS multi-task architecture refactoring. BLE with native BLEDevice. morseTask stack increased to 8192 bytes.
v6.9.0Base version by VK2IDL. Complete Morse keyer, BLE Nordic UART, SD player, WinKey 2.3, K3NG serial, LVGL 5 tabs, clock, QRSS, Farnsworth, beacon, contest.

Getting Started

Installation

1

Clone the repository

git clone https://github.com/mfalco1959/IW1RMM_CW_Encoder.git

Or download the ZIP from GitHub and extract it.

2

Install the ESP32 board package

In Arduino IDE: File → Preferences → Additional boards manager URLs, add:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Then Tools → Board → Boards Manager → search esp32 → install esp32 by Espressif Systems.

⚠ Tested with ESP32 Arduino Core 3.x. The BLE and DacESP32 libraries require Core 3.x — do not use 2.x.

3

Install required libraries

In Arduino IDE: Sketch → Include Library → Manage Libraries

LibraryVersionAuthorHow to install
lvgl8.4.0LVGLLibrary Manager → search lvgl
TFT_eSPI2.5.43BodmerLibrary Manager → search TFT_eSPI
XPT2046_Touchscreen1.4Paul StoffregenLibrary Manager → search XPT2046
DacESP322.1.2Thomas JentzschLibrary Manager → search DacESP32
SDbuilt-inArduinoBuilt-in — no install needed
SPIbuilt-inArduinoBuilt-in — no install needed
Preferences (NVS)built-inEspressifBuilt-in with ESP32 Core
BLEDevice / BLEServer / BLEUtils / BLE2902built-inEspressifBuilt-in with ESP32 Core
esp_bt.hbuilt-inEspressifBuilt-in with ESP32 Core (ESP-IDF)
4

Configure TFT_eSPI

Copy docs/User_Setup_example.h to your TFT_eSPI library folder (typically Documents/Arduino/libraries/TFT_eSPI/) and rename it User_Setup.h, replacing the existing file. Key settings for the CYD:

#define ILI9341_DRIVER
#define TFT_MISO  12
#define TFT_MOSI  13
#define TFT_SCLK  14
#define TFT_CS    15
#define TFT_DC     2
#define TFT_RST   -1
#define TOUCH_CS  -1
#define SPI_FREQUENCY  40000000

⚠ Make sure TFT_MISO 12 is defined and NOT commented out — the SD card will fail otherwise.

5

Copy lv_conf.h

Copy include/lv_conf.h from this repository into the sketch folder (same directory as IW1RMM_CW_Encoder.ino). This file enables the fonts used by the UI — without it the sketch will not compile.

6

Arduino IDE upload settings

Select board and configure upload options exactly as shown:

SettingValue
BoardESP32 Dev Module
Flash ModeDIO
Flash Frequency40 MHz
Partition SchemeHuge APP (3MB No OTA/1MB SPIFFS)
Upload Speed115200
Core Debug LevelNone

DIO + 40 MHz are mandatory. CYD boards often use ZBIT ZB25VQ32 flash chips that are sensitive to faster or QIO settings — using QIO or 80 MHz will cause upload failures or boot loops.

💡 Upload speed: 115200 baud is the safe recommended value. If you plan to upload only occasionally, you may try increasing the speed (e.g. 460800 or 921600) to reduce upload time, but stability depends on your USB cable and PC driver.

7

Open the sketch and upload

Open IW1RMM_CW_Encoder/IW1RMM_CW_Encoder.ino in Arduino IDE. Connect the CYD via USB-C. Select the correct COM port under Tools → Port. Click Upload.

On first boot, the touch calibration wizard will start automatically. Follow the on-screen instructions to touch each of the 4 corner crosshairs. Calibration is saved permanently — it will not repeat on subsequent boots.

8

Alternative: flash precompiled binary with esptool

If you prefer not to use Arduino IDE, flash the precompiled .bin directly:

python -m esptool --chip esp32 --port COM4 --baud 115200 \
  --before default-reset --after hard-reset \
  write-flash -z --flash-mode dio --flash-freq 40m \
  --flash-size detect 0x10000 IW1RMM_CW_Encoder_v714.bin

Replace COM4 with your actual port (Linux: /dev/ttyUSB0, Mac: /dev/cu.usbserial-*).


3D Printable Case

Enclosure for the CYD

A complete printable enclosure designed for the ESP32-2432S028R board. Print with PLA or PETG, 0.2 mm layer height. Files render in 3D directly on GitHub.

🖨️

Case-Front_Panel.stl

Front panel
🖨️

Case-Rear_Panel.stl

Rear panel
🖨️

Speaker-Cap.stl

Speaker cap
🖨️

Washer.stl

Washer

Documentation

Reference Documents

📘

Device & Features Guide

English · PDF
📘

Guida Dispositivo e Funzioni

Italiano · PDF
📙

Software Routine Analysis

English · PDF · v7.1.4
📙

Analisi Routine Software

Italiano · PDF · v6.9.0
⚙️

Source Code

GitHub Repository

Acknowledgements

Credits

VK2IDL

Original CW Encoder firmware. This project is built upon VK2IDL's foundational work and would not exist without it.

K3NG — Anthony Good

K3NG Arduino CW Keyer — command set and protocol reference.
github.com/k3ng

K1EL

WinKey 2/3 protocol specification and WK3 IC datasheet.
k1el.com

LVGL

Light and Versatile Graphics Library — the embedded GUI engine powering this project.
lvgl.io

Brian Lough

ESP32 Cheap Yellow Display community — documentation, pinouts and hardware resources.

IW1RMM — Mauri

Architecture, WinKey protocol, BLE, FreeRTOS integration, LVGL UI, touch calibration, K3NG extensions. Savona, Italy — 2025/2026.