
Unicorne choc
EyalYe/unicorne
A unibody Corne: both halves of the Corne v3 key layout on one PCB, each half rotated 16°, with an Azoteq TPS43 trackpad in the middle (it sits on the case, over the nice!nano) and a nice!nano v2 at the top.

A unibody Corne: both halves of the Corne v3 key layout on one PCB, each half rotated 16°, with an Azoteq TPS43 trackpad in the middle (it sits on the case, over the nice!nano) and a nice!nano v2 at the top.
Unicorne is an open-source printed circuit board by EyalYe, from the EyalYe/unicorne repository on GitHub. It is a 2-layer board of 293.4 × 118.8 mm with 175 parts on 130 nets, routed with 2,736 tracks and 451 vias.
It is built around the SN74LV1T125DBV, 1N4148W and SK6812MINI-E, with the AO3401A among its other parts. Its parts include 96 diodes, 44 switches, 6 connectors, 5 resistors and 2 capacitors. It belongs with the nRF52 and nRF5x boards of this library.
A unibody Corne: both halves of the Corne v3 key layout on one PCB, each half rotated 16°, with an Azoteq TPS43 trackpad in the middle (it sits on the case, over the nice!nano) and a nice!nano v2 at the top.
Status: layout fixed, schematic done, MX and Choc boards fully routed (DRC: 0 unconnected, 0 copper violations).
42 keys (3×6 + 3 thumbs per half), outer pinky columns break off for a 36-key board
Key spacing, stagger, thumb cluster and LED positions copied from crkbd v3-final (19.0 mm pitch)
Two board versions with the same placement: Kailh MX hotswap, and Kailh Choc hotswap (fits Choc V1 and V2)
nice!nano v2 on the top side, components up, USB on the top edge; the edge is notched for the mid-mount USB-C, whose shell drops below the nano's underside
TPS43 trackpad wired to six bare pads (no FPC, to keep it thin). It sits on the case above the board, so it may cover the nice!nano; its position is the one that brings the halves closest together (higher and it meets the inner columns' top keycaps, lower and the thumb keycaps). It is drawn on F.Fab and User.Drawings only, with no 3D model on the board
Optional LEDs: 12 SK6812MINI underglow + 42 SK6812MINI-E per key, on their own MOSFET-switched supply. A solder jumper picks the source: the nice!nano's 3.3 V VCC (up to its 1 A regulator), or an external supply up to 5 V on the LED IN pads for full brightness. Never the battery.
MSK-12C02 battery cut-off switch, through-hole battery pads
Exposed pads: expansion header (3V3, GND, UART, I2C) and GPIO header (P0.24, P1.00, P0.11)
Pro Micro mode: a Pro Micro-footprint controller without the nice!nano's three inner pins (P1.01, P1.02, P1.07) works with three solder jumpers bridged, which move those nets to outer pins that aren't the Pro Micro I2C pair:
| Jumper | Net (nice!nano pin) | Bridged to | That pin's other use, lost in this mode |
|---|---|---|---|
| JP4 | COL5 (P1.01) | P0.24 | free GPIO / sensor MISO |
| JP5 | COL6 (P1.02) | P0.11 | free GPIO / sensor CS |
| JP6 | ROW5 (P1.07) | P0.08 | UART RX |
I2C (SDA/SCL), the trackpad's RDY, LED data (P0.06) and LED power (P1.00) keep working. Leave all three open with a nice!nano, or two controller pins drive one net. In firmware, point COL5, COL6 and ROW5 at the bridged pins.
The full pin plan and parts list are in mock/index.html (open it in a browser).
Everything is hand-soldered. Quantities are for one board; the 36-key build needs 36 of each per-key part.
| Ref | Qty | Part | Footprint | Notes |
|---|---|---|---|---|
| U1 | 1 | nice!nano v2 | through-hole, top side | Needs the 3 inner pads (P1.01, P1.02, P1.07) too; use low-profile sockets or solder directly |
| SW1–42 | 42 | Key switches: MX, or Choc V1/V2 | hotswap | MX on unicorne.kicad_pcb, Choc on unicorne-choc.kicad_pcb |
| — | 42 | Hotswap sockets: Kailh MX, or Kailh Choc | SMD, bottom | The Choc socket fits both V1 and V2 switches |
| D1–42 | 42 | 1N4148W diode | SOD-123, bottom | |
| SW43 | 1 | MSK-12C02 slide switch | SMD, bottom, top edge | Battery cut-off |
| SW44 | 1 | TS-1136 H4.3 tactile switch (6.0×3.5 mm, 4.3 mm tall, 2 pins) | through-hole, top, beside the nano | Reset |
| J1 | — | Battery B+ / B− pads | through-hole, 4.8 mm | Solder the battery leads here |
| J2 | — | TPS43 pads | through-hole, 2.54 mm | Wires to the trackpad (trackpad build) |
| J5 | — | Sensor pads | through-hole, 2.54 mm | Wires to a PAW3395 / PMW3360 board (sensor build) |
| J3 | 1 | 1×6 pin header, 2.54 mm | through-hole | Optional: expansion (3V3, GND, UART, I2C) |
| J4 | 1 | 1×4 pin header, 2.54 mm | through-hole | Optional: GPIO (P0.24, P1.00, P0.11) |
| R3, R4 | 2 | 4.7 kΩ resistor | 0603 hand-solder | Trackpad build only (I2C pull-ups); leave off with a sensor |
| R5 | 1 | 10 kΩ resistor | 0603 hand-solder | Trackpad / sensor reset pull-up |
Leave all of these off for a board without lighting.
| Ref | Qty | Part | Footprint | Notes |
|---|---|---|---|---|
| LED1–12 | 12 | SK6812MINI | 3.5 mm PLCC4, bottom | Underglow |
| LED13–54 | 42 | SK6812MINI-E | reverse mount, bottom | Per-key; shines up through a cutout |
| JP2 | — | 3-pad solder jumper | — | LED source: bridge VCC–centre, or EXT–centre for J6 |
| J6 | — | LED IN pads (V+, GND) | through-hole, 2.54 mm | External LED supply up to 5 V, e.g. a USB-C breakout; only with JP2 on EXT |
| Q1 | 1 | AO3401A P-MOSFET | SOT-23 | Switches the LED supply |
| Q2 | 1 | 2N7002 N-MOSFET | SOT-23 | Driven by P1.00 |
| R1, R2 | 2 | 100 kΩ resistor | 0603 hand-solder | Keep the LEDs off during boot |
| C1 | 1 | 10 µF capacitor | 0603 hand-solder | LED supply |
| U2 | 1 | SN74LV1T125 buffer | SOT-23-5 hand-solder | LED data level shifter, needed only with JP2 on EXT; must be the LV1T (not 74LVC1G125) so 3.3 V data works at 5 V |
| C2 | 1 | 100 nF capacitor | 0603 hand-solder | U2 decoupling; leave off with U2 |
| JP3 | — | Solder jumper | — | U2 bypass: bridge it with JP2 on VCC and U2 left off |
| JP1 | — | Solder jumper | — | Bridge it to send LED data from P0.06 (through U2) |
| JP4–JP6 | — | Solder jumpers | — | Pro Micro mode only: bridge all three without a nice!nano; open with one |
| Qty | Part | Notes |
|---|---|---|
| 1 | Azoteq TPS43 trackpad (43.3 × 40.3 mm) | Trackpad build; or a PAW3395 / PMW3360 sensor board for a trackball (3.3 V supply) |
| 1 | 3.7 V LiPo battery | Sits under the trackpad on the bottom; size it to your case |
| 42 | Keycaps, MX or Choc | 40 × 1u and 2 × 1.5u (the big thumb key on each half) |
| 10 | M2 button-head screws (ISO 7380) + standoffs | Mounting holes H1–H10; standoff height depends on the case |
Upload export/jlcpcb/unicorne-mx-jlcpcb.zip or unicorne-choc-jlcpcb.zip (gerbers plus Excellon drills,
plated and non-plated separate). Settings:
| Option | Value |
|---|---|
| Layers | 2 |
| Thickness | 1.6 mm |
| Size | about 293 × 119 mm (read from the outline) |
| Min. via / hole | 0.3 mm via drill, 0.5 mm mouse-bite holes |
| Min. track / spacing | 0.2 mm / 0.2 mm (0.15 mm rule minimum) |
| Surface finish | HASL (lead-free if you prefer) |
| Everything else | defaults |
No assembly: every part is hand-soldered (see the parts list). Regenerate the zips with
python3 tools/export_gerbers.py after any board change; it refuses to export a board that fails DRC.
export/unicorne-mx.step and export/unicorne-choc.step are the full boards with parts, for designing a
case (rendered previews next to them). Sockets and the Cherry MX and Choc V1 switches are real models; the nice!nano,
TPS43, SK6812MINI and MSK-12C02 are size-accurate placeholder boxes from tools/step_box.py.
Regenerate with python3 tools/export_3d.py after any board change.

The top plate, as a starting point for a case. Plates are solid (no break lines), so there is one per switch type and size:
| Plate | Cutouts | Thickness |
|---|---|---|
plate/unicorne-mx-42-plate.kicad_pcb, plate/unicorne-mx-36-plate.kicad_pcb | 14.0 mm | 1.5 mm |
plate/unicorne-choc-42-plate.kicad_pcb, plate/unicorne-choc-36-plate.kicad_pcb | 13.8 mm | 1.2 mm |
Each has the same outline, coordinates and M2 holes as its PCB, a 44.3 x 41.3 mm opening for the TPS43,
an opening over the nice!nano that runs out through the top edge (so the USB stays reachable) and a window
over the reset switch, both with 0.5 mm clearance.
The 36-key plates are cut evenly on both sides where the PCB snaps off its outer columns (on Choc, whose
break lines differ by side, at their average), with rounded corners.
export/plate/ holds, per plate:
*-jlcpcb.zip: order as an FR4 board, no copper (the copper layers are included empty so JLCPCB's
viewer reads the stack); set the thickness above.*.dxf: Edge.Cuts outline in mm, for laser-cut aluminium, steel or acrylic.*.step: the plate solid, in the same coordinates as the board STEP files.*.png: a render.
| Path | Contents |
|---|---|
unicorne.kicad_pro | KiCad 10 project |
unicorne.kicad_sch, matrix.kicad_sch, leds.kicad_sch | Schematic (generated, see below) |
unicorne.kicad_pcb | MX hotswap PCB (generated, see below) |
unicorne-choc.kicad_pcb, unicorne-choc.kicad_pro | Choc V1/V2 hotswap PCB, same placement |
unicorne.kicad_dru | Extra DRC rules (LED cutout edge clearance) |
lib/ | Project symbols and footprints; third-party credits in lib/ATTRIBUTION.md |
tools/fp_tactile.py | Generates the reset switch footprint |
tools/layout.py | Key, trackpad and outline geometry → mock/layout.json, mock/unicorne.svg |
tools/gen_schematic.py | Generates the schematic sheets from mock/layout.json |
tools/gen_pcb.py | Builds both PCBs from the schematic netlist and mock/layout.json |
tools/krt_route.py | Routes a freshly generated board (used for both boards): fixed lanes, then KiCadRoutingTools 0.23.7 for every other signal at standard JLCPCB sizes with no via in or next to a pad, the maze router for anything left, GND pours and stitching, then its plane repair. Expects KiCadRoutingTools in ~/Development/tools/KiCadRoutingTools with its own venv |
tools/finish_route.py | The older all-in-house router: fixed lanes, then KiCad's ratsnest with the maze router, GND pours and stitching; up to 10 attempts, then GND repair and stub cleanup. Also keeps new vias out of pads |
tools/gnd_repair.py | Finds GND copper the pours left cut off and joins it (a via, or rip-up and reroute of whatever boxes it in) |
tools/lanes.py, tools/maze_route.py | Fixed routing lanes for the key grid; the grid A* router |
tools/route.py | Freerouting driver (not used for the final boards) |
tools/step_box.py, lib/3d/ | Placeholder STEP models and the socket / Choc switch models |
tools/export_3d.py, export/ | STEP export of both boards, and 3D renders |
tools/export_gerbers.py, export/jlcpcb/ | JLCPCB gerber + drill zips |
docs/led-map.md, docs/led-map.csv | Every LED's index in the data chain (0-based, for firmware), its reference, spot and the key's matrix row and column |
tools/led_map.py | Generates the LED map from the board |
tools/led_order.json | The LED chain order, picked in the LED Chain Order page; gen_schematic.py uses it when present |
tools/waves.py | Wavy silkscreen pattern on both sides of the routed PCBs |
tools/gen_plate.py, plate/, export/plate/ | 42- and 36-key switch plates and their exports |
mock/ | Layout data, a 1:1 printable SVG and the design overview page |
# Geometry (needs KiCad's bundled Python for the outline)
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 tools/layout.py
# Schematic (overwrites the three .kicad_sch files)
python3 tools/gen_schematic.py
# PCBs (overwrite the board files; placement, outline, holes, silkscreen, no tracks)
# then route them; both steps throw away any hand routing
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 tools/gen_pcb.py mx
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 tools/gen_pcb.py choc
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 tools/krt_route.py mx
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 tools/krt_route.py choc
# On MX the plane repair reaches U2 pad 3 (GND, boxed in by LED_DIN) only through a via in the
# pad, which krt_route.py removes, leaving that pad unconnected. The committed board joins it by
# hand: a via at (160.65, 137.45) between pads 3 and 4, a back-layer track to pad 3 and a
# front-layer track to the GND copper.
# LED map for firmware (chain index -> LED, switch, matrix position)
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 tools/led_map.py
# Wavy silkscreen on both PCBs (redraws only the waves, leaves the routing alone)
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 tools/waves.py
# Switch plates and their exports (reads hole positions from the routed boards)
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 tools/gen_plate.pyThe nice!nano footprint comes from bstiq/nice-nano-kicad under GPLv3; the hotswap footprints from keyswitch-kicad-library under MIT.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 42 | 1N4148W | Diode_SMD:D_SOD-123 | D1, D2, D10, D11, D12, D13, D14, D15, D16, D17, D18, D19, D20, D21, D22, D23 +26 |
| 42 | SK6812MINI-E | LED_SMD:LED_SK6812MINI-E_3.2x2.8mm_P1.5mm_ReverseMount | LED1, LED2, LED10, LED12, LED14, LED15, LED16, LED17, LED19, LED20, LED21, LED22, LED24, LED25, LED27, LED28 +26 |
| 12 | SK6812MINI | unicorne:LED_SK6812MINI_PLCC4_3.5x3.5mm_P1.75mm | LED4, LED8, LED11, LED13, LED18, LED23, LED26, LED29, LED37, LED40, LED45, LED47 |
| 10 | M2 | MountingHole:MountingHole_2.2mm_M2_ISO7380 | H1, H2, H3, H4, H5, H6, H7, H8, H9, H10 |
| 2 | 100k | Resistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolder | R1, R2 |
| 2 | 4.7k | Resistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolder | R3, R4 |
| 2 | mouse bites | MB1, MB2 | |
| 1 | 100nF | Capacitor_SMD:C_0603_1608Metric_Pad1.08x0.95mm_HandSolder | C2 |
| 1 | 10k | Resistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolder | R5 |
| 1 | 10uF | Capacitor_SMD:C_0603_1608Metric_Pad1.08x0.95mm_HandSolder | C1 |
| 1 | 2N7002 | Package_TO_SOT_SMD:SOT-23 | Q2 |
| 1 | AO3401A | Package_TO_SOT_SMD:SOT-23 | Q1 |
| 1 | Battery | Connector_Wire:SolderWire-0.5sqmm_1x02_P4.8mm_D0.9mm_OD2.3mm | J1 |
| 1 | COL5 to P0.24 | Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm | JP4 |
| 1 | COL6 to P0.11 | Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm | JP5 |
| 1 | Expansion | Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical | J3 |
| 1 | GPIO | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | J4 |
| 1 | LED data | Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm | JP1 |
| 1 | LED power in | Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical | J6 |
| 1 | LED source | Jumper:SolderJumper-3_P1.3mm_Open_RoundedPad1.0x1.5mm | JP2 |
| 1 | PAW3395 / PMW3360 | Connector_PinHeader_2.54mm:PinHeader_1x08_P2.54mm_Vertical | J5 |
| 1 | Power | unicorne:SW_SPDT_Shouhan_MSK12C02 | SW43 |
| 1 | R0C0 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW1 |
| 1 | R0C1 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW2 |
| 1 | R0C2 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW3 |
| 1 | R0C3 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW4 |
| 1 | R0C4 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW5 |
| 1 | R0C5 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW6 |
| 1 | R0C6 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW19 |
| 1 | R1C0 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW7 |
| 1 | R1C1 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW8 |
| 1 | R1C2 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW9 |
| 1 | R1C3 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW10 |
| 1 | R1C4 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW11 |
| 1 | R1C5 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW12 |
| 1 | R1C6 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW20 |
| 1 | R2C0 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW13 |
| 1 | R2C1 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW14 |
| 1 | R2C2 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW15 |
| 1 | R2C3 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW16 |
| 1 | R2C4 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW17 |
| 1 | R2C5 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW18 |
| 1 | R2C6 | unicorne:SW_Hotswap_Kailh_MX_1.50u | SW21 |
| 1 | R3C0 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW22 |
| 1 | R3C1 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW23 |
| 1 | R3C2 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW24 |
| 1 | R3C3 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW25 |
| 1 | R3C4 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW26 |
| 1 | R3C5 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW27 |
| 1 | R3C6 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW40 |
| 1 | R4C0 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW28 |
| 1 | R4C1 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW29 |
| 1 | R4C2 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW30 |
| 1 | R4C3 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW31 |
| 1 | R4C4 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW32 |
| 1 | R4C5 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW33 |
| 1 | R4C6 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW41 |
| 1 | R5C0 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW34 |
| 1 | R5C1 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW35 |
| 1 | R5C2 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW36 |
| 1 | R5C3 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW37 |
| 1 | R5C4 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW38 |
| 1 | R5C5 | unicorne:SW_Hotswap_Kailh_MX_1.00u | SW39 |
| 1 | R5C6 | unicorne:SW_Hotswap_Kailh_MX_1.50u | SW42 |
| 1 | ROW5 to P0.08 | Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm | JP6 |
| 1 | Reset | unicorne:SW_Tactile_SPST_3.5x6mm_H4.3mm_THT | SW44 |
| 1 | SN74LV1T125 | Package_TO_SOT_SMD:SOT-23-5_HandSoldering | U2 |
| 1 | TPS43 | Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical | J2 |
| 1 | U2 bypass | Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm | JP3 |
| 1 | nice!nano v2 | unicorne:nice_nano | U1 |
It measures 293.4 × 118.8 mm and has 2 copper layers, 1.6 mm thick.
175 parts, built around the SN74LV1T125DBV, 1N4148W, SK6812MINI-E and AO3401A. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the EyalYe/unicorne repository on GitHub, at the commit this page was made from: the board is unicorne.kicad_pcb and its schematic leds.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask EyalYe before reusing the design.

EyalYe/unicorne
A unibody Corne: both halves of the Corne v3 key layout on one PCB, each half rotated 16°, with an Azoteq TPS43 trackpad in the middle (it sits on the case, over the nice!nano) and a nice!nano v2 at the top.


DovydasTEDS/teds-kb-numpad
a numpad / 17-key keypad with per-key rgb lighting, qmk firmware and soon to be added via and possibly signalrgb support!

Charading/SHEGO16-QMK-Hall-Effect-Macropad
An RP2040-powered 4x4 15 key macropad with a knob on the top row, that runs custom QMK firmware that allows analogue hall effect sensors to work, also has SOCD, works with VIA and SignalRGB

DovydasTEDS/teds-kb-100
A 100% ISO-105 Mechanical keyboard - custom PCB, custom case. It has per-key rgb leds and a rotary encoder. The firmware is written in QMK.


varaddorle007/deck-8
Open-source 8-key macro pad with 2 knobs, OLED and Bluetooth: PCB, case and ZMK firmware

