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

This commit is contained in:
Nick Brassel 2025-02-17 08:44:50 +11:00
commit 55baed3380
No known key found for this signature in database
82 changed files with 1368 additions and 187 deletions

View File

@ -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!

View File

@ -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"
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"],

View File

@ -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, _______, _______, _______, _______, _______, _______, _______, _______
)
};

View File

@ -1,8 +1,8 @@
# A-JAZZ AKC084
# A-JAZZ AKC084 (AKP846)
A customizable 84keys keyboard
![akc084](https://i.imgur.com/381vaD7.png)
![akc084](https://i.imgur.com/6D0jBco.png)
* 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

View File

@ -1,7 +1,5 @@
# TriangleLabs AL1
![AL1](imgur.com image replace me!)
* 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)

View File

@ -1,7 +1,5 @@
# dc60
![dc60](imgur.com image replace me!)
A 60% PCB sold with the Alf DC60.
Keyboard Maintainer: [MechMerlin](https://github.com/mechmerlin)

View File

@ -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):

View File

@ -1,9 +1,5 @@
# unloved_bastard
![unloved_bastard](imgur.com image replace me!)
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

View File

@ -1,4 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF
DEFAULT_FOLDER = westm/westm9/rev2

View File

@ -1,4 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF
DEFAULT_FOLDER = westm/westm68/rev2

View File

@ -1,4 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF
DEFAULT_FOLDER = cannonkeys/db60/rev2

View File

@ -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
}
}

View File

@ -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": [

View File

@ -3,5 +3,3 @@ CUSTOM_MATRIX = yes
SRC += matrix.c
UART_DRIVER_REQUIRED = yes
DEFAULT_FOLDER = converter/palm_usb/stowaway

View File

@ -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.

View File

@ -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

View File

@ -1,7 +1,5 @@
# Jetfire
![jetfire](imgur.com image replace me!)
The Duck Jetfire is a hybrid full size and 1800 layout keyboard that went on
Group Buy in November 2017.

View File

@ -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):

View File

@ -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):

View File

@ -0,0 +1,2 @@
AUDIO_SUPPORTED = no
BACKLIGHT_SUPPORTED = no

View File

@ -1,4 +0,0 @@
AUDIO_SUPPORTED = no
BACKLIGHT_SUPPORTED = no
DEFAULT_FOLDER = handwired/meck_tkl/blackpill_f401

View File

@ -2,8 +2,6 @@
![novem](https://i.imgur.com/nPjBE9b.jpg)
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.

View File

@ -2,5 +2,3 @@ CUSTOM_MATRIX = yes
# project specific files
SRC = matrix.c
DEFAULT_FOLDER = hhkb/ansi/32u4

View File

@ -0,0 +1,4 @@
CUSTOM_MATRIX = yes
# project specific files
SRC = matrix.c

View File

@ -1,7 +1,5 @@
# h75_singa
![h75_singa](imgur.com image replace me!) - TBD
New 75% PCB for Singa Keyboards
* Keyboard Maintainer: [hineybush](https://github.com/hineybush)

View File

@ -0,0 +1,3 @@
CUSTOM_MATRIX = yes
SRC += matrix.c

View File

@ -0,0 +1,3 @@
CUSTOM_MATRIX = yes
SRC += matrix.c

View File

@ -1,5 +0,0 @@
CUSTOM_MATRIX = yes
SRC += matrix.c
DEFAULT_FOLDER = kakunpc/angel64/rev1

View File

@ -1,12 +1,6 @@
# business_card
![business_card](imgur.com image replace me!)
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):

View File

@ -1,9 +1,5 @@
# Ergodicity
![ergodicity](imgur.com image replace me!)
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)

View File

@ -1,7 +1,5 @@
# Kira 75
![kira75](imgur.com image replace me!)
75% keyboard designed by thesiscamper
Keyboard Maintainer: [MechMerlin](https://github.com/mechmerlin)

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -2,8 +2,6 @@
![Classy TKL](https://i.imgur.com/p1dxfYKl.jpg)
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

View File

@ -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):

View File

@ -1,7 +1,5 @@
# delphine
![delphine](imgur.com image replace me!)
A Number-Pad PCB, Mono backlight and RGB backlight version, Dolpad compatible.
* Keyboard Maintainer: [Mechlovin'](https://github.com/mechlovin)

View File

@ -2,8 +2,6 @@
![Mokulua](https://i.imgur.com/7fifiQch.jpg)
*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/

View File

@ -1,7 +1,5 @@
# Meme
![meme](imgur.com image replace me!)
65% gasket mount keyboard.
Keyboard Maintainer: [MechMerlin](https://github.com/mechmerlin)

View File

@ -2,11 +2,8 @@
![Mint60](https://i.imgur.com/suOE8HN.jpg)
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):

View File

@ -1,3 +1 @@
POINTING_DEVICE_DRIVER = adns9800
DEFAULT_FOLDER = oddball/v1

View File

@ -0,0 +1 @@
POINTING_DEVICE_DRIVER = adns9800

View File

@ -0,0 +1 @@
POINTING_DEVICE_DRIVER = adns9800

View File

@ -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):

View File

@ -0,0 +1 @@
RGB_MATRIX_CUSTOM_KB = yes

View File

@ -0,0 +1 @@
RGB_MATRIX_CUSTOM_KB = yes

View File

@ -1,3 +0,0 @@
RGB_MATRIX_CUSTOM_KB = yes
DEFAULT_FOLDER = teleport/native/iso

View File

@ -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

View File

@ -0,0 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF

View File

@ -0,0 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF

View File

@ -0,0 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF

View File

@ -0,0 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF

View File

@ -1,2 +1,5 @@
# Processor frequency
F_CPU = 8000000
CUSTOM_MATRIX = yes
SRC += matrix.c

View File

@ -1,3 +1,6 @@
CUSTOM_MATRIX = yes
SRC += matrix.c
# Disable unsupported hardware
RGBLIGHT_SUPPORTED = no
AUDIO_SUPPORTED = no

View File

@ -1,4 +0,0 @@
CUSTOM_MATRIX = yes
SRC += matrix.c
DEFAULT_FOLDER = woodkeys/meira/promicro

View File

@ -0,0 +1 @@
SRC += rgb_functions.c

View File

@ -1,3 +0,0 @@
SRC += rgb_functions.c
DEFAULT_FOLDER = work_louder/loop/rev3

View File

@ -0,0 +1 @@
SRC += rgb_functions.c

View File

@ -1,3 +0,0 @@
SRC += rgb_functions.c
DEFAULT_FOLDER = work_louder/work_board/rev3

View File

@ -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):

View File

@ -0,0 +1,2 @@
RGBLIGHT_SUPPORTED = no
BACKLIGHT_SUPPORTED = no

View File

@ -0,0 +1,2 @@
RGBLIGHT_SUPPORTED = no
BACKLIGHT_SUPPORTED = no

View File

@ -1,4 +0,0 @@
RGBLIGHT_SUPPORTED = no
BAKCLIGHT_SUPPORTED = no
DEFAULT_FOLDER = zsa/planck_ez/base

View File

@ -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':

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -47,7 +47,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
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

View File

@ -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

View File

@ -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
};

View File

@ -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

View File

@ -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<uint16_t>, 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);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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);
}

View File

@ -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