Merge remote-tracking branch 'origin/develop' into xap

This commit is contained in:
QMK Bot 2024-11-21 06:23:28 +00:00
commit 808c1ab7eb
4 changed files with 155 additions and 110 deletions

View File

@ -4,52 +4,51 @@ This page describes the support for [Compatible Microcontrollers](compatible_mic
If you have not yet you should read the [Keyboard Guidelines](hardware_keyboard_guidelines) to get a sense of how keyboards fit into QMK. If you have not yet you should read the [Keyboard Guidelines](hardware_keyboard_guidelines) to get a sense of how keyboards fit into QMK.
QMK has a number of features to simplify working with keyboards. For most, you don't have to write a single line of code. To get started, run `qmk new-keyboard`: QMK has a number of features to simplify working with keyboards. For most, you don't have to write a single line of code. To get started, run `qmk new-keyboard`:
``` ```
$ qmk new-keyboard $ qmk new-keyboard
Ψ Generating a new QMK keyboard directory Ψ Generating a new QMK keyboard directory
Name Your Keyboard Project Ψ Name Your Keyboard Project
For more infomation, see: Ψ For more information, see:
https://docs.qmk.fm/hardware_keyboard_guidelines#naming-your-keyboardproject https://docs.qmk.fm/hardware_keyboard_guidelines#naming-your-keyboard-project
Keyboard Name? mycoolkeeb
Ψ Attribution
Ψ Used for maintainer, copyright, etc.
Your GitHub Username? [jsmith]
Ψ More Attribution
Ψ Used for maintainer, copyright, etc.
Your Real Name? [John Smith]
Ψ Pick Base Layout
Ψ As a starting point, one of the common layouts can be used to
bootstrap the process
Default Layout?
1. 60_abnt2
...
65. none of the above
Please enter your choice: [65]
Ψ What Powers Your Project
Ψ Is your board using a separate development board, such as a Pro Micro,
or is the microcontroller integrated onto the PCB?
keyboard Name? mycoolkeeb For more information, see:
https://docs.qmk.fm/compatible_microcontrollers
Attribution Using a Development Board? [y/n] y
Used for maintainer, copyright, etc Ψ Select Development Board
Ψ For more information, see:
Your GitHub Username? [jsmith] https://docs.qmk.fm/compatible_microcontrollers
Development Board?
More Attribution 1. bit_c_pro
Used for maintainer, copyright, etc ...
14. promicro
Your Real Name? [John Smith] ...
18. svlinky
Pick Base Layout Please enter your choice: [14]
As a starting point, one of the common layouts can be used to bootstrap the process
Default Layout?
1. 60_ansi
...
50. tkl_iso
51. none of the above
Please enter your choice: [51]
What Powers Your Project
For more infomation, see:
https://docs.qmk.fm/#/compatible_microcontrollers
MCU?
1. atmega32u4
...
22. STM32F303
Please enter your choice: [12]
Ψ Created a new keyboard called mycoolkeeb. Ψ Created a new keyboard called mycoolkeeb.
Ψ To start working on things, `cd` into keyboards/mycoolkeeb, Ψ Build Command: qmk compile -kb mycoolkeeb -km default.
Ψ or open the directory in your preferred text editor. Ψ Project Location: /Users/jsmith/qmk_firmware/keyboards/mycoolkeeb.
Ψ And build with qmk compile -kb mycoolkeeb -km default. Ψ Now update the config files to match the hardware!
``` ```
This will create all the files needed to support your new keyboard, and populate the settings with default values. Now you just need to customize it for your keyboard. This will create all the files needed to support your new keyboard, and populate the settings with default values. Now you just need to customize it for your keyboard.
@ -58,13 +57,13 @@ This will create all the files needed to support your new keyboard, and populate
This is where you'll describe your keyboard. Please follow the [Keyboard Readme Template](documentation_templates#keyboard-readmemd-template) when writing your `readme.md`. You're encouraged to place an image at the top of your `readme.md`, please use an external service such as [Imgur](https://imgur.com) to host the images. This is where you'll describe your keyboard. Please follow the [Keyboard Readme Template](documentation_templates#keyboard-readmemd-template) when writing your `readme.md`. You're encouraged to place an image at the top of your `readme.md`, please use an external service such as [Imgur](https://imgur.com) to host the images.
## `info.json` ## `keyboard.json`
The `info.json` file is where you configure the hardware and feature set for your keyboard. There are a lot of options that can be placed in that file, too many to list here. For a complete overview of available options see the [Data Driven Configuration Options](reference_info_json) page. The `keyboard.json` file is where you configure the hardware and feature set for your keyboard. There are a lot of options that can be placed in that file, too many to list here. For a complete overview of available options see the [Data Driven Configuration Options](reference_info_json) page.
### Hardware Configuration ### Hardware Configuration
At the top of the `info.json` you'll find USB related settings. These control how your keyboard appears to the Operating System. If you don't have a good reason to change you should leave the `usb.vid` as `0xFEED`. For the `usb.pid` you should pick a number that is not yet in use. At the top of the `keyboard.json` you'll find USB related settings. These control how your keyboard appears to the Operating System. If you don't have a good reason to change you should leave the `usb.vid` as `0xFEED`. For the `usb.pid` you should pick a number that is not yet in use.
Do change the `manufacturer` and `keyboard_name` lines to accurately reflect your keyboard. Do change the `manufacturer` and `keyboard_name` lines to accurately reflect your keyboard.
@ -82,10 +81,11 @@ Do change the `manufacturer` and `keyboard_name` lines to accurately reflect you
Windows and macOS will display the `manufacturer` and `keyboard_name` in the list of USB devices. `lsusb` on Linux instead prefers the values in the list maintained by the [USB ID Repository](http://www.linux-usb.org/usb-ids.html). By default, it will only use `manufacturer` and `keyboard_name` if the list does not contain that `usb.vid` / `usb.pid`. `sudo lsusb -v` will show the values reported by the device, and they are also present in kernel logs after plugging it in. Windows and macOS will display the `manufacturer` and `keyboard_name` in the list of USB devices. `lsusb` on Linux instead prefers the values in the list maintained by the [USB ID Repository](http://www.linux-usb.org/usb-ids.html). By default, it will only use `manufacturer` and `keyboard_name` if the list does not contain that `usb.vid` / `usb.pid`. `sudo lsusb -v` will show the values reported by the device, and they are also present in kernel logs after plugging it in.
::: :::
### Matrix Configuration ### Matrix Configuration
The next section of the `info` file deals with your keyboard's matrix. The first thing you should define is which pins on your MCU are connected to rows and columns. To do so simply specify the names of those pins: The next section of the `keyboard.json` deals with your keyboard's matrix. The first thing you should define is which pins on your MCU are connected to rows and columns. To do so simply specify the names of those pins:
#### Diode Matrix
```json ```json
"matrix_pins": { "matrix_pins": {
@ -94,7 +94,7 @@ The next section of the `info` file deals with your keyboard's matrix. The first
}, },
``` ```
The size of the `matrix_pins.cols` and `matrix_pins.rows` arrays infer the size of the matrix (previously `MATRIX_ROWS` and `MATRIX_COLS`). The matrix dimensions are inferred from the length of the `matrix_pins.cols` and `matrix_pins.rows` arrays (previously specified explicitly in `config.h` with `MATRIX_ROWS` and `MATRIX_COLS`).
Finally, you can specify the direction your diodes point. This can be `COL2ROW` or `ROW2COL`. Finally, you can specify the direction your diodes point. This can be `COL2ROW` or `ROW2COL`.
@ -103,54 +103,56 @@ Finally, you can specify the direction your diodes point. This can be `COL2ROW`
``` ```
#### Direct Pin Matrix #### Direct Pin Matrix
To configure a keyboard where each switch is connected to a separate pin and ground instead of sharing row and column pins, use `matrix_pins.direct`. The mapping defines the pins of each switch in rows and columns, from left to right. The size of the `matrix_pins.direct` array infers the size of the matrix. Use `NO_PIN` to fill in blank spaces. Overrides the behaviour of `diode_direction`, `matrix_pins.cols` and `matrix_pins.rows`.
To configure a keyboard where each switch is connected to a separate pin and ground instead of sharing row and column pins, use `matrix_pins.direct`. This overrides the behaviour of `diode_direction`, `matrix_pins.cols` and `matrix_pins.rows`, and they should not be specified together.
```json ```json
"matrix_pins": { "matrix_pins": {
"direct": [ "direct": [
["F1", "E6", "B0", "B2", "B3" ], ["F1", "E6", "B0", "B2", "B3"],
["F5", "F0", "B1", "B7", "D2" ], ["F5", "F0", "B1", "B7", "D2"],
["F6", "F7", "C7", "D5", "D3" ], ["F6", "F7", "C7", "D5", "D3"],
["B5", "C6", "B6", "NO_PIN", "NO_PIN"] ["B5", "C6", "B6", null, null]
] ]
}, },
``` ```
### Layout macros Here, the matrix dimensions are inferred directly from the dimensions of the `matrix_pins.direct` array. Since there are no row or column pins to prescribe the matrix dimensions, you can arrange it however you like. Each "row" must contain the same number of "column"s; use `null` to fill in blank spaces, but try to minimize them.
Next is configuring Layout Macro(s). These define the physical arrangement of keys, and its position within the matrix that a switch are connected to. This allows you to have a physical arrangement of keys that differs from the wiring matrix. ### Layout Macros
Next is configuring layout macro(s). These define the physical arrangement of keys, and their position within the matrix that switches are connected to. This allows you to have a physical arrangement of keys that differs from the wiring matrix.
```json ```json
"layouts": { "layouts": {
"LAYOUT_ortho_4x4": { "LAYOUT_ortho_4x4": {
"layout": [ "layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 }, {"matrix": [0, 0], "x": 0, "y": 0},
{ "matrix": [0, 1], "x": 1, "y": 0 }, {"matrix": [0, 1], "x": 1, "y": 0},
{ "matrix": [0, 2], "x": 2, "y": 0 }, {"matrix": [0, 2], "x": 2, "y": 0},
{ "matrix": [0, 3], "x": 3, "y": 0 }, {"matrix": [0, 3], "x": 3, "y": 0},
{ "matrix": [1, 0], "x": 0, "y": 1 }, {"matrix": [1, 0], "x": 0, "y": 1},
{ "matrix": [1, 1], "x": 1, "y": 1 }, {"matrix": [1, 1], "x": 1, "y": 1},
{ "matrix": [1, 2], "x": 2, "y": 1 }, {"matrix": [1, 2], "x": 2, "y": 1},
{ "matrix": [1, 3], "x": 3, "y": 1 }, {"matrix": [1, 3], "x": 3, "y": 1},
{ "matrix": [2, 0], "x": 0, "y": 2 }, {"matrix": [2, 0], "x": 0, "y": 2},
{ "matrix": [2, 1], "x": 1, "y": 2 }, {"matrix": [2, 1], "x": 1, "y": 2},
{ "matrix": [2, 2], "x": 2, "y": 2 }, {"matrix": [2, 2], "x": 2, "y": 2},
{ "matrix": [2, 3], "x": 3, "y": 2 }, {"matrix": [2, 3], "x": 3, "y": 2},
{ "matrix": [3, 0], "x": 0, "y": 3 }, {"matrix": [3, 0], "x": 0, "y": 3},
{ "matrix": [3, 1], "x": 1, "y": 3 }, {"matrix": [3, 1], "x": 1, "y": 3},
{ "matrix": [3, 2], "x": 2, "y": 3 }, {"matrix": [3, 2], "x": 2, "y": 3},
{ "matrix": [3, 3], "x": 3, "y": 3 } {"matrix": [3, 3], "x": 3, "y": 3}
] ]
} }
} }
``` ```
In the above example, In the above example,
* `LAYOUT_ortho_4x4` defines the name of the layout macro * `LAYOUT_ortho_4x4` defines the name of the layout macro
* It must conform to the [layout guidelines](hardware_keyboard_guidelines#keyboard-name-h) * It must conform to the [layout guidelines](hardware_keyboard_guidelines#keyboard-name-h)
* `"matrix": [0, 0]` defines the electrical position * `"matrix": [0, 0]` defines the matrix row and column that the key is associated with
::: tip ::: tip
See also: [Split Keyboard Layout Macro](features/split_keyboard#layout-macro) and [Matrix to Physical Layout](understanding_qmk#matrix-to-physical-layout-map). See also: [Split Keyboard Layout Macro](features/split_keyboard#layout-macro) and [Matrix to Physical Layout](understanding_qmk#matrix-to-physical-layout-map).
@ -158,9 +160,10 @@ See also: [Split Keyboard Layout Macro](features/split_keyboard#layout-macro) an
## Additional Configuration ## Additional Configuration
There are a lot of features that can be turned on or off, configured or tuned. Some of these have yet to be migrated over to [Data Driven Configuration](data_driven_config). The following sections cover the process for when an `info.json` option is unavailable. There are a lot of features that can be turned on or off, configured or tuned. Some of these have yet to be migrated over to [Data Driven Configuration](data_driven_config). The following sections cover the process for when a data-driven option is unavailable.
### Configuration Options ### Configuration Options
For available options for `config.h`, you should see the [Config Options](config_options#the-configh-file) page for more details. For available options for `config.h`, you should see the [Config Options](config_options#the-configh-file) page for more details.
### Build Options ### Build Options

View File

@ -8,7 +8,7 @@ from pathlib import Path
from dotty_dict import dotty from dotty_dict import dotty
from milc import cli from milc import cli
from milc.questions import choice, question from milc.questions import choice, question, yesno
from qmk.git import git_get_username from qmk.git import git_get_username
from qmk.json_schema import load_jsonschema from qmk.json_schema import load_jsonschema
@ -131,60 +131,70 @@ def _question(*args, **kwargs):
return ret return ret
def prompt_keyboard(): def prompt_heading_subheading(heading, subheading):
prompt = """{fg_yellow}Name Your Keyboard Project{style_reset_all} cli.log.info(f"{{fg_yellow}}{heading}{{style_reset_all}}")
For more infomation, see: cli.log.info(subheading)
https://docs.qmk.fm/hardware_keyboard_guidelines#naming-your-keyboard-project
Keyboard Name? """
def prompt_keyboard():
prompt_heading_subheading("Name Your Keyboard Project", """For more information, see:
https://docs.qmk.fm/hardware_keyboard_guidelines#naming-your-keyboard-project""")
errmsg = 'Keyboard already exists! Please choose a different name:' errmsg = 'Keyboard already exists! Please choose a different name:'
return _question(prompt, reprompt=errmsg, validate=lambda x: not keyboard(x).exists()) return _question("Keyboard Name?", reprompt=errmsg, validate=lambda x: not keyboard(x).exists())
def prompt_user(): def prompt_user():
prompt = """ prompt_heading_subheading("Attribution", "Used for maintainer, copyright, etc.")
{fg_yellow}Attribution{style_reset_all}
Used for maintainer, copyright, etc
Your GitHub Username? """ return question("Your GitHub Username?", default=git_get_username())
return question(prompt, default=git_get_username())
def prompt_name(def_name): def prompt_name(def_name):
prompt = """ prompt_heading_subheading("More Attribution", "Used for maintainer, copyright, etc.")
{fg_yellow}More Attribution{style_reset_all}
Used for maintainer, copyright, etc
Your Real Name? """ return question("Your Real Name?", default=def_name)
return question(prompt, default=def_name)
def prompt_layout(): def prompt_layout():
prompt = """ prompt_heading_subheading("Pick Base Layout", """As a starting point, one of the common layouts can be used to
{fg_yellow}Pick Base Layout{style_reset_all} bootstrap the process""")
As a starting point, one of the common layouts can be used to bootstrap the process
Default Layout? """
# avoid overwhelming user - remove some? # avoid overwhelming user - remove some?
filtered_layouts = [x for x in available_layouts if not any(xs in x for xs in ['_split', '_blocker', '_tsangan', '_f13'])] filtered_layouts = [x for x in available_layouts if not any(xs in x for xs in ['_split', '_blocker', '_tsangan', '_f13'])]
filtered_layouts.append("none of the above") filtered_layouts.append("none of the above")
return choice(prompt, filtered_layouts, default=len(filtered_layouts) - 1) return choice("Default Layout?", filtered_layouts, default=len(filtered_layouts) - 1)
def prompt_mcu_type():
prompt_heading_subheading(
"What Powers Your Project", """Is your board using a separate development board, such as a Pro Micro,
or is the microcontroller integrated onto the PCB?
For more information, see:
https://docs.qmk.fm/compatible_microcontrollers"""
)
return yesno("Using a Development Board?")
def prompt_dev_board():
prompt_heading_subheading("Select Development Board", """For more information, see:
https://docs.qmk.fm/compatible_microcontrollers""")
return choice("Development Board?", dev_boards, default=dev_boards.index("promicro"))
def prompt_mcu(): def prompt_mcu():
prompt = """ prompt_heading_subheading("Select Microcontroller", """For more information, see:
{fg_yellow}What Powers Your Project{style_reset_all} https://docs.qmk.fm/compatible_microcontrollers""")
For more infomation, see:
https://docs.qmk.fm/#/compatible_microcontrollers
MCU? """
# remove any options strictly used for compatibility # remove any options strictly used for compatibility
filtered_mcu = [x for x in (dev_boards + mcu_types) if not any(xs in x for xs in ['cortex', 'unknown'])] filtered_mcu = [x for x in mcu_types if not any(xs in x for xs in ['cortex', 'unknown'])]
return choice(prompt, filtered_mcu, default=filtered_mcu.index("atmega32u4")) return choice("Microcontroller?", filtered_mcu, default=filtered_mcu.index("atmega32u4"))
@cli.argument('-kb', '--keyboard', help='Specify the name for the new keyboard directory', arg_only=True, type=keyboard_name) @cli.argument('-kb', '--keyboard', help='Specify the name for the new keyboard directory', arg_only=True, type=keyboard_name)
@ -211,7 +221,11 @@ def new_keyboard(cli):
user_name = cli.config.new_keyboard.name if cli.config.new_keyboard.name else prompt_user() user_name = cli.config.new_keyboard.name if cli.config.new_keyboard.name else prompt_user()
real_name = cli.args.realname or cli.config.new_keyboard.name if cli.args.realname or cli.config.new_keyboard.name else prompt_name(user_name) real_name = cli.args.realname or cli.config.new_keyboard.name if cli.args.realname or cli.config.new_keyboard.name else prompt_name(user_name)
default_layout = cli.args.layout if cli.args.layout else prompt_layout() default_layout = cli.args.layout if cli.args.layout else prompt_layout()
mcu = cli.args.type if cli.args.type else prompt_mcu()
if cli.args.type:
mcu = cli.args.type
else:
mcu = prompt_dev_board() if prompt_mcu_type() else prompt_mcu()
config = {} config = {}
if mcu in dev_boards: if mcu in dev_boards:

View File

@ -1,5 +1,6 @@
"""This script automates the copying of the default keymap into your own keymap. """This script automates the copying of the default keymap into your own keymap.
""" """
import re
import shutil import shutil
from milc import cli from milc import cli
@ -13,6 +14,13 @@ from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.userspace import UserspaceDefs 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(): def prompt_keyboard():
prompt = """{fg_yellow}Select Keyboard{style_reset_all} 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}. 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!') cli.log.error(f'Default keymap {{fg_cyan}}{keymap_path_default}{{fg_reset}} does not exist!')
return False 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(): if keymap_path_new.exists():
cli.log.error(f'Keymap {{fg_cyan}}{user_name}{{fg_reset}} already exists! Please choose a different name.') cli.log.error(f'Keymap {{fg_cyan}}{user_name}{{fg_reset}} already exists! Please choose a different name.')
return False return False

View File

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