diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index ce9bd0f3161..25649ce9437 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -45,7 +45,7 @@ jobs:
stale-pr-label: stale
days-before-pr-stale: 45
days-before-pr-close: 30
- exempt-pr-labels: bug,awaiting review,breaking_change,in progress,on hold
+ exempt-pr-labels: bug,awaiting review,breaking_change,in progress,on hold,needs-core-wireless,crippled-firmware
stale-pr-message: >
Thank you for your contribution!
diff --git a/data/mappings/keyboard_aliases.hjson b/data/mappings/keyboard_aliases.hjson
index d03ff33f2c1..09549baf69e 100644
--- a/data/mappings/keyboard_aliases.hjson
+++ b/data/mappings/keyboard_aliases.hjson
@@ -1626,9 +1626,15 @@
"buzzard": {
"target": "buzzard/rev1"
},
+ "cannonkeys/db60": {
+ "target": "cannonkeys/db60/rev2"
+ },
"clickety_split/leeloo": {
"target": "clickety_split/leeloo/rev3"
},
+ "converter/palm_usb": {
+ "target": "converter/palm_usb/stowaway"
+ },
"crkbd": {
"target": "crkbd/rev1"
},
@@ -1713,6 +1719,9 @@
"handwired/dactyl_manuform/6x6": {
"target": "handwired/dactyl_manuform/6x6/promicro"
},
+ "handwired/meck_tkl": {
+ "target": "handwired/meck_tkl/blackpill_f401"
+ },
"handwired/ms_sculpt_mobile": {
"target": "handwired/ms_sculpt_mobile/teensy2pp"
},
@@ -1752,6 +1761,9 @@
"hillside/46": {
"target": "hillside/46/0_1"
},
+ "hhkb/ansi": {
+ "target": "hhkb/ansi/32u4"
+ },
"hillside/48": {
"target": "hillside/48/0_1"
},
@@ -1797,6 +1809,9 @@
"kakunpc/angel17": {
"target": "kakunpc/angel17/rev1"
},
+ "kakunpc/angel64": {
+ "target": "kakunpc/angel64/rev1"
+ },
"kakunpc/business_card": {
"target": "kakunpc/business_card/beta"
},
@@ -2148,6 +2163,9 @@
"takashiski/namecard2x4": {
"target": "takashiski/namecard2x4/rev2"
},
+ "teleport/native": {
+ "target": "teleport/native/iso"
+ },
"themadnoodle/noodlepad": {
"target": "themadnoodle/noodlepad/v1"
},
@@ -2181,6 +2199,21 @@
"vitamins_included": {
"target": "vitamins_included/rev2"
},
+ "westm/westm68": {
+ "target": "westm/westm68/rev2"
+ },
+ "westm/westm9": {
+ "target": "westm/westm9/rev2"
+ },
+ "woodkeys/meira": {
+ "target": "woodkeys/meira/promicro"
+ },
+ "work_louder/loop": {
+ "target": "work_louder/loop/rev3"
+ },
+ "work_louder/work_board": {
+ "target": "work_louder/work_board/rev3"
+ },
"yanghu/unicorne": {
"target": "yanghu/unicorne/f411"
},
@@ -2195,5 +2228,8 @@
},
"yynmt/acperience12": {
"target": "yynmt/acperience12/rev1"
+ },
+ "zsa/planck_ez": {
+ "target": "zsa/planck_ez/base"
}
}
diff --git a/drivers/painter/sh1107/qp_sh1107.c b/drivers/painter/sh1107/qp_sh1107.c
new file mode 100644
index 00000000000..f4cbd49e402
--- /dev/null
+++ b/drivers/painter/sh1107/qp_sh1107.c
@@ -0,0 +1,218 @@
+#include "qp_internal.h"
+#include "qp_comms.h"
+#include "qp_surface_internal.h"
+#include "qp_oled_panel.h"
+#include "qp_sh1107.h"
+#include "qp_sh1107_opcodes.h"
+#include "qp_surface.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Driver storage
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef struct sh1107_device_t {
+ oled_panel_painter_device_t oled;
+
+ uint8_t framebuffer[SURFACE_REQUIRED_BUFFER_BYTE_SIZE(128, 128, 1)];
+} sh1107_device_t;
+
+static sh1107_device_t sh1107_drivers[SH1107_NUM_DEVICES] = {0};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter API implementations
+
+// Initialisation
+__attribute__((weak)) bool qp_sh1107_init(painter_device_t device, painter_rotation_t rotation) {
+ sh1107_device_t *driver = (sh1107_device_t *)device;
+
+ // Change the surface geometry based on the panel rotation
+ if (rotation == QP_ROTATION_90 || rotation == QP_ROTATION_270) {
+ driver->oled.surface.base.panel_width = driver->oled.base.panel_height;
+ driver->oled.surface.base.panel_height = driver->oled.base.panel_width;
+ } else {
+ driver->oled.surface.base.panel_width = driver->oled.base.panel_width;
+ driver->oled.surface.base.panel_height = driver->oled.base.panel_height;
+ }
+
+ // Init the internal surface
+ if (!qp_init(&driver->oled.surface.base, QP_ROTATION_0)) {
+ qp_dprintf("Failed to init internal surface in qp_sh1107_init\n");
+ return false;
+ }
+
+ // clang-format off
+ uint8_t sh1107_init_sequence[] = {
+ // Command, Delay, N, Data[N]
+ SH1107_SET_MUX_RATIO, 0, 1, 0x7F, // 1/128 duty
+ SH1107_DISPLAY_OFFSET, 0, 1, 0x00,
+ SH1107_SET_START_LINE, 0, 1, 0x00, // Different from SH1106
+ SH1107_SET_SEGMENT_REMAP_INV, 0, 0,
+ SH1107_COM_SCAN_DIR_DEC, 0, 0,
+ SH1107_COM_PADS_HW_CFG, 0, 1, 0x12,
+ SH1107_SET_CONTRAST, 0, 1, 0x7F,
+ SH1107_ALL_ON_RESUME, 0, 0,
+ SH1107_NON_INVERTING_DISPLAY, 0, 0,
+ SH1107_SET_OSC_DIVFREQ, 0, 1, 0x80,
+ SH1107_SET_CHARGE_PUMP, 0, 1, 0x14,
+ SH1107_DISPLAY_ON, 0, 0,
+ };
+ // clang-format on
+
+ // If the display width is anything other than the default 128 pixels, change SH1107_SET_MUX_RATIO data byte to the correct value.
+ if (driver->oled.base.panel_width != 128) {
+ sh1107_init_sequence[3] = driver->oled.base.panel_width - 1;
+ }
+
+ // If the display width is less than the default 128 pixels, change SH1107_DISPLAY_OFFSET to use the center columns.
+ if (driver->oled.base.panel_width < 128) {
+ sh1107_init_sequence[7] = (128U - driver->oled.base.panel_width) / 2;
+ }
+
+ // For smaller displays, change SH1107_COM_PADS_HW_CFG data byte from alternative (0x12) to sequential (0x02) configuration
+ if (driver->oled.base.panel_height <= 64) {
+ sh1107_init_sequence[20] = 0x02;
+ }
+
+ qp_comms_bulk_command_sequence(device, sh1107_init_sequence, sizeof(sh1107_init_sequence));
+ return true;
+}
+
+// Screen flush
+bool qp_sh1107_flush(painter_device_t device) {
+ sh1107_device_t *driver = (sh1107_device_t *)device;
+
+ if (!driver->oled.surface.dirty.is_dirty) {
+ return true;
+ }
+
+ switch (driver->oled.base.rotation) {
+ default:
+ case QP_ROTATION_0:
+ qp_oled_panel_page_column_flush_rot0(device, &driver->oled.surface.dirty, driver->framebuffer);
+ break;
+ case QP_ROTATION_90:
+ qp_oled_panel_page_column_flush_rot90(device, &driver->oled.surface.dirty, driver->framebuffer);
+ break;
+ case QP_ROTATION_180:
+ qp_oled_panel_page_column_flush_rot180(device, &driver->oled.surface.dirty, driver->framebuffer);
+ break;
+ case QP_ROTATION_270:
+ qp_oled_panel_page_column_flush_rot270(device, &driver->oled.surface.dirty, driver->framebuffer);
+ break;
+ }
+
+ // Clear the dirty area
+ qp_flush(&driver->oled.surface);
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Driver vtable
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const oled_panel_painter_driver_vtable_t sh1107_driver_vtable = {
+ .base =
+ {
+ .init = qp_sh1107_init,
+ .power = qp_oled_panel_power,
+ .clear = qp_oled_panel_clear,
+ .flush = qp_sh1107_flush,
+ .pixdata = qp_oled_panel_passthru_pixdata,
+ .viewport = qp_oled_panel_passthru_viewport,
+ .palette_convert = qp_oled_panel_passthru_palette_convert,
+ .append_pixels = qp_oled_panel_passthru_append_pixels,
+ .append_pixdata = qp_oled_panel_passthru_append_pixdata,
+ },
+ .opcodes =
+ {
+ .display_on = SH1107_DISPLAY_ON,
+ .display_off = SH1107_DISPLAY_OFF,
+ .set_page = SH1107_PAGE_ADDR,
+ .set_column_lsb = SH1107_SETCOLUMN_LSB,
+ .set_column_msb = SH1107_SETCOLUMN_MSB,
+ },
+};
+
+#ifdef QUANTUM_PAINTER_SH1107_SPI_ENABLE
+// Factory function for creating a handle to the SH1107 device
+painter_device_t qp_sh1107_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode) {
+ for (uint32_t i = 0; i < SH1107_NUM_DEVICES; ++i) {
+ sh1107_device_t *driver = &sh1107_drivers[i];
+ if (!driver->oled.base.driver_vtable) {
+ painter_device_t surface = qp_make_mono1bpp_surface_advanced(&driver->oled.surface, 1, panel_width, panel_height, driver->framebuffer);
+ if (!surface) {
+ return NULL;
+ }
+
+ // Setup the OLED device
+ driver->oled.base.driver_vtable = (const painter_driver_vtable_t *)&sh1107_driver_vtable;
+ driver->oled.base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable;
+ driver->oled.base.native_bits_per_pixel = 1; // 1bpp mono
+ driver->oled.base.panel_width = panel_width;
+ driver->oled.base.panel_height = panel_height;
+ driver->oled.base.rotation = QP_ROTATION_0;
+ driver->oled.base.offset_x = 0;
+ driver->oled.base.offset_y = 0;
+
+ // SPI and other pin configuration
+ driver->oled.base.comms_config = &driver->oled.spi_dc_reset_config;
+ driver->oled.spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin;
+ driver->oled.spi_dc_reset_config.spi_config.divisor = spi_divisor;
+ driver->oled.spi_dc_reset_config.spi_config.lsb_first = false;
+ driver->oled.spi_dc_reset_config.spi_config.mode = spi_mode;
+ driver->oled.spi_dc_reset_config.dc_pin = dc_pin;
+ driver->oled.spi_dc_reset_config.reset_pin = reset_pin;
+ driver->oled.spi_dc_reset_config.command_params_uses_command_pin = true;
+
+ if (!qp_internal_register_device((painter_device_t)driver)) {
+ memset(driver, 0, sizeof(sh1107_device_t));
+ return NULL;
+ }
+
+ return (painter_device_t)driver;
+ }
+ }
+ return NULL;
+}
+
+#endif // QUANTUM_PAINTER_SH1107_SPI_ENABLE
+
+#ifdef QUANTUM_PAINTER_SH1107_I2C_ENABLE
+// Factory function for creating a handle to the SH1107 device
+painter_device_t qp_sh1107_make_i2c_device(uint16_t panel_width, uint16_t panel_height, uint8_t i2c_address) {
+ for (uint32_t i = 0; i < SH1107_NUM_DEVICES; ++i) {
+ sh1107_device_t *driver = &sh1107_drivers[i];
+ if (!driver->oled.base.driver_vtable) {
+ // Instantiate the surface
+ painter_device_t surface = qp_make_mono1bpp_surface_advanced(&driver->oled.surface, 1, panel_width, panel_height, driver->framebuffer);
+ if (!surface) {
+ return NULL;
+ }
+
+ // Setup the OLED device
+ driver->oled.base.driver_vtable = (const painter_driver_vtable_t *)&sh1107_driver_vtable;
+ driver->oled.base.comms_vtable = (const painter_comms_vtable_t *)&i2c_comms_cmddata_vtable;
+ driver->oled.base.native_bits_per_pixel = 1; // 1bpp mono
+ driver->oled.base.panel_width = panel_width;
+ driver->oled.base.panel_height = panel_height;
+ driver->oled.base.rotation = QP_ROTATION_0;
+ driver->oled.base.offset_x = 0;
+ driver->oled.base.offset_y = 0;
+
+ // I2C configuration
+ driver->oled.base.comms_config = &driver->oled.i2c_config;
+ driver->oled.i2c_config.chip_address = i2c_address;
+
+ if (!qp_internal_register_device((painter_device_t)driver)) {
+ memset(driver, 0, sizeof(sh1107_device_t));
+ return NULL;
+ }
+
+ return (painter_device_t)driver;
+ }
+ }
+ return NULL;
+}
+
+#endif // QUANTUM_PAINTER_SH1107_I2C_ENABLE
diff --git a/drivers/painter/sh1107/qp_sh1107.h b/drivers/painter/sh1107/qp_sh1107.h
new file mode 100644
index 00000000000..2b866d7dc85
--- /dev/null
+++ b/drivers/painter/sh1107/qp_sh1107.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include "gpio.h"
+#include "qp_internal.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter SH1107 configurables (add to your keyboard's config.h)
+
+#if defined(QUANTUM_PAINTER_SH1107_SPI_ENABLE) && !defined(SH1107_NUM_SPI_DEVICES)
+/**
+ * @def This controls the maximum number of SPI SH1107 devices that Quantum Painter can communicate with at any one time.
+ * Increasing this number allows for multiple displays to be used.
+ */
+# define SH1107_NUM_SPI_DEVICES 1
+#else
+# define SH1107_NUM_SPI_DEVICES 0
+#endif
+
+#if defined(QUANTUM_PAINTER_SH1107_I2C_ENABLE) && !defined(SH1107_NUM_I2C_DEVICES)
+/**
+ * @def This controls the maximum number of I2C SH1107 devices that Quantum Painter can communicate with at any one time.
+ * Increasing this number allows for multiple displays to be used.
+ */
+# define SH1107_NUM_I2C_DEVICES 1
+#else
+# define SH1107_NUM_I2C_DEVICES 0
+#endif
+
+#define SH1107_NUM_DEVICES ((SH1107_NUM_SPI_DEVICES) + (SH1107_NUM_I2C_DEVICES))
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter SH1107 device factories
+
+#ifdef QUANTUM_PAINTER_SH1107_SPI_ENABLE
+
+/**
+ * Factory method for an SH1107 SPI LCD device.
+ *
+ * @param panel_width[in] the width of the display in pixels (usually 64)
+ * @param panel_height[in] the height of the display in pixels (usually 128)
+ * @param chip_select_pin[in] the GPIO pin used for SPI chip select
+ * @param dc_pin[in] the GPIO pin used for D/C control
+ * @param reset_pin[in] the GPIO pin used for RST
+ * @param spi_divisor[in] the SPI divisor to use when communicating with the display
+ * @param spi_mode[in] the SPI mode to use when communicating with the display
+ * @return the device handle used with all drawing routines in Quantum Painter
+ */
+painter_device_t qp_sh1107_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
+
+#endif // QUANTUM_PAINTER_SH1107_SPI_ENABLE
+
+#ifdef QUANTUM_PAINTER_SH1107_I2C_ENABLE
+
+/**
+ * Factory method for an SH1107 I2C LCD device.
+ *
+ * @param panel_width[in] the width of the display in pixels (usually 64)
+ * @param panel_height[in] the height of the display in pixels (usually 128)
+ * @param i2c_address[in] the I2C address to use
+ * @return the device handle used with all drawing routines in Quantum Painter
+ */
+painter_device_t qp_sh1107_make_i2c_device(uint16_t panel_width, uint16_t panel_height, uint8_t i2c_address);
+
+#endif // QUANTUM_PAINTER_SH1107_I2C_ENABLE
diff --git a/drivers/painter/sh1107/qp_sh1107_opcodes.h b/drivers/painter/sh1107/qp_sh1107_opcodes.h
new file mode 100644
index 00000000000..818bf409289
--- /dev/null
+++ b/drivers/painter/sh1107/qp_sh1107_opcodes.h
@@ -0,0 +1,25 @@
+// Copyright 2024 Steve Branam (@smbranam)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#define SH1107_DISPLAY_ON 0xAF
+#define SH1107_DISPLAY_OFF 0xAE
+#define SH1107_SET_OSC_DIVFREQ 0xD5
+#define SH1107_SET_MUX_RATIO 0xA8
+#define SH1107_DISPLAY_OFFSET 0xD3
+#define SH1107_SET_START_LINE 0xDC // Key/sole difference from SH1106 (which uses 0x40)
+#define SH1107_SET_CHARGE_PUMP 0x8D
+#define SH1107_SET_SEGMENT_REMAP_NORMAL 0xA0
+#define SH1107_SET_SEGMENT_REMAP_INV 0xA1
+#define SH1107_COM_SCAN_DIR_INC 0xC0
+#define SH1107_COM_SCAN_DIR_DEC 0xC8
+#define SH1107_COM_PADS_HW_CFG 0xDA
+#define SH1107_SET_CONTRAST 0x81
+#define SH1107_SET_PRECHARGE_PERIOD 0xD9
+#define SH1107_VCOM_DESELECT_LEVEL 0xDB
+#define SH1107_ALL_ON_RESUME 0xA4
+#define SH1107_NON_INVERTING_DISPLAY 0xA6
+#define SH1107_DEACTIVATE_SCROLL 0x2E
+#define SH1107_SETCOLUMN_LSB 0x00
+#define SH1107_SETCOLUMN_MSB 0x10
+#define SH1107_PAGE_ADDR 0xB0
diff --git a/keyboards/a_jazz/akc084/keyboard.json b/keyboards/a_jazz/akc084/keyboard.json
index a489a5ade50..a8290ea75f4 100644
--- a/keyboards/a_jazz/akc084/keyboard.json
+++ b/keyboards/a_jazz/akc084/keyboard.json
@@ -20,7 +20,7 @@
},
"indicators": {
"caps_lock": "A9",
- "num_lock": "A10"
+ "scroll_lock": "A10"
},
"matrix_pins": {
"cols": ["B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10", "B11", "B12", "B13"],
diff --git a/keyboards/a_jazz/akc084/keymaps/default/keymap.c b/keyboards/a_jazz/akc084/keymaps/default/keymap.c
index 0ea7355fecb..2bd7992707f 100644
--- a/keyboards/a_jazz/akc084/keymaps/default/keymap.c
+++ b/keyboards/a_jazz/akc084/keymaps/default/keymap.c
@@ -25,19 +25,19 @@ const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
- KC_ESC, 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_PSCR, KC_SCRL, KC_PAUS, KC_MUTE,
+ KC_ESC, 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_PSCR, KC_PAUS, KC_DEL, KC_MUTE,
KC_GRV, 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_DEL,
- 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_PGUP,
- 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_PGDN,
+ 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_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT
),
[1] = LAYOUT(
- _______, KC_MSEL, KC_VOLD, KC_VOLU, KC_MUTE, KC_MSTP, KC_MPRV, KC_MPLY, KC_MNXT, KC_MAIL, KC_WHOM, KC_MYCM, KC_CALC, _______, _______, _______, _______,
+ _______, KC_MSEL, KC_VOLD, KC_VOLU, KC_MUTE, KC_MSTP, KC_MPRV, KC_MPLY, KC_MNXT, KC_MAIL, KC_WHOM, KC_MYCM, KC_CALC, _______, _______, KC_SCRL, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_END,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PSCR,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_SCRL,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+ _______, GU_TOGG, _______, _______, _______, _______, _______, _______, _______, _______
)
};
\ No newline at end of file
diff --git a/keyboards/a_jazz/akc084/readme.md b/keyboards/a_jazz/akc084/readme.md
index d93c8a687d4..4be104f5817 100644
--- a/keyboards/a_jazz/akc084/readme.md
+++ b/keyboards/a_jazz/akc084/readme.md
@@ -1,8 +1,8 @@
-# A-JAZZ AKC084
+# A-JAZZ AKC084 (AKP846)
A customizable 84keys keyboard
-
+
* Keyboard Maintainer: [Feng](https://github.com/fenggx-a-jazz)
* Hardware Supported: [a-jazz](https://www.a-jazz.com)
* Hardware Availability: [a-jazz](https://ajazzstore.com/collections/all/products/ajazz-akp846)
@@ -18,6 +18,6 @@ Flashing example for this keyboard:
See the build environment setup and the make instructions for more information. Brand new to QMK? Start with our Complete Newbs Guide.
## Bootloader ESC the bootloader in 3 ways:
-* **Bootmagic reset: Hold down Enter in the keyboard then replug
+* **Bootmagic reset: Hold down Esc in the keyboard then replug
* **Physical reset button: Briefly press the button on the back of the PCB
* **Keycode in layout: Press the key mapped to QK_BOOT
diff --git a/keyboards/al1/readme.md b/keyboards/al1/readme.md
index 3531e2fdc6b..4dcf83f05f1 100644
--- a/keyboards/al1/readme.md
+++ b/keyboards/al1/readme.md
@@ -1,7 +1,5 @@
# TriangleLabs AL1
-
-
* Keyboard Maintainer: [MechMerlin](https://github.com/mechmerlin), [Olivia](https://github.com/olivia)
* Hardware Supported: AL1 PCB
* Hardware Availability: [GroupBuy](https://geekhack.org/index.php?topic=93258.0)
diff --git a/keyboards/alf/dc60/readme.md b/keyboards/alf/dc60/readme.md
index d8e20a8f4f7..628878e8de3 100644
--- a/keyboards/alf/dc60/readme.md
+++ b/keyboards/alf/dc60/readme.md
@@ -1,7 +1,5 @@
# dc60
-
-
A 60% PCB sold with the Alf DC60.
Keyboard Maintainer: [MechMerlin](https://github.com/mechmerlin)
diff --git a/keyboards/biacco42/meishi2/readme.md b/keyboards/biacco42/meishi2/readme.md
index 97c5465f866..b190ff38ce4 100644
--- a/keyboards/biacco42/meishi2/readme.md
+++ b/keyboards/biacco42/meishi2/readme.md
@@ -5,8 +5,7 @@
meishi2 - The better micro macro keyboard
Keyboard Maintainer: [Biacco42](https://github.com/Biacco42)
-Hardware Supported: The PCBs, controllers supported
-Hardware Availability: [links to where you can find this hardware](https://github.com/Biacco42/meishi2)
+Hardware Availability: https://github.com/Biacco42/meishi2
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/bpiphany/unloved_bastard/readme.md b/keyboards/bpiphany/unloved_bastard/readme.md
index 9909d5af3fc..b11a9bfa773 100644
--- a/keyboards/bpiphany/unloved_bastard/readme.md
+++ b/keyboards/bpiphany/unloved_bastard/readme.md
@@ -1,9 +1,5 @@
# unloved_bastard
-
-
-A short description of the keyboard/project
-
Keyboard Maintainer: [Alexander Fougner](https://github.com/fougner)
Hardware Supported: CoolerMaster Masterkeys S PBT (Not the Pro versions with backlighting etc)
Hardware Availability: Pretty much anywhere
diff --git a/keyboards/westm/westm9/rules.mk b/keyboards/cannonkeys/db60/hotswap/rules.mk
similarity index 64%
rename from keyboards/westm/westm9/rules.mk
rename to keyboards/cannonkeys/db60/hotswap/rules.mk
index 3ff78857b35..0ab54aaaf71 100644
--- a/keyboards/westm/westm9/rules.mk
+++ b/keyboards/cannonkeys/db60/hotswap/rules.mk
@@ -1,4 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF
-
-DEFAULT_FOLDER = westm/westm9/rev2
diff --git a/keyboards/westm/westm68/rules.mk b/keyboards/cannonkeys/db60/j02/rules.mk
similarity index 63%
rename from keyboards/westm/westm68/rules.mk
rename to keyboards/cannonkeys/db60/j02/rules.mk
index 2a716f41c4a..0ab54aaaf71 100644
--- a/keyboards/westm/westm68/rules.mk
+++ b/keyboards/cannonkeys/db60/j02/rules.mk
@@ -1,4 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF
-
-DEFAULT_FOLDER = westm/westm68/rev2
diff --git a/keyboards/cannonkeys/db60/rules.mk b/keyboards/cannonkeys/db60/rev2/rules.mk
similarity index 62%
rename from keyboards/cannonkeys/db60/rules.mk
rename to keyboards/cannonkeys/db60/rev2/rules.mk
index 60addd7fe72..0ab54aaaf71 100644
--- a/keyboards/cannonkeys/db60/rules.mk
+++ b/keyboards/cannonkeys/db60/rev2/rules.mk
@@ -1,4 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF
-
-DEFAULT_FOLDER = cannonkeys/db60/rev2
diff --git a/keyboards/converter/palm_usb/info.json b/keyboards/converter/palm_usb/info.json
deleted file mode 100644
index c5b893d7576..00000000000
--- a/keyboards/converter/palm_usb/info.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "keyboard_name": "Stowaway Converter",
- "manufacturer": "QMK",
- "url": "",
- "maintainer": "qmk",
- "usb": {
- "vid": "0xFEED",
- "pid": "0x0001",
- "device_version": "1.0.0"
- },
- "processor": "atmega32u4",
- "bootloader": "caterina",
- "features": {
- "bootmagic": false,
- "mousekey": false,
- "extrakey": false,
- "console": true,
- "command": true
- }
-}
diff --git a/keyboards/converter/palm_usb/config.h b/keyboards/converter/palm_usb/stowaway/config.h
similarity index 100%
rename from keyboards/converter/palm_usb/config.h
rename to keyboards/converter/palm_usb/stowaway/config.h
diff --git a/keyboards/converter/palm_usb/stowaway/keyboard.json b/keyboards/converter/palm_usb/stowaway/keyboard.json
index 9a263327adf..c93957b7d83 100644
--- a/keyboards/converter/palm_usb/stowaway/keyboard.json
+++ b/keyboards/converter/palm_usb/stowaway/keyboard.json
@@ -1,4 +1,22 @@
{
+ "keyboard_name": "Stowaway Converter",
+ "manufacturer": "QMK",
+ "url": "",
+ "maintainer": "qmk",
+ "usb": {
+ "vid": "0xFEED",
+ "pid": "0x0001",
+ "device_version": "1.0.0"
+ },
+ "processor": "atmega32u4",
+ "bootloader": "caterina",
+ "features": {
+ "bootmagic": false,
+ "mousekey": false,
+ "extrakey": false,
+ "console": true,
+ "command": true
+ },
"layouts": {
"LAYOUT": {
"layout": [
diff --git a/keyboards/converter/palm_usb/matrix.c b/keyboards/converter/palm_usb/stowaway/matrix.c
similarity index 100%
rename from keyboards/converter/palm_usb/matrix.c
rename to keyboards/converter/palm_usb/stowaway/matrix.c
diff --git a/keyboards/converter/palm_usb/readme.md b/keyboards/converter/palm_usb/stowaway/readme.md
similarity index 100%
rename from keyboards/converter/palm_usb/readme.md
rename to keyboards/converter/palm_usb/stowaway/readme.md
diff --git a/keyboards/converter/palm_usb/rules.mk b/keyboards/converter/palm_usb/stowaway/rules.mk
similarity index 65%
rename from keyboards/converter/palm_usb/rules.mk
rename to keyboards/converter/palm_usb/stowaway/rules.mk
index bdb3bb0d6bb..ccb8eb9ecc3 100644
--- a/keyboards/converter/palm_usb/rules.mk
+++ b/keyboards/converter/palm_usb/stowaway/rules.mk
@@ -3,5 +3,3 @@ CUSTOM_MATRIX = yes
SRC += matrix.c
UART_DRIVER_REQUIRED = yes
-
-DEFAULT_FOLDER = converter/palm_usb/stowaway
diff --git a/keyboards/cool836a/readme.md b/keyboards/cool836a/readme.md
index dd3ace3cbc3..9473b7136ac 100644
--- a/keyboards/cool836a/readme.md
+++ b/keyboards/cool836a/readme.md
@@ -28,7 +28,7 @@ git clone のあと、
-----------------
## English
-- [Here](https://github.com/telzo2000/cool836A) are a full description of this project and build guide by the great Designer: [m.ki](imgur.com image replace me!)
+- [Here](https://github.com/telzo2000/cool836A) are a full description of this project and build guide by the great Designer: m.ki
- Each virsions(A, B+, C+) of cool836A has the same circuit and that means you can install this firmware on any of them.
- However, this repository is currently(Jan 7, 2021) tested on ver.B+ (RED version) only. Feel free to contact [ME](https://github.com/ketcha-k) for any problems.
diff --git a/keyboards/deltapad/readme.md b/keyboards/deltapad/readme.md
index 858f99b4365..f5dae4d9b0a 100644
--- a/keyboards/deltapad/readme.md
+++ b/keyboards/deltapad/readme.md
@@ -1,15 +1,10 @@
# deltapad
-
-
-*A short description of the keyboard/project*
-
A 4x4 keypad
* Keyboard Maintainer: [Richard Snijder](https://github.com/rich239)
* Hardware Supported: Atmel 32u4 based keypads
-
Make example for this keyboard (after setting up your build environment):
make deltapad:default
diff --git a/keyboards/duck/jetfire/readme.md b/keyboards/duck/jetfire/readme.md
index 8de2f5ced6f..2e12315d6b8 100644
--- a/keyboards/duck/jetfire/readme.md
+++ b/keyboards/duck/jetfire/readme.md
@@ -1,7 +1,5 @@
# Jetfire
-
-
The Duck Jetfire is a hybrid full size and 1800 layout keyboard that went on
Group Buy in November 2017.
diff --git a/keyboards/ericrlau/numdiscipline/readme.md b/keyboards/ericrlau/numdiscipline/readme.md
index bd040df2a51..9770432e56c 100644
--- a/keyboards/ericrlau/numdiscipline/readme.md
+++ b/keyboards/ericrlau/numdiscipline/readme.md
@@ -13,7 +13,6 @@ A modified version of the through hole 65% Discipline keyboard by cftkb.
Other Information:
* Keyboard Maintainer: [ELau](https://github.com/ericrlau)
-* Hardware Supported: The PCBs, controllers supported
* Hardware Availability: https://github.com/ericrlau/NumDiscipline
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/handwired/fc200rt_qmk/readme.md b/keyboards/handwired/fc200rt_qmk/readme.md
index 6490227806a..2b7a0dd1ecc 100644
--- a/keyboards/handwired/fc200rt_qmk/readme.md
+++ b/keyboards/handwired/fc200rt_qmk/readme.md
@@ -25,7 +25,6 @@ Choose any key from the corrosponding row and column and solder it to the pin on
_NOTE: Some of the keys had mislabled columns and rows, so make sure the columns are all connected without diodes to one another, and that the rows are soldered after the diode_
* Keyboard Maintainer: [NaCly](https://github.com/Na-Cly)
-* Hardware Supported: The PCBs, controllers supported
* Hardware Availability: Leopold FC200RT + Teensy 2.0
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/handwired/meck_tkl/blackpill_f401/rules.mk b/keyboards/handwired/meck_tkl/blackpill_f401/rules.mk
new file mode 100644
index 00000000000..6e47ffcd670
--- /dev/null
+++ b/keyboards/handwired/meck_tkl/blackpill_f401/rules.mk
@@ -0,0 +1,2 @@
+AUDIO_SUPPORTED = no
+BACKLIGHT_SUPPORTED = no
diff --git a/keyboards/handwired/meck_tkl/rules.mk b/keyboards/handwired/meck_tkl/rules.mk
deleted file mode 100644
index cdf3900ff0d..00000000000
--- a/keyboards/handwired/meck_tkl/rules.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-AUDIO_SUPPORTED = no
-BACKLIGHT_SUPPORTED = no
-
-DEFAULT_FOLDER = handwired/meck_tkl/blackpill_f401
diff --git a/keyboards/handwired/novem/readme.md b/keyboards/handwired/novem/readme.md
index c259c2cb828..4ccf8152361 100644
--- a/keyboards/handwired/novem/readme.md
+++ b/keyboards/handwired/novem/readme.md
@@ -2,8 +2,6 @@

-A short description of the keyboard/project
-
* Keyboard Maintainer: [Jose I. Martinez](https://github.com/mechanicalguy21)
* Hardware Supported: This is a handwired keyboard created over a 3d printed case.
STL will be shared soon.
diff --git a/keyboards/hhkb/ansi/rules.mk b/keyboards/hhkb/ansi/32u2/rules.mk
similarity index 64%
rename from keyboards/hhkb/ansi/rules.mk
rename to keyboards/hhkb/ansi/32u2/rules.mk
index 841565b8465..94eaaab9c06 100644
--- a/keyboards/hhkb/ansi/rules.mk
+++ b/keyboards/hhkb/ansi/32u2/rules.mk
@@ -2,5 +2,3 @@ CUSTOM_MATRIX = yes
# project specific files
SRC = matrix.c
-
-DEFAULT_FOLDER = hhkb/ansi/32u4
diff --git a/keyboards/hhkb/ansi/32u4/rules.mk b/keyboards/hhkb/ansi/32u4/rules.mk
new file mode 100644
index 00000000000..94eaaab9c06
--- /dev/null
+++ b/keyboards/hhkb/ansi/32u4/rules.mk
@@ -0,0 +1,4 @@
+CUSTOM_MATRIX = yes
+
+# project specific files
+SRC = matrix.c
diff --git a/keyboards/hineybush/h75_singa/readme.md b/keyboards/hineybush/h75_singa/readme.md
index 815785834cb..b110fd5b14b 100644
--- a/keyboards/hineybush/h75_singa/readme.md
+++ b/keyboards/hineybush/h75_singa/readme.md
@@ -1,7 +1,5 @@
# h75_singa
- - TBD
-
New 75% PCB for Singa Keyboards
* Keyboard Maintainer: [hineybush](https://github.com/hineybush)
diff --git a/keyboards/kakunpc/angel64/alpha/rules.mk b/keyboards/kakunpc/angel64/alpha/rules.mk
new file mode 100644
index 00000000000..09c02c88b0d
--- /dev/null
+++ b/keyboards/kakunpc/angel64/alpha/rules.mk
@@ -0,0 +1,3 @@
+CUSTOM_MATRIX = yes
+
+SRC += matrix.c
diff --git a/keyboards/kakunpc/angel64/rev1/rules.mk b/keyboards/kakunpc/angel64/rev1/rules.mk
new file mode 100644
index 00000000000..09c02c88b0d
--- /dev/null
+++ b/keyboards/kakunpc/angel64/rev1/rules.mk
@@ -0,0 +1,3 @@
+CUSTOM_MATRIX = yes
+
+SRC += matrix.c
diff --git a/keyboards/kakunpc/angel64/rules.mk b/keyboards/kakunpc/angel64/rules.mk
deleted file mode 100644
index c95d5297bd7..00000000000
--- a/keyboards/kakunpc/angel64/rules.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-CUSTOM_MATRIX = yes
-
-SRC += matrix.c
-
-DEFAULT_FOLDER = kakunpc/angel64/rev1
diff --git a/keyboards/kakunpc/business_card/readme.md b/keyboards/kakunpc/business_card/readme.md
index cbd05af4108..98fdf1be907 100644
--- a/keyboards/kakunpc/business_card/readme.md
+++ b/keyboards/kakunpc/business_card/readme.md
@@ -1,12 +1,6 @@
# business_card
-
-
-A short description of the keyboard/project
-
-Keyboard Maintainer: [kakunpc](https://github.com/kakunpc)
-Hardware Supported: The PCBs, controllers supported
-Hardware Availability: links to where you can find this hardware
+* Keyboard Maintainer: [kakunpc](https://github.com/kakunpc)
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/keebio/ergodicity/readme.md b/keyboards/keebio/ergodicity/readme.md
index 0f841d6e3eb..61f4ee658c4 100644
--- a/keyboards/keebio/ergodicity/readme.md
+++ b/keyboards/keebio/ergodicity/readme.md
@@ -1,9 +1,5 @@
# Ergodicity
-
-
-A short description of the keyboard/project
-
Keyboard Maintainer: [nooges/bakingpy](https://github.com/nooges)
Hardware Supported: Ergodicity PCB w/ATmega32u4
Hardware Availability: [Keebio](https://keeb.io)
diff --git a/keyboards/kira/kira75/readme.md b/keyboards/kira/kira75/readme.md
index a30b60d179d..237e81d06b0 100644
--- a/keyboards/kira/kira75/readme.md
+++ b/keyboards/kira/kira75/readme.md
@@ -1,7 +1,5 @@
# Kira 75
-
-
75% keyboard designed by thesiscamper
Keyboard Maintainer: [MechMerlin](https://github.com/mechmerlin)
diff --git a/keyboards/kprepublic/bm16a/v1/readme.md b/keyboards/kprepublic/bm16a/v1/readme.md
index d24a8795055..6ad3773371c 100644
--- a/keyboards/kprepublic/bm16a/v1/readme.md
+++ b/keyboards/kprepublic/bm16a/v1/readme.md
@@ -5,7 +5,6 @@
A 16 key macropad, with USB C, RGB underglow and backlight.
* Keyboard Maintainer: QMK Community
-* Hardware Supported: The PCBs, controllers supported
* Hardware Availability: [KPrepublic](https://kprepublic.com/products/bm16a-16-keys-custom-mechanical-keyboard-pcb-plate-programmed-numpad-layouts-qmk-firmware-with-rgb-bottom-underglow-alps-mx); [AliExpress](https://www.aliexpress.com/store/product/bm16a-16-keys-Custom-Mechanical-Keyboard-PCB-plate-programmed-numpad-layouts-qmk-firmware-with-rgb-bottom/3034003_32970629907.html)
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/kprepublic/bm16s/readme.md b/keyboards/kprepublic/bm16s/readme.md
index 6a887e553ae..5b121cdaeae 100644
--- a/keyboards/kprepublic/bm16s/readme.md
+++ b/keyboards/kprepublic/bm16s/readme.md
@@ -3,7 +3,6 @@
A 16-key macropad, with USB C and per-key RGB backlighting. This is a variant of the BM16A, but with low profile Choc switches.
* Keyboard Maintainer: QMK Community
-* Hardware Supported: The PCBs, controllers supported
* Hardware Availability: [KPrepublic](https://kprepublic.com/collections/pcb/products/bm16s-16-keys-custom-mechanical-keyboard-pcb-plate-programmed-numpad-layouts-qmk-firmware-with-rgb-switch-leds-choc-switch); [AliExpress](https://www.aliexpress.com/item/bm16s-16-keys-Custom-Mechanical-Keyboard-PCB-plate-programmed-numpad-layouts-qmk-firmware-with-rgb-switch/32999247908.html); [Massdrop](https://www.massdrop.com/buy/78169)
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/marksard/treadstone32/readme.md b/keyboards/marksard/treadstone32/readme.md
index 170c6bc7618..4e3d5446989 100644
--- a/keyboards/marksard/treadstone32/readme.md
+++ b/keyboards/marksard/treadstone32/readme.md
@@ -4,9 +4,7 @@
A 32-key Symmetric staggered keyboard.
-Keyboard Maintainer: [marksard](https://github.com/marksard)
-Hardware Supported: The PCBs, controllers supported
-Hardware Availability: links to where you can find this hardware
+* Keyboard Maintainer: [marksard](https://github.com/marksard)
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/marksard/treadstone48/readme.md b/keyboards/marksard/treadstone48/readme.md
index c5f6f8f73fe..692891447c5 100644
--- a/keyboards/marksard/treadstone48/readme.md
+++ b/keyboards/marksard/treadstone48/readme.md
@@ -4,9 +4,7 @@
A 47 (or 48) keys Symmetric Staggered keyboard.
-Keyboard Maintainer: [marksard](https://github.com/marksard)
-Hardware Supported: The PCBs, controllers supported
-Hardware Availability: links to where you can find this hardware
+* Keyboard Maintainer: [marksard](https://github.com/marksard)
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/masterworks/classy_tkl/readme.md b/keyboards/masterworks/classy_tkl/readme.md
index 0557ed7f4c4..1e5903483cf 100644
--- a/keyboards/masterworks/classy_tkl/readme.md
+++ b/keyboards/masterworks/classy_tkl/readme.md
@@ -2,8 +2,6 @@

-A short description of the keyboard/project
-
* Keyboard Maintainer: [Mathias Andersson](https://github.com/wraul)
* Hardware Supported: [Classy TKL PCB](https://github.com/4pplet/classyTKL)
* Hardware Availability: https://geekhack.org/index.php?topic=105933
diff --git a/keyboards/mb44/readme.md b/keyboards/mb44/readme.md
index 3cd59ecdb13..3029c69f9e2 100644
--- a/keyboards/mb44/readme.md
+++ b/keyboards/mb44/readme.md
@@ -5,8 +5,6 @@
To reset and put into bootloader mode, please use the hardware reset button on the botton of the PCB. If the PCB is on the default firmware, software reset is available by holding the bottom left corner key and pressing `B` in the standard qwerty layout.
* Keyboard Maintainer: [melonbred](https://github.com/melonbred)
-* Hardware Supported: The PCBs, controllers supported
-* Hardware Availability: Links to where you can find this hardware
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/mechlovin/delphine/readme.md b/keyboards/mechlovin/delphine/readme.md
index 9a5389a5f33..397a0ada407 100644
--- a/keyboards/mechlovin/delphine/readme.md
+++ b/keyboards/mechlovin/delphine/readme.md
@@ -1,7 +1,5 @@
# delphine
-
-
A Number-Pad PCB, Mono backlight and RGB backlight version, Dolpad compatible.
* Keyboard Maintainer: [Mechlovin'](https://github.com/mechlovin)
diff --git a/keyboards/mechwild/mokulua/readme.md b/keyboards/mechwild/mokulua/readme.md
index 24f01b10d46..5a6b69e66e2 100644
--- a/keyboards/mechwild/mokulua/readme.md
+++ b/keyboards/mechwild/mokulua/readme.md
@@ -2,8 +2,6 @@

-*A short description of the keyboard/project*
-
* Keyboard Maintainer: [Kyle McCreery](https://github.com/kylemccreery)
* Hardware Supported: Mokulua v1.3
* Hardware Availability: https://mechwild.com/product/mokulua/
diff --git a/keyboards/meme/readme.md b/keyboards/meme/readme.md
index 94b55d746ef..7b09a5e18fb 100644
--- a/keyboards/meme/readme.md
+++ b/keyboards/meme/readme.md
@@ -1,7 +1,5 @@
# Meme
-
-
65% gasket mount keyboard.
Keyboard Maintainer: [MechMerlin](https://github.com/mechmerlin)
diff --git a/keyboards/mint60/readme.md b/keyboards/mint60/readme.md
index 1824c682f86..3a28f56181b 100644
--- a/keyboards/mint60/readme.md
+++ b/keyboards/mint60/readme.md
@@ -2,11 +2,8 @@

-A short description of the keyboard/project
-
Keyboard Maintainer: [Eucalyn](https://github.com/eucalyn) [@eucalyn_](https://twitter.com/eucalyn_)
Hardware Supported: The Mint60 PCBs, ProMicro supported
-Hardware Availability: links to where you can find this hardware
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/oddball/rules.mk b/keyboards/oddball/v1/rules.mk
similarity index 53%
rename from keyboards/oddball/rules.mk
rename to keyboards/oddball/v1/rules.mk
index 2fc8995acbe..84de35aeb14 100644
--- a/keyboards/oddball/rules.mk
+++ b/keyboards/oddball/v1/rules.mk
@@ -1,3 +1 @@
POINTING_DEVICE_DRIVER = adns9800
-
-DEFAULT_FOLDER = oddball/v1
diff --git a/keyboards/oddball/v2/rules.mk b/keyboards/oddball/v2/rules.mk
new file mode 100644
index 00000000000..84de35aeb14
--- /dev/null
+++ b/keyboards/oddball/v2/rules.mk
@@ -0,0 +1 @@
+POINTING_DEVICE_DRIVER = adns9800
diff --git a/keyboards/oddball/v2_1/rules.mk b/keyboards/oddball/v2_1/rules.mk
new file mode 100644
index 00000000000..84de35aeb14
--- /dev/null
+++ b/keyboards/oddball/v2_1/rules.mk
@@ -0,0 +1 @@
+POINTING_DEVICE_DRIVER = adns9800
diff --git a/keyboards/pegasus/readme.md b/keyboards/pegasus/readme.md
index c523c035404..9c6d575e923 100644
--- a/keyboards/pegasus/readme.md
+++ b/keyboards/pegasus/readme.md
@@ -5,8 +5,6 @@
Pegasus is a 40% keyboard with a 12.75u "WKL" layout with 0.75u blockers.
* Keyboard Maintainer: [melonbred](https://github.com/melonbred)
-* Hardware Supported: The PCBs, controllers supported
-* Hardware Availability: Links to where you can find this hardware
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/teleport/native/ansi/rules.mk b/keyboards/teleport/native/ansi/rules.mk
new file mode 100644
index 00000000000..942ef4c5dbd
--- /dev/null
+++ b/keyboards/teleport/native/ansi/rules.mk
@@ -0,0 +1 @@
+RGB_MATRIX_CUSTOM_KB = yes
diff --git a/keyboards/teleport/native/iso/rules.mk b/keyboards/teleport/native/iso/rules.mk
new file mode 100644
index 00000000000..942ef4c5dbd
--- /dev/null
+++ b/keyboards/teleport/native/iso/rules.mk
@@ -0,0 +1 @@
+RGB_MATRIX_CUSTOM_KB = yes
diff --git a/keyboards/teleport/native/rules.mk b/keyboards/teleport/native/rules.mk
deleted file mode 100644
index 53dc2b17475..00000000000
--- a/keyboards/teleport/native/rules.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-RGB_MATRIX_CUSTOM_KB = yes
-
-DEFAULT_FOLDER = teleport/native/iso
diff --git a/keyboards/tgr/tris/readme.md b/keyboards/tgr/tris/readme.md
index c9cc1990696..e01e7decaad 100644
--- a/keyboards/tgr/tris/readme.md
+++ b/keyboards/tgr/tris/readme.md
@@ -1,7 +1,5 @@
# TGR Tris/Tris CE
-A short description of the keyboard/project
-
* Keyboard Maintainer: [poisonking](https://github.com/halfenergized)
* Hardware Supported: Tris PCB
* Hardware Availability: https://geekhack.org/index.php?topic=86221.0
diff --git a/keyboards/westm/westm68/rev1/rules.mk b/keyboards/westm/westm68/rev1/rules.mk
new file mode 100644
index 00000000000..0ab54aaaf71
--- /dev/null
+++ b/keyboards/westm/westm68/rev1/rules.mk
@@ -0,0 +1,2 @@
+# Wildcard to allow APM32 MCU
+DFU_SUFFIX_ARGS = -v FFFF -p FFFF
diff --git a/keyboards/westm/westm68/rev2/rules.mk b/keyboards/westm/westm68/rev2/rules.mk
new file mode 100644
index 00000000000..0ab54aaaf71
--- /dev/null
+++ b/keyboards/westm/westm68/rev2/rules.mk
@@ -0,0 +1,2 @@
+# Wildcard to allow APM32 MCU
+DFU_SUFFIX_ARGS = -v FFFF -p FFFF
diff --git a/keyboards/westm/westm9/rev1/rules.mk b/keyboards/westm/westm9/rev1/rules.mk
new file mode 100644
index 00000000000..0ab54aaaf71
--- /dev/null
+++ b/keyboards/westm/westm9/rev1/rules.mk
@@ -0,0 +1,2 @@
+# Wildcard to allow APM32 MCU
+DFU_SUFFIX_ARGS = -v FFFF -p FFFF
diff --git a/keyboards/westm/westm9/rev2/rules.mk b/keyboards/westm/westm9/rev2/rules.mk
new file mode 100644
index 00000000000..0ab54aaaf71
--- /dev/null
+++ b/keyboards/westm/westm9/rev2/rules.mk
@@ -0,0 +1,2 @@
+# Wildcard to allow APM32 MCU
+DFU_SUFFIX_ARGS = -v FFFF -p FFFF
diff --git a/keyboards/woodkeys/meira/featherble/rules.mk b/keyboards/woodkeys/meira/featherble/rules.mk
index 3437a35bdf1..44ebb2c1fe2 100644
--- a/keyboards/woodkeys/meira/featherble/rules.mk
+++ b/keyboards/woodkeys/meira/featherble/rules.mk
@@ -1,2 +1,5 @@
# Processor frequency
F_CPU = 8000000
+
+CUSTOM_MATRIX = yes
+SRC += matrix.c
diff --git a/keyboards/woodkeys/meira/promicro/rules.mk b/keyboards/woodkeys/meira/promicro/rules.mk
index 09057bea54b..32a05accc57 100644
--- a/keyboards/woodkeys/meira/promicro/rules.mk
+++ b/keyboards/woodkeys/meira/promicro/rules.mk
@@ -1,3 +1,6 @@
+CUSTOM_MATRIX = yes
+SRC += matrix.c
+
# Disable unsupported hardware
RGBLIGHT_SUPPORTED = no
AUDIO_SUPPORTED = no
diff --git a/keyboards/woodkeys/meira/rules.mk b/keyboards/woodkeys/meira/rules.mk
deleted file mode 100644
index 423c14cfb73..00000000000
--- a/keyboards/woodkeys/meira/rules.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-CUSTOM_MATRIX = yes
-SRC += matrix.c
-
-DEFAULT_FOLDER = woodkeys/meira/promicro
diff --git a/keyboards/work_louder/loop/post_rules.mk b/keyboards/work_louder/loop/post_rules.mk
new file mode 100644
index 00000000000..e0822c009b2
--- /dev/null
+++ b/keyboards/work_louder/loop/post_rules.mk
@@ -0,0 +1 @@
+SRC += rgb_functions.c
diff --git a/keyboards/work_louder/loop/rules.mk b/keyboards/work_louder/loop/rules.mk
deleted file mode 100644
index 53c3227972d..00000000000
--- a/keyboards/work_louder/loop/rules.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-SRC += rgb_functions.c
-
-DEFAULT_FOLDER = work_louder/loop/rev3
diff --git a/keyboards/work_louder/work_board/post_rules.mk b/keyboards/work_louder/work_board/post_rules.mk
new file mode 100644
index 00000000000..e0822c009b2
--- /dev/null
+++ b/keyboards/work_louder/work_board/post_rules.mk
@@ -0,0 +1 @@
+SRC += rgb_functions.c
diff --git a/keyboards/work_louder/work_board/rules.mk b/keyboards/work_louder/work_board/rules.mk
deleted file mode 100644
index a4c45393c01..00000000000
--- a/keyboards/work_louder/work_board/rules.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-SRC += rgb_functions.c
-
-DEFAULT_FOLDER = work_louder/work_board/rev3
diff --git a/keyboards/x16/readme.md b/keyboards/x16/readme.md
index 6434af99c7b..cfe83905d73 100644
--- a/keyboards/x16/readme.md
+++ b/keyboards/x16/readme.md
@@ -3,7 +3,6 @@
A 16 key macropad, with USB C
* Keyboard Maintainer: QMK Community
-* Hardware Supported: The PCBs, controllers supported
* Hardware Availability: The x16 was discontinued by [x16](https://yinxianwei.github.io/x16/)
Make example for this keyboard (after setting up your build environment):
diff --git a/keyboards/zsa/planck_ez/base/rules.mk b/keyboards/zsa/planck_ez/base/rules.mk
new file mode 100644
index 00000000000..c0b951fba9d
--- /dev/null
+++ b/keyboards/zsa/planck_ez/base/rules.mk
@@ -0,0 +1,2 @@
+RGBLIGHT_SUPPORTED = no
+BACKLIGHT_SUPPORTED = no
diff --git a/keyboards/zsa/planck_ez/glow/rules.mk b/keyboards/zsa/planck_ez/glow/rules.mk
new file mode 100644
index 00000000000..c0b951fba9d
--- /dev/null
+++ b/keyboards/zsa/planck_ez/glow/rules.mk
@@ -0,0 +1,2 @@
+RGBLIGHT_SUPPORTED = no
+BACKLIGHT_SUPPORTED = no
diff --git a/keyboards/zsa/planck_ez/rules.mk b/keyboards/zsa/planck_ez/rules.mk
deleted file mode 100644
index 67921c96ed8..00000000000
--- a/keyboards/zsa/planck_ez/rules.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-RGBLIGHT_SUPPORTED = no
-BAKCLIGHT_SUPPORTED = no
-
-DEFAULT_FOLDER = zsa/planck_ez/base
diff --git a/lib/python/qmk/c_parse.py b/lib/python/qmk/c_parse.py
index 08d23cf5ba9..785b9404562 100644
--- a/lib/python/qmk/c_parse.py
+++ b/lib/python/qmk/c_parse.py
@@ -24,7 +24,7 @@ def _get_chunks(it, size):
return iter(lambda: tuple(islice(it, size)), ())
-def _preprocess_c_file(file):
+def preprocess_c_file(file):
"""Load file and strip comments
"""
file_contents = file.read_text(encoding='utf-8')
@@ -66,7 +66,7 @@ def find_layouts(file):
parsed_layouts = {}
# Search the file for LAYOUT macros and aliases
- file_contents = _preprocess_c_file(file)
+ file_contents = preprocess_c_file(file)
for line in file_contents.split('\n'):
if layout_macro_define_regex.match(line.lstrip()) and '(' in line and 'LAYOUT' in line:
@@ -248,7 +248,7 @@ def _parse_led_config(file, matrix_cols, matrix_rows):
current_row_index = 0
current_row = []
- for _type, value in lex(_preprocess_c_file(file), CLexer()):
+ for _type, value in lex(preprocess_c_file(file), CLexer()):
if not found_g_led_config:
# Check for type
if value == 'led_config_t':
diff --git a/lib/python/qmk/cli/format/text.py b/lib/python/qmk/cli/format/text.py
index ff44cf2cd98..d05953b98f2 100644
--- a/lib/python/qmk/cli/format/text.py
+++ b/lib/python/qmk/cli/format/text.py
@@ -11,7 +11,7 @@ from qmk.commands import get_chunks
def dos2unix_run(files):
"""Spawn multiple dos2unix subprocess avoiding too long commands on formatting everything
"""
- for chunk in get_chunks(files, 10):
+ for chunk in get_chunks([normpath(file).as_posix() for file in files], 10):
dos2unix = cli.run(['dos2unix', *chunk])
if dos2unix.returncode:
diff --git a/lib/python/qmk/cli/lint.py b/lib/python/qmk/cli/lint.py
index efb29704ae3..c09e377ad67 100644
--- a/lib/python/qmk/cli/lint.py
+++ b/lib/python/qmk/cli/lint.py
@@ -10,7 +10,7 @@ from qmk.keyboard import keyboard_completer, keyboard_folder_or_all, is_all_keyb
from qmk.keymap import locate_keymap, list_keymaps
from qmk.path import keyboard
from qmk.git import git_get_ignored_files
-from qmk.c_parse import c_source_files
+from qmk.c_parse import c_source_files, preprocess_c_file
CHIBIOS_CONF_CHECKS = ['chconf.h', 'halconf.h', 'mcuconf.h', 'board.h']
INVALID_KB_FEATURES = set(['encoder_map', 'dip_switch_map', 'combo', 'tap_dance', 'via'])
@@ -33,12 +33,64 @@ def _list_defaultish_keymaps(kb):
return keymaps
+def _get_readme_files(kb, km=None):
+ """Return potential keyboard/keymap readme files
+ """
+ search_path = locate_keymap(kb, km).parent if km else keyboard(kb)
+
+ readme_files = []
+
+ if not km:
+ current_path = Path(search_path.parts[0])
+ for path_part in search_path.parts[1:]:
+ current_path = current_path / path_part
+ readme_files.extend(current_path.glob('*readme.md'))
+
+ for file in search_path.glob("**/*readme.md"):
+ # Ignore keymaps when only globing keyboard files
+ if not km and 'keymaps' in file.parts:
+ continue
+ readme_files.append(file)
+
+ return set(readme_files)
+
+
+def _get_build_files(kb, km=None):
+ """Return potential keyboard/keymap build files
+ """
+ search_path = locate_keymap(kb, km).parent if km else keyboard(kb)
+
+ build_files = []
+
+ if not km:
+ current_path = Path()
+ for path_part in search_path.parts:
+ current_path = current_path / path_part
+ build_files.extend(current_path.glob('*rules.mk'))
+
+ for file in search_path.glob("**/*rules.mk"):
+ # Ignore keymaps when only globing keyboard files
+ if not km and 'keymaps' in file.parts:
+ continue
+ build_files.append(file)
+
+ return set(build_files)
+
+
def _get_code_files(kb, km=None):
"""Return potential keyboard/keymap code files
"""
search_path = locate_keymap(kb, km).parent if km else keyboard(kb)
code_files = []
+
+ if not km:
+ current_path = Path()
+ for path_part in search_path.parts:
+ current_path = current_path / path_part
+ code_files.extend(current_path.glob('*.h'))
+ code_files.extend(current_path.glob('*.c'))
+
for file in c_source_files([search_path]):
# Ignore keymaps when only globing keyboard files
if not km and 'keymaps' in file.parts:
@@ -48,6 +100,43 @@ def _get_code_files(kb, km=None):
return code_files
+def _is_invalid_readme(file):
+ """Check if file contains any unfilled content
+ """
+ tokens = [
+ '%KEYBOARD%',
+ '%REAL_NAME%',
+ '%USER_NAME%',
+ 'image replace me!',
+ 'A short description of the keyboard/project',
+ 'The PCBs, controllers supported',
+ 'Links to where you can find this hardware',
+ ]
+
+ for line in file.read_text(encoding='utf-8').split("\n"):
+ if any(token in line for token in tokens):
+ return True
+ return False
+
+
+def _is_empty_rules(file):
+ """Check if file contains any useful content
+ """
+ for line in file.read_text(encoding='utf-8').split("\n"):
+ if len(line) > 0 and not line.isspace() and not line.startswith('#'):
+ return False
+ return True
+
+
+def _is_empty_include(file):
+ """Check if file contains any useful content
+ """
+ for line in preprocess_c_file(file).split("\n"):
+ if len(line) > 0 and not line.isspace() and not line.startswith('#pragma once'):
+ return False
+ return True
+
+
def _has_license(file):
"""Check file has a license header
"""
@@ -91,37 +180,28 @@ def _chibios_conf_includenext_check(target):
return None
-def _rules_mk_assignment_only(kb):
+def _rules_mk_assignment_only(rules_mk):
"""Check the keyboard-level rules.mk to ensure it only has assignments.
"""
- keyboard_path = keyboard(kb)
- current_path = Path()
errors = []
+ continuation = None
+ for i, line in enumerate(rules_mk.open()):
+ line = line.strip()
- for path_part in keyboard_path.parts:
- current_path = current_path / path_part
- rules_mk = current_path / 'rules.mk'
+ if '#' in line:
+ line = line[:line.index('#')]
- if rules_mk.exists():
+ if continuation:
+ line = continuation + line
continuation = None
- for i, line in enumerate(rules_mk.open()):
- line = line.strip()
+ if line:
+ if line[-1] == '\\':
+ continuation = line[:-1]
+ continue
- if '#' in line:
- line = line[:line.index('#')]
-
- if continuation:
- line = continuation + line
- continuation = None
-
- if line:
- if line[-1] == '\\':
- continuation = line[:-1]
- continue
-
- if line and '=' not in line:
- errors.append(f'Non-assignment code on line +{i} {rules_mk}: {line}')
+ if line and '=' not in line:
+ errors.append(f'Non-assignment code on line +{i} {rules_mk}: {line}')
return errors
@@ -162,7 +242,7 @@ def keymap_check(kb, km):
return ok
-def keyboard_check(kb):
+def keyboard_check(kb): # noqa C901
"""Perform the keyboard level checks.
"""
ok = True
@@ -175,13 +255,6 @@ def keyboard_check(kb):
if not _handle_invalid_features(kb, kb_info):
ok = False
- rules_mk_assignment_errors = _rules_mk_assignment_only(kb)
- if rules_mk_assignment_errors:
- ok = False
- cli.log.error('%s: Non-assignment code found in rules.mk. Move it to post_rules.mk instead.', kb)
- for assignment_error in rules_mk_assignment_errors:
- cli.log.error(assignment_error)
-
invalid_files = git_get_ignored_files(f'keyboards/{kb}/')
for file in invalid_files:
if 'keymap' in file:
@@ -189,11 +262,34 @@ def keyboard_check(kb):
cli.log.error(f'{kb}: The file "{file}" should not exist!')
ok = False
+ for file in _get_readme_files(kb):
+ if _is_invalid_readme(file):
+ cli.log.error(f'{kb}: The file "{file}" still contains template tokens!')
+ ok = False
+
+ for file in _get_build_files(kb):
+ if _is_empty_rules(file):
+ cli.log.error(f'{kb}: The file "{file}" is effectively empty and should be removed!')
+ ok = False
+
+ if file.suffix in ['rules.mk']:
+ rules_mk_assignment_errors = _rules_mk_assignment_only(file)
+ if rules_mk_assignment_errors:
+ ok = False
+ cli.log.error('%s: Non-assignment code found in rules.mk. Move it to post_rules.mk instead.', kb)
+ for assignment_error in rules_mk_assignment_errors:
+ cli.log.error(assignment_error)
+
for file in _get_code_files(kb):
if not _has_license(file):
cli.log.error(f'{kb}: The file "{file}" does not have a license header!')
ok = False
+ if file.name in ['config.h']:
+ if _is_empty_include(file):
+ cli.log.error(f'{kb}: The file "{file}" is effectively empty and should be removed!')
+ ok = False
+
if file.name in CHIBIOS_CONF_CHECKS:
check_error = _chibios_conf_includenext_check(file)
if check_error is not None:
diff --git a/platforms/chibios/drivers/backlight_pwm.c b/platforms/chibios/drivers/backlight_pwm.c
index 25fe7962b02..47ad0084156 100644
--- a/platforms/chibios/drivers/backlight_pwm.c
+++ b/platforms/chibios/drivers/backlight_pwm.c
@@ -28,9 +28,9 @@
// Support for pins which are on TIM1_CH1N
#ifdef BACKLIGHT_PWM_COMPLEMENTARY_OUTPUT
# if BACKLIGHT_ON_STATE == 1
-# define PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW;
-# else
# define PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH;
+# else
+# define PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW;
# endif
#else
# if BACKLIGHT_ON_STATE == 1
diff --git a/quantum/action.c b/quantum/action.c
index a39631ba3e9..be85192d25a 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -47,7 +47,12 @@ along with this program. If not, see .
int tp_buttons;
#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
-int retro_tapping_counter = 0;
+bool retro_tap_primed = false;
+uint16_t retro_tap_curr_key = 0;
+# if !(defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
+uint8_t retro_tap_curr_mods = 0;
+uint8_t retro_tap_next_mods = 0;
+# endif
#endif
#if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
@@ -77,7 +82,13 @@ void action_exec(keyevent_t event) {
debug_event(event);
ac_dprintf("\n");
#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
- retro_tapping_counter++;
+ uint16_t event_keycode = get_event_keycode(event, false);
+ if (event.pressed) {
+ retro_tap_primed = false;
+ retro_tap_curr_key = event_keycode;
+ } else if (retro_tap_curr_key == event_keycode) {
+ retro_tap_primed = true;
+ }
#endif
}
@@ -531,7 +542,8 @@ void process_action(keyrecord_t *record, action_t action) {
# if defined(RETRO_TAPPING) && defined(DUMMY_MOD_NEUTRALIZER_KEYCODE)
// Send a dummy keycode to neutralize flashing modifiers
// if the key was held and then released with no interruptions.
- if (retro_tapping_counter == 2) {
+ uint16_t ev_kc = get_event_keycode(event, false);
+ if (retro_tap_primed && retro_tap_curr_key == ev_kc) {
neutralize_flashing_modifiers(get_mods());
}
# endif
@@ -817,6 +829,10 @@ void process_action(keyrecord_t *record, action_t action) {
case ACT_LAYER_TAP_EXT:
# endif
led_set(host_keyboard_leds());
+# ifndef NO_ACTION_ONESHOT
+ // don't release the key
+ do_release_oneshot = false;
+# endif
break;
default:
break;
@@ -825,30 +841,44 @@ void process_action(keyrecord_t *record, action_t action) {
#ifndef NO_ACTION_TAPPING
# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
- if (!is_tap_action(action)) {
- retro_tapping_counter = 0;
- } else {
+ if (is_tap_action(action)) {
if (event.pressed) {
if (tap_count > 0) {
- retro_tapping_counter = 0;
+ retro_tap_primed = false;
+ } else {
+# if !(defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
+ retro_tap_curr_mods = retro_tap_next_mods;
+ retro_tap_next_mods = get_mods();
+# endif
}
} else {
+ uint16_t event_keycode = get_event_keycode(event, false);
+# if !(defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
+ uint8_t curr_mods = get_mods();
+# endif
if (tap_count > 0) {
- retro_tapping_counter = 0;
- } else {
+ retro_tap_primed = false;
+ } else if (retro_tap_curr_key == event_keycode) {
if (
# ifdef RETRO_TAPPING_PER_KEY
- get_retro_tapping(get_event_keycode(record->event, false), record) &&
+ get_retro_tapping(event_keycode, record) &&
# endif
- retro_tapping_counter == 2) {
+ retro_tap_primed) {
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
process_auto_shift(action.layer_tap.code, record);
# else
+ register_mods(retro_tap_curr_mods);
+ wait_ms(TAP_CODE_DELAY);
tap_code(action.layer_tap.code);
+ wait_ms(TAP_CODE_DELAY);
+ unregister_mods(retro_tap_curr_mods);
# endif
}
- retro_tapping_counter = 0;
+ retro_tap_primed = false;
}
+# if !(defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
+ retro_tap_next_mods = curr_mods;
+# endif
}
}
# endif
diff --git a/quantum/painter/qp.h b/quantum/painter/qp.h
index 3dc77b42cfb..f7fdb027893 100644
--- a/quantum/painter/qp.h
+++ b/quantum/painter/qp.h
@@ -557,6 +557,12 @@ int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, pai
# define SH1106_NUM_DEVICES 0
#endif // QUANTUM_PAINTER_SH1106_ENABLE
+#ifdef QUANTUM_PAINTER_SH1107_ENABLE
+# include "qp_sh1107.h"
+#else // QUANTUM_PAINTER_SH1107_ENABLE
+# define SH1107_NUM_DEVICES 0
+#endif // QUANTUM_PAINTER_SH1107_ENABLE
+
#ifdef QUANTUM_PAINTER_LD7032_ENABLE
# include "qp_ld7032.h"
#else // QUANTUM_PAINTER_LD7032_ENABLE
diff --git a/quantum/painter/qp_internal.c b/quantum/painter/qp_internal.c
index 5097edfa074..24b881bd090 100644
--- a/quantum/painter/qp_internal.c
+++ b/quantum/painter/qp_internal.c
@@ -19,6 +19,7 @@ enum {
+ (GC9107_NUM_DEVICES) // GC9107
+ (SSD1351_NUM_DEVICES) // SSD1351
+ (SH1106_NUM_DEVICES) // SH1106
+ + (SH1107_NUM_DEVICES) // SH1107
+ (LD7032_NUM_DEVICES) // LD7032
};
diff --git a/quantum/painter/rules.mk b/quantum/painter/rules.mk
index b773dd091c3..10c2698092b 100644
--- a/quantum/painter/rules.mk
+++ b/quantum/painter/rules.mk
@@ -18,6 +18,8 @@ VALID_QUANTUM_PAINTER_DRIVERS := \
ssd1351_spi \
sh1106_i2c \
sh1106_spi \
+ sh1107_i2c \
+ sh1107_spi \
ld7032_i2c \
ld7032_spi
@@ -184,6 +186,29 @@ define handle_quantum_painter_driver
$(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \
$(DRIVER_PATH)/painter/sh1106/qp_sh1106.c
+ else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),sh1107_spi)
+ QUANTUM_PAINTER_NEEDS_SURFACE := yes
+ QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
+ QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
+ OPT_DEFS += -DQUANTUM_PAINTER_SH1107_ENABLE -DQUANTUM_PAINTER_SH1107_SPI_ENABLE
+ COMMON_VPATH += \
+ $(DRIVER_PATH)/painter/oled_panel \
+ $(DRIVER_PATH)/painter/sh1107
+ SRC += \
+ $(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \
+ $(DRIVER_PATH)/painter/sh1107/qp_sh1107.c
+
+ else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),sh1107_i2c)
+ QUANTUM_PAINTER_NEEDS_SURFACE := yes
+ QUANTUM_PAINTER_NEEDS_COMMS_I2C := yes
+ OPT_DEFS += -DQUANTUM_PAINTER_SH1107_ENABLE -DQUANTUM_PAINTER_SH1107_I2C_ENABLE
+ COMMON_VPATH += \
+ $(DRIVER_PATH)/painter/oled_panel \
+ $(DRIVER_PATH)/painter/sh1107
+ SRC += \
+ $(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \
+ $(DRIVER_PATH)/painter/sh1107/qp_sh1107.c
+
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ld7032_spi)
QUANTUM_PAINTER_NEEDS_SURFACE := yes
QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
diff --git a/tests/basic/test_one_shot_keys.cpp b/tests/basic/test_one_shot_keys.cpp
index 64a8673a5cd..92db52f811e 100644
--- a/tests/basic/test_one_shot_keys.cpp
+++ b/tests/basic/test_one_shot_keys.cpp
@@ -168,7 +168,7 @@ TEST_F(OneShot, OSMChainingTwoOSMs) {
tap_key(osm_key1);
VERIFY_AND_CLEAR(driver);
- /* Press and relesea OSM2 */
+ /* Press and release OSM2 */
EXPECT_NO_REPORT(driver);
tap_key(osm_key2);
VERIFY_AND_CLEAR(driver);
@@ -353,3 +353,337 @@ TEST_F(OneShot, OSLWithOsmAndAdditionalKeypress) {
run_one_scan_loop();
VERIFY_AND_CLEAR(driver);
}
+
+TEST_F(OneShot, OSLWithMoAndAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey mo_key = KeymapKey{1, 1, 0, MO(2)};
+ KeymapKey regular_key = KeymapKey{2, 1, 1, KC_A};
+
+ set_keymap({osl_key, mo_key, regular_key});
+
+ /* Press OSL key */
+ EXPECT_NO_REPORT(driver);
+ osl_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release OSL key */
+ EXPECT_NO_REPORT(driver);
+ osl_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press MO */
+ EXPECT_NO_REPORT(driver);
+ mo_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release MO */
+ EXPECT_NO_REPORT(driver);
+ mo_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ VERIFY_AND_CLEAR(driver);
+}
+
+class OneShotLayerParametrizedTestFixture : public ::testing::WithParamInterface, public OneShot {};
+
+TEST_P(OneShotLayerParametrizedTestFixture, OSLWithActionAndAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey action_key = KeymapKey{1, 1, 0, GetParam()};
+ KeymapKey regular_key = KeymapKey{2, 1, 1, KC_A};
+
+ set_keymap({osl_key, action_key, regular_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Tag Action key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(action_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+INSTANTIATE_TEST_CASE_P(OneShotLayerTests, OneShotLayerParametrizedTestFixture, ::testing::Values(TG(2), TO(2)));
+
+TEST_F(OneShot, OSLWithDFAndAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey df_key = KeymapKey{1, 1, 0, DF(2)};
+ KeymapKey regular_key = KeymapKey{2, 1, 1, KC_A};
+
+ set_keymap({osl_key, df_key, regular_key});
+
+ layer_state_t default_layer_state_bak = default_layer_state;
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press DF key */
+ EXPECT_NO_REPORT(driver);
+ df_key.press();
+ run_one_scan_loop();
+ EXPECT_EQ(default_layer_state, 0b001);
+
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release DF key */
+ EXPECT_NO_REPORT(driver);
+ df_key.release();
+ run_one_scan_loop();
+ EXPECT_EQ(default_layer_state, 0b100);
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ default_layer_state = default_layer_state_bak;
+}
+
+TEST_F(OneShot, OSLChainingTwoOSLsAndAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl1_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey osl2_key = KeymapKey{1, 1, 0, OSL(2)};
+ KeymapKey regular_key = KeymapKey{2, 1, 1, KC_A};
+
+ set_keymap({osl1_key, osl2_key, regular_key});
+
+ /* Press and release first OSL key */
+ EXPECT_NO_REPORT(driver);
+ osl1_key.press();
+ run_one_scan_loop();
+ osl1_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press and release second OSL */
+ EXPECT_NO_REPORT(driver);
+ osl2_key.press();
+ run_one_scan_loop();
+ osl2_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(2));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key */
+ EXPECT_NO_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(OneShot, OSLWithShortLT) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey lt_key = KeymapKey(1, 1, 0, LT(2, KC_A));
+
+ set_keymap({osl_key, lt_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Tap LT key. */
+ EXPECT_REPORT(driver, (lt_key.report_code)).Times(1);
+ EXPECT_EMPTY_REPORT(driver);
+ tap_key(lt_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(OneShot, OSLWithLongLTAndRegularKey) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey lt_key = KeymapKey(1, 1, 0, LT(2, KC_A));
+ KeymapKey regular_key = KeymapKey(2, 1, 1, KC_B);
+
+ set_keymap({osl_key, lt_key, regular_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press LT key. */
+ EXPECT_NO_REPORT(driver);
+ lt_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Idle for tapping term of mod tap hold key. */
+ EXPECT_NO_REPORT(driver);
+ idle_for(TAPPING_TERM + 1);
+ VERIFY_AND_CLEAR(driver);
+ EXPECT_TRUE(layer_state_is(2));
+
+ /* Press regular key. */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key. */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(OneShot, OSLWithShortModTapKeyAndRegularKey) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey mod_tap_hold_key = KeymapKey(1, 1, 0, SFT_T(KC_P));
+ KeymapKey regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({osl_key, mod_tap_hold_key, regular_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press mod-tap-hold key. */
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_REPORT(driver, (KC_P));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key. */
+ EXPECT_REPORT(driver, (regular_key.report_code));
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key. */
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(OneShot, OSLWithLongModTapKeyAndRegularKey) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey mod_tap_hold_key = KeymapKey(1, 1, 0, SFT_T(KC_P));
+ KeymapKey regular_key = KeymapKey(1, 2, 0, KC_A);
+
+ set_keymap({osl_key, mod_tap_hold_key, regular_key});
+
+ /* Tap OSL key */
+ EXPECT_NO_REPORT(driver);
+ tap_key(osl_key);
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press mod-tap-hold key. */
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Idle for tapping term of mod tap hold key. */
+ EXPECT_REPORT(driver, (KC_LSFT));
+ idle_for(TAPPING_TERM + 1);
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Press regular key. */
+ EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ /* Release regular key. */
+ EXPECT_NO_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
\ No newline at end of file
diff --git a/tests/tap_hold_configurations/retro_tapping/test_key_roll.cpp b/tests/tap_hold_configurations/retro_tapping/test_key_roll.cpp
new file mode 100644
index 00000000000..afcbde99379
--- /dev/null
+++ b/tests/tap_hold_configurations/retro_tapping/test_key_roll.cpp
@@ -0,0 +1,408 @@
+/* Copyright 2024 John Rigoni
+ *
+ * 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 3 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 .
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "keycodes.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class RetroTapKeyRoll : public TestFixture {};
+
+TEST_F(RetroTapKeyRoll, regular_to_left_gui_mod_over_tap_term) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, LGUI_T(KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_B);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ EXPECT_REPORT(driver, (KC_B));
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM);
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_B, KC_LEFT_GUI));
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_GUI));
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_GUI, DUMMY_MOD_NEUTRALIZER_KEYCODE));
+ EXPECT_REPORT(driver, (KC_LEFT_GUI));
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_P));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, regular_to_mod_over_tap_term) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_A));
+ auto regular_key = KeymapKey(0, 2, 0, KC_B);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ EXPECT_REPORT(driver, (KC_B));
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_B, KC_LEFT_SHIFT));
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_A));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, regular_to_mod_under_tap_term) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_A));
+ auto regular_key = KeymapKey(0, 2, 0, KC_B);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ EXPECT_REPORT(driver, (KC_B));
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_A));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, mod_under_tap_term_to_regular) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, LGUI_T(KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_B);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_P));
+ EXPECT_REPORT(driver, (KC_B, KC_P));
+ EXPECT_REPORT(driver, (KC_B));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, mod_over_tap_term_to_regular) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_A));
+ auto regular_key = KeymapKey(0, 2, 0, KC_B);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_B));
+ regular_key.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_B));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_EMPTY_REPORT(driver);
+ regular_key.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, mod_under_tap_term_to_mod_under_tap_term) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_gui = KeymapKey(0, 1, 0, LGUI_T(KC_P));
+ auto mod_tap_hold_lshft = KeymapKey(0, 2, 0, SFT_T(KC_A));
+
+ set_keymap({mod_tap_hold_gui, mod_tap_hold_lshft});
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_lshft.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_gui.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_A));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_lshft.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_P));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_gui.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, mod_over_tap_term_to_mod_under_tap_term) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_gui = KeymapKey(0, 1, 0, LGUI_T(KC_P));
+ auto mod_tap_hold_lshft = KeymapKey(0, 2, 0, SFT_T(KC_A));
+
+ set_keymap({mod_tap_hold_gui, mod_tap_hold_lshft});
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ mod_tap_hold_lshft.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_gui.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_lshft.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_P));
+ EXPECT_REPORT(driver, (KC_P));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_gui.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, mod_under_tap_term_to_mod_over_tap_term) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_gui = KeymapKey(0, 1, 0, LGUI_T(KC_P));
+ auto mod_tap_hold_lshft = KeymapKey(0, 2, 0, SFT_T(KC_A));
+
+ set_keymap({mod_tap_hold_gui, mod_tap_hold_lshft});
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_lshft.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_LEFT_GUI));
+ mod_tap_hold_gui.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_GUI));
+ mod_tap_hold_lshft.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_GUI, DUMMY_MOD_NEUTRALIZER_KEYCODE));
+ EXPECT_REPORT(driver, (KC_LEFT_GUI));
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ EXPECT_REPORT(driver, (KC_P, KC_LEFT_SHIFT));
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_gui.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, mod_under_tap_term_to_mod_over_tap_term_offset) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_gui = KeymapKey(0, 1, 0, LGUI_T(KC_P));
+ auto mod_tap_hold_lshft = KeymapKey(0, 2, 0, SFT_T(KC_A));
+
+ set_keymap({mod_tap_hold_gui, mod_tap_hold_lshft});
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_lshft.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_gui.press();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_A));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_lshft.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_GUI));
+ EXPECT_REPORT(driver, (KC_LEFT_GUI, DUMMY_MOD_NEUTRALIZER_KEYCODE));
+ EXPECT_REPORT(driver, (KC_LEFT_GUI));
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_P));
+ EXPECT_EMPTY_REPORT(driver);
+ idle_for(TAPPING_TERM);
+ mod_tap_hold_gui.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, mod_over_tap_term_to_mod_over_tap_term) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_gui = KeymapKey(0, 1, 0, LGUI_T(KC_P));
+ auto mod_tap_hold_lshft = KeymapKey(0, 2, 0, SFT_T(KC_A));
+
+ set_keymap({mod_tap_hold_gui, mod_tap_hold_lshft});
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ mod_tap_hold_lshft.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_LEFT_GUI));
+ mod_tap_hold_gui.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_GUI));
+ mod_tap_hold_lshft.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_GUI, DUMMY_MOD_NEUTRALIZER_KEYCODE));
+ EXPECT_REPORT(driver, (KC_LEFT_GUI));
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ EXPECT_REPORT(driver, (KC_P, KC_LEFT_SHIFT));
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_gui.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
+
+TEST_F(RetroTapKeyRoll, mod_to_mod_to_mod) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_lalt = KeymapKey(0, 1, 0, LALT_T(KC_R));
+ auto mod_tap_hold_lshft = KeymapKey(0, 2, 0, SFT_T(KC_A));
+ auto mod_tap_hold_lctrl = KeymapKey(0, 3, 0, LCTL_T(KC_C));
+
+ set_keymap({mod_tap_hold_lalt, mod_tap_hold_lshft, mod_tap_hold_lctrl});
+
+ EXPECT_REPORT(driver, (KC_LEFT_ALT));
+ mod_tap_hold_lalt.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_LEFT_ALT));
+ mod_tap_hold_lshft.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ mod_tap_hold_lalt.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_CTRL, KC_LEFT_SHIFT));
+ EXPECT_NO_REPORT(driver);
+ mod_tap_hold_lctrl.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_REPORT(driver, (KC_LEFT_CTRL));
+ mod_tap_hold_lshft.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ EXPECT_REPORT(driver, (KC_C, KC_LEFT_SHIFT));
+ EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
+ EXPECT_EMPTY_REPORT(driver);
+ mod_tap_hold_lctrl.release();
+ run_one_scan_loop();
+ VERIFY_AND_CLEAR(driver);
+}
diff --git a/util/install/gentoo.sh b/util/install/gentoo.sh
index 49e80490bec..3c8f417fb7b 100755
--- a/util/install/gentoo.sh
+++ b/util/install/gentoo.sh
@@ -22,7 +22,7 @@ _qmk_install() {
echo "sys-devel/gcc multilib\ncross-arm-none-eabi/newlib nano" | sudo tee --append /etc/portage/package.use/qmkfirmware >/dev/null
sudo emerge -auN sys-devel/gcc
sudo emerge -au --noreplace \
- app-arch/unzip app-arch/zip net-misc/wget sys-devel/clang \
+ app-arch/unzip app-arch/zip net-misc/wget llvm-core/clang \
sys-devel/crossdev \>=dev-lang/python-3.7 dev-embedded/avrdude \
dev-embedded/dfu-programmer app-mobilephone/dfu-util sys-apps/hwloc \
dev-libs/hidapi