StackmatLink gives your traditional timer the superpower to seamlessly enter the modern wireless ecosystem. As an open-source hardware and software solution based on the ESP32-S3, it precisely captures raw analog signals from the audio port of standard Stackmat timers (like the GAN Halo or other compatible devices) and converts them into the official GAN Smart Timer Bluetooth Protocol with zero latency.
No need for expensive native Bluetooth hardware, and no more cable clutter. StackmatLink instantly transforms your classic non-Bluetooth timer into a smart device, syncing every solve wirelessly and flawlessly to apps like csTimer.
- Protocol Conversion: Seamlessly parses Stackmat Gen4 (1200 Baud) signals and encapsulates them into the official GAN Bluetooth protocol (including the
0xFEmagic packet and CRC16/CCITT-FALSE checksums). - Intelligent State Inference: Specifically handles the GAN Halo
'I'(Idle) state. It dynamically infersRunningandStoppedstates based on packet timing to ensure absolute compatibility with csTimer. - Dual-Core Concurrency for Zero Latency:
- Core 1: Dedicated to high-priority, high-precision signal sampling and UART parsing at 1200 Baud.
- Core 0: Handles the NimBLE Bluetooth stack and characteristic Notify updates to ensure rapid data transmission without interrupting signal processing.
- Automatic Phase Correction: Built-in logic detects inverted signals (common when using different LM393 wiring configurations) and corrects them on the fly.
- Robust Connectivity & Visibility: Implements a connection polling mechanism (
getConnectedCount) to maintain stable data synchronization, with optimized BLE advertising parameters for instant discovery on macOS, Windows, and iOS.
.
├── GEMINI.md # Agent instructions & project overview
├── LICENSE # MIT License
├── README.md # English Documentation
├── README_ZH.md # Chinese Documentation
├── stackmatlink.ino # Main Arduino source code
└── hardware/
├── Case/ # 3D printed case designs (STL, Blender)
├── PCB/ # PCB design and production files (Gerber, Project)
└── Wiring/ # Circuit diagrams and references
To build StackmatLink, you will need the following parts:
| Component | Description | Notes |
|---|---|---|
| MCU | ESP32-S3 | Tested on N16R8. Custom PCB uses ESP32-S3-SuperMini, but compatible with all S3 variants. |
| Status LED | NeoPixel (WS2812) | Optional. Onboard on the SuperMini or externally wired. |
| Comparator IC | LM393 | Voltage Comparator (SMD/SOP-8 version). |
| Resistor Network | 3× 10kΩ Resistors | 1× for pull-up, 2× for a 1.65V voltage divider reference. |
| Audio Jack | 3.5mm Audio Jack | Tip: Signal, Sleeve: GND. |
| Custom PCB | StackmatLink Board | Gerber files provided in hardware/PCB/ for manufacturing. |
| Enclosure | 3D Printed Case | Optional. STL files provided in hardware/Case/ for 3D printing. |
| Component | ESP32-S3 Pin | Description |
|---|---|---|
| LM393 VCC | 3.3V |
Power Supply |
| LM393 GND | GND |
Common Ground |
| LM393 Output | GPIO 4 |
Requires 10kΩ Pull-up to 3.3V |
| NeoPixel DI | GPIO 48 |
Status LED (Onboard on SuperMini) |
| 3.5mm Tip | LM393 IN+ |
Raw Timer Signal |
| Ref GND | LM393 IN- |
1.65V Ref (via Voltage Divider) |
Since the timer outputs a weak analog audio signal (~0.7V–2.5V, sine-ish wave) prone to noise:
- Analog Stage: The signal enters the LM393
IN+. - Comparison: The LM393 compares it against a fixed 1.65V reference on
IN-. - Digital Stage:
Signal > 1.65V→ Output3.3V(High);Signal < 1.65V→ Output0V(Low). - Result: A clean, digital square wave is generated for the ESP32 UART to read.
- PCB Design (
hardware/PCB/): Production-ready Gerber files and project source. - 3D Printed Case (
hardware/Case/): STL files and the original Blender source file for modifications.
- Install the Arduino IDE.
- Install the ESP32 Board Package:
- Go to File > Preferences (or Arduino IDE > Settings on macOS).
- In the "Additional boards manager URLs" field, add:
https://espressif.github.io/arduino-esp32/package_esp32_index.json - Go to Tools > Board > Boards Manager...
- Search for "esp32" and install the package by Espressif Systems.
- Install the
NimBLE-ArduinoandAdafruit_NeoPixellibraries via the Arduino Library Manager. - Open
stackmatlink.ino, select your ESP32-S3 Dev Module (or your specific variant), and click Upload.Note: If
USB CDC On Bootis enabled on your board, use the Native USB port for serial debugging.
- Power Up: Connect the ESP32-S3 to power, and plug the audio cable into your timer.
- Verify Signal: Open the Serial Monitor at
115200 baud. The NeoPixel LED will glow Blue when the timer is actively running. - Connect to csTimer:
- Navigate to csTimer.net (Chrome/Edge recommended).
- Go to
Settings->Timer->Entering Type-> select Bluetooth Timer. - Click the Bluetooth icon at the top of csTimer and pair with "GAN-Timer".
- Go!: Your physical timer is now fully synced with your digital sessions.
- No Data Parsed: If the Serial Monitor shows raw activity but no time is parsed, try toggling the
invertedparameter in thestackmatTaskcode. - Connectivity Issues: Ensure you are using Chrome (Windows/macOS/Android) or a WebBLE browser like Bluefy (iOS) for the best Web Bluetooth experience.
- LED Status Meanings:
- 🔵 Blue: Timer is running.
- ⚪ White (Solid or Blinking): Timer is reset and ready.
Copyright (c) 2026 liusonwood.
- Software (Firmware): Licensed under the MIT License.
- Hardware (PCB & Case): Licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) License. Commercial reproduction or sales of the physical hardware without prior permission are strictly prohibited.
Contributions and PRs are always welcome!
- The
NimBLE-ArduinoandAdafruit_NeoPixelcommunities. - The
csTimerproject and the GAN Timer driver reference.
⚠️ WARNING: Security Notice
StackmatLink is an open-source project and this is the only official repository. Beware of fake clones or 'installers' on GitHub offering.zipor.exefiles. This project is provided purely as source code and hardware design files.
本项目由我最初构思,并在 AI 对编程的辅助下耗时两小时实现。


