# IN-12 nixie clock: open firmware Replacement firmware for a RetroModding **NixieIN12v2** WiFi nixie clock (the 5 V, USB-C version sold on AliExpress): 4x IN-12 tubes, 2x IN-3 neon dots, 4 WS2812 LEDs, an ESP8266 (ESP-12) and a light sensor. The closed stock firmware (SV1.3) is replaced by [ESP_UniClock](https://github.com/gpeter62/ESP_UniClock) with a new display driver for this board, WiFi updates and Home Assistant control. ## Features - Time from NTP with time zone and EU summer time, 12/24 h, day/night brightness, auto dimming from the light sensor, digit animations, cathode-poisoning protection, blinking colon - WS2812 backlight: fixed colour or one of nine animated effects - UniClock's web page for all settings - Firmware updates over WiFi (ArduinoOTA) - Home Assistant over MQTT discovery: tubes on/off, day/night brightness, auto dim, backlight (on/off, brightness, colour), LED effect, cathode protect, SignalRGB on/off, light and WiFi-signal sensors - SignalRGB: the backlight can show up in SignalRGB as a WLED device (see below) ## The hardware The pinout was taken from the stock firmware by disassembly and checked on the clock; details and evidence are in [docs/stock-firmware-pins.md](docs/stock-firmware-pins.md). | Function | GPIO | |---|---| | 2x 74HC595 (cathodes, anodes, dots) DATA / CLOCK | 13 / 14 (hardware SPI) | | 74HC595 latch | 15 | | WS2812 data | 12 | | Light sensor (LDR) | A0 | The two shift registers hold one 16-bit word: bits 0-9 are the cathodes for digits 0-9, bits 11-14 the tube anodes (bit 11 = left tube), bit 10 the neon dots and bit 15 the decimal points. The tubes are multiplexed, one at a time. This board has no RTC chip and no buttons. > **Warning:** the board makes about 170 V for the tubes whenever USB-C is connected. ## Repository layout | Path | Contents | |---|---| | [firmware/uniclock/](firmware/uniclock/) | ESP_UniClock with the board support (PlatformIO project, see its [README](firmware/uniclock/README.md)) | | `firmware/uniclock/ESP32_UniClock2/nixie595.ino` | Display driver for this board | | `firmware/uniclock/ESP32_UniClock2/clocks.h` | Board configuration, `CLOCK_90` | | [docs/](docs/) | Pinout analysis of the stock firmware, schematic of the related 12 V board | | [tools/](tools/) | Python helpers used to disassemble the stock firmware | The stock firmware dump is not included: it contains the WiFi password. ## Building and flashing Install [PlatformIO](https://platformio.org/), then in `firmware/uniclock/`: ```sh pio run # build pio run -t upload # first flash, over serial pio run -t uploadfs # web page files, over serial pio run -e nixie_in12_ota -t upload # later updates, over WiFi ``` The first flash needs a USB-serial adapter (3.3 V logic) on the programming header (GND, GPIO0, RST, RXD, TXD, 3.3V). The clock stays powered from its own USB-C, so leave the adapter's 3.3V unconnected. There is no auto-reset: before each serial upload, hold GPIO0 to GND, tap RST to GND and release GPIO0. Set the serial port and the clock's IP address in `platformio.ini`. Back up the stock firmware first (`esptool read-flash 0 0x400000 stock.bin`); it is the only way back. On first boot the clock opens a WiFi access point called **UNICLOCK**. Connect to it and set your WiFi on http://192.168.4.1. For Home Assistant, enter the MQTT broker on the clock's web page and restart the clock; it then shows up under Settings > Devices > MQTT. Optional passwords for the web page and OTA updates go in `firmware/uniclock/ESP32_UniClock2/secrets.h` (see `secrets.h.example`; the file is gitignored). ## SignalRGB Turn on **SignalRGB (WLED)** on the RGB page of the web UI (or the SignalRGB switch in Home Assistant). The clock then answers like a WLED device with one LED per tube, LED 0 = left tube: mDNS `_wled._tcp`, `/json/info` and `/json/state` without a password, and colour frames over UDP (WLED realtime on port 21324, DDP on 4048). SignalRGB should find it by itself; if not, add it by IP address. SignalRGB only drives as many LEDs as the component on the device's channel has, so give the channel a component with 4 LEDs. While SignalRGB sends colours it controls the LEDs (at most 30 frames per second, `WLED_MAX_FPS` in `clocks.h`); 2.5 s after it stops, the normal effect comes back. The alarm flash always wins. Two more switches on the same page: - **SignalRGB off with tubes**: the LEDs stay dark at night and while the tubes are off. - **SignalRGB uses RGB Brightness**: colours are scaled by the RGB brightness and auto dim; off = colours as SignalRGB sends them. ## Changes to ESP_UniClock Besides the new driver and configuration: - NeoPixels on any ESP8266 pin, sent only when they change and between tube slots (the bit-banged update blocks interrupts and made the tubes flicker) - ArduinoOTA; Home Assistant integration rewritten for ArduinoHA 2.1 - WLED emulation for SignalRGB (`wled.ino`); its settings are stored after the UniClock settings in EEPROM, so the update keeps all existing settings - EU summer-time rules (upstream ended summer time on the US date); switching DST on no longer shifts the clock by an hour in winter - Saving the firmware URL no longer starts an HTTP update; optional web password - Small fixes: PlatformIO build, MQTT message buffer overflow, cathode-protect random start, LED gamma ## Credits and license ESP_UniClock is © Peter Gautier and licensed GPL-3.0-or-later; the modified firmware in `firmware/uniclock/` is under the same license. The libraries in `firmware/uniclock/lib/` keep their own licenses. The board support, analysis and changes were made with [Claude Code](https://claude.com/claude-code).