Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions keyboards/metakey/tenet/boards/METAKEY_TENET/board.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2026 Connor Gallopo (@connorgallopo)
// SPDX-License-Identifier: GPL-2.0-or-later

/*
* PAL static configuration for the Metakey Tenet 70.
*
* USB_DM=PA11, USB_DP=PA12 (fixed by silicon).
* SWDIO=PA13, SWCLK=PA14 — preserved for SWD recovery.
*/

#include "hal.h"

#define PBIT(PORT, LINE) ((PAL_PORT(LINE) == PORT) ? (1 << PAL_PAD(LINE)) : 0)
#define PAFIO_L(PORT, LINE, AF) (((PAL_PORT(LINE) == PORT) && (PAL_PAD(LINE) < 8)) ? (AF << (PAL_PAD(LINE) << 2)) : 0)
#define PAFIO_H(PORT, LINE, AF) (((PAL_PORT(LINE) == PORT) && (PAL_PAD(LINE) >= 8)) ? (AF << ((PAL_PAD(LINE) - 8) << 2)) : 0)
#define PAFIO(PORT, N, LINE, AF) ((N) ? PAFIO_H(PORT, LINE, AF) : PAFIO_L(PORT, LINE, AF))

// Matrix rows (outputs, active low).
#define OUT_BITS(PORT) ( \
PBIT(PORT, B8) | PBIT(PORT, B7) | PBIT(PORT, B6) | PBIT(PORT, C3) | PBIT(PORT, C2) | \
0)

// Matrix cols (inputs with pull-ups). Col 17 = PA11 handled in matrix.c;
// col 14 = PA14 (SWCLK) AFIO override done in matrix_init_custom().
#define IN_BITS(PORT) ( \
PBIT(PORT, A6) | PBIT(PORT, A7) | PBIT(PORT, A8) | PBIT(PORT, A9) | PBIT(PORT, A10) | \
PBIT(PORT, A14) | \
PBIT(PORT, B13) | PBIT(PORT, B14) | PBIT(PORT, B15) | \
PBIT(PORT, C0) | PBIT(PORT, C4) | PBIT(PORT, C5) | PBIT(PORT, C8) | \
PBIT(PORT, C10) | PBIT(PORT, C11) | PBIT(PORT, C12) | PBIT(PORT, C13) | \
0)

#define AF_BITS(PORT, N) ( \
PAFIO(PORT, N, B8, AFIO_GPIO) | PAFIO(PORT, N, B7, AFIO_GPIO) | PAFIO(PORT, N, B6, AFIO_GPIO) | \
PAFIO(PORT, N, C3, AFIO_GPIO) | PAFIO(PORT, N, C2, AFIO_GPIO) | \
PAFIO(PORT, N, A6, AFIO_GPIO) | PAFIO(PORT, N, A7, AFIO_GPIO) | PAFIO(PORT, N, A8, AFIO_GPIO) | \
PAFIO(PORT, N, A9, AFIO_GPIO) | PAFIO(PORT, N, A10, AFIO_GPIO) | \
PAFIO(PORT, N, A0, AFIO_GPIO) | PAFIO(PORT, N, A1, AFIO_GPIO) | PAFIO(PORT, N, A4, AFIO_GPIO) | \
PAFIO(PORT, N, A5, AFIO_GPIO) | \
PAFIO(PORT, N, C0, AFIO_GPIO) | PAFIO(PORT, N, C1, AFIO_GPIO) | PAFIO(PORT, N, C4, AFIO_GPIO) | \
PAFIO(PORT, N, C5, AFIO_GPIO) | PAFIO(PORT, N, C6, AFIO_GPIO) | PAFIO(PORT, N, C7, AFIO_GPIO) | \
PAFIO(PORT, N, D0, AFIO_GPIO) | PAFIO(PORT, N, B2, AFIO_GPIO) | \
0)

