Compare commits

...

9 Commits

Author SHA1 Message Date
Selwyn
d8d82245c5
Merge 6432540c7e into 9bea332a21 2024-11-20 22:22:14 -08:00
Ryan
9bea332a21
qmk via2json: Improve macro parsing (#24345) 2024-11-21 17:20:05 +11:00
Ryan
8cbcdcac62
qmk new-keymap: validate keymap name (#23420) 2024-11-21 17:18:51 +11:00
Selwyn
6432540c7e
Use Imgur since GH gist image does not load inline
To heck with it
2024-07-15 17:17:41 +02:00
Selwyn
080deee26f
Rename to keyboard.json 2024-07-10 16:53:11 +02:00
Selwyn
c5f6ea4acb
Replace checked in image with hosted image 2024-07-10 16:52:08 +02:00
Selwyn
b9b0582c7b
Clarify bootloader instructions and missing QK_BOOT functionality 2024-07-04 16:20:19 +02:00
Selwyn
a7f071691e
Remove invalid code comments 2024-07-04 16:20:19 +02:00
Selwyn
5716ba08d4
Add keyboard QK65 R2 2024-07-04 16:20:19 +02:00
7 changed files with 314 additions and 9 deletions

View File

@ -0,0 +1,111 @@
{
"manufacturer": "Qwertykeys",
"keyboard_name": "QK65 Hotswap",
"maintainer": "Siilwyn",
"bootloader": "custom",
"diode_direction": "COL2ROW",
"qmk": {
"tap_keycode_delay": 5
},
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"nkro": true
},
"matrix_pins": {
"cols": ["A7", "B0", "B1", "B2", "B10", "B11", "B12", "B13", "B14", "B15", "A8", "B6", "B7", "A6", "A15"],
"rows": ["A1", "A2", "A3", "A4", "A5"]
},
"indicators": {
"caps_lock": "A0",
"on_state": 0
},
"processor": "STM32F103",
"board": "STM32_F103_STM32DUINO",
"url": "https://www.qwertykeys.com/",
"usb": {
"device_version": "0.0.2",
"pid": "0x514B",
"vid": "0x4F53",
"force_nkro": true
},
"community_layouts": ["65_ansi_blocker"],
"layouts": {
"LAYOUT_65_ansi_blocker": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 13], "x": 13, "y": 0, "w": 2},
{"matrix": [0, 14], "x": 15, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 1], "x": 1.5, "y": 1},
{"matrix": [1, 2], "x": 2.5, "y": 1},
{"matrix": [1, 3], "x": 3.5, "y": 1},
{"matrix": [1, 4], "x": 4.5, "y": 1},
{"matrix": [1, 5], "x": 5.5, "y": 1},
{"matrix": [1, 6], "x": 6.5, "y": 1},
{"matrix": [1, 7], "x": 7.5, "y": 1},
{"matrix": [1, 8], "x": 8.5, "y": 1},
{"matrix": [1, 9], "x": 9.5, "y": 1},
{"matrix": [1, 10], "x": 10.5, "y": 1},
{"matrix": [1, 11], "x": 11.5, "y": 1},
{"matrix": [1, 12], "x": 12.5, "y": 1},
{"matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
{"matrix": [1, 14], "x": 15, "y": 1},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 1], "x": 1.75, "y": 2},
{"matrix": [2, 2], "x": 2.75, "y": 2},
{"matrix": [2, 3], "x": 3.75, "y": 2},
{"matrix": [2, 4], "x": 4.75, "y": 2},
{"matrix": [2, 5], "x": 5.75, "y": 2},
{"matrix": [2, 6], "x": 6.75, "y": 2},
{"matrix": [2, 7], "x": 7.75, "y": 2},
{"matrix": [2, 8], "x": 8.75, "y": 2},
{"matrix": [2, 9], "x": 9.75, "y": 2},
{"matrix": [2, 10], "x": 10.75, "y": 2},
{"matrix": [2, 11], "x": 11.75, "y": 2},
{"matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"matrix": [2, 14], "x": 15, "y": 2},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"matrix": [3, 1], "x": 2.25, "y": 3},
{"matrix": [3, 2], "x": 3.25, "y": 3},
{"matrix": [3, 3], "x": 4.25, "y": 3},
{"matrix": [3, 4], "x": 5.25, "y": 3},
{"matrix": [3, 5], "x": 6.25, "y": 3},
{"matrix": [3, 6], "x": 7.25, "y": 3},
{"matrix": [3, 7], "x": 8.25, "y": 3},
{"matrix": [3, 8], "x": 9.25, "y": 3},
{"matrix": [3, 9], "x": 10.25, "y": 3},
{"matrix": [3, 10], "x": 11.25, "y": 3},
{"matrix": [3, 11], "x": 12.25, "y": 3, "w": 1.75},
{"matrix": [3, 13], "x": 14, "y": 3},
{"matrix": [3, 14], "x": 15, "y": 3},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
{"matrix": [4, 4], "x": 3.75, "y": 4, "w": 6.25},
{"matrix": [4, 7], "x": 10, "y": 4, "w": 1.25},
{"matrix": [4, 8], "x": 11.25, "y": 4, "w": 1.25},
{"matrix": [4, 12], "x": 13, "y": 4},
{"matrix": [4, 13], "x": 14, "y": 4},
{"matrix": [4, 14], "x": 15, "y": 4}
]
}
}
}

