From 30ea52548de7a4a3c6fc8ade4ec62e22deca6331 Mon Sep 17 00:00:00 2001
From: "Peter J. A. Cock"
Date: Mon, 9 Mar 2026 17:44:57 +0000
Subject: [PATCH 1/2] Goldilocks32 firmware (based on Bivvy16D and Bivouac34)
See my ZMK firmware. Physical maps based on conversion with
https://shield-wizard.genteure.workers.dev/
---
keyboards/goldilocks32/keyboard.json | 72 ++++++++++++++++
.../goldilocks32/keymaps/default/keymap.c | 39 +++++++++
keyboards/goldilocks32/keymaps/vial/config.h | 10 +++
keyboards/goldilocks32/keymaps/vial/keymap.c | 1 +
keyboards/goldilocks32/keymaps/vial/rules.mk | 2 +
keyboards/goldilocks32/keymaps/vial/vial.json | 48 +++++++++++
keyboards/goldilocks32/readme.md | 82 +++++++++++++++++++
7 files changed, 254 insertions(+)
create mode 100644 keyboards/goldilocks32/keyboard.json
create mode 100644 keyboards/goldilocks32/keymaps/default/keymap.c
create mode 100644 keyboards/goldilocks32/keymaps/vial/config.h
create mode 120000 keyboards/goldilocks32/keymaps/vial/keymap.c
create mode 100644 keyboards/goldilocks32/keymaps/vial/rules.mk
create mode 100644 keyboards/goldilocks32/keymaps/vial/vial.json
create mode 100644 keyboards/goldilocks32/readme.md
diff --git a/keyboards/goldilocks32/keyboard.json b/keyboards/goldilocks32/keyboard.json
new file mode 100644
index 0000000..9454696
--- /dev/null
+++ b/keyboards/goldilocks32/keyboard.json
@@ -0,0 +1,72 @@
+{
+ "manufacturer": "peterjc",
+ "keyboard_name": "Goldilocks32",
+ "maintainer": "Peter J. A. Cock",
+ "bootloader": "rp2040",
+ "diode_direction": "COL2ROW",
+ "features": {
+ "bootmagic": true,
+ "extrakey": true,
+ "mousekey": true,
+ "nkro": false
+ },
+ "matrix_pins": {
+ "cols": ["GP28", "GP22", "GP15", "GP7", "GP2", "GP26", "GP12", "GP5", "GP4", "GP14", "GP27", "GP3", "GP13", "GP9", "GP20", "GP29"],
+ "rows": ["GP21", "GP11", "GP16", "GP23", "GP0", "GP10", "GP1", "GP8", "GP6"]
+ },
+ "processor": "RP2040",
+ "url": "",
+ "usb": {
+ "device_version": "1.0.0",
+ "pid": "0x0000",
+ "vid": "0xFEED"
+ },
+ "ws2812": {
+ "driver": "vendor",
+ "pin": "GP17"
+ },
+ "layouts": {
+ "LAYOUT_default": {
+ "layout": [
+
+ {"label": "q", "hand": "L", "matrix": [0, 0], "x": 0.36, "y": 0.33, "h": 1.4, "r": 10, "rx": 0.86, "ry": 0.83 },
+ {"label": "w", "hand": "L", "matrix": [0, 1], "x": 1.4, "y": 0.05, "r": 10.0, "rx": 1.9, "ry": 0.55 },
+ {"label": "e", "hand": "L", "matrix": [0, 2], "x": 2.76, "y": 0.0, "r": 18.0, "rx": 3.26, "ry": 0.5 },
+ {"label": "r", "hand": "L", "matrix": [0, 3], "x": 3.69, "y": 0.84, "r": 22.0, "rx": 4.19, "ry": 1.34 },
+ {"label": "t", "hand": "L", "matrix": [4, 4], "x": 4.45, "y": 1.69, "r": 22.0, "rx": 4.95, "ry": 2.19 },
+ {"label": "y", "hand": "R", "matrix": [6, 11], "x": 7.0, "y": 1.69, "r": -22.0, "rx": 7.5, "ry": 2.19 },
+ {"label": "u", "hand": "R", "matrix": [5, 12], "x": 7.76, "y": 0.84, "r": -22.0, "rx": 8.26, "ry": 1.34 },
+ {"label": "i", "hand": "R", "matrix": [6, 13], "x": 8.7, "y": 0.0, "r": -18.0, "rx": 9.2, "ry": 0.5 },
+ {"label": "o", "hand": "R", "matrix": [5, 14], "x": 10.05, "y": 0.05, "r": -10.0, "rx": 10.55, "ry": 0.55 },
+ {"label": "p", "hand": "R", "matrix": [2, 15], "x": 11.07, "y": 0.33, "h": 1.4, "r": -10, "rx": 10.57, "ry": 0.83 },
+ {"label": "a", "hand": "L", "matrix": [1, 0], "x": 0.0, "y": 1.65 },
+ {"label": "s", "hand": "L", "matrix": [2, 1], "x": 1.24, "y": 1.03, "r": 10.0, "rx": 1.74, "ry": 1.53 },
+ {"label": "d", "hand": "L", "matrix": [3, 2], "x": 2.46, "y": 0.95, "r": 18.0, "rx": 2.96, "ry": 1.45 },
+ {"label": "f", "hand": "L", "matrix": [4, 3], "x": 3.34, "y": 1.77, "r": 22.0, "rx": 3.84, "ry": 2.27 },
+ {"label": "g", "hand": "L", "matrix": [7, 4], "x": 4.1, "y": 2.62, "r": 22.0, "rx": 4.6, "ry": 3.12 },
+ {"label": "h", "hand": "R", "matrix": [4, 11], "x": 7.35, "y": 2.62, "r": -22.0, "rx": 7.85, "ry": 3.12 },
+ {"label": "j", "hand": "R", "matrix": [4, 12], "x": 8.11, "y": 1.77, "r": -22.0, "rx": 8.61, "ry": 2.27 },
+ {"label": "k", "hand": "R", "matrix": [1, 13], "x": 8.99, "y": 0.95, "r": -18.0, "rx": 9.49, "ry": 1.45 },
+ {"label": "l", "hand": "R", "matrix": [1, 14], "x": 10.22, "y": 1.03, "r": -10.0, "rx": 10.72, "ry": 1.53 },
+ {"label": ";", "hand": "R", "matrix": [6, 15], "x": 11.45, "y": 1.65 },
+ {"label": "z", "hand": "L", "matrix": [7, 5], "x": 0.0, "y": 2.65 },
+ {"label": "x", "hand": "L", "matrix": [1, 5], "x": 1.07, "y": 2.02, "r": 10.0, "rx": 1.57, "ry": 2.52 },
+ {"label": "c", "hand": "L", "matrix": [2, 6], "x": 2.17, "y": 1.9, "r": 18.0, "rx": 2.67, "ry": 2.4 },
+ {"label": "v", "hand": "L", "matrix": [7, 6], "x": 2.99, "y": 2.7, "r": 22.0, "rx": 3.49, "ry": 3.2 },
+ {"label": "b", "hand": "L", "matrix": [3, 7], "x": 3.48, "y": 4.01, "r": 37.0, "rx": 3.98, "ry": 4.51 },
+ {"label": "n", "hand": "R", "matrix": [2, 8], "x": 7.97, "y": 4.01, "r": -37.0, "rx": 8.47, "ry": 4.51 },
+ {"label": "m", "hand": "R", "matrix": [5, 9], "x": 8.46, "y": 2.7, "r": -22.0, "rx": 8.96, "ry": 3.2 },
+ {"label": ",", "hand": "R", "matrix": [3, 9], "x": 9.28, "y": 1.9, "r": -18.0, "rx": 9.78, "ry": 2.4 },
+ {"label": ".", "hand": "R", "matrix": [3, 10], "x": 10.38, "y": 2.02, "r": -10.0, "rx": 10.88, "ry": 2.52 },
+ {"label": "/", "hand": "R", "matrix": [6, 10], "x": 11.45, "y": 2.65 },
+ {"label": "⬆️", "hand": "L", "matrix": [8, 12], "x": 1.25, "y": 3.25, "w": 0.9, "h": 0.9 },
+ {"label": "⬅️", "hand": "L", "matrix": [8, 6], "x": 0.35, "y": 4.15, "w": 0.9, "h": 0.9 },
+ {"label": "⏺️", "hand": "L", "matrix": [8, 13], "x": 1.25, "y": 4.15, "w": 0.9, "h": 0.9 },
+ {"label": "➡️", "hand": "L", "matrix": [8, 7], "x": 2.15, "y": 4.15, "w": 0.9, "h": 0.9 },
+ {"label": "⬇️", "hand": "L", "matrix": [8, 3], "x": 1.25, "y": 5.05, "w": 0.9, "h": 0.9 },
+ {"label": "BkSp", "hand": "L", "matrix": [7, 7], "x": 4.28, "y": 4.64, "r": 37.0, "rx": 4.78, "ry": 5.14 },
+ {"label": "Spc", "hand": "R", "matrix": [5, 8], "x": 7.17, "y": 4.61, "r": -37.0, "rx": 7.67, "ry": 5.14 }
+ ]
+ }
+ }
+}
diff --git a/keyboards/goldilocks32/keymaps/default/keymap.c b/keyboards/goldilocks32/keymaps/default/keymap.c
new file mode 100644
index 0000000..be90cc8
--- /dev/null
+++ b/keyboards/goldilocks32/keymaps/default/keymap.c
@@ -0,0 +1,39 @@
+// Copyright 2023 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include QMK_KEYBOARD_H
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Physical layout close to this:
+ *
+ * ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐
+ * │ Q │ W │ E │ R ├───┐ ┌───┤ U │ I │ O │ P │
+ * ├───┼───┼───┼───┤ T │ │ Y ├───┼───┼───┼───┤
+ * │ A │ S │ D │ F ├───┤ ├───┤ J │ K │ L │ ; │
+ * ├───┼───┼───┼───┤ G │ │ H ├───┼───┼───┼───┤
+ * │ Z │ X │ C │ V ├───┘ └───┤ M │ , │ . │ / │
+ * └───┴───┴───┴───┘ └───┴───┴───┴───┘
+ * ┌───┬───┐ ┌───┬───┐
+ * (5-way) │ B │BkS│ │SPC│ N │
+ * └───┴───┘ └───┴───┘
+ * Home-row mods,
+ * ASDF are Left-GUI, Left-Alt, Left-Ctrl, Left-Shift
+ * JKL; are Right-Shift, Left-Ctrl, Left-Alt, Left-GUI
+ *
+ * The logical layout here is 5 rows:
+ *
+ * Q W E R T Y U I O P
+ * A S D F G H J K L ;
+ * Z X C V B N M , . /
+ * ⬆️ ⬅️ ⏺️ ➡️ ⬇️
+ * ⌫ ␠
+ *
+ */
+ [0] = LAYOUT_default(
+ KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,
+ MT(MOD_LGUI, KC_A), MT(MOD_LALT, KC_S), MT(MOD_LCTL, KC_D), MT(MOD_LSFT, KC_F), KC_G, KC_H, MT(MOD_RSFT, KC_J), MT(MOD_LCTL, KC_K), MT(MOD_LALT, KC_L), MT(MOD_LGUI, KC_SCLN),
+ KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH,
+ KC_UP, KC_LEFT, KC_ENTER, KC_RIGHT, KC_DOWN,
+ KC_BSPC, KC_SPC
+ )
+};
diff --git a/keyboards/goldilocks32/keymaps/vial/config.h b/keyboards/goldilocks32/keymaps/vial/config.h
new file mode 100644
index 0000000..e5b642c
--- /dev/null
+++ b/keyboards/goldilocks32/keymaps/vial/config.h
@@ -0,0 +1,10 @@
+#pragma once
+
+/* Randomly generated as per Vial docs */
+#define VIAL_KEYBOARD_UID {0x1C, 0xF4, 0xA2, 0x03, 0x11, 0x30, 0xC7, 0x53}
+
+#define DYNAMIC_KEYMAP_LAYER_COUNT 6
+
+/* Top left key at matrix 0,0 (Q) and top right of left hand at matrix 4,4 (T) */
+#define VIAL_UNLOCK_COMBO_ROWS { 0, 0 }
+#define VIAL_UNLOCK_COMBO_COLS { 4, 4 }
diff --git a/keyboards/goldilocks32/keymaps/vial/keymap.c b/keyboards/goldilocks32/keymaps/vial/keymap.c
new file mode 120000
index 0000000..41460f2
--- /dev/null
+++ b/keyboards/goldilocks32/keymaps/vial/keymap.c
@@ -0,0 +1 @@
+../default/keymap.c
\ No newline at end of file
diff --git a/keyboards/goldilocks32/keymaps/vial/rules.mk b/keyboards/goldilocks32/keymaps/vial/rules.mk
new file mode 100644
index 0000000..4f7618e
--- /dev/null
+++ b/keyboards/goldilocks32/keymaps/vial/rules.mk
@@ -0,0 +1,2 @@
+VIA_ENABLE = yes
+VIAL_ENABLE = yes
diff --git a/keyboards/goldilocks32/keymaps/vial/vial.json b/keyboards/goldilocks32/keymaps/vial/vial.json
new file mode 100644
index 0000000..84e1f46
--- /dev/null
+++ b/keyboards/goldilocks32/keymaps/vial/vial.json
@@ -0,0 +1,48 @@
+{
+ "layouts": {
+ "keymap":
+ [
+ [{"r":10,"rx":0.86,"ry":0.83,"x":-0.5,"y":-0.5,"h":1.4,"h2":1},"0,0"],
+ [{"rx":1.89,"ry":0.55,"x":-0.5,"y":-0.5},"0,1"],
+ [{"r":18,"rx":3.24,"ry":0.5,"x":-0.5,"y":-0.5},"0,2"],
+ [{"r":22,"rx":4.17,"ry":1.39,"x":-0.5,"y":-0.5},"0,3"],
+ [{"rx":4.93,"ry":2.29,"x":-0.5,"y":-0.5},"4,4"],
+ [{"r":-22,"rx":6.5,"x":-0.5,"y":-0.5},"6,11"],
+ [{"rx":7.26,"ry":1.39,"x":-0.5,"y":-0.5},"5,12"],
+ [{"r":-18,"rx":8.19,"ry":0.5,"x":-0.5,"y":-0.5},"6,13"],
+ [{"r":-10,"rx":9.54,"ry":0.55,"x":-0.5,"y":-0.5},"5,14"],
+ [{"rx":10.57,"ry":0.83,"x":-0.5,"y":-0.5,"h":1.4,"h2":1},"2,15"],
+ [{"r":0,"rx":0,"ry":0,"y":1.73},"1,0"],
+ [{"r":10,"rx":1.73,"ry":1.57,"x":-0.5,"y":-0.5},"2,1"],
+ [{"r":18,"rx":2.96,"ry":1.48,"x":-0.5,"y":-0.5},"3,2"],
+ [{"r":22,"rx":3.83,"ry":2.35,"x":-0.5,"y":-0.5},"4,3"],
+ [{"rx":4.59,"ry":3.25,"x":-0.5,"y":-0.5},"7,4"],
+ [{"r":-22,"rx":6.84,"x":-0.5,"y":-0.5},"4,11"],
+ [{"rx":7.6,"ry":2.35,"x":-0.5,"y":-0.5},"4,12"],
+ [{"r":-18,"rx":8.47,"ry":1.48,"x":-0.5,"y":-0.5},"1,13"],
+ [{"r":-10,"rx":9.7,"ry":1.57,"x":-0.5,"y":-0.5},"1,14"],
+ [{"r":0,"rx":0,"ry":0,"x":10.43,"y":1.73},"6,15"],
+ ["7,5"],
+ [{"r":10,"rx":1.57,"ry":2.59,"x":-0.5,"y":-0.5},"1,5"],
+ [{"r":18,"rx":2.67,"ry":2.46,"x":-0.5,"y":-0.5},"2,6"],
+ [{"r":22,"rx":3.49,"ry":3.3,"x":-0.5,"y":-0.5},"7,6"],
+ [{"r":37,"rx":3.98,"ry":4.7,"x":-0.5,"y":-0.5},"3,7"],
+ [{"r":-37,"rx":7.45,"x":-0.5,"y":-0.5},"2,8"],
+ [{"r":-22,"rx":7.94,"ry":3.3,"x":-0.5,"y":-0.5},"5,9"],
+ [{"r":-18,"rx":8.76,"ry":2.46,"x":-0.5,"y":-0.5},"3,9"],
+ [{"r":-10,"rx":9.86,"ry":2.59,"x":-0.5,"y":-0.5},"3,10"],
+ [{"r":0,"rx":0,"ry":0,"x":10.43,"y":2.76},"6,10"],
+ [{"x":1.25,"y":-0.39,"w":0.9,"h":0.9,"w2":1,"h2":1},"8,12"],
+ [{"x":0.35,"y":-0.1,"w":0.9,"h":0.9,"w2":1,"h2":1},"8,6",{"w":0.9,"h":0.9,"w2":1,"h2":1},"8,13",{"w":0.9,"h":0.9,"w2":1,"h2":1},"8,7"],
+ [{"x":1.25,"y":-0.1,"w":0.9,"h":0.9,"w2":1,"h2":1},"8,3"],
+ [{"r":37,"rx":4.78,"ry":5.38,"x":-0.5,"y":-0.5},"7,7"],
+ [{"r":-37,"rx":6.65,"x":-0.5,"y":-0.5},"5,8"]
+ ]
+ },
+ "lighting": "none",
+ "matrix": {
+ "cols": 16,
+ "rows": 9
+ },
+ "name": "Goldilocks32"
+}
diff --git a/keyboards/goldilocks32/readme.md b/keyboards/goldilocks32/readme.md
new file mode 100644
index 0000000..46e7b1c
--- /dev/null
+++ b/keyboards/goldilocks32/readme.md
@@ -0,0 +1,82 @@
+# Goldilocks32 keyboard firmware
+
+You can [download pre-compiled Goldilocks32 firmware](https://github.com/peterjc/qmk_userspace/releases),
+`goldilocks32_vial.uf2` with Vial support is recommended as you can the use
+the [Vial GUI tool](https://get.vial.today/) to configure your layout by point-and-click.
+This is the default keymap:
+
+
+
+This is firmware for a Raspberry Pi PR2040 (or potentially RP2350) 'Pro Micro' controller
+tented monoblock 32 key design, my [Goldilocks32 keyboard](https://codeberg.org/peterjc/pico-keyboards/src/branch/main/goldilocks32).
+
+This is a *diode-free* design with a sparse 9 by 16 scanning matrix designed using this
+[25 vertex mostly girth 8 graph with 37 edges](https://houseofgraphs.org/graphs/56260).
+Excluding the degree 5 vertex used for the 5-way navigation button, that becomes a sparse
+8 by 16 scanning matrix using this [24 vertex girth 8 graph of maximal 32 edges](https://houseofgraphs.org/graphs/54531)
+(using 24 vertices or GPIO pins, with 32 edges or keys with 6KRO - see this
+[blog post](https://astrobeano.blogspot.com/2025/05/topology-meets-custom-keyboard-circuit.html)
+for background, and this more recent
+[blog post](https://astrobeano.blogspot.com/2025/12/5-way-switch-in-diode-free-graph-theory.html)
+for the navigation button addition (as done in my [Bivvy16D](../bivvy16d) keyboard.
+
+This matrix shows the 9×16 sparse bipartite scanning matrix. The keys are assigned so the
+scanning column order matches the physical columns (starting with Q and A as the first
+column), with the scanning rows sorted to ensure Q is top left as the first matrix entry.
+The allocation of keys to matrix elements and scanning matrix rows and columns
+to GPIO pins was arbitrary and down to how easy it was to layout the PCB traces:
+
+| GP | 28 | 22 | 15 | 7 | 2 | 26 | 12 | 5 | 4 | 14 | 27 | 3 | 13 | 9 | 20 | 29 |
+|---:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:----:|:-----:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
+| 21 | Q | W | E | R | | | | | | | | | | | | |
+| 11 | A | | | | | X | | | | | | | | K | L | |
+| 16 | | S | | | | | C | | N | | | | | | | P |
+| 23 | | | D | | | | | B | | , | . | | | | | |
+| 0 | | | | F | T | | | | | | | H | J | | | |
+| 10 | | | | | | | | | Space | M | | | U | | 0 | |
+| 1 | | | | | | | | | | | / | Y | | I | | ; |
+| 8 | | | | | G | Z | V | BkSp | | | | | | | | |
+| 6 | | | | ⬇️ | | | ⬅️ | ➡️ | | | | | ⬆️ | ⏺️ | | |
+
+Note (aside from the bottom row for the navigation button) there are four entries for each
+row, and two for each column.
+The keys here are labeled as per Qwerty, with B, backspace, space and N for the thumbs,
+and up/down/left/right/push as ⬆️/⬇️/⬅️/➡️/⏺️ for the navigation button.
+
+| Q | W | E | R | T | | | Y | U | I | O | P |
+|:-:|:-:|:-:|:-:|:-:|:-----:|:-----:|:-:|:-:|:-:|:-:|:-:|
+| A | S | D | F | G | | | H | J | K | L | - |
+| Z | X | C | V | | | | | M | , | . | / |
+| | | | | B | BkSpc | Space | N | | | | |
+
+This minimal default layout is rendered as an image above.
+
+If you are using a single thumb key, this is electrically the same as the more tucked
+thumb (B or N by default).
+
+* Keyboard Maintainer: [Peter J. A. Cock](https://github.com/peterjc)
+* Hardware Supported: Goldilocks32 (no-diode twin PCB) using Raspberry Pi Pico
+* Hardware Availability: https://codeberg.org/peterjc/pico-keyboards/src/branch/main/goldilocks32
+* Download Firmware pre-compiled with Vial support: [goldilocks32_vial.uf2](https://github.com/peterjc/qmk_userspace/releases/download/latest/goldilocks32_vial.uf2)
+
+See also the [Goldilocks32 ZMK firmware](https://github.com/peterjc/zmk-keyboard-graph-theory/tree/main/boards/shields/goldilocks32).
+
+## Compiling
+
+Make example for this keyboard (after setting up your build environment):
+
+ make goldilocks32:default
+
+Flashing example for this keyboard:
+
+ make goldilocks32:default:flash
+
+See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
+
+## Bootloader
+
+Enter the bootloader in 3 ways:
+
+* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (top left key, Qwerty `Q`) and plug in the keyboard
+* **Physical reset button**: Briefly press the button on the front of the controller (if physically accessible from the front of the keyboard)
+* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
From 7eca44c442895538a1a305e682d1fc147ef87b85 Mon Sep 17 00:00:00 2001
From: "Peter J. A. Cock"
Date: Mon, 9 Mar 2026 17:58:26 +0000
Subject: [PATCH 2/2] Build Goldilocks32
---
qmk.json | 1 +
vial.json | 1 +
2 files changed, 2 insertions(+)
diff --git a/qmk.json b/qmk.json
index 2bbcbee..31379a1 100644
--- a/qmk.json
+++ b/qmk.json
@@ -5,6 +5,7 @@
["bivvy16d", "default"],
["bivouac34", "default"],
["bivouac34", "peterjc"],
+ ["goldilocks32", "default"],
["slump52", "default"]
]
}
diff --git a/vial.json b/vial.json
index 9b5e78f..5c30db8 100644
--- a/vial.json
+++ b/vial.json
@@ -4,6 +4,7 @@
["tutte_coxeter_36k", "vial"],
["bivvy16d", "vial"],
["bivouac34", "vial"],
+ ["goldilocks32", "vial"],
["slump52", "vial"]
]
}