const PALConfig pal_default_config = {
.setup[0] = { // GPIO A
.DIR = OUT_BITS(IOPORTA),
.INE = IN_BITS(IOPORTA),
.PU = IN_BITS(IOPORTA),
.PD = 0x0000,
.OD = 0x0000,
.DRV = 0x0000,
.LOCK = 0x0000,
.OUT = 0x0000,
.CFG[0] = AF_BITS(IOPORTA, 0),
.CFG[1] = AF_BITS(IOPORTA, 1),
},
.setup[1] = { // GPIO B
.DIR = OUT_BITS(IOPORTB),
.INE = IN_BITS(IOPORTB),
.PU = IN_BITS(IOPORTB),
.PD = 0x0000,
.OD = 0x0000,
.DRV = 0x0000,
.LOCK = 0x0000,
.OUT = 0x0000,
.CFG[0] = AF_BITS(IOPORTB, 0),
.CFG[1] = AF_BITS(IOPORTB, 1),
},
.setup[2] = { // GPIO C
.DIR = OUT_BITS(IOPORTC),
.INE = IN_BITS(IOPORTC),
.PU = IN_BITS(IOPORTC),
.PD = 0x0000,
.OD = 0x0000,
.DRV = 0x0000,
.LOCK = 0x0000,
.OUT = 0x0000,
.CFG[0] = AF_BITS(IOPORTC, 0),
.CFG[1] = AF_BITS(IOPORTC, 1),
},
.setup[3] = { // GPIO D
.DIR = OUT_BITS(IOPORTD),
.INE = IN_BITS(IOPORTD),
.PU = IN_BITS(IOPORTD),
.PD = 0x0000,
.OD = 0x0000,
.DRV = 0x0000,
.LOCK = 0x0000,
.OUT = 0x0000,
.CFG[0] = AF_BITS(IOPORTD, 0),
.CFG[1] = AF_BITS(IOPORTD, 1),
},
.ESSR[0] = 0x00000000,
.ESSR[1] = 0x00000000,
};

void __early_init(void) { ht32_clock_init(); }

void boardInit(void) {}
20 changes: 20 additions & 0 deletions keyboards/metakey/tenet/boards/METAKEY_TENET/board.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2026 Connor Gallopo (@connorgallopo)
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#define BOARD_NAME "Metakey Tenet 70"

#define HT32F52352

#define FLASH_SIZE (0x20000 - 0x4000) // 128kB - 16kB bootloader

#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
2 changes: 2 additions & 0 deletions keyboards/metakey/tenet/boards/METAKEY_TENET/board.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BOARDSRC = $(BOARD_PATH)/boards/METAKEY_TENET/board.c
BOARDINC = $(BOARD_PATH)/boards/METAKEY_TENET
31 changes: 31 additions & 0 deletions keyboards/metakey/tenet/chconf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Copyright 2020 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*
* This file was auto-generated by:
* `qmk chibios-confmigrate -i keyboards/annepro2/chconf.h -r platforms/chibios/common/configs/chconf.h`
*/

#pragma once

#define CH_CFG_ST_FREQUENCY 1000

#define CH_CFG_ST_TIMEDELTA 0

#define CH_CFG_TIME_QUANTUM 20


#include_next <chconf.h>
31 changes: 31 additions & 0 deletions keyboards/metakey/tenet/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2026 Connor Gallopo (@connorgallopo)
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "pin_defs.h"

/* OLED: SSD1326 256x32, driven directly by the main MCU over I2C0
* (PB0 SDA / PB1 SCL at AFIO mode 7, PD1 active-low RST). Driver at
* ssd1326.c uses raw register writes — chibios-contrib has no HT32 I2C LLD. */

/* Orientation detect: stock firmware reads PA15 (pin idx 0x29) via
* FUN_0000a0ec at Ghidra 0xa0ec. HIGH = regular, LOW = southpaw.
* Exposed as `tenet_read_orientation()`. */

/* Keyboard-reserved EEPROM datablock: 16 bytes persistent OLED text plus
* headroom for future state. */
#define EECONFIG_KB_DATA_SIZE 32

/* HT32 has no on-chip EEPROM. QMK uses a RAM-backed transient store, sized for
* core eeconfig plus the keyboard data block and RGB matrix state. */
#define TRANSIENT_EEPROM_SIZE 1024

#define PERMISSIVE_HOLD

/* RGB Matrix: 76 LEDs across the mainboard (64) and daughterboard (12)
* sub-MCUs. ws2812_custom.c mirrors stock's SPI1 sub-MCU command protocol. */
#define RGB_MATRIX_LED_COUNT 76
#define RGB_MATRIX_KEYPRESSES
#define RGB_MATRIX_DEFAULT_VAL 100
#define RGB_MATRIX_SLEEP
31 changes: 31 additions & 0 deletions keyboards/metakey/tenet/halconf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Copyright 2020 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*
* This file was auto-generated by:
* `qmk chibios-confmigrate -i keyboards/annepro2/halconf.h -r platforms/chibios/common/configs/halconf.h`
*/

#pragma once

#define HAL_USE_SERIAL TRUE

#define SERIAL_USB_BUFFERS_SIZE 256

#define HAL_USE_SPI FALSE
#define HAL_USE_I2C FALSE

#include_next <halconf.h>
108 changes: 108 additions & 0 deletions keyboards/metakey/tenet/keyboard.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{
"manufacturer": "Metakey",
"keyboard_name": "Tenet 70 (QMK)",
"maintainer": "connorgallopo",
"url": "https://clickclack.io/pages/metakey-tenet",
"usb": {
"vid": "0x3311",
"pid": "0xF005",
"device_version": "0.0.1"
},
"processor": "cortex-m0plus",
"bootloader": "custom",
"diode_direction": "COL2ROW",
"matrix_size": {
"rows": 5,
"cols": 18
},
"features": {
"bootmagic": true,
"console": true,
"extrakey": true,
"mousekey": true,
"nkro": true
},
"layouts": {
"LAYOUT": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0, "label": "Esc"},
{"matrix": [0, 1], "x": 1, "y": 0, "label": "1"},
{"matrix": [0, 2], "x": 2, "y": 0, "label": "2"},
{"matrix": [0, 3], "x": 3, "y": 0, "label": "3"},
{"matrix": [0, 4], "x": 4, "y": 0, "label": "4"},
{"matrix": [0, 5], "x": 5, "y": 0, "label": "5"},
{"matrix": [0, 6], "x": 6, "y": 0, "label": "6"},
{"matrix": [0, 7], "x": 7, "y": 0, "label": "7"},
{"matrix": [0, 8], "x": 8, "y": 0, "label": "8"},
{"matrix": [0, 9], "x": 9, "y": 0, "label": "9"},
{"matrix": [0, 10], "x": 10, "y": 0, "label": "0"},
{"matrix": [0, 11], "x": 11, "y": 0, "label": "-"},
{"matrix": [0, 12], "x": 12, "y": 0, "label": "="},
{"matrix": [2, 13], "x": 13, "y": 0, "w": 2, "label": "Bksp"},
{"matrix": [0, 15], "x": 16.25,"y": 0, "label": "Ins"},
{"matrix": [0, 16], "x": 17.25,"y": 0, "label": "Home"},
{"matrix": [0, 17], "x": 18.25,"y": 0, "label": "PgUp"},

{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5, "label": "Tab"},
{"matrix": [1, 1], "x": 1.5, "y": 1, "label": "Q"},
{"matrix": [1, 2], "x": 2.5, "y": 1, "label": "W"},
{"matrix": [1, 3], "x": 3.5, "y": 1, "label": "E"},
{"matrix": [1, 4], "x": 4.5, "y": 1, "label": "R"},
{"matrix": [1, 5], "x": 5.5, "y": 1, "label": "T"},
{"matrix": [1, 6], "x": 6.5, "y": 1, "label": "Y"},
{"matrix": [1, 7], "x": 7.5, "y": 1, "label": "U"},
{"matrix": [1, 8], "x": 8.5, "y": 1, "label": "I"},
{"matrix": [1, 9], "x": 9.5, "y": 1, "label": "O"},
{"matrix": [1, 10], "x": 10.5, "y": 1, "label": "P"},
{"matrix": [1, 11], "x": 11.5, "y": 1, "label": "["},
{"matrix": [1, 12], "x": 12.5, "y": 1, "label": "]"},
{"matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5, "label": "Backslash"},
{"matrix": [1, 15], "x": 16.25,"y": 1, "label": "Del"},
{"matrix": [1, 16], "x": 17.25,"y": 1, "label": "End"},
{"matrix": [1, 17], "x": 18.25,"y": 1, "label": "PgDn"},

{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75, "label": "Ctrl"},
{"matrix": [2, 1], "x": 1.75, "y": 2, "label": "A"},
{"matrix": [2, 2], "x": 2.75, "y": 2, "label": "S"},
{"matrix": [2, 3], "x": 3.75, "y": 2, "label": "D"},
{"matrix": [2, 4], "x": 4.75, "y": 2, "label": "F"},
{"matrix": [2, 5], "x": 5.75, "y": 2, "label": "G"},
{"matrix": [2, 6], "x": 6.75, "y": 2, "label": "H"},
{"matrix": [2, 7], "x": 7.75, "y": 2, "label": "J"},
{"matrix": [2, 8], "x": 8.75, "y": 2, "label": "K"},
{"matrix": [2, 9], "x": 9.75, "y": 2, "label": "L"},
{"matrix": [2, 10], "x": 10.75,"y": 2, "label": "Semi"},
{"matrix": [2, 11], "x": 11.75,"y": 2, "label": "Quote"},
{"matrix": [2, 12], "x": 12.75,"y": 2, "w": 2.25, "label": "Enter"},

{"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25, "label": "LShift"},
{"matrix": [3, 2], "x": 2.25, "y": 3, "label": "Z"},
{"matrix": [3, 3], "x": 3.25, "y": 3, "label": "X"},
{"matrix": [3, 4], "x": 4.25, "y": 3, "label": "C"},
{"matrix": [3, 5], "x": 5.25, "y": 3, "label": "V"},
{"matrix": [3, 6], "x": 6.25, "y": 3, "label": "B"},
{"matrix": [3, 7], "x": 7.25, "y": 3, "label": "N"},
{"matrix": [3, 8], "x": 8.25, "y": 3, "label": "M"},
{"matrix": [3, 9], "x": 9.25, "y": 3, "label": "Comma"},
{"matrix": [3, 10], "x": 10.25,"y": 3, "label": "Dot"},
{"matrix": [3, 11], "x": 11.25,"y": 3, "label": "Slash"},
{"matrix": [3, 12], "x": 12.25,"y": 3, "w": 1.75, "label": "RShift"},
{"matrix": [3, 13], "x": 14, "y": 3, "label": "Fn2"},
{"matrix": [3, 15], "x": 16.25,"y": 3, "label": "OLED-"},
{"matrix": [3, 16], "x": 17.25,"y": 3, "label": "Up"},
{"matrix": [3, 17], "x": 18.25,"y": 3, "label": "OLED+"},

{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.5, "label": "LCtrl"},
{"matrix": [4, 1], "x": 1.5, "y": 4, "label": "Win"},
{"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.5, "label": "Alt"},
{"matrix": [4, 4], "x": 4, "y": 4, "w": 7, "label": "Space"},
{"matrix": [4, 6], "x": 11, "y": 4, "w": 1.5, "label": "RAlt"},
{"matrix": [4, 7], "x": 12.5, "y": 4, "label": "Fn"},
{"matrix": [4, 8], "x": 13.5, "y": 4, "w": 1.5, "label": "RCtrl"},
{"matrix": [4, 15], "x": 16.25,"y": 4, "label": "Left"},
{"matrix": [4, 16], "x": 17.25,"y": 4, "label": "Down"},
{"matrix": [4, 17], "x": 18.25,"y": 4, "label": "Right"}
]
}
}
}
27 changes: 27 additions & 0 deletions keyboards/metakey/tenet/keymaps/default/keymap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2026 Connor Gallopo (@connorgallopo)
// SPDX-License-Identifier: GPL-2.0-or-later

#include QMK_KEYBOARD_H

enum tenet_layers {
_BASE = 0,
_FN,
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_BASE] = LAYOUT(
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, KC_HOME, KC_PGUP,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, KC_DEL, KC_END, KC_PGDN,
KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(_FN), KC_OLED_L, KC_UP, KC_OLED_R,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(_FN), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),

[_FN] = LAYOUT(
QK_BOOT, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_OLED_EDIT, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
};
Loading