View File

@ -0,0 +1,48 @@
// Copyright 2023 Selwyn (@Siilwyn)
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
*
* Esc 1 2 3 4 5 6 7 8 9 0 - = BackspHom
*
* Tab Q W E R T Y U I O P [ ] \ PgU
*
* Caps A S D F G H J K L ; ' Enter PgD
*
* Shift Z X C V B N M , . / Shift End
*
* CtrlGUI Alt Alt Fn
*
*/
[0] = LAYOUT_65_ansi_blocker(
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_HOME,
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_BSLS, KC_PGUP,
KC_CAPS, 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_PGDN,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_LEFT, KC_DOWN, KC_RGHT
),
/*
*
* ` F1 F2 F3 F4 F5 F6 F7 F8 F9 F10F11F12 Delete
*
* PSc
*
*
*
* MutVl-Vl+
*
*
*
*/
[1] = LAYOUT_65_ansi_blocker(
KC_GRV, 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_DEL, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PSCR, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______
)
};

View File

@ -0,0 +1,87 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* STM32F103x8 memory setup for use with the STM32Duino bootloader.
*/
f103_flash_size = 128k;
MEMORY
{
flash0 : org = 0x08006000, len = f103_flash_size - 0x6000
flash1 : org = 0x00000000, len = 0
flash2 : org = 0x00000000, len = 0
flash3 : org = 0x00000000, len = 0
flash4 : org = 0x00000000, len = 0
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
flash7 : org = 0x00000000, len = 0
ram0 : org = 0x20000000, len = 20k
ram1 : org = 0x00000000, len = 0
ram2 : org = 0x00000000, len = 0
ram3 : org = 0x00000000, len = 0
ram4 : org = 0x00000000, len = 0
ram5 : org = 0x00000000, len = 0
ram6 : org = 0x00000000, len = 0
ram7 : org = 0x00000000, len = 0
}
/* For each data/text section two region are defined, a virtual region
and a load region (_LMA suffix).*/
/* Flash region to be used for exception vectors.*/
REGION_ALIAS("VECTORS_FLASH", flash0);
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
/* Flash region to be used for constructors and destructors.*/
REGION_ALIAS("XTORS_FLASH", flash0);
REGION_ALIAS("XTORS_FLASH_LMA", flash0);
/* Flash region to be used for code text.*/
REGION_ALIAS("TEXT_FLASH", flash0);
REGION_ALIAS("TEXT_FLASH_LMA", flash0);
/* Flash region to be used for read only data.*/
REGION_ALIAS("RODATA_FLASH", flash0);
REGION_ALIAS("RODATA_FLASH_LMA", flash0);
/* Flash region to be used for various.*/
REGION_ALIAS("VARIOUS_FLASH", flash0);
REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
/* Flash region to be used for RAM(n) initialization data.*/
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
/* RAM region to be used for Main stack. This stack accommodates the processing
of all exceptions and interrupts.*/
REGION_ALIAS("MAIN_STACK_RAM", ram0);
/* RAM region to be used for the process stack. This is the stack used by
the main() function.*/
REGION_ALIAS("PROCESS_STACK_RAM", ram0);
/* RAM region to be used for data segment.*/
REGION_ALIAS("DATA_RAM", ram0);
REGION_ALIAS("DATA_RAM_LMA", flash0);
/* RAM region to be used for BSS segment.*/
REGION_ALIAS("BSS_RAM", ram0);
/* RAM region to be used for the default heap.*/
REGION_ALIAS("HEAP_RAM", ram0);
/* Generic rules inclusion.*/
INCLUDE rules.ld

View File

@ -0,0 +1,26 @@
# QK65 - Hotswap R2 PCB
![White QK65 R2](https://i.imgur.com/te8LNCf.jpeg)
A 65% made by Qwertykeys.
* Keyboard Maintainer: [Selwyn](https://github.com/Siilwyn)
* Hardware Supported: QK65 hotswap R2 PCB
Make example for this keyboard (after setting up your build environment):
make qwertykeys/qk65/r2:default
Flashing example for this keyboard:
make qwertykeys/qk65/r2: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 two ways:
* **Bootloader key**: Hold down the `B` key and plug in the keyboard.
Note that the `B` key is hardcoded to the physical QWERTY layout `B` location on the PCB and `QK_BOOT` does not work.
* **Physical reset button**: Briefly press the SW1 button on the back of the PCB.

View File

@ -0,0 +1,5 @@
MCU_LDSCRIPT = STM32F103x8_0x08006000_bootloader
BOOTLOADER_TYPE = stm32duino
OPT_DEFS += -DBOOTLOADER_STM32DUINO
DFU_ARGS = -d 1688:2220 -a 0 -s 0x08006000
DFU_SUFFIX_ARGS = -v 1688 -p 2220

View File

@ -1,5 +1,6 @@
"""This script automates the copying of the default keymap into your own keymap.
"""
import re
import shutil
from milc import cli
@ -13,6 +14,13 @@ from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.userspace import UserspaceDefs
def validate_keymap_name(name):
"""Returns True if the given keymap name contains only a-z, 0-9 and underscore characters.
"""
regex = re.compile(r'^[a-zA-Z0-9][a-zA-Z0-9_]+$')
return bool(regex.match(name))
def prompt_keyboard():
prompt = """{fg_yellow}Select Keyboard{style_reset_all}
If you`re unsure you can view a full list of supported keyboards with {fg_yellow}qmk list-keyboards{style_reset_all}.
@ -60,6 +68,10 @@ def new_keymap(cli):
cli.log.error(f'Default keymap {{fg_cyan}}{keymap_path_default}{{fg_reset}} does not exist!')
return False
if not validate_keymap_name(user_name):
cli.log.error('Keymap names must contain only {fg_cyan}a-z{fg_reset}, {fg_cyan}0-9{fg_reset} and {fg_cyan}_{fg_reset}! Please choose a different name.')
return False
if keymap_path_new.exists():
cli.log.error(f'Keymap {{fg_cyan}}{user_name}{{fg_reset}} already exists! Please choose a different name.')
return False

View File

@ -29,6 +29,7 @@ def _convert_macros(via_macros):
if len(via_macros) == 0:
return list()
split_regex = re.compile(r'(}\,)|(\,{)')
macro_group_regex = re.compile(r'({.+?})')
macros = list()
for via_macro in via_macros:
# Split VIA macro to its elements
@ -38,13 +39,28 @@ def _convert_macros(via_macros):
macro_data = list()
for m in macro:
if '{' in m or '}' in m:
# Found keycode(s)
keycodes = m.split(',')
# Remove whitespaces and curly braces from around keycodes
keycodes = list(map(lambda s: s.strip(' {}'), keycodes))
# Remove the KC prefix
keycodes = list(map(lambda s: s.replace('KC_', ''), keycodes))
macro_data.append({"action": "tap", "keycodes": keycodes})
# Split macro groups
macro_groups = macro_group_regex.findall(m)
for macro_group in macro_groups:
# Remove whitespaces and curly braces from around group
macro_group = macro_group.strip(' {}')
macro_action = 'tap'
macro_keycodes = []
if macro_group[0] == '+':
macro_action = 'down'
macro_keycodes.append(macro_group[1:])
elif macro_group[0] == '-':
macro_action = 'up'
macro_keycodes.append(macro_group[1:])
else:
macro_keycodes.extend(macro_group.split(',') if ',' in macro_group else [macro_group])
# Remove the KC prefixes
macro_keycodes = list(map(lambda s: s.replace('KC_', ''), macro_keycodes))
macro_data.append({"action": macro_action, "keycodes": macro_keycodes})
else:
# Found text
macro_data.append(m)
@ -54,13 +70,13 @@ def _convert_macros(via_macros):
def _fix_macro_keys(keymap_data):
macro_no = re.compile(r'MACRO0?([0-9]{1,2})')
macro_no = re.compile(r'MACRO0?\(([0-9]{1,2})\)')
for i in range(0, len(keymap_data)):
for j in range(0, len(keymap_data[i])):
kc = keymap_data[i][j]
m = macro_no.match(kc)
if m:
keymap_data[i][j] = f'MACRO_{m.group(1)}'
keymap_data[i][j] = f'MC_{m.group(1)}'
return keymap_data