Skip to content

Repository files navigation

DailyDuino HexPad 16 — nRF52840 Firmware

A 4×4 BLE + USB HID macropad with 16 WS2812B RGB LEDs, 7 switchable profiles, and a JSON configuration protocol over three transports (USB Serial, USB Raw HID, BLE NUS).

Supported hardware: nice!nano · Tenstar Robot Pro Micro nRF52840 (any board that exposes raw nRF52840 GPIO numbers with an identity pin map).


Features

Feature Detail
Keys 4×4 matrix, 8 ms per-key debounce
Profiles 7 profiles, switchable via button
LEDs 16× WS2812B — 5 modes per profile (per-key, solid, rainbow, reactive, breathe)
Indicator LEDs 4 LEDs: profile binary display, battery bar, pairing flash, charging sweep
BLE HID Keyboard + consumer-control, multi-bond
USB HID Keyboard + consumer-control (always active, no pairing needed)
BLE Battery Service Standard 0x180F, updated every 60 s
Config transports USB CDC Serial · USB Raw HID · BLE NUS (same JSON protocol on all three)
Storage LittleFS on internal flash; auto-format on corruption
Deep sleep System OFF (~2 µA) after 15 min idle (battery only); any key or button wakes
LED dimming WS2812B dims to off after 5 min idle, restores on keypress
Battery monitor ADC on P0.04, 12-bit, 8-sample average, non-linear LiPo curve
Charging detect Heuristic: USB connected + voltage rising over 2 min
Factory reset Hold button ≥ 5 s at boot

Default profiles

# Name Layout
1 Hex 0-9, A-F hex keypad (orange row + green keys)
2 Numpad Standard numpad layout (7-8-9-/ · 4-5-6-* · 1-2-3-· · 0-.-Enter-+)
3 Media Play/Pause, Next, Prev, Stop, Vol+, Vol−, Mute
4-7 Profile 4-7 Empty (distinct LED colours)

Pin map

Uses raw nRF52840 GPIO numbers (P0.xx = 0–31, P1.xx = 32+).
Compiled with board target adafruit:nrf52:pca10056 (identity g_ADigitalPinMap).

GPIO # nRF52840 nice!nano label Function
11 P0.11 D7 Row 0 (open-drain scan, ext. 10 kΩ pull-up)
32 P1.00 D6 Row 1 (open-drain scan, ext. 10 kΩ pull-up)
24 P0.24 D5 Row 2 (open-drain scan, ext. 10 kΩ pull-up)
22 P0.22 D4 Row 3 (open-drain scan, ext. 10 kΩ pull-up)
20 P0.20 D3 Col 0 (driven LOW during scan)
17 P0.17 D2 Col 1 (driven LOW during scan)
8 P0.08 D0 Col 2 (driven LOW during scan)
6 P0.06 D1 Col 3 (driven LOW during scan)
10 P0.10 D8 WS2812B DIN
13 P0.13 VCC enable (set HIGH at boot to power WS2812B)
9 P0.09 D9 Indicator LED bit 0 (LSB)
2 P0.02 D10 Indicator LED bit 1
29 P0.29 D15 Indicator LED bit 2
31 P0.31 D14 Indicator LED bit 3 (MSB)
4 P0.04 A0 Battery ADC (AIN2, voltage divider ÷2)
36 P1.04 A1 Profile button (INPUT_PULLUP, active LOW)

Matrix wiring

Diode direction: column → row (anode on column wire, cathode on row wire).

Rows are scanned open-drain: each row pin switches between OUTPUT LOW (scan active) and INPUT (high-Z idle) to avoid bus conflicts. Column pins use INPUT_PULLUP (internal ~13 kΩ) plus external 10 kΩ pull-ups (combined ~5.6 kΩ).

A pressed key forward-biases the diode and pulls the column pin LOW.

WS2812B LED strip wiring (snake)

Key row 0 (top) ←  pixels 15 14 13 12
Key row 1       →  pixels  8  9 10 11
Key row 2       ←  pixels  7  6  5  4
Key row 3 (bot) →  pixels  0  1  2  3

Strip connector attaches at physical bottom-left.

Indicator LED binary encoding

Pattern Profile
○○○● 1
○○●○ 2
○○●● 3
○●○○ 4
○●○● 5
○●●○ 6
○●●● 7

LED 0 (LSB) slow-pulses when battery ≤ 10 %. All 4 LEDs flash ~8 Hz in pairing mode. Double-tap shows a 3-second battery bar (1–4 LEDs filled).


Profile button gestures

Gesture Action
Single tap Cycle to next profile (1 → 2 → … → 7 → 1)
Double tap Show battery level for 3 s
Hold 3 s Enter BLE pairing mode (clears bonds, restarts advertising)
Release after long hold Exit pairing mode

Build

Required tools & libraries

Tool / Library Version Notes
arduino-cli or Arduino IDE 2 any
Adafruit nRF52 BSP ≥ 1.6 (1.7.0 tested) includes Bluefruit + TinyUSB
ArduinoJson ≥ 7.0
Adafruit NeoPixel any

BSP board manager URL:

https://adafruit.github.io/arduino-board-index/package_adafruit_index.json

Compile + flash (arduino-cli)

# Compile
arduino-cli compile --fqbn adafruit:nrf52:pca10056 --output-dir build HexPad-nRF52840.ino

# Convert to UF2
python3 /path/to/uf2conv.py \
    --family 0xADA52840 --base 0x26000 \
    build/HexPad-nRF52840.ino.hex \
    -o build/HexPad-nRF52840.uf2

uf2conv.py ships with the Adafruit nRF52 BSP at: ~/.arduino15/packages/adafruit/hardware/nrf52/<version>/tools/uf2conv/uf2conv.py

Board target must be adafruit:nrf52:pca10056 (Nordic nRF52840 DK). This board definition has an identity g_ADigitalPinMap so raw GPIO numbers in code map directly to physical pins. Using adafruit:nrf52:feather52840 will map all GPIO numbers wrong.

Flash

Enter the bootloader (double-tap reset — LED pulses). A mass-storage drive appears. Copy HexPad-nRF52840.uf2 onto it; device reboots automatically.

Factory reset

Hold the profile button while plugging in USB (or at power-on). Keep holding for 5 seconds until the indicator LEDs blink 3 times. All profiles reset to defaults and the active profile is saved.


USB device identity

Field Value
VID / PID 0x1209 / 0xDD16
Manufacturer DailyDuino
Product DailyDuino Hexpad 16
HID reports Report ID 1: keyboard · ID 2: consumer · ID 3: vendor config (32 B)

BLE

Field Value
Device name DailyDuino Hexpad 16
TX power +4 dBm
BLE ATT MTU 247 bytes (BANDWIDTH_MAX, HVN queue = 3)
Advertising Fast 30 s, then slow; restarts on disconnect
NUS TXD 6E400003-B5A3-F393-E0A9-E50E24DCCA9E (notify)
NUS RXD 6E400002-B5A3-F393-E0A9-E50E24DCCA9E (write)
Battery Service UUID 0x180F

Config protocol

All three transports speak the same line-delimited JSON protocol (newline \n as message terminator).

Transport How to connect
USB CDC Serial 115200 baud — any serial terminal
USB Raw HID Report ID 3, 32-byte reports — vendor 0xFF60, usage 0x61
BLE NUS Write to RXD characteristic; responses arrive on TXD notifications

Commands

Command Required fields Response
info Device name, firmware, proto version, profile count, battery %
get_profile profile (0-6, optional) Full profile: name, LED config, all 16 key bindings, per-key LED colors
set_key profile, key (0-15), action object {"ok":true}
set_led profile, any of: enabled, brightness, mode, color, anim_speed {"ok":true}
set_led_color profile, key (0-15), rgb ([r,g,b]) {"ok":true}
set_profile_name profile, name {"ok":true}
switch_profile profile (0-6) {"ok":true}
get_battery pct, mv, charging, usb
save Persists current config to LittleFS
reset_defaults Restores factory defaults and saves
sleep Enters System OFF deep sleep

All requests may include an "id" field; the value is echoed back in the response.

Key action types

Type Extra fields Description
none No action
key keycode, mods Single HID keycode with modifier mask
combo keys (array), mods Multiple keycodes sent simultaneously
text text (string) Types a string via ASCII→HID lookup
consumer consumer (uint16) HID consumer-control usage code
macro steps (array) Sequence of press/release/tap/delay steps

Modifier mask bits: LCTRL=0x01 LSHIFT=0x02 LALT=0x04 LGUI=0x08 RCTRL=0x10 RSHIFT=0x20 RALT=0x40 RGUI=0x80

LED modes

Value Name Description
0 per-key Individual RGB per key stored in profile
1 solid All keys one colour
2 rainbow Hue cycle animation across all keys
3 reactive Keys flash white on press, fade to base colour
4 breathe All keys pulse in/out at anim_speed rate

Example session

→ {"cmd":"info"}
← {"ok":true,"name":"DailyDuino Hexpad 16","firmware":"3.0.0-nrf","proto":2,"profiles":7,"keys":16,"leds":16,"profile":0,"battery":85}

→ {"cmd":"get_profile","profile":0}
← {"ok":true,"profile":0,"data":{"name":"Hex","led":{...},"keys":[...],"led_colors":[...]}}

→ {"cmd":"set_key","profile":0,"key":0,"action":{"type":"key","keycode":4,"mods":0}}
← {"ok":true}

→ {"cmd":"save"}
← {"ok":true}

Power

Threshold Value
Deep sleep trigger 15 min idle, battery only (USB connected = no sleep)
LED dim trigger 5 min idle
Battery full 4200 mV
Battery empty 3000 mV
Low battery warning ≤ 3300 mV (~10 %)
Wake sources Any column pin LOW or button pin LOW (GPIO SENSE)

Source files

File Purpose
HexPad-nRF52840.ino Main sketch — setup, loop, key + button event dispatch
Config.h / .cpp Pin constants, data structures, LittleFS persistence, factory defaults
Matrix.h / .cpp 4×4 scan with open-drain rows, 8 ms debounce
HIDOutput.h / .cpp BLE HID + USB HID reports, BLE NUS, USB Raw HID, held-key tracking
LedControl.h / .cpp WS2812B driver, 5 animation modes, snake LED map, idle dimming
Indicator.h / .cpp 4-LED indicator: profile, battery, pairing, charging, low-batt
Button.h / .cpp Debounced single / double / long-press state machine
Power.h / .cpp Battery ADC, BLE BAS, charging heuristic, deep sleep
Protocol.h / .cpp Transport-agnostic JSON command dispatcher
INTERFACE.md Config protocol reference for client developers

About

BLE + USB macropad firmware for nRF52840. Features 16 programmable keys, 7 profiles, RGB LEDs, and a JSON config app. Works on nice!nano and Tenstar Pro Micro.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages