From a3cbc8a004f6ec5b0e1df326353a2a2fc8221129 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 28 Feb 2021 15:50:15 +0000 Subject: Overhaul bootmagic logic to have single entrypoint (#8532) * Relocate bootmagic logic to have single entrypoint * Align init of layer state --- tmk_core/common/bootmagic.c | 163 --------------------------------------- tmk_core/common/bootmagic.h | 102 ------------------------ tmk_core/common/bootmagic_lite.c | 49 ------------ tmk_core/common/keyboard.c | 10 --- tmk_core/common/magic.c | 39 ---------- tmk_core/common/magic.h | 3 - 6 files changed, 366 deletions(-) delete mode 100644 tmk_core/common/bootmagic.c delete mode 100644 tmk_core/common/bootmagic.h delete mode 100644 tmk_core/common/bootmagic_lite.c delete mode 100644 tmk_core/common/magic.c delete mode 100644 tmk_core/common/magic.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c deleted file mode 100644 index c1b3adf94d..0000000000 --- a/tmk_core/common/bootmagic.c +++ /dev/null @@ -1,163 +0,0 @@ -#include -#include -#include "wait.h" -#include "matrix.h" -#include "bootloader.h" -#include "debug.h" -#include "keymap.h" -#include "host.h" -#include "action_layer.h" -#include "eeconfig.h" -#include "bootmagic.h" - -keymap_config_t keymap_config; - -/** \brief Bootmagic - * - * FIXME: needs doc - */ -void bootmagic(void) { - /* check signature */ - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } - - /* do scans in case of bounce */ - print("bootmagic scan: ... "); - uint8_t scan = 100; - while (scan--) { - matrix_scan(); - wait_ms(10); - } - print("done.\n"); - - /* bootmagic skip */ - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) { - return; - } - - /* eeconfig clear */ - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) { - eeconfig_init(); - } - - /* bootloader */ - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) { - bootloader_jump(); - } - - /* debug enable */ - debug_config.raw = eeconfig_read_debug(); - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) { - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) { - debug_config.matrix = !debug_config.matrix; - } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) { - debug_config.keyboard = !debug_config.keyboard; - } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) { - debug_config.mouse = !debug_config.mouse; - } else { - debug_config.enable = !debug_config.enable; - } - } - eeconfig_update_debug(debug_config.raw); - - /* keymap config */ - keymap_config.raw = eeconfig_read_keymap(); - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) { - keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) { - keymap_config.capslock_to_control = !keymap_config.capslock_to_control; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) { - keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) { - keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) { - keymap_config.no_gui = !keymap_config.no_gui; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) { - keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) { - keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace; - } - if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) { - keymap_config.nkro = !keymap_config.nkro; - } - eeconfig_update_keymap(keymap_config.raw); - - /* default layer */ - uint8_t default_layer = 0; - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { - default_layer |= (1 << 0); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { - default_layer |= (1 << 1); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { - default_layer |= (1 << 2); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { - default_layer |= (1 << 3); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { - default_layer |= (1 << 4); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { - default_layer |= (1 << 5); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { - default_layer |= (1 << 6); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { - default_layer |= (1 << 7); - } - if (default_layer) { - eeconfig_update_default_layer(default_layer); - default_layer_set((layer_state_t)default_layer); - } else { - default_layer = eeconfig_read_default_layer(); - default_layer_set((layer_state_t)default_layer); - } - /* Also initialize layer state to trigger callback functions for layer_state */ - layer_state_set_kb((layer_state_t)layer_state); - - /* EE_HANDS handedness */ - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_LEFT)) { - eeconfig_update_handedness(true); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_RIGHT)) { - eeconfig_update_handedness(false); - } -} - -/** \brief Scan Keycode - * - * FIXME: needs doc - */ -static bool scan_keycode(uint8_t keycode) { - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row_t matrix_row = matrix_get_row(r); - for (uint8_t c = 0; c < MATRIX_COLS; c++) { - if (matrix_row & ((matrix_row_t)1 << c)) { - if (keycode == keymap_key_to_keycode(0, (keypos_t){.row = r, .col = c})) { - return true; - } - } - } - } - return false; -} - -/** \brief Bootmagic Scan Keycode - * - * FIXME: needs doc - */ -bool bootmagic_scan_keycode(uint8_t keycode) { - if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; - - return scan_keycode(keycode); -} diff --git a/tmk_core/common/bootmagic.h b/tmk_core/common/bootmagic.h deleted file mode 100644 index 8209d0194f..0000000000 --- a/tmk_core/common/bootmagic.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -/* FIXME: Add special doxygen comments for defines here. */ - -/* bootmagic salt key */ -#ifndef BOOTMAGIC_KEY_SALT -# define BOOTMAGIC_KEY_SALT KC_SPACE -#endif - -/* skip bootmagic and eeconfig */ -#ifndef BOOTMAGIC_KEY_SKIP -# define BOOTMAGIC_KEY_SKIP KC_ESC -#endif - -/* eeprom clear */ -#ifndef BOOTMAGIC_KEY_EEPROM_CLEAR -# define BOOTMAGIC_KEY_EEPROM_CLEAR KC_BSPACE -#endif - -/* kick up bootloader */ -#ifndef BOOTMAGIC_KEY_BOOTLOADER -# define BOOTMAGIC_KEY_BOOTLOADER KC_B -#endif - -/* debug enable */ -#ifndef BOOTMAGIC_KEY_DEBUG_ENABLE -# define BOOTMAGIC_KEY_DEBUG_ENABLE KC_D -#endif -#ifndef BOOTMAGIC_KEY_DEBUG_MATRIX -# define BOOTMAGIC_KEY_DEBUG_MATRIX KC_X -#endif -#ifndef BOOTMAGIC_KEY_DEBUG_KEYBOARD -# define BOOTMAGIC_KEY_DEBUG_KEYBOARD KC_K -#endif -#ifndef BOOTMAGIC_KEY_DEBUG_MOUSE -# define BOOTMAGIC_KEY_DEBUG_MOUSE KC_M -#endif -#ifndef BOOTMAGIC_KEY_EE_HANDS_LEFT -# define BOOTMAGIC_KEY_EE_HANDS_LEFT KC_L -#endif -#ifndef BOOTMAGIC_KEY_EE_HANDS_RIGHT -# define BOOTMAGIC_KEY_EE_HANDS_RIGHT KC_R -#endif - -/* - * keymap config - */ -#ifndef BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK -# define BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK KC_LCTRL -#endif -#ifndef BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL -# define BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL KC_CAPSLOCK -#endif -#ifndef BOOTMAGIC_KEY_SWAP_LALT_LGUI -# define BOOTMAGIC_KEY_SWAP_LALT_LGUI KC_LALT -#endif -#ifndef BOOTMAGIC_KEY_SWAP_RALT_RGUI -# define BOOTMAGIC_KEY_SWAP_RALT_RGUI KC_RALT -#endif -#ifndef BOOTMAGIC_KEY_NO_GUI -# define BOOTMAGIC_KEY_NO_GUI KC_LGUI -#endif -#ifndef BOOTMAGIC_KEY_SWAP_GRAVE_ESC -# define BOOTMAGIC_KEY_SWAP_GRAVE_ESC KC_GRAVE -#endif -#ifndef BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE -# define BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE KC_BSLASH -#endif -#ifndef BOOTMAGIC_HOST_NKRO -# define BOOTMAGIC_HOST_NKRO KC_N -#endif - -/* - * change default layer - */ -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_0 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_0 KC_0 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_1 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_1 KC_1 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_2 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_2 KC_2 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_3 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_3 KC_3 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_4 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_4 KC_4 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_5 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_5 KC_5 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_6 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_6 KC_6 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_7 KC_7 -#endif - -void bootmagic(void); -bool bootmagic_scan_keycode(uint8_t keycode); diff --git a/tmk_core/common/bootmagic_lite.c b/tmk_core/common/bootmagic_lite.c deleted file mode 100644 index cbf756a175..0000000000 --- a/tmk_core/common/bootmagic_lite.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "quantum.h" - -/** \brief Reset eeprom - * - * ...just incase someone wants to only change the eeprom behaviour - */ -__attribute__((weak)) void bootmagic_lite_reset_eeprom(void) { -#if defined(VIA_ENABLE) - via_eeprom_reset(); -#else - eeconfig_disable(); -#endif -} - -/** \brief The lite version of TMK's bootmagic based on Wilba. - * - * 100% less potential for accidentally making the keyboard do stupid things. - */ -__attribute__((weak)) void bootmagic_lite(void) { - // We need multiple scans because debouncing can't be turned off. - matrix_scan(); -#if defined(DEBOUNCE) && DEBOUNCE > 0 - wait_ms(DEBOUNCE * 2); -#else - wait_ms(30); -#endif - matrix_scan(); - - // If the configured key (commonly Esc) is held down on power up, - // reset the EEPROM valid state and jump to bootloader. - // This isn't very generalized, but we need something that doesn't - // rely on user's keymaps in firmware or EEPROM. - uint8_t row = BOOTMAGIC_LITE_ROW; - uint8_t col = BOOTMAGIC_LITE_COLUMN; - -#if defined(SPLIT_KEYBOARD) && defined(BOOTMAGIC_LITE_ROW_RIGHT) && defined(BOOTMAGIC_LITE_COLUMN_RIGHT) - if (!is_keyboard_left()) { - row = BOOTMAGIC_LITE_ROW_RIGHT; - col = BOOTMAGIC_LITE_COLUMN_RIGHT; - } -#endif - - if (matrix_get_row(row) & (1 << col)) { - bootmagic_lite_reset_eeprom(); - - // Jump to bootloader. - bootloader_jump(); - } -} diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index ce3255c069..65d9e00c7a 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -34,11 +34,6 @@ along with this program. If not, see . #ifdef BACKLIGHT_ENABLE # include "backlight.h" #endif -#ifdef BOOTMAGIC_ENABLE -# include "bootmagic.h" -#else -# include "magic.h" -#endif #ifdef MOUSEKEY_ENABLE # include "mousekey.h" #endif @@ -296,11 +291,6 @@ void keyboard_init(void) { #ifdef ADB_MOUSE_ENABLE adb_mouse_init(); #endif -#ifdef BOOTMAGIC_ENABLE - bootmagic(); -#else - magic(); -#endif #ifdef BACKLIGHT_ENABLE backlight_init(); #endif diff --git a/tmk_core/common/magic.c b/tmk_core/common/magic.c deleted file mode 100644 index e14994164e..0000000000 --- a/tmk_core/common/magic.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#if defined(__AVR__) -# include -#endif -#include "matrix.h" -#include "bootloader.h" -#include "debug.h" -#include "keymap.h" -#include "host.h" -#include "action_layer.h" -#include "eeconfig.h" -#include "magic.h" - -keymap_config_t keymap_config; - -/** \brief Magic - * - * FIXME: Needs doc - */ -void magic(void) { - /* check signature */ - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } - - /* debug enable */ - debug_config.raw = eeconfig_read_debug(); - - /* keymap config */ - keymap_config.raw = eeconfig_read_keymap(); - - uint8_t default_layer = 0; - default_layer = eeconfig_read_default_layer(); - default_layer_set((layer_state_t)default_layer); - - /* Also initialize layer state to trigger callback functions for layer_state */ - layer_state_set_kb((layer_state_t)layer_state); -} diff --git a/tmk_core/common/magic.h b/tmk_core/common/magic.h deleted file mode 100644 index a6552c04dc..0000000000 --- a/tmk_core/common/magic.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void magic(void); -- cgit v1.2.3 From 415a8bc249d5c366487f69b3547198d17044a5de Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 28 Feb 2021 15:52:43 +0000 Subject: ARM - Refactor SLEEP_LED to support more platforms (#8403) * Initial refactor of ARM SLEEP_LED to enable more platforms * fix build issues * Disable SLEEP_LED for boards with no caps lock code * Enable GPT14 for boards with caps lock code and SLEEP_LED enabled * Enable GPT for boards with caps lock code and SLEEP_LED enabled --- tmk_core/common/chibios/sleep_led.c | 88 ++++++++++++++----------------------- 1 file changed, 33 insertions(+), 55 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c index 5595eec0e5..477056a454 100644 --- a/tmk_core/common/chibios/sleep_led.c +++ b/tmk_core/common/chibios/sleep_led.c @@ -9,21 +9,13 @@ * Use LP timer on Kinetises, TIM14 on STM32F0. */ -#if defined(KL2x) || defined(K20x) - -/* Use Low Power Timer (LPTMR) */ -# define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR -# define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF - -#elif defined(STM32F0XX) - -/* Use TIM14 manually */ -# define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER -# define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF - +#ifndef SLEEP_LED_GPT_DRIVER +# if defined(STM32F0XX) +# define SLEEP_LED_GPT_DRIVER GPTD14 +# endif #endif -#if defined(KL2x) || defined(K20x) || defined(STM32F0XX) /* common parts for timers/interrupts */ +#if defined(KL2x) || defined(K20x) || defined(SLEEP_LED_GPT_DRIVER) /* common parts for timers/interrupts */ /* Breathing Sleep LED brighness(PWM On period) table * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle @@ -33,10 +25,7 @@ */ static const uint8_t breathing_table[64] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -/* interrupt handler */ -OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { - OSAL_IRQ_PROLOGUE(); - +void sleep_led_timer_callback(void) { /* Software PWM * timer:1111 1111 1111 1111 * \_____/\/ \_______/____ count(0-255) @@ -64,17 +53,16 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { if (timer.pwm.count == breathing_table[timer.pwm.index]) { led_set(0); } - - /* Reset the counter */ - RESET_COUNTER; - - OSAL_IRQ_EPILOGUE(); } #endif /* common parts for known platforms */ #if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */ +/* Use Low Power Timer (LPTMR) */ +# define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR +# define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF + /* LPTMR clock options */ # define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */ # define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ @@ -86,6 +74,18 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { # define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER # endif +/* interrupt handler */ +OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { + OSAL_IRQ_PROLOGUE(); + + sleep_led_timer_callback(); + + /* Reset the counter */ + RESET_COUNTER; + + OSAL_IRQ_EPILOGUE(); +} + /* Initialise the timer */ void sleep_led_init(void) { /* Make sure the clock to the LPTMR is enabled */ @@ -159,45 +159,23 @@ void sleep_led_toggle(void) { LPTMR0->CSR ^= LPTMRx_CSR_TEN; } -#elif defined(STM32F0XX) /* platform selection: STM32F0XX */ - -/* Initialise the timer */ -void sleep_led_init(void) { - /* enable clock */ - rccEnableTIM14(FALSE); /* low power enable = FALSE */ - rccResetTIM14(); - - /* prescale */ - /* Assuming 48MHz internal clock */ - /* getting cca 65484 irqs/sec */ - STM32_TIM14->PSC = 733; +#elif defined(SLEEP_LED_GPT_DRIVER) - /* auto-reload */ - /* 0 => interrupt every time */ - STM32_TIM14->ARR = 3; +static void gptTimerCallback(GPTDriver *gptp) { + (void)gptp; + sleep_led_timer_callback(); +} - /* enable counter update event interrupt */ - STM32_TIM14->DIER |= STM32_TIM_DIER_UIE; +static const GPTConfig gptcfg = {1000000, gptTimerCallback, 0, 0}; - /* register interrupt vector */ - nvicEnableVector(STM32_TIM14_NUMBER, 2); /* vector, priority */ -} +/* Initialise the timer */ +void sleep_led_init(void) { gptStart(&SLEEP_LED_GPT_DRIVER, &gptcfg); } -void sleep_led_enable(void) { - /* Enable the timer */ - STM32_TIM14->CR1 = STM32_TIM_CR1_CEN | STM32_TIM_CR1_URS; - /* URS => update event only on overflow; setting UG bit disabled */ -} +void sleep_led_enable(void) { gptStartContinuous(&SLEEP_LED_GPT_DRIVER, gptcfg.frequency / 0xFFFF); } -void sleep_led_disable(void) { - /* Disable the timer */ - STM32_TIM14->CR1 = 0; -} +void sleep_led_disable(void) { gptStopTimer(&SLEEP_LED_GPT_DRIVER); } -void sleep_led_toggle(void) { - /* Toggle the timer */ - STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN; -} +void sleep_led_toggle(void) { (SLEEP_LED_GPT_DRIVER.state == GPT_READY) ? sleep_led_enable() : sleep_led_disable(); } #else /* platform selection: not on familiar chips */ -- cgit v1.2.3 From 5ba4391cf29ce624f17593417212b3dbca1609ad Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 28 Feb 2021 15:52:58 +0000 Subject: Refactor of USB code within split_common (#11890) * Initial refactor of usb code within split_common * Add headers * Correct disable condition * Format * Align func name --- tmk_core/common/chibios/chibios_config.h | 2 ++ tmk_core/common/usb_util.c | 29 +++++++++++++++++++++++++++++ tmk_core/common/usb_util.h | 22 ++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 tmk_core/common/usb_util.c create mode 100644 tmk_core/common/usb_util.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index b4d96465d1..bebf026de7 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -15,6 +15,8 @@ */ #pragma once +#define SPLIT_USB_DETECT // Force this on for now + #if defined(STM32F1XX) # define USE_GPIOV1 #endif diff --git a/tmk_core/common/usb_util.c b/tmk_core/common/usb_util.c new file mode 100644 index 0000000000..e4c50fcb10 --- /dev/null +++ b/tmk_core/common/usb_util.c @@ -0,0 +1,29 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 "usb_util.h" +#include "wait.h" + +__attribute__((weak)) void usb_disable(void) {} +__attribute__((weak)) bool usb_connected_state(void) { return true; } +__attribute__((weak)) bool usb_vbus_state(void) { +#ifdef USB_VBUS_PIN + setPinInput(USB_VBUS_PIN); + wait_us(5); + return readPin(USB_VBUS_PIN); +#else + return true; +#endif +} diff --git a/tmk_core/common/usb_util.h b/tmk_core/common/usb_util.h new file mode 100644 index 0000000000..4ebedb1e71 --- /dev/null +++ b/tmk_core/common/usb_util.h @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include + +void usb_disable(void); +bool usb_connected_state(void); +bool usb_vbus_state(void); -- cgit v1.2.3 From 0e984b6e7e216a62df0b5d53f6a8f0d4bc13dca3 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Mon, 1 Mar 2021 08:57:02 -0800 Subject: Add ability to toggle One Shot functionality (#4198) Co-authored-by: Nick Brassel Co-authored-by: Ryan --- tmk_core/common/action_util.c | 58 ++++++++++++++++++++++++++++++++++++------- tmk_core/common/action_util.h | 5 ++++ 2 files changed, 54 insertions(+), 9 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c index 000503b082..a57c8bf66a 100644 --- a/tmk_core/common/action_util.c +++ b/tmk_core/common/action_util.c @@ -147,12 +147,16 @@ void clear_oneshot_swaphands(void) { * FIXME: needs doc */ void set_oneshot_layer(uint8_t layer, uint8_t state) { - oneshot_layer_data = layer << 3 | state; - layer_on(layer); + if (!keymap_config.oneshot_disable) { + oneshot_layer_data = layer << 3 | state; + layer_on(layer); # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_layer_time = timer_read(); + oneshot_layer_time = timer_read(); # endif - oneshot_layer_changed_kb(get_oneshot_layer()); + oneshot_layer_changed_kb(get_oneshot_layer()); + } else { + layer_on(layer); + } } /** \brief Reset oneshot layer * @@ -172,7 +176,7 @@ void reset_oneshot_layer(void) { void clear_oneshot_layer_state(oneshot_fullfillment_t state) { uint8_t start_state = oneshot_layer_data; oneshot_layer_data &= ~state; - if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) { + if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) { layer_off(get_oneshot_layer()); reset_oneshot_layer(); } @@ -182,6 +186,39 @@ void clear_oneshot_layer_state(oneshot_fullfillment_t state) { * FIXME: needs doc */ bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); } + +/** \brief set oneshot + * + * FIXME: needs doc + */ +void oneshot_set(bool active) { + if (keymap_config.oneshot_disable != active) { + keymap_config.oneshot_disable = active; + eeconfig_update_keymap(keymap_config.raw); + dprintf("Oneshot: active: %d\n", active); + } +} + +/** \brief toggle oneshot + * + * FIXME: needs doc + */ +void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); } + +/** \brief enable oneshot + * + * FIXME: needs doc + */ +void oneshot_enable(void) { oneshot_set(true); } + +/** \brief disable oneshot + * + * FIXME: needs doc + */ +void oneshot_disable(void) { oneshot_set(false); } + +bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; } + #endif /** \brief Send keyboard report @@ -321,14 +358,17 @@ void del_oneshot_mods(uint8_t mods) { * FIXME: needs doc */ void set_oneshot_mods(uint8_t mods) { - if (oneshot_mods != mods) { + if (!keymap_config.oneshot_disable) { + if (oneshot_mods != mods) { # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = timer_read(); + oneshot_time = timer_read(); # endif - oneshot_mods = mods; - oneshot_mods_changed_kb(mods); + oneshot_mods = mods; + oneshot_mods_changed_kb(mods); + } } } + /** \brief clear oneshot mods * * FIXME: needs doc diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h index ff29f79b09..f2b3897ae5 100644 --- a/tmk_core/common/action_util.h +++ b/tmk_core/common/action_util.h @@ -85,6 +85,11 @@ void oneshot_mods_changed_kb(uint8_t mods); void oneshot_layer_changed_user(uint8_t layer); void oneshot_layer_changed_kb(uint8_t layer); +void oneshot_toggle(void); +void oneshot_enable(void); +void oneshot_disable(void); +bool is_oneshot_enabled(void); + /* inspect */ uint8_t has_anymod(void); -- cgit v1.2.3 From cde2859a6591b1274da20978bd158f20229faa88 Mon Sep 17 00:00:00 2001 From: XScorpion2 Date: Tue, 2 Mar 2021 14:32:15 -0600 Subject: Split RGB Matrix (#11055) * Split RGB Matrix * Suspend State sync for rgb matrix --- tmk_core/common/avr/suspend.c | 4 ++++ tmk_core/common/chibios/suspend.c | 8 ++++++++ tmk_core/common/eeconfig.c | 2 +- tmk_core/common/eeconfig.h | 9 +++++---- 4 files changed, 18 insertions(+), 5 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 47a82a2eec..d52c8ac410 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -28,6 +28,10 @@ # include "rgblight.h" #endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif + /** \brief Suspend idle * * FIXME: needs doc diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 49e20641fb..17f024caba 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -24,6 +24,10 @@ # include "rgblight.h" #endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif + /** \brief suspend idle * * FIXME: needs doc @@ -53,6 +57,10 @@ void suspend_power_down(void) { backlight_set(0); #endif +#ifdef RGB_MATRIX_ENABLE + rgb_matrix_task(); +#endif + // Turn off LED indicators uint8_t leds_off = 0; #if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 5e3ebe6ee6..92a5092176 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -57,7 +57,7 @@ void eeconfig_init_quantum(void) { eeprom_update_dword(EECONFIG_HAPTIC, 0); eeprom_update_byte(EECONFIG_VELOCIKEY, 0); eeprom_update_dword(EECONFIG_RGB_MATRIX, 0); - eeprom_update_byte(EECONFIG_RGB_MATRIX_SPEED, 0); + eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0); // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS // within the emulated eeprom via dfu-util or another tool diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 86b9e6f99b..39bc51d5db 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -21,7 +21,7 @@ along with this program. If not, see . #include #ifndef EECONFIG_MAGIC_NUMBER -# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEB // When changing, decrement this value to avoid future re-init issues +# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA // When changing, decrement this value to avoid future re-init issues #endif #define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF @@ -44,11 +44,12 @@ along with this program. If not, see . #define EECONFIG_HAPTIC (uint32_t *)24 #define EECONFIG_RGB_MATRIX (uint32_t *)28 -#define EECONFIG_RGB_MATRIX_SPEED (uint8_t *)32 +// Speed & Flags +#define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32 // TODO: Combine these into a single word and single block of EEPROM -#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)33 +#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 // Size of EEPROM being used, other code can refer to this for available EEPROM -#define EECONFIG_SIZE 34 +#define EECONFIG_SIZE 35 /* debug bit */ #define EECONFIG_DEBUG_ENABLE (1 << 0) #define EECONFIG_DEBUG_MATRIX (1 << 1) -- cgit v1.2.3 From 9155b59e1a496b64f7aa576e6e4cb84fd0a9607b Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 8 Mar 2021 16:55:00 +1100 Subject: LED Matrix: decouple from Backlight (#12054) --- tmk_core/common/eeconfig.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 39bc51d5db..9e18fd4e15 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -43,9 +43,14 @@ along with this program. If not, see . #define EECONFIG_VELOCIKEY (uint8_t *)23 #define EECONFIG_HAPTIC (uint32_t *)24 + +// Mutually exclusive +#define EECONFIG_LED_MATRIX (uint32_t *)28 #define EECONFIG_RGB_MATRIX (uint32_t *)28 // Speed & Flags +#define EECONFIG_LED_MATRIX_EXTENDED (uint16_t *)32 #define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32 + // TODO: Combine these into a single word and single block of EEPROM #define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 // Size of EEPROM being used, other code can refer to this for available EEPROM -- cgit v1.2.3 From 40c7ecfdeaf50ab76e10854a84aebfcb82ddb092 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Wed, 10 Mar 2021 22:47:36 +0000 Subject: Move gpio wait logic to wait.h (#12067) --- tmk_core/common/arm_atsam/_wait.h | 22 ++++++ tmk_core/common/avr/_wait.h | 29 +++++++ tmk_core/common/chibios/_wait.h | 55 ++++++++++++++ tmk_core/common/chibios/chibios_config.h | 1 + tmk_core/common/chibios/wait.c | 89 ++++++++++++++++++++++ tmk_core/common/test/_wait.h | 22 ++++++ tmk_core/common/wait.h | 125 +++++-------------------------- 7 files changed, 235 insertions(+), 108 deletions(-) create mode 100644 tmk_core/common/arm_atsam/_wait.h create mode 100644 tmk_core/common/avr/_wait.h create mode 100644 tmk_core/common/chibios/_wait.h create mode 100644 tmk_core/common/chibios/wait.c create mode 100644 tmk_core/common/test/_wait.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/arm_atsam/_wait.h b/tmk_core/common/arm_atsam/_wait.h new file mode 100644 index 0000000000..41b686b56c --- /dev/null +++ b/tmk_core/common/arm_atsam/_wait.h @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include "clks.h" + +#define wait_ms(ms) CLK_delay_ms(ms) +#define wait_us(us) CLK_delay_us(us) +#define waitInputPinDelay() diff --git a/tmk_core/common/avr/_wait.h b/tmk_core/common/avr/_wait.h new file mode 100644 index 0000000000..56eb316faf --- /dev/null +++ b/tmk_core/common/avr/_wait.h @@ -0,0 +1,29 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include + +#define wait_ms(ms) _delay_ms(ms) +#define wait_us(us) _delay_us(us) + +/* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. + * But here's more margin to make it two clocks. */ +#ifndef GPIO_INPUT_PIN_DELAY +# define GPIO_INPUT_PIN_DELAY 2 +#endif + +#define waitInputPinDelay() __builtin_avr_delay_cycles(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h new file mode 100644 index 0000000000..5bface53e1 --- /dev/null +++ b/tmk_core/common/chibios/_wait.h @@ -0,0 +1,55 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include + +/* chThdSleepX of zero maps to infinite - so we map to a tiny delay to still yield */ +#define wait_ms(ms) \ + do { \ + if (ms != 0) { \ + chThdSleepMilliseconds(ms); \ + } else { \ + chThdSleepMicroseconds(1); \ + } \ + } while (0) +#define wait_us(us) \ + do { \ + if (us != 0) { \ + chThdSleepMicroseconds(us); \ + } else { \ + chThdSleepMicroseconds(1); \ + } \ + } while (0) + +/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus + * to which the GPIO is connected. + * The connected buses differ depending on the various series of MCUs. + * And since the instruction execution clock of the CPU and the bus clock of GPIO are different, + * there is a delay of several clocks to read the change of the input signal. + * + * Define this delay with the GPIO_INPUT_PIN_DELAY macro. + * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. + * (A fairly large value of 0.25 microseconds is set.) + */ + +#include "wait.c" + +#ifndef GPIO_INPUT_PIN_DELAY +# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) +#endif + +#define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index bebf026de7..9a66ac3174 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -30,4 +30,5 @@ # define USE_I2CV1 # define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed # define USE_GPIOV1 +# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY #endif diff --git a/tmk_core/common/chibios/wait.c b/tmk_core/common/chibios/wait.c new file mode 100644 index 0000000000..c6270fd95e --- /dev/null +++ b/tmk_core/common/chibios/wait.c @@ -0,0 +1,89 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ + +#ifndef __OPTIMIZE__ +# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" +#endif + +#define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" + +__attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ + /* The argument n must be a constant expression. + * That way, compiler optimization will remove unnecessary code. */ + if (n < 1) { + return; + } + if (n > 8) { + unsigned int n8 = n / 8; + n = n - n8 * 8; + switch (n8) { + case 16: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 15: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 14: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 13: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 12: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 11: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 10: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 9: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 8: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 7: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 6: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 5: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 4: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 3: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 2: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 1: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 0: + break; + } + } + switch (n) { + case 8: + asm volatile("nop" ::: "memory"); + case 7: + asm volatile("nop" ::: "memory"); + case 6: + asm volatile("nop" ::: "memory"); + case 5: + asm volatile("nop" ::: "memory"); + case 4: + asm volatile("nop" ::: "memory"); + case 3: + asm volatile("nop" ::: "memory"); + case 2: + asm volatile("nop" ::: "memory"); + case 1: + asm volatile("nop" ::: "memory"); + case 0: + break; + } +} \ No newline at end of file diff --git a/tmk_core/common/test/_wait.h b/tmk_core/common/test/_wait.h new file mode 100644 index 0000000000..4e22f593b7 --- /dev/null +++ b/tmk_core/common/test/_wait.h @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include + +void wait_ms(uint32_t ms); +#define wait_us(us) wait_ms(us / 1000) +#define waitInputPinDelay() diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h index 28224fe3aa..cf7180fb07 100644 --- a/tmk_core/common/wait.h +++ b/tmk_core/common/wait.h @@ -1,3 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ #pragma once #include @@ -6,114 +21,8 @@ extern "C" { #endif -#if defined(__ARMEL__) || defined(__ARMEB__) -# ifndef __OPTIMIZE__ -# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" -# endif - -# define wait_cpuclock(x) wait_cpuclock_allnop(x) - -# define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" - -__attribute__((always_inline)) static inline void wait_cpuclock_allnop(unsigned int n) { /* n: 1..135 */ - /* The argument n must be a constant expression. - * That way, compiler optimization will remove unnecessary code. */ - if (n < 1) { - return; - } - if (n > 8) { - unsigned int n8 = n / 8; - n = n - n8 * 8; - switch (n8) { - case 16: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 15: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 14: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 13: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 12: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 11: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 10: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 9: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 8: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 7: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 6: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 5: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 4: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 3: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 2: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 1: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 0: - break; - } - } - switch (n) { - case 8: - asm volatile("nop" ::: "memory"); - case 7: - asm volatile("nop" ::: "memory"); - case 6: - asm volatile("nop" ::: "memory"); - case 5: - asm volatile("nop" ::: "memory"); - case 4: - asm volatile("nop" ::: "memory"); - case 3: - asm volatile("nop" ::: "memory"); - case 2: - asm volatile("nop" ::: "memory"); - case 1: - asm volatile("nop" ::: "memory"); - case 0: - break; - } -} -#endif - -#if defined(__AVR__) -# include -# define wait_ms(ms) _delay_ms(ms) -# define wait_us(us) _delay_us(us) -# define wait_cpuclock(x) __builtin_avr_delay_cycles(x) -#elif defined PROTOCOL_CHIBIOS -# include -# define wait_ms(ms) \ - do { \ - if (ms != 0) { \ - chThdSleepMilliseconds(ms); \ - } else { \ - chThdSleepMicroseconds(1); \ - } \ - } while (0) -# define wait_us(us) \ - do { \ - if (us != 0) { \ - chThdSleepMicroseconds(us); \ - } else { \ - chThdSleepMicroseconds(1); \ - } \ - } while (0) -#elif defined PROTOCOL_ARM_ATSAM -# include "clks.h" -# define wait_ms(ms) CLK_delay_ms(ms) -# define wait_us(us) CLK_delay_us(us) -#else // Unit tests -void wait_ms(uint32_t ms); -# define wait_us(us) wait_ms(us / 1000) +#if __has_include_next("_wait.h") +# include_next "_wait.h" /* Include the platforms _wait.h */ #endif #ifdef __cplusplus -- cgit v1.2.3 From 1d341ffbb0dfbf45139c103123549c3c0fec816e Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 16 Mar 2021 20:45:21 +0100 Subject: core: add support for MK66F18 (Teensy 3.6) micro controller (#12258) This is in preparation for https://github.com/qmk/qmk_firmware/pull/10171 --- tmk_core/common/chibios/bootloader.c | 2 +- tmk_core/common/chibios/chibios_config.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 6cabcc4b81..4a175a6283 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -79,7 +79,7 @@ void enter_bootloader_mode_if_requested(void) { } } -#elif defined(KL2x) || defined(K20x) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS +#elif defined(KL2x) || defined(K20x) || defined(MK66F18) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS /* Kinetis */ # if defined(BOOTLOADER_KIIBOHD) diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index 9a66ac3174..1d8ace4955 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -32,3 +32,7 @@ # define USE_GPIOV1 # define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY #endif + +#if defined(MK66F18) +# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY +#endif -- cgit v1.2.3 From 2ae38e9c43cc689be65f04ea5c101b9f46a38c5e Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 28 Mar 2021 17:59:44 +1100 Subject: LED Matrix: Config functions (#12361) --- tmk_core/common/keyboard.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 65d9e00c7a..e473806b21 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -49,6 +49,9 @@ along with this program. If not, see . #ifdef RGBLIGHT_ENABLE # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif #ifdef RGB_MATRIX_ENABLE # include "rgb_matrix.h" #endif @@ -412,6 +415,9 @@ MATRIX_LOOP_END: rgblight_task(); #endif +#ifdef LED_MATRIX_ENABLE + led_matrix_task(); +#endif #ifdef RGB_MATRIX_ENABLE rgb_matrix_task(); #endif -- cgit v1.2.3 From e95a4f4f52f7792927c480e76dba11c5a8cbd07e Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 30 Mar 2021 12:11:40 +0200 Subject: core: add pin_defs for MK66F18 (#12419) This is in preparation for https://github.com/qmk/qmk_firmware/pull/10171 --- tmk_core/common/chibios/pin_defs.h | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/pin_defs.h b/tmk_core/common/chibios/pin_defs.h index 86bc1076e8..c03f8de0c2 100644 --- a/tmk_core/common/chibios/pin_defs.h +++ b/tmk_core/common/chibios/pin_defs.h @@ -70,6 +70,23 @@ # define A13 PAL_LINE(GPIOA, 13) # define A14 PAL_LINE(GPIOA, 14) # define A15 PAL_LINE(GPIOA, 15) +# define A16 PAL_LINE(GPIOA, 16) +# define A17 PAL_LINE(GPIOA, 17) +# define A18 PAL_LINE(GPIOA, 18) +# define A19 PAL_LINE(GPIOA, 19) +# define A20 PAL_LINE(GPIOA, 20) +# define A21 PAL_LINE(GPIOA, 21) +# define A22 PAL_LINE(GPIOA, 22) +# define A23 PAL_LINE(GPIOA, 23) +# define A24 PAL_LINE(GPIOA, 24) +# define A25 PAL_LINE(GPIOA, 25) +# define A26 PAL_LINE(GPIOA, 26) +# define A27 PAL_LINE(GPIOA, 27) +# define A28 PAL_LINE(GPIOA, 28) +# define A29 PAL_LINE(GPIOA, 29) +# define A30 PAL_LINE(GPIOA, 30) +# define A31 PAL_LINE(GPIOA, 31) +# define A32 PAL_LINE(GPIOA, 32) # define B0 PAL_LINE(GPIOB, 0) # define B1 PAL_LINE(GPIOB, 1) # define B2 PAL_LINE(GPIOB, 2) @@ -90,6 +107,19 @@ # define B17 PAL_LINE(GPIOB, 17) # define B18 PAL_LINE(GPIOB, 18) # define B19 PAL_LINE(GPIOB, 19) +# define B20 PAL_LINE(GPIOB, 20) +# define B21 PAL_LINE(GPIOB, 21) +# define B22 PAL_LINE(GPIOB, 22) +# define B23 PAL_LINE(GPIOB, 23) +# define B24 PAL_LINE(GPIOB, 24) +# define B25 PAL_LINE(GPIOB, 25) +# define B26 PAL_LINE(GPIOB, 26) +# define B27 PAL_LINE(GPIOB, 27) +# define B28 PAL_LINE(GPIOB, 28) +# define B29 PAL_LINE(GPIOB, 29) +# define B30 PAL_LINE(GPIOB, 30) +# define B31 PAL_LINE(GPIOB, 31) +# define B32 PAL_LINE(GPIOB, 32) # define C0 PAL_LINE(GPIOC, 0) # define C1 PAL_LINE(GPIOC, 1) # define C2 PAL_LINE(GPIOC, 2) @@ -106,6 +136,23 @@ # define C13 PAL_LINE(GPIOC, 13) # define C14 PAL_LINE(GPIOC, 14) # define C15 PAL_LINE(GPIOC, 15) +# define C16 PAL_LINE(GPIOC, 16) +# define C17 PAL_LINE(GPIOC, 17) +# define C18 PAL_LINE(GPIOC, 18) +# define C19 PAL_LINE(GPIOC, 19) +# define C20 PAL_LINE(GPIOC, 20) +# define C21 PAL_LINE(GPIOC, 21) +# define C22 PAL_LINE(GPIOC, 22) +# define C23 PAL_LINE(GPIOC, 23) +# define C24 PAL_LINE(GPIOC, 24) +# define C25 PAL_LINE(GPIOC, 25) +# define C26 PAL_LINE(GPIOC, 26) +# define C27 PAL_LINE(GPIOC, 27) +# define C28 PAL_LINE(GPIOC, 28) +# define C29 PAL_LINE(GPIOC, 29) +# define C30 PAL_LINE(GPIOC, 30) +# define C31 PAL_LINE(GPIOC, 31) +# define C32 PAL_LINE(GPIOC, 32) # define D0 PAL_LINE(GPIOD, 0) # define D1 PAL_LINE(GPIOD, 1) # define D2 PAL_LINE(GPIOD, 2) @@ -122,6 +169,23 @@ # define D13 PAL_LINE(GPIOD, 13) # define D14 PAL_LINE(GPIOD, 14) # define D15 PAL_LINE(GPIOD, 15) +# define D16 PAL_LINE(GPIOD, 16) +# define D17 PAL_LINE(GPIOD, 17) +# define D18 PAL_LINE(GPIOD, 18) +# define D19 PAL_LINE(GPIOD, 19) +# define D20 PAL_LINE(GPIOD, 20) +# define D21 PAL_LINE(GPIOD, 21) +# define D22 PAL_LINE(GPIOD, 22) +# define D23 PAL_LINE(GPIOD, 23) +# define D24 PAL_LINE(GPIOD, 24) +# define D25 PAL_LINE(GPIOD, 25) +# define D26 PAL_LINE(GPIOD, 26) +# define D27 PAL_LINE(GPIOD, 27) +# define D28 PAL_LINE(GPIOD, 28) +# define D29 PAL_LINE(GPIOD, 29) +# define D30 PAL_LINE(GPIOD, 30) +# define D31 PAL_LINE(GPIOD, 31) +# define D32 PAL_LINE(GPIOD, 32) # define E0 PAL_LINE(GPIOE, 0) # define E1 PAL_LINE(GPIOE, 1) # define E2 PAL_LINE(GPIOE, 2) @@ -138,6 +202,23 @@ # define E13 PAL_LINE(GPIOE, 13) # define E14 PAL_LINE(GPIOE, 14) # define E15 PAL_LINE(GPIOE, 15) +# define E16 PAL_LINE(GPIOE, 16) +# define E17 PAL_LINE(GPIOE, 17) +# define E18 PAL_LINE(GPIOE, 18) +# define E19 PAL_LINE(GPIOE, 19) +# define E20 PAL_LINE(GPIOE, 20) +# define E21 PAL_LINE(GPIOE, 21) +# define E22 PAL_LINE(GPIOE, 22) +# define E23 PAL_LINE(GPIOE, 23) +# define E24 PAL_LINE(GPIOE, 24) +# define E25 PAL_LINE(GPIOE, 25) +# define E26 PAL_LINE(GPIOE, 26) +# define E27 PAL_LINE(GPIOE, 27) +# define E28 PAL_LINE(GPIOE, 28) +# define E29 PAL_LINE(GPIOE, 29) +# define E30 PAL_LINE(GPIOE, 30) +# define E31 PAL_LINE(GPIOE, 31) +# define E32 PAL_LINE(GPIOE, 32) # define F0 PAL_LINE(GPIOF, 0) # define F1 PAL_LINE(GPIOF, 1) # define F2 PAL_LINE(GPIOF, 2) -- cgit v1.2.3 From ce99f98bb5217ede628cfbf7e20924346b4279da Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 13 Apr 2021 19:51:03 +1000 Subject: LED Matrix: suspend code (#12509) --- tmk_core/common/avr/suspend.c | 3 +++ tmk_core/common/chibios/suspend.c | 6 ++++++ tmk_core/common/keyboard.c | 3 +++ 3 files changed, 12 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index d52c8ac410..96b19a77fd 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -28,6 +28,9 @@ # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif #ifdef RGB_MATRIX_ENABLE # include "rgb_matrix.h" #endif diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 17f024caba..b3949185e9 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -24,6 +24,9 @@ # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif #ifdef RGB_MATRIX_ENABLE # include "rgb_matrix.h" #endif @@ -57,6 +60,9 @@ void suspend_power_down(void) { backlight_set(0); #endif +#ifdef LED_MATRIX_ENABLE + led_matrix_task(); +#endif #ifdef RGB_MATRIX_ENABLE rgb_matrix_task(); #endif diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index e473806b21..132affe7a8 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -330,6 +330,9 @@ void keyboard_init(void) { * This is differnet than keycode events as no layer processing, or filtering occurs. */ void switch_events(uint8_t row, uint8_t col, bool pressed) { +#if defined(LED_MATRIX_ENABLE) + process_led_matrix(row, col, pressed); +#endif #if defined(RGB_MATRIX_ENABLE) process_rgb_matrix(row, col, pressed); #endif -- cgit v1.2.3 From 891d18d3565090abd5f218a8787acc3e25349b73 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Sun, 25 Apr 2021 13:40:56 +1000 Subject: Add initial support for tinyuf2 bootloader (when hosted on F411 blackpill) (#12600) * Add support for jumping to tinyuf2 bootloader. Adds blackpill UF2 example. * Update flashing.md * Update chconf.h * Update config.h * Update halconf.h * Update mcuconf.h --- tmk_core/common/chibios/bootloader.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 4a175a6283..f91ac7d9eb 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -13,7 +13,22 @@ # define STM32_BOOTLOADER_DUAL_BANK FALSE #endif -#if STM32_BOOTLOADER_DUAL_BANK +#ifdef BOOTLOADER_TINYUF2 + +# define DBL_TAP_MAGIC 0xf01669ef // From tinyuf2's board_api.h + +// defined by linker script +extern uint32_t _board_dfu_dbl_tap[]; +# define DBL_TAP_REG _board_dfu_dbl_tap[0] + +void bootloader_jump(void) { + DBL_TAP_REG = DBL_TAP_MAGIC; + NVIC_SystemReset(); +} + +void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */ } + +#elif STM32_BOOTLOADER_DUAL_BANK // Need pin definitions # include "config_common.h" -- cgit v1.2.3 From 412e7a03e49d044a2dea0fb38b05fb24c8d6eabe Mon Sep 17 00:00:00 2001 From: Purdea Andrei Date: Sun, 25 Apr 2021 11:57:49 +0300 Subject: eeprom driver: Refactor where eeprom driver initialisation (and EEPROM emulation initialisation) occurs to make it non-target-specific. (#12671) --- tmk_core/common/keyboard.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 132affe7a8..24baf41c00 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -94,6 +94,12 @@ along with this program. If not, see . #ifdef DIP_SWITCH_ENABLE # include "dip_switch.h" #endif +#ifdef STM32_EEPROM_ENABLE +# include "eeprom_stm32.h" +#endif +#ifdef EEPROM_DRIVER +# include "eeprom_driver.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { return last_input_modification_time; } @@ -231,6 +237,12 @@ void keyboard_setup(void) { disable_jtag(); #endif print_set_sendchar(sendchar); +#ifdef STM32_EEPROM_ENABLE + EEPROM_Init(); +#endif +#ifdef EEPROM_DRIVER + eeprom_driver_init(); +#endif matrix_setup(); keyboard_pre_init_kb(); } -- cgit v1.2.3 From 8c12fa2e59583b22969aea2c6eeab054a23ea064 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 25 Apr 2021 19:00:22 +1000 Subject: Format code according to conventions (#12682) Co-authored-by: QMK Bot --- tmk_core/common/chibios/bootloader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index f91ac7d9eb..11f7abf432 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -26,7 +26,8 @@ void bootloader_jump(void) { NVIC_SystemReset(); } -void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */ } +void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */ +} #elif STM32_BOOTLOADER_DUAL_BANK -- cgit v1.2.3 From d8167779cdfb243cb140782210d2cc6a7cb9b123 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Wed, 28 Apr 2021 19:39:54 -0700 Subject: Change RGB/LED Matrix to use a simple define for USB suspend (#12697) --- tmk_core/common/avr/suspend.c | 7 +++++++ tmk_core/common/chibios/suspend.c | 6 ++++++ 2 files changed, 13 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 96b19a77fd..1c2bf9cb46 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -163,6 +163,10 @@ void suspend_power_down(void) { rgblight_suspend(); # endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(true); +# endif + // Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt) # if defined(WDT_vect) power_down(WDTO_15MS); @@ -214,6 +218,9 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(false); +# endif suspend_wakeup_init_kb(); } diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index b3949185e9..1f4f93c455 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -83,6 +83,9 @@ void suspend_power_down(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_suspend(); #endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(true); +# endif #ifdef AUDIO_ENABLE stop_all_notes(); #endif /* AUDIO_ENABLE */ @@ -151,5 +154,8 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(false); +# endif suspend_wakeup_init_kb(); } -- cgit v1.2.3 From 39bc8163d013b5c7e148b7e95b3883dc0adb95ba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 29 Apr 2021 13:36:47 +1000 Subject: [CI] Format code according to conventions (#12731) Co-authored-by: QMK Bot --- tmk_core/common/avr/suspend.c | 4 ++-- tmk_core/common/chibios/suspend.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 1c2bf9cb46..e9ee0aefdd 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -218,9 +218,9 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif -# if defined(RGB_MATRIX_ENABLE) +#if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); -# endif +#endif suspend_wakeup_init_kb(); } diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 1f4f93c455..14a9aecb31 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -83,9 +83,9 @@ void suspend_power_down(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_suspend(); #endif -# if defined(RGB_MATRIX_ENABLE) +#if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(true); -# endif +#endif #ifdef AUDIO_ENABLE stop_all_notes(); #endif /* AUDIO_ENABLE */ @@ -154,8 +154,8 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif -# if defined(RGB_MATRIX_ENABLE) +#if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); -# endif +#endif suspend_wakeup_init_kb(); } -- cgit v1.2.3 From f0b30e0027cb890c7510fa22e5824a43c0d9e86f Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sun, 9 May 2021 23:21:09 -0700 Subject: Make Swap Hands use PROGMEM (#12284) This converts the array that the Swap Hands feature uses to use PROGMEM, and to read from that array, as such. Since this array never changes at runtime, there is no reason to keep it in memory. Especially for AVR boards, as memory is a precious resource. --- tmk_core/common/action.c | 3 ++- tmk_core/common/action.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index aae5cbfa5f..f41665b06c 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -133,7 +133,8 @@ void process_hand_swap(keyevent_t *event) { bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit); if (do_swap) { - event->key = hand_swap_config[pos.row][pos.col]; + event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); + event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); swap_state[pos.row] |= col_bit; } else { swap_state[pos.row] &= ~(col_bit); diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 9a991de1c2..6c84561785 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -78,7 +78,7 @@ extern bool disable_action_cache; /* Code for handling one-handed key modifiers. */ #ifdef SWAP_HANDS_ENABLE extern bool swap_hands; -extern const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; +extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; # if (MATRIX_COLS <= 8) typedef uint8_t swap_state_row_t; # elif (MATRIX_COLS <= 16) -- cgit v1.2.3 From da0c551692b117e4f91ca3e446155027290e3c96 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Wed, 12 May 2021 18:24:44 -0700 Subject: Add missing LED Matrix suspend code to suspend.c (#12878) Co-authored-by: Ryan --- tmk_core/common/avr/suspend.c | 7 +++++++ tmk_core/common/chibios/suspend.c | 8 ++++++++ 2 files changed, 15 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index e9ee0aefdd..690d7f38ca 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -163,6 +163,9 @@ void suspend_power_down(void) { rgblight_suspend(); # endif +# if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(true); +# endif # if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(true); # endif @@ -218,6 +221,10 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif + +#if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(false); +#endif #if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); #endif diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 14a9aecb31..38517e06f0 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -83,6 +83,10 @@ void suspend_power_down(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_suspend(); #endif + +#if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(true); +#endif #if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(true); #endif @@ -154,6 +158,10 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif + +#if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(false); +#endif #if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); #endif -- cgit v1.2.3 From 58142f0726147d538167ff3ab793743348f40dcd Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Tue, 18 May 2021 17:02:28 +1000 Subject: Fixup housekeeping from being invoked twice per loop. (#12933) --- tmk_core/common/keyboard.c | 12 +++++++++--- tmk_core/common/keyboard.h | 5 +++-- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 24baf41c00..3d6092e71c 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -280,6 +280,15 @@ __attribute__((weak)) void housekeeping_task_kb(void) {} */ __attribute__((weak)) void housekeeping_task_user(void) {} +/** \brief housekeeping_task + * + * Invokes hooks for executing code after QMK is done after each loop iteration. + */ +void housekeeping_task(void) { + housekeeping_task_kb(); + housekeeping_task_user(); +} + /** \brief keyboard_init * * FIXME: needs doc @@ -374,9 +383,6 @@ void keyboard_task(void) { bool encoders_changed = false; #endif - housekeeping_task_kb(); - housekeeping_task_user(); - uint8_t matrix_changed = matrix_scan(); if (matrix_changed) last_matrix_activity_trigger(); diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index eaf74bac58..779973f1d6 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -70,8 +70,9 @@ void keyboard_pre_init_user(void); void keyboard_post_init_kb(void); void keyboard_post_init_user(void); -void housekeeping_task_kb(void); -void housekeeping_task_user(void); +void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol +void housekeeping_task_kb(void); // To be overridden by keyboard-level code +void housekeeping_task_user(void); // To be overridden by user/keymap-level code uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity -- cgit v1.2.3 From 06aea834c420d5c11bbcf64d37596cb0cee9af98 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 27 May 2021 15:21:15 +1000 Subject: Backlight: add defines for default level and breathing state (#12560) --- tmk_core/common/eeconfig.c | 11 ----------- tmk_core/common/eeconfig.h | 5 ----- 2 files changed, 16 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 92a5092176..ffa56ab56d 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -155,17 +155,6 @@ void eeconfig_update_keymap(uint16_t val) { eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, (val >> 8) & 0xFF); } -/** \brief eeconfig read backlight - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } -/** \brief eeconfig update backlight - * - * FIXME: needs doc - */ -void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); } - /** \brief eeconfig read audio * * FIXME: needs doc diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 9e18fd4e15..a88071729d 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -94,11 +94,6 @@ void eeconfig_update_default_layer(uint8_t val); uint16_t eeconfig_read_keymap(void); void eeconfig_update_keymap(uint16_t val); -#ifdef BACKLIGHT_ENABLE -uint8_t eeconfig_read_backlight(void); -void eeconfig_update_backlight(uint8_t val); -#endif - #ifdef AUDIO_ENABLE uint8_t eeconfig_read_audio(void); void eeconfig_update_audio(uint8_t val); -- cgit v1.2.3 From 7d1194de01ea94f065bd5176607b4d66279ef51b Mon Sep 17 00:00:00 2001 From: James Young <18669334+noroadsleft@users.noreply.github.com> Date: Sat, 29 May 2021 13:53:10 -0700 Subject: run: qmk cformat --core-only --- tmk_core/common/action.c | 83 +++++++++++++++++-------------------- tmk_core/common/action.h | 2 +- tmk_core/common/chibios/sleep_led.c | 4 +- tmk_core/common/keyboard.h | 6 +-- 4 files changed, 44 insertions(+), 51 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index f41665b06c..bd41d28b66 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -773,10 +773,9 @@ void register_code(uint8_t code) { } #endif - else if - IS_KEY(code) { - // TODO: should push command_proc out of this block? - if (command_proc(code)) return; + else if IS_KEY (code) { + // TODO: should push command_proc out of this block? + if (command_proc(code)) return; #ifndef NO_ACTION_ONESHOT /* TODO: remove @@ -793,35 +792,33 @@ void register_code(uint8_t code) { } else */ #endif - { - // Force a new key press if the key is already pressed - // without this, keys with the same keycode, but different - // modifiers will be reported incorrectly, see issue #1708 - if (is_key_pressed(keyboard_report, code)) { - del_key(code); - send_keyboard_report(); - } - add_key(code); + { + // Force a new key press if the key is already pressed + // without this, keys with the same keycode, but different + // modifiers will be reported incorrectly, see issue #1708 + if (is_key_pressed(keyboard_report, code)) { + del_key(code); send_keyboard_report(); } - } - else if - IS_MOD(code) { - add_mods(MOD_BIT(code)); + add_key(code); send_keyboard_report(); } + } else if IS_MOD (code) { + add_mods(MOD_BIT(code)); + send_keyboard_report(); + } #ifdef EXTRAKEY_ENABLE - else if - IS_SYSTEM(code) { host_system_send(KEYCODE2SYSTEM(code)); } - else if - IS_CONSUMER(code) { host_consumer_send(KEYCODE2CONSUMER(code)); } + else if IS_SYSTEM (code) { + host_system_send(KEYCODE2SYSTEM(code)); + } else if IS_CONSUMER (code) { + host_consumer_send(KEYCODE2CONSUMER(code)); + } #endif #ifdef MOUSEKEY_ENABLE - else if - IS_MOUSEKEY(code) { - mousekey_on(code); - mousekey_send(); - } + else if IS_MOUSEKEY (code) { + mousekey_on(code); + mousekey_send(); + } #endif } @@ -866,26 +863,22 @@ void unregister_code(uint8_t code) { } #endif - else if - IS_KEY(code) { - del_key(code); - send_keyboard_report(); - } - else if - IS_MOD(code) { - del_mods(MOD_BIT(code)); - send_keyboard_report(); - } - else if - IS_SYSTEM(code) { host_system_send(0); } - else if - IS_CONSUMER(code) { host_consumer_send(0); } + else if IS_KEY (code) { + del_key(code); + send_keyboard_report(); + } else if IS_MOD (code) { + del_mods(MOD_BIT(code)); + send_keyboard_report(); + } else if IS_SYSTEM (code) { + host_system_send(0); + } else if IS_CONSUMER (code) { + host_consumer_send(0); + } #ifdef MOUSEKEY_ENABLE - else if - IS_MOUSEKEY(code) { - mousekey_off(code); - mousekey_send(); - } + else if IS_MOUSEKEY (code) { + mousekey_off(code); + mousekey_send(); + } #endif } diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 6c84561785..8cb4722c6e 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -77,7 +77,7 @@ extern bool disable_action_cache; /* Code for handling one-handed key modifiers. */ #ifdef SWAP_HANDS_ENABLE -extern bool swap_hands; +extern bool swap_hands; extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; # if (MATRIX_COLS <= 8) typedef uint8_t swap_state_row_t; diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c index 477056a454..1c65016a42 100644 --- a/tmk_core/common/chibios/sleep_led.c +++ b/tmk_core/common/chibios/sleep_led.c @@ -65,7 +65,7 @@ void sleep_led_timer_callback(void) { /* LPTMR clock options */ # define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */ -# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ +# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ # define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */ # define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */ @@ -121,7 +121,7 @@ void sleep_led_init(void) { MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock # if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others MCG->MC |= MCG_MC_LIRC_DIV2_DIV2; -# endif /* KL27 */ +# endif /* KL27 */ MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock // to work in stop mode, also MCG_C1_IREFSTEN // Divide 4MHz by 2^N (N=6) => 62500 irqs/sec => diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index 779973f1d6..08f4e84f94 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -70,9 +70,9 @@ void keyboard_pre_init_user(void); void keyboard_post_init_kb(void); void keyboard_post_init_user(void); -void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol -void housekeeping_task_kb(void); // To be overridden by keyboard-level code -void housekeeping_task_user(void); // To be overridden by user/keymap-level code +void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol +void housekeeping_task_kb(void); // To be overridden by keyboard-level code +void housekeeping_task_user(void); // To be overridden by user/keymap-level code uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity -- cgit v1.2.3 From b72f10c6357eee628ab1f3762f66ba8a0a279a4e Mon Sep 17 00:00:00 2001 From: Takeshi ISHII <2170248+mtei@users.noreply.github.com> Date: Mon, 7 Jun 2021 18:23:21 +0900 Subject: Add readPort() and some API to 'tmk_core/common/*/gpio.h' (#12754) * add readPort() and some API to 'tmk_core/common/*/gpio.h' The following macros have been added to gpio.h. * readPort(port) * setPortBitInput(port, bit) * setPortBitInputHigh(port, bit) * setPortBitOutput(port, bit) * writePortBitLow(port, bit) * writePortBitHigh(port, bit) * add data type 'port_data_t' into gpio.h * rename qmk_pin to pin --- tmk_core/common/avr/gpio.h | 15 +++++++++++++++ tmk_core/common/chibios/gpio.h | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/avr/gpio.h b/tmk_core/common/avr/gpio.h index 231556c29c..e9be68491d 100644 --- a/tmk_core/common/avr/gpio.h +++ b/tmk_core/common/avr/gpio.h @@ -20,6 +20,8 @@ typedef uint8_t pin_t; +/* Operation of GPIO by pin. */ + #define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) #define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) #define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low") @@ -32,3 +34,16 @@ typedef uint8_t pin_t; #define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) #define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF)) + +/* Operation of GPIO by port. */ + +typedef uint8_t port_data_t; + +#define readPort(port) PINx_ADDRESS(port) + +#define setPortBitInput(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) &= ~_BV((bit)&0xF)) +#define setPortBitInputHigh(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) |= _BV((bit)&0xF)) +#define setPortBitOutput(port, bit) (DDRx_ADDRESS(port) |= _BV((bit)&0xF)) + +#define writePortBitLow(port, bit) (PORTx_ADDRESS(port) &= ~_BV((bit)&0xF)) +#define writePortBitHigh(port, bit) (PORTx_ADDRESS(port) |= _BV((bit)&0xF)) diff --git a/tmk_core/common/chibios/gpio.h b/tmk_core/common/chibios/gpio.h index 5d0e142abc..4d057f1cab 100644 --- a/tmk_core/common/chibios/gpio.h +++ b/tmk_core/common/chibios/gpio.h @@ -20,6 +20,8 @@ typedef ioline_t pin_t; +/* Operation of GPIO by pin. */ + #define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT) #define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP) #define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN) @@ -32,3 +34,17 @@ typedef ioline_t pin_t; #define readPin(pin) palReadLine(pin) #define togglePin(pin) palToggleLine(pin) + +/* Operation of GPIO by port. */ + +typedef uint16_t port_data_t; + +#define readPort(pin) palReadPort(PAL_PORT(pin)) + +#define setPortBitInput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT) +#define setPortBitInputHigh(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLUP) +#define setPortBitInputLow(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLDOWN) +#define setPortBitOutput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_OUTPUT_PUSHPULL) + +#define writePortBitLow(pin, bit) palClearLine(PAL_LINE(PAL_PORT(pin), bit)) +#define writePortBitHigh(pin, bit) palSetLine(PAL_LINE(PAL_PORT(pin), bit)) -- cgit v1.2.3 From b829a1d2648abd0751e9d3505554547faf643425 Mon Sep 17 00:00:00 2001 From: Simon Arlott <70171+nomis@users.noreply.github.com> Date: Wed, 9 Jun 2021 08:23:21 +0100 Subject: Avoid 8-bit timer overflows in debounce algorithms (#12240) * Add fast_timer_t that is 16-bit or 32-bit based on architecture A 16-bit timer will overflow sooner but be faster to compare on AVR. * Avoid 8-bit timer overflows in debounce algorithms Count down remaining elapsed time instead of trying to do 8-bit timer comparisons. Add a "none" implementation that is automatically used if DEBOUNCE is 0 otherwise it will break the _pk/_pr count down. * Avoid unnecessary polling of the entire matrix in sym_eager_pk The matrix only needs to be updated when a debounce timer expires. * Avoid unnecessary polling of the entire matrix in sym_eager_pr The matrix only needs to be updated when a debounce timer expires. The use of the "needed_update" variable is trying to do what "matrix_need_update" was added to fix but didn't work because it only applied when all keys finished debouncing. * Fix sym_defer_g timing inconsistency compared to other debounce algorithms DEBOUNCE=5 should process the key after 5ms, not 6ms * Add debounce tests --- tmk_core/common/arm_atsam/_timer.h | 19 +++++++++++++++++++ tmk_core/common/avr/_timer.h | 19 +++++++++++++++++++ tmk_core/common/chibios/_timer.h | 19 +++++++++++++++++++ tmk_core/common/timer.h | 24 ++++++++++++++++++++---- 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 tmk_core/common/arm_atsam/_timer.h create mode 100644 tmk_core/common/avr/_timer.h create mode 100644 tmk_core/common/chibios/_timer.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/arm_atsam/_timer.h b/tmk_core/common/arm_atsam/_timer.h new file mode 100644 index 0000000000..77402b612a --- /dev/null +++ b/tmk_core/common/arm_atsam/_timer.h @@ -0,0 +1,19 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +// The platform is 32-bit, so prefer 32-bit timers to avoid overflow +#define FAST_TIMER_T_SIZE 32 diff --git a/tmk_core/common/avr/_timer.h b/tmk_core/common/avr/_timer.h new file mode 100644 index 0000000000..b81e0f68b7 --- /dev/null +++ b/tmk_core/common/avr/_timer.h @@ -0,0 +1,19 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +// The platform is 8-bit, so prefer 16-bit timers to reduce code size +#define FAST_TIMER_T_SIZE 16 diff --git a/tmk_core/common/chibios/_timer.h b/tmk_core/common/chibios/_timer.h new file mode 100644 index 0000000000..77402b612a --- /dev/null +++ b/tmk_core/common/chibios/_timer.h @@ -0,0 +1,19 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +// The platform is 32-bit, so prefer 32-bit timers to avoid overflow +#define FAST_TIMER_T_SIZE 32 diff --git a/tmk_core/common/timer.h b/tmk_core/common/timer.h index 58f637dd93..928811a2b7 100644 --- a/tmk_core/common/timer.h +++ b/tmk_core/common/timer.h @@ -1,5 +1,6 @@ /* Copyright 2011 Jun Wako +Copyright 2021 Simon Arlott 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 @@ -17,13 +18,13 @@ along with this program. If not, see . #pragma once +#if __has_include_next("_timer.h") +# include_next "_timer.h" /* Include the platform's _timer.h */ +#endif + #include #include -#if defined(__AVR__) -# include "avr/timer_avr.h" -#endif - #define TIMER_DIFF(a, b, max) ((max == UINT8_MAX) ? ((uint8_t)((a) - (b))) : ((max == UINT16_MAX) ? ((uint16_t)((a) - (b))) : ((max == UINT32_MAX) ? ((uint32_t)((a) - (b))) : ((a) >= (b) ? (a) - (b) : (max) + 1 - (b) + (a))))) #define TIMER_DIFF_8(a, b) TIMER_DIFF(a, b, UINT8_MAX) #define TIMER_DIFF_16(a, b) TIMER_DIFF(a, b, UINT16_MAX) @@ -47,6 +48,21 @@ uint32_t timer_elapsed32(uint32_t last); #define timer_expired(current, future) ((uint16_t)(current - future) < UINT16_MAX / 2) #define timer_expired32(current, future) ((uint32_t)(current - future) < UINT32_MAX / 2) +// Use an appropriate timer integer size based on architecture (16-bit will overflow sooner) +#if FAST_TIMER_T_SIZE < 32 +# define TIMER_DIFF_FAST(a, b) TIMER_DIFF_16(a, b) +# define timer_expired_fast(current, future) timer_expired(current, future) +typedef uint16_t fast_timer_t; +fast_timer_t inline timer_read_fast(void) { return timer_read(); } +fast_timer_t inline timer_elapsed_fast(fast_timer_t last) { return timer_elapsed(last); } +#else +# define TIMER_DIFF_FAST(a, b) TIMER_DIFF_32(a, b) +# define timer_expired_fast(current, future) timer_expired32(current, future) +typedef uint32_t fast_timer_t; +fast_timer_t inline timer_read_fast(void) { return timer_read32(); } +fast_timer_t inline timer_elapsed_fast(fast_timer_t last) { return timer_elapsed32(last); } +#endif + #ifdef __cplusplus } #endif -- cgit v1.2.3 From b2fdd4874434ef6921a436fc82d9f24909c726f8 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 10 Jun 2021 17:16:09 +1000 Subject: Add ST7565 LCD driver (#13089) Co-authored-by: Joakim Tufvegren --- tmk_core/common/keyboard.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 3d6092e71c..249da85bd2 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -85,6 +85,9 @@ along with this program. If not, see . #ifdef OLED_DRIVER_ENABLE # include "oled_driver.h" #endif +#ifdef ST7565_ENABLE +# include "st7565.h" +#endif #ifdef VELOCIKEY_ENABLE # include "velocikey.h" #endif @@ -306,6 +309,9 @@ void keyboard_init(void) { #ifdef OLED_DRIVER_ENABLE oled_init(OLED_ROTATION_0); #endif +#ifdef ST7565_ENABLE + st7565_init(DISPLAY_ROTATION_0); +#endif #ifdef PS2_MOUSE_ENABLE ps2_mouse_init(); #endif @@ -470,6 +476,18 @@ MATRIX_LOOP_END: # endif #endif +#ifdef ST7565_ENABLE + st7565_task(); +# ifndef ST7565_DISABLE_TIMEOUT + // Wake up display if user is using those fabulous keys or spinning those encoders! +# ifdef ENCODER_ENABLE + if (matrix_changed || encoders_changed) st7565_on(); +# else + if (matrix_changed) st7565_on(); +# endif +# endif +#endif + #ifdef MOUSEKEY_ENABLE // mousekey repeat & acceleration mousekey_task(); -- cgit v1.2.3 From e2c58934052e2ca93a92cd97ef8b9c0425fa3cf6 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 16 Jun 2021 06:53:27 +0200 Subject: core: make RESET key work with Teensy 4.x (#13076) related to https://github.com/kinx-project/kint/issues/5 --- tmk_core/common/chibios/bootloader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 11f7abf432..76d52ea608 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -95,7 +95,7 @@ void enter_bootloader_mode_if_requested(void) { } } -#elif defined(KL2x) || defined(K20x) || defined(MK66F18) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS +#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS /* Kinetis */ # if defined(BOOTLOADER_KIIBOHD) -- cgit v1.2.3 From ef92c9ee2cf4745637635ec1895399e4f013914c Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Fri, 18 Jun 2021 01:09:43 +0200 Subject: Add CRC8 calculation subsystem to quantum (#12641) * Intended usage is data validation in split transport code. * Default space efficient algorithm. * Opt-in fast table based algorithmn with #define CRC8_USE_TABLE switch. * Define switches for size and speed optimized versions, the default is size optimized by using uint_least8_t as datatype for calculations. * #define CRC8_OPTIMIZE_SPEED uses uint_fast8_t as datatype for calculations, this only affects 32-bit Archs like ARM and RISC-V. * Placeholder crc_init() function for hardware backed crc calculation, not implemented yet. --- tmk_core/common/keyboard.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 249da85bd2..28fa97bc8f 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -103,6 +103,9 @@ along with this program. If not, see . #ifdef EEPROM_DRIVER # include "eeprom_driver.h" #endif +#if defined(CRC_ENABLE) +# include "crc.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { return last_input_modification_time; } @@ -300,6 +303,9 @@ void keyboard_init(void) { timer_init(); sync_timer_init(); matrix_init(); +#if defined(CRC_ENABLE) + crc_init(); +#endif #ifdef VIA_ENABLE via_init(); #endif -- cgit v1.2.3 From 172e6a703041363decd6fc829542f33180c13beb Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Fri, 18 Jun 2021 09:10:06 +1000 Subject: Extensible split data sync (#11930) * Extensible split data sync capability through transactions. - Split common transport has been split up between the transport layer and data layer. - Split "transactions" model used, with convergence between I2C and serial data definitions. - Slave matrix "generation count" is used to determine if the full slave matrix needs to be retrieved. - Encoders get the same "generation count" treatment. - All other blocks of data are synchronised when a change is detected. - All transmissions have a globally-configurable deadline before a transmission is forced (`FORCED_SYNC_THROTTLE_MS`, default 100ms). - Added atomicity for all core-synced data, preventing partial updates - Added retries to AVR i2c_master's i2c_start, to minimise the number of failed transactions when interrupts are disabled on the slave due to atomicity checks. - Some keyboards have had slight modifications made in order to ensure that they still build due to firmware size restrictions. * Fixup LED_MATRIX compile. * Parameterise ERROR_DISCONNECT_COUNT. --- tmk_core/common/host.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c index e7d92cfac6..a8b391e893 100644 --- a/tmk_core/common/host.c +++ b/tmk_core/common/host.c @@ -17,6 +17,7 @@ along with this program. If not, see . #include //#include +#include "keyboard.h" #include "keycode.h" #include "host.h" #include "util.h" @@ -35,15 +36,20 @@ void host_set_driver(host_driver_t *d) { driver = d; } host_driver_t *host_get_driver(void) { return driver; } +#ifdef SPLIT_KEYBOARD +uint8_t split_led_state = 0; +void set_split_host_keyboard_leds(uint8_t led_state) { split_led_state = led_state; } +#endif + uint8_t host_keyboard_leds(void) { +#ifdef SPLIT_KEYBOARD + if (!is_keyboard_master()) return split_led_state; +#endif if (!driver) return 0; return (*driver->keyboard_leds)(); } -led_t host_keyboard_led_state(void) { - if (!driver) return (led_t){0}; - return (led_t)((*driver->keyboard_leds)()); -} +led_t host_keyboard_led_state(void) { return (led_t)host_keyboard_leds(); } /* send report */ void host_keyboard_send(report_keyboard_t *report) { -- cgit v1.2.3 From 8d9f527081d3a5fc8a0286e47022a70df8eb9111 Mon Sep 17 00:00:00 2001 From: Joakim Tufvegren Date: Sun, 20 Jun 2021 04:18:00 +0200 Subject: Add sync_timer support over serial_link (i.e. Ergodox Infinity) (#12845) --- tmk_core/common/sync_timer.c | 2 +- tmk_core/common/sync_timer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/sync_timer.c b/tmk_core/common/sync_timer.c index de24b463b6..68b92d8b43 100644 --- a/tmk_core/common/sync_timer.c +++ b/tmk_core/common/sync_timer.c @@ -26,7 +26,7 @@ SOFTWARE. #include "sync_timer.h" #include "keyboard.h" -#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) +#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) volatile int32_t sync_timer_ms; void sync_timer_init(void) { sync_timer_ms = 0; } diff --git a/tmk_core/common/sync_timer.h b/tmk_core/common/sync_timer.h index 9ddef45bb2..744e2b50d5 100644 --- a/tmk_core/common/sync_timer.h +++ b/tmk_core/common/sync_timer.h @@ -32,7 +32,7 @@ SOFTWARE. extern "C" { #endif -#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) +#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) void sync_timer_init(void); void sync_timer_update(uint32_t time); uint16_t sync_timer_read(void); -- cgit v1.2.3 From c232882fda0669e28312446feac3cadb254962e8 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sat, 26 Jun 2021 11:48:48 +0100 Subject: Allow configuration of USB_VBUS_PIN on chibios (#13342) --- tmk_core/common/chibios/chibios_config.h | 4 +++- tmk_core/common/usb_util.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index 1d8ace4955..23c65f9428 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -15,7 +15,9 @@ */ #pragma once -#define SPLIT_USB_DETECT // Force this on for now +#ifndef USB_VBUS_PIN +# define SPLIT_USB_DETECT // Force this on when dedicated pin is not used +#endif #if defined(STM32F1XX) # define USE_GPIOV1 diff --git a/tmk_core/common/usb_util.c b/tmk_core/common/usb_util.c index e4c50fcb10..d4134a0446 100644 --- a/tmk_core/common/usb_util.c +++ b/tmk_core/common/usb_util.c @@ -13,8 +13,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include "quantum.h" #include "usb_util.h" -#include "wait.h" __attribute__((weak)) void usb_disable(void) {} __attribute__((weak)) bool usb_connected_state(void) { return true; } -- cgit v1.2.3 From 8da8aabbe5796232c0f17f849badd455d42b0277 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sat, 3 Jul 2021 00:19:52 -0700 Subject: Improve layer mask handling (#13065) --- tmk_core/common/action_layer.c | 12 ++++++------ tmk_core/common/action_layer.h | 29 +++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index af2d7d964b..ed1a4bd20d 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -131,32 +131,32 @@ bool layer_state_cmp(layer_state_t cmp_layer_state, uint8_t layer) { if (!cmp_layer_state) { return layer == 0; } - return (cmp_layer_state & (1UL << layer)) != 0; + return (cmp_layer_state & ((layer_state_t)1 << layer)) != 0; } /** \brief Layer move * * Turns on the given layer and turn off all other layers */ -void layer_move(uint8_t layer) { layer_state_set(1UL << layer); } +void layer_move(uint8_t layer) { layer_state_set((layer_state_t)1 << layer); } /** \brief Layer on * * Turns on given layer */ -void layer_on(uint8_t layer) { layer_state_set(layer_state | (1UL << layer)); } +void layer_on(uint8_t layer) { layer_state_set(layer_state | ((layer_state_t)1 << layer)); } /** \brief Layer off * * Turns off given layer */ -void layer_off(uint8_t layer) { layer_state_set(layer_state & ~(1UL << layer)); } +void layer_off(uint8_t layer) { layer_state_set(layer_state & ~((layer_state_t)1 << layer)); } /** \brief Layer invert * * Toggle the given layer (set it if it's unset, or unset it if it's set) */ -void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ (1UL << layer)); } +void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ ((layer_state_t)1 << layer)); } /** \brief Layer or * @@ -258,7 +258,7 @@ uint8_t layer_switch_get_layer(keypos_t key) { layer_state_t layers = layer_state | default_layer_state; /* check top layer first */ for (int8_t i = MAX_LAYER - 1; i >= 0; i--) { - if (layers & (1UL << i)) { + if (layers & ((layer_state_t)1 << i)) { action = action_for_key(i, key); if (action.code != ACTION_TRANSPARENT) { return i; diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h index d72cd3e3a5..b87d096eed 100644 --- a/tmk_core/common/action_layer.h +++ b/tmk_core/common/action_layer.h @@ -21,6 +21,29 @@ along with this program. If not, see . #include "keyboard.h" #include "action.h" +#ifdef DYNAMIC_KEYMAP_ENABLE +# ifndef DYNAMIC_KEYMAP_LAYER_COUNT +# define DYNAMIC_KEYMAP_LAYER_COUNT 4 +# endif +# if DYNAMIC_KEYMAP_LAYER_COUNT <= 8 +# ifndef LAYER_STATE_8BIT +# define LAYER_STATE_8BIT +# endif +# elif DYNAMIC_KEYMAP_LAYER_COUNT <= 16 +# ifndef LAYER_STATE_16BIT +# define LAYER_STATE_16BIT +# endif +# else +# ifndef LAYER_STATE_32BIT +# define LAYER_STATE_32BIT +# endif +# endif +#endif + +#if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT) +# define LAYER_STATE_32BIT +#endif + #if defined(LAYER_STATE_8BIT) typedef uint8_t layer_state_t; # define MAX_LAYER_BITS 3 @@ -35,13 +58,15 @@ typedef uint16_t layer_state_t; # define MAX_LAYER 16 # endif # define get_highest_layer(state) biton16(state) -#else +#elif defined(LAYER_STATE_32BIT) typedef uint32_t layer_state_t; # define MAX_LAYER_BITS 5 # ifndef MAX_LAYER # define MAX_LAYER 32 # endif # define get_highest_layer(state) biton32(state) +#else +# error Layer Mask size not specified. HOW?! #endif /* @@ -92,7 +117,7 @@ layer_state_t layer_state_set_kb(layer_state_t state); # define layer_state_set(layer) # define layer_state_is(layer) (layer == 0) -# define layer_state_cmp(state, layer) (state == 0 ? layer == 0 : (state & 1UL << layer) != 0) +# define layer_state_cmp(state, layer) (state == 0 ? layer == 0 : (state & (layer_state_t)1 << layer) != 0) # define layer_debug() # define layer_clear() -- cgit v1.2.3 From a535d24ecfd465124cdb255e53b5cc301cbda6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Tue, 6 Jul 2021 01:24:48 +0200 Subject: core: chibios: bootloader: use integer pointers as volatile (#13450) This prevents gcc from incorrectly trying to validate array bounds. ``` tmk_core/common/chibios/bootloader.c: error: '__builtin_memcpy' offset [0, 21] is out of the bounds [0, 0] [-Werror=array-bounds] 107 | __builtin_memcpy((void *) VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578#c16 Fixes #12925 --- tmk_core/common/chibios/bootloader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 76d52ea608..f9514ee5f3 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -103,7 +103,8 @@ void enter_bootloader_mode_if_requested(void) { # define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000 const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; __attribute__((weak)) void bootloader_jump(void) { - __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic)); + void *volatile vbat = (void *)VBAT; + __builtin_memcpy(vbat, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic)); // request reset SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk; } -- cgit v1.2.3 From 9c74fd14bc9777ec45cc93fa57bf83ab17b988db Mon Sep 17 00:00:00 2001 From: Chris Cullin Date: Tue, 13 Jul 2021 01:51:23 +1000 Subject: Enable g_is31_leds PROGMEM for RGB Matrix IS31FL3737 driver (#13480) --- tmk_core/common/progmem.h | 1 + 1 file changed, 1 insertion(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h index 4e4771e523..3a7a169682 100644 --- a/tmk_core/common/progmem.h +++ b/tmk_core/common/progmem.h @@ -3,6 +3,7 @@ #if defined(__AVR__) # include #else +# include # define PROGMEM # define PSTR(x) x # define PGM_P const char* -- cgit v1.2.3 From 52cfc9259b58a3a11a244fbe35c49c7dd1a9cae0 Mon Sep 17 00:00:00 2001 From: Jonas Gessner Date: Tue, 13 Jul 2021 19:13:51 +0200 Subject: [Feature] Key Overrides (#11422) --- tmk_core/common/action_util.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c index a57c8bf66a..2b3c00cba0 100644 --- a/tmk_core/common/action_util.c +++ b/tmk_core/common/action_util.c @@ -27,6 +27,10 @@ extern keymap_config_t keymap_config; static uint8_t real_mods = 0; static uint8_t weak_mods = 0; static uint8_t macro_mods = 0; +#ifdef KEY_OVERRIDE_ENABLE +static uint8_t weak_override_mods = 0; +static uint8_t suppressed_mods = 0; +#endif #ifdef USB_6KRO_ENABLE # define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) @@ -229,6 +233,7 @@ void send_keyboard_report(void) { keyboard_report->mods = real_mods; keyboard_report->mods |= weak_mods; keyboard_report->mods |= macro_mods; + #ifndef NO_ACTION_ONESHOT if (oneshot_mods) { # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) @@ -244,6 +249,13 @@ void send_keyboard_report(void) { } #endif + +#ifdef KEY_OVERRIDE_ENABLE + // These need to be last to be able to properly control key overrides + keyboard_report->mods &= ~suppressed_mods; + keyboard_report->mods |= weak_override_mods; +#endif + host_keyboard_send(keyboard_report); } @@ -299,6 +311,22 @@ void set_weak_mods(uint8_t mods) { weak_mods = mods; } */ void clear_weak_mods(void) { weak_mods = 0; } +#ifdef KEY_OVERRIDE_ENABLE +/** \brief set weak mods used by key overrides. DO not call this manually + */ +void set_weak_override_mods(uint8_t mods) { weak_override_mods = mods; } +/** \brief clear weak mods used by key overrides. DO not call this manually + */ +void clear_weak_override_mods(void) { weak_override_mods = 0; } + +/** \brief set suppressed mods used by key overrides. DO not call this manually + */ +void set_suppressed_override_mods(uint8_t mods) { suppressed_mods = mods; } +/** \brief clear suppressed mods used by key overrides. DO not call this manually + */ +void clear_suppressed_override_mods(void) { suppressed_mods = 0; } +#endif + /* macro modifier */ /** \brief get macro mods * -- cgit v1.2.3 From 366be0f7e9b4f408b7494fcb68142ac70d909170 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Fri, 16 Jul 2021 17:08:34 +0100 Subject: Migrate arm_atsam print logic to use common framework (#13554) --- tmk_core/common/arm_atsam/_print.h | 34 ------------------ tmk_core/common/arm_atsam/printf.c | 72 ------------------------------------- tmk_core/common/arm_atsam/printf.h | 7 ---- tmk_core/common/arm_atsam/printf.mk | 1 - 4 files changed, 114 deletions(-) delete mode 100644 tmk_core/common/arm_atsam/_print.h delete mode 100644 tmk_core/common/arm_atsam/printf.c delete mode 100644 tmk_core/common/arm_atsam/printf.h delete mode 100644 tmk_core/common/arm_atsam/printf.mk (limited to 'tmk_core/common') diff --git a/tmk_core/common/arm_atsam/_print.h b/tmk_core/common/arm_atsam/_print.h deleted file mode 100644 index 04320ee38b..0000000000 --- a/tmk_core/common/arm_atsam/_print.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2012 Jun Wako */ -/* Very basic print functions, intended to be used with usb_debug_only.c - * http://www.pjrc.com/teensy/ - * Copyright (c) 2008 PJRC.COM, LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#pragma once - -#include "arm_atsam/printf.h" - -// Create user & normal print defines -#define xprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__) -#define print(s) __xprintf(s) -#define println(s) __xprintf(s "\r\n") -#define uprint(s) __xprintf(s) -#define uprintln(s) __xprintf(s "\r\n") -#define uprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__) diff --git a/tmk_core/common/arm_atsam/printf.c b/tmk_core/common/arm_atsam/printf.c deleted file mode 100644 index 2cb59706a8..0000000000 --- a/tmk_core/common/arm_atsam/printf.c +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2018 Massdrop Inc. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include "printf.h" -#include "sendchar.h" - -#ifdef CONSOLE_ENABLE - -# include "samd51j18a.h" -# include "arm_atsam_protocol.h" -# include -# include - -void console_printf(char *fmt, ...) { - while (udi_hid_con_b_report_trans_ongoing) { - } // Wait for any previous transfers to complete - - static char console_printbuf[CONSOLE_PRINTBUF_SIZE]; // Print and send buffer - va_list va; - int result; - - va_start(va, fmt); - result = vsnprintf(console_printbuf, CONSOLE_PRINTBUF_SIZE, fmt, va); - va_end(va); - - uint32_t irqflags; - char * pconbuf = console_printbuf; // Pointer to start send from - int send_out = CONSOLE_EPSIZE; // Bytes to send per transfer - - while (result > 0) { // While not error and bytes remain - while (udi_hid_con_b_report_trans_ongoing) { - } // Wait for any previous transfers to complete - - irqflags = __get_PRIMASK(); - __disable_irq(); - __DMB(); - - if (result < CONSOLE_EPSIZE) { // If remaining bytes are less than console epsize - memset(udi_hid_con_report, 0, CONSOLE_EPSIZE); // Clear the buffer - send_out = result; // Send remaining size - } - - memcpy(udi_hid_con_report, pconbuf, send_out); // Copy data into the send buffer - - udi_hid_con_b_report_valid = 1; // Set report valid - udi_hid_con_send_report(); // Send report - - __DMB(); - __set_PRIMASK(irqflags); - - result -= send_out; // Decrement result by bytes sent - pconbuf += send_out; // Increment buffer point by bytes sent - } -} - -#endif // CONSOLE_ENABLE - -void print_set_sendchar(sendchar_func_t send) {} \ No newline at end of file diff --git a/tmk_core/common/arm_atsam/printf.h b/tmk_core/common/arm_atsam/printf.h deleted file mode 100644 index 95557f5b01..0000000000 --- a/tmk_core/common/arm_atsam/printf.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#define CONSOLE_PRINTBUF_SIZE 512 - -void console_printf(char *fmt, ...); - -#define __xprintf console_printf diff --git a/tmk_core/common/arm_atsam/printf.mk b/tmk_core/common/arm_atsam/printf.mk deleted file mode 100644 index f70e02731f..0000000000 --- a/tmk_core/common/arm_atsam/printf.mk +++ /dev/null @@ -1 +0,0 @@ -TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c -- cgit v1.2.3 From 5d7f2823c947264d3ff3bb4f057f8e050d6b4af1 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Thu, 22 Jul 2021 23:01:19 +0100 Subject: Implement GPIO abstraction for atsam (#13567) * Implement GPIO abstraction for atsam * Convert Drop boards to normal matrix config * Work round pin conflicts and matrix delay --- tmk_core/common/arm_atsam/atomic_util.h | 37 +++++++++++++++ tmk_core/common/arm_atsam/gpio.h | 71 ++++++++++++++++++++++++++++ tmk_core/common/arm_atsam/pin_defs.h | 84 +++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 tmk_core/common/arm_atsam/atomic_util.h create mode 100644 tmk_core/common/arm_atsam/gpio.h create mode 100644 tmk_core/common/arm_atsam/pin_defs.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/arm_atsam/atomic_util.h b/tmk_core/common/arm_atsam/atomic_util.h new file mode 100644 index 0000000000..848542d23a --- /dev/null +++ b/tmk_core/common/arm_atsam/atomic_util.h @@ -0,0 +1,37 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include "samd51j18a.h" + +static __inline__ uint8_t __interrupt_disable__(void) { + __disable_irq(); + + return 1; +} + +static __inline__ void __interrupt_enable__(const uint8_t *__s) { + __enable_irq(); + + __asm__ volatile("" ::: "memory"); + (void)__s; +} + +#define ATOMIC_BLOCK(type) for (type, __ToDo = __interrupt_disable__(); __ToDo; __ToDo = 0) +#define ATOMIC_FORCEON uint8_t sreg_save __attribute__((__cleanup__(__interrupt_enable__))) = 0 + +#define ATOMIC_BLOCK_RESTORESTATE _Static_assert(0, "ATOMIC_BLOCK_RESTORESTATE not implemented") +#define ATOMIC_BLOCK_FORCEON ATOMIC_BLOCK(ATOMIC_FORCEON) diff --git a/tmk_core/common/arm_atsam/gpio.h b/tmk_core/common/arm_atsam/gpio.h new file mode 100644 index 0000000000..c2d5a30889 --- /dev/null +++ b/tmk_core/common/arm_atsam/gpio.h @@ -0,0 +1,71 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include "stdint.h" +#include "samd51j18a.h" + +#include "pin_defs.h" + +typedef uint8_t pin_t; + +#define SAMD_PORT(pin) ((pin & 0x20) >> 5) +#define SAMD_PIN(pin) (pin & 0x1f) +#define SAMD_PIN_MASK(pin) (1 << (pin & 0x1f)) + +#define setPinInput(pin) \ + do { \ + PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \ + PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \ + } while (0) + +#define setPinInputHigh(pin) \ + do { \ + PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \ + PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \ + PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \ + PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \ + } while (0) + +#define setPinInputLow(pin) \ + do { \ + PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \ + PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ + PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \ + PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \ + } while (0) + +#define setPinOutput(pin) \ + do { \ + PORT->Group[SAMD_PORT(pin)].DIRSET.reg = SAMD_PIN_MASK(pin); \ + PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ + } while (0) + +#define writePinHigh(pin) \ + do { \ + PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \ + } while (0) + +#define writePinLow(pin) \ + do { \ + PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ + } while (0) + +#define writePin(pin, level) ((level) ? (writePinHigh(pin)) : (writePinLow(pin))) + +#define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0) + +#define togglePin(pin) (PORT->Group[SAMD_PORT(pin)].OUTTGL.reg = SAMD_PIN_MASK(pin)) diff --git a/tmk_core/common/arm_atsam/pin_defs.h b/tmk_core/common/arm_atsam/pin_defs.h new file mode 100644 index 0000000000..5b50b23910 --- /dev/null +++ b/tmk_core/common/arm_atsam/pin_defs.h @@ -0,0 +1,84 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include "samd51j18a.h" + +#define A00 PIN_PA00 +#define A01 PIN_PA01 +#define A02 PIN_PA02 +#define A03 PIN_PA03 +#define A04 PIN_PA04 +#define A05 PIN_PA05 +#define A06 PIN_PA06 +#define A07 PIN_PA07 +#define A08 PIN_PA08 +#define A09 PIN_PA09 +#define A10 PIN_PA10 +#define A11 PIN_PA11 +#define A12 PIN_PA12 +#define A13 PIN_PA13 +#define A14 PIN_PA14 +#define A15 PIN_PA15 +#define A16 PIN_PA16 +#define A17 PIN_PA17 +#define A18 PIN_PA18 +#define A19 PIN_PA19 +#define A20 PIN_PA20 +#define A21 PIN_PA21 +#define A22 PIN_PA22 +#define A23 PIN_PA23 +#define A24 PIN_PA24 +#define A25 PIN_PA25 +#define A26 PIN_PA26 +#define A27 PIN_PA27 +#define A28 PIN_PA28 +#define A29 PIN_PA29 +#define A30 PIN_PA30 +#define A31 PIN_PA31 + +#define B00 PIN_PB00 +#define B01 PIN_PB01 +#define B02 PIN_PB02 +#define B03 PIN_PB03 +#define B04 PIN_PB04 +#define B05 PIN_PB05 +#define B06 PIN_PB06 +#define B07 PIN_PB07 +#define B08 PIN_PB08 +#define B09 PIN_PB09 +#define B10 PIN_PB10 +#define B11 PIN_PB11 +#define B12 PIN_PB12 +#define B13 PIN_PB13 +#define B14 PIN_PB14 +#define B15 PIN_PB15 +#define B16 PIN_PB16 +#define B17 PIN_PB17 +#define B18 PIN_PB18 +#define B19 PIN_PB19 +#define B20 PIN_PB20 +#define B21 PIN_PB21 +#define B22 PIN_PB22 +#define B23 PIN_PB23 +#define B24 PIN_PB24 +#define B25 PIN_PB25 +#define B26 PIN_PB26 +#define B27 PIN_PB27 +#define B28 PIN_PB28 +#define B29 PIN_PB29 +#define B30 PIN_PB30 +#define B31 PIN_PB31 -- cgit v1.2.3 From 567da49ed027a936a6f56aa069aad0db4605a198 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sat, 24 Jul 2021 12:13:06 +0100 Subject: Avoid LTO conficts on arm_atsam (#13676) --- tmk_core/common/usb_util.c | 2 +- tmk_core/common/usb_util.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/usb_util.c b/tmk_core/common/usb_util.c index d4134a0446..dd1deeaa11 100644 --- a/tmk_core/common/usb_util.c +++ b/tmk_core/common/usb_util.c @@ -16,7 +16,7 @@ #include "quantum.h" #include "usb_util.h" -__attribute__((weak)) void usb_disable(void) {} +__attribute__((weak)) void usb_disconnect(void) {} __attribute__((weak)) bool usb_connected_state(void) { return true; } __attribute__((weak)) bool usb_vbus_state(void) { #ifdef USB_VBUS_PIN diff --git a/tmk_core/common/usb_util.h b/tmk_core/common/usb_util.h index 4ebedb1e71..13db9fbfbd 100644 --- a/tmk_core/common/usb_util.h +++ b/tmk_core/common/usb_util.h @@ -17,6 +17,6 @@ #include -void usb_disable(void); +void usb_disconnect(void); bool usb_connected_state(void); bool usb_vbus_state(void); -- cgit v1.2.3 From b5bcd5b0a18079df1252a718588255c62d24a054 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sat, 24 Jul 2021 19:56:45 +0100 Subject: Refactor some platform dependent logic (#13675) --- tmk_core/common/arm_atsam/platform.h | 18 ++++++++++++++++++ tmk_core/common/avr/platform.h | 20 ++++++++++++++++++++ tmk_core/common/chibios/platform.h | 19 +++++++++++++++++++ tmk_core/common/print.h | 2 +- tmk_core/common/timer.h | 5 ----- 5 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 tmk_core/common/arm_atsam/platform.h create mode 100644 tmk_core/common/avr/platform.h create mode 100644 tmk_core/common/chibios/platform.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/arm_atsam/platform.h b/tmk_core/common/arm_atsam/platform.h new file mode 100644 index 0000000000..f296d1d535 --- /dev/null +++ b/tmk_core/common/arm_atsam/platform.h @@ -0,0 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +// here just to please the build diff --git a/tmk_core/common/avr/platform.h b/tmk_core/common/avr/platform.h new file mode 100644 index 0000000000..45d9dcebfa --- /dev/null +++ b/tmk_core/common/avr/platform.h @@ -0,0 +1,20 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include +#include +#include diff --git a/tmk_core/common/chibios/platform.h b/tmk_core/common/chibios/platform.h new file mode 100644 index 0000000000..8243dcec53 --- /dev/null +++ b/tmk_core/common/chibios/platform.h @@ -0,0 +1,19 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include +#include "chibios_config.h" diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h index 48f91e6342..8c055f549e 100644 --- a/tmk_core/common/print.h +++ b/tmk_core/common/print.h @@ -47,7 +47,7 @@ void print_set_sendchar(sendchar_func_t func); # define uprintln(s) printf(s "\r\n") # define uprintf printf -# endif /* __AVR__ / PROTOCOL_CHIBIOS / PROTOCOL_ARM_ATSAM */ +# endif /* __has_include_next("_print.h") */ #else /* NO_PRINT */ # undef xprintf // Remove print defines diff --git a/tmk_core/common/timer.h b/tmk_core/common/timer.h index 58f637dd93..abddcea857 100644 --- a/tmk_core/common/timer.h +++ b/tmk_core/common/timer.h @@ -18,11 +18,6 @@ along with this program. If not, see . #pragma once #include -#include - -#if defined(__AVR__) -# include "avr/timer_avr.h" -#endif #define TIMER_DIFF(a, b, max) ((max == UINT8_MAX) ? ((uint8_t)((a) - (b))) : ((max == UINT16_MAX) ? ((uint16_t)((a) - (b))) : ((max == UINT32_MAX) ? ((uint32_t)((a) - (b))) : ((a) >= (b) ? (a) - (b) : (max) + 1 - (b) + (a))))) #define TIMER_DIFF_8(a, b) TIMER_DIFF(a, b, UINT8_MAX) -- cgit v1.2.3 From e6462119199addb6c6e99613699017b633a48155 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Thu, 29 Jul 2021 03:00:39 +0100 Subject: Fix unit tests after recent refactor (#13765) --- tmk_core/common/test/platform.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tmk_core/common/test/platform.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/test/platform.h b/tmk_core/common/test/platform.h new file mode 100644 index 0000000000..f296d1d535 --- /dev/null +++ b/tmk_core/common/test/platform.h @@ -0,0 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +// here just to please the build -- cgit v1.2.3 From 70fb3e1aaf406cbbd5137916a93ed814d6891ef2 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sat, 31 Jul 2021 14:35:30 +0100 Subject: __flash? (#13799) --- tmk_core/common/progmem.h | 1 + 1 file changed, 1 insertion(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h index 3a7a169682..a70d8e299f 100644 --- a/tmk_core/common/progmem.h +++ b/tmk_core/common/progmem.h @@ -5,6 +5,7 @@ #else # include # define PROGMEM +# define __flash # define PSTR(x) x # define PGM_P const char* # define memcpy_P(dest, src, n) memcpy(dest, src, n) -- cgit v1.2.3 From 720c676403660eacb880528f04a5c1d328b84650 Mon Sep 17 00:00:00 2001 From: xyzz <1065521+xyzz@users.noreply.github.com> Date: Mon, 2 Aug 2021 00:27:57 -0400 Subject: flash_stm32: don't unlock flash if already unlocked (#13841) On stm32f4 after reboot from DFU it was observed that the flash is already unlocked. In that case, attempting to unlock it again causes a data abort. --- tmk_core/common/chibios/flash_stm32.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c index e8b3dc4bc9..66f2b13768 100644 --- a/tmk_core/common/chibios/flash_stm32.c +++ b/tmk_core/common/chibios/flash_stm32.c @@ -161,9 +161,11 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) { * @retval None */ void FLASH_Unlock(void) { - /* Authorize the FPEC Access */ - FLASH->KEYR = FLASH_KEY1; - FLASH->KEYR = FLASH_KEY2; + if (FLASH->CR & FLASH_CR_LOCK) { + /* Authorize the FPEC Access */ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } } /** -- cgit v1.2.3 From 34de7ca224d613e1ae19a45860e27c15d40254dd Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Tue, 3 Aug 2021 18:49:33 +0100 Subject: Move print/debug files to quantum (#12069) * move print/debug files to quantum * Update comments --- tmk_core/common/debug.c | 25 ------ tmk_core/common/debug.h | 169 ---------------------------------------- tmk_core/common/lib_printf.mk | 9 --- tmk_core/common/nodebug.h | 26 ------- tmk_core/common/print.h | 135 -------------------------------- tmk_core/common/printf.c | 27 ------- tmk_core/common/sendchar.h | 33 -------- tmk_core/common/sendchar_null.c | 19 ----- tmk_core/common/sendchar_uart.c | 23 ------ 9 files changed, 466 deletions(-) delete mode 100644 tmk_core/common/debug.c delete mode 100644 tmk_core/common/debug.h delete mode 100644 tmk_core/common/lib_printf.mk delete mode 100644 tmk_core/common/nodebug.h delete mode 100644 tmk_core/common/print.h delete mode 100644 tmk_core/common/printf.c delete mode 100644 tmk_core/common/sendchar.h delete mode 100644 tmk_core/common/sendchar_null.c delete mode 100644 tmk_core/common/sendchar_uart.c (limited to 'tmk_core/common') diff --git a/tmk_core/common/debug.c b/tmk_core/common/debug.c deleted file mode 100644 index ea62deaa8c..0000000000 --- a/tmk_core/common/debug.c +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2011 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#include "debug.h" - -debug_config_t debug_config = { - .enable = false, // - .matrix = false, // - .keyboard = false, // - .mouse = false, // - .reserved = 0 // -}; diff --git a/tmk_core/common/debug.h b/tmk_core/common/debug.h deleted file mode 100644 index 3d2e2315ef..0000000000 --- a/tmk_core/common/debug.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -Copyright 2011 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#include -#include "print.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Debug output control - */ -typedef union { - struct { - bool enable : 1; - bool matrix : 1; - bool keyboard : 1; - bool mouse : 1; - uint8_t reserved : 4; - }; - uint8_t raw; -} debug_config_t; - -extern debug_config_t debug_config; - -#ifdef __cplusplus -} -#endif - -/* for backward compatibility */ -#define debug_enable (debug_config.enable) -#define debug_matrix (debug_config.matrix) -#define debug_keyboard (debug_config.keyboard) -#define debug_mouse (debug_config.mouse) - -/* - * Debug print utils - */ -#ifndef NO_DEBUG - -# define dprint(s) \ - do { \ - if (debug_enable) print(s); \ - } while (0) -# define dprintln(s) \ - do { \ - if (debug_enable) println(s); \ - } while (0) -# define dprintf(fmt, ...) \ - do { \ - if (debug_enable) xprintf(fmt, ##__VA_ARGS__); \ - } while (0) -# define dmsg(s) dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s)) - -/* Deprecated. DO NOT USE these anymore, use dprintf instead. */ -# define debug(s) \ - do { \ - if (debug_enable) print(s); \ - } while (0) -# define debugln(s) \ - do { \ - if (debug_enable) println(s); \ - } while (0) -# define debug_msg(s) \ - do { \ - if (debug_enable) { \ - print(__FILE__); \ - print(" at "); \ - print_dec(__LINE__); \ - print(" in "); \ - print(": "); \ - print(s); \ - } \ - } while (0) -# define debug_dec(data) \ - do { \ - if (debug_enable) print_dec(data); \ - } while (0) -# define debug_decs(data) \ - do { \ - if (debug_enable) print_decs(data); \ - } while (0) -# define debug_hex4(data) \ - do { \ - if (debug_enable) print_hex4(data); \ - } while (0) -# define debug_hex8(data) \ - do { \ - if (debug_enable) print_hex8(data); \ - } while (0) -# define debug_hex16(data) \ - do { \ - if (debug_enable) print_hex16(data); \ - } while (0) -# define debug_hex32(data) \ - do { \ - if (debug_enable) print_hex32(data); \ - } while (0) -# define debug_bin8(data) \ - do { \ - if (debug_enable) print_bin8(data); \ - } while (0) -# define debug_bin16(data) \ - do { \ - if (debug_enable) print_bin16(data); \ - } while (0) -# define debug_bin32(data) \ - do { \ - if (debug_enable) print_bin32(data); \ - } while (0) -# define debug_bin_reverse8(data) \ - do { \ - if (debug_enable) print_bin_reverse8(data); \ - } while (0) -# define debug_bin_reverse16(data) \ - do { \ - if (debug_enable) print_bin_reverse16(data); \ - } while (0) -# define debug_bin_reverse32(data) \ - do { \ - if (debug_enable) print_bin_reverse32(data); \ - } while (0) -# define debug_hex(data) debug_hex8(data) -# define debug_bin(data) debug_bin8(data) -# define debug_bin_reverse(data) debug_bin8(data) - -#else /* NO_DEBUG */ - -# define dprint(s) -# define dprintln(s) -# define dprintf(fmt, ...) -# define dmsg(s) -# define debug(s) -# define debugln(s) -# define debug_msg(s) -# define debug_dec(data) -# define debug_decs(data) -# define debug_hex4(data) -# define debug_hex8(data) -# define debug_hex16(data) -# define debug_hex32(data) -# define debug_bin8(data) -# define debug_bin16(data) -# define debug_bin32(data) -# define debug_bin_reverse8(data) -# define debug_bin_reverse16(data) -# define debug_bin_reverse32(data) -# define debug_hex(data) -# define debug_bin(data) -# define debug_bin_reverse(data) - -#endif /* NO_DEBUG */ diff --git a/tmk_core/common/lib_printf.mk b/tmk_core/common/lib_printf.mk deleted file mode 100644 index 10d2d8468d..0000000000 --- a/tmk_core/common/lib_printf.mk +++ /dev/null @@ -1,9 +0,0 @@ -PRINTF_PATH = $(LIB_PATH)/printf - -TMK_COMMON_SRC += $(PRINTF_PATH)/printf.c -TMK_COMMON_SRC += $(COMMON_DIR)/printf.c -TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_FLOAT -TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL -TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG -TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T -VPATH += $(PRINTF_PATH) diff --git a/tmk_core/common/nodebug.h b/tmk_core/common/nodebug.h deleted file mode 100644 index 0b176684bd..0000000000 --- a/tmk_core/common/nodebug.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#ifndef NO_DEBUG -# define NO_DEBUG -# include "debug.h" -# undef NO_DEBUG -#else -# include "debug.h" -#endif diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h deleted file mode 100644 index 8c055f549e..0000000000 --- a/tmk_core/common/print.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright 2012 Jun Wako */ -/* Very basic print functions, intended to be used with usb_debug_only.c - * http://www.pjrc.com/teensy/ - * Copyright (c) 2008 PJRC.COM, LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma once - -#include -#include -#include "util.h" -#include "sendchar.h" -#include "progmem.h" - -void print_set_sendchar(sendchar_func_t func); - -#ifndef NO_PRINT -# if __has_include_next("_print.h") -# include_next "_print.h" /* Include the platforms print.h */ -# else -// Fall back to lib/printf -# include "printf.h" // lib/printf/printf.h - -// Create user & normal print defines -# define print(s) printf(s) -# define println(s) printf(s "\r\n") -# define xprintf printf -# define uprint(s) printf(s) -# define uprintln(s) printf(s "\r\n") -# define uprintf printf - -# endif /* __has_include_next("_print.h") */ -#else /* NO_PRINT */ -# undef xprintf -// Remove print defines -# define print(s) -# define println(s) -# define xprintf(fmt, ...) -# define uprintf(fmt, ...) -# define uprint(s) -# define uprintln(s) - -#endif /* NO_PRINT */ - -#ifdef USER_PRINT -// Remove normal print defines -# undef print -# undef println -# undef xprintf -# define print(s) -# define println(s) -# define xprintf(fmt, ...) -#endif - -#define print_dec(i) xprintf("%u", i) -#define print_decs(i) xprintf("%d", i) -/* hex */ -#define print_hex4(i) xprintf("%X", i) -#define print_hex8(i) xprintf("%02X", i) -#define print_hex16(i) xprintf("%04X", i) -#define print_hex32(i) xprintf("%08lX", i) -/* binary */ -#define print_bin4(i) xprintf("%04b", i) -#define print_bin8(i) xprintf("%08b", i) -#define print_bin16(i) xprintf("%016b", i) -#define print_bin32(i) xprintf("%032lb", i) -#define print_bin_reverse8(i) xprintf("%08b", bitrev(i)) -#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i)) -#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i)) -/* print value utility */ -#define print_val_dec(v) xprintf(#v ": %u\n", v) -#define print_val_decs(v) xprintf(#v ": %d\n", v) -#define print_val_hex8(v) xprintf(#v ": %X\n", v) -#define print_val_hex16(v) xprintf(#v ": %02X\n", v) -#define print_val_hex32(v) xprintf(#v ": %04lX\n", v) -#define print_val_bin8(v) xprintf(#v ": %08b\n", v) -#define print_val_bin16(v) xprintf(#v ": %016b\n", v) -#define print_val_bin32(v) xprintf(#v ": %032lb\n", v) -#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v)) -#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v)) -#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v)) - -// User print disables the normal print messages in the body of QMK/TMK code and -// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do -// a spot of debugging but lack flash resources for allowing all of the codebase to -// print (and store their wasteful strings). -// -// !!! DO NOT USE USER PRINT CALLS IN THE BODY OF QMK/TMK !!! - -/* decimal */ -#define uprint_dec(i) uprintf("%u", i) -#define uprint_decs(i) uprintf("%d", i) -/* hex */ -#define uprint_hex4(i) uprintf("%X", i) -#define uprint_hex8(i) uprintf("%02X", i) -#define uprint_hex16(i) uprintf("%04X", i) -#define uprint_hex32(i) uprintf("%08lX", i) -/* binary */ -#define uprint_bin4(i) uprintf("%04b", i) -#define uprint_bin8(i) uprintf("%08b", i) -#define uprint_bin16(i) uprintf("%016b", i) -#define uprint_bin32(i) uprintf("%032lb", i) -#define uprint_bin_reverse8(i) uprintf("%08b", bitrev(i)) -#define uprint_bin_reverse16(i) uprintf("%016b", bitrev16(i)) -#define uprint_bin_reverse32(i) uprintf("%032lb", bitrev32(i)) -/* print value utility */ -#define uprint_val_dec(v) uprintf(#v ": %u\n", v) -#define uprint_val_decs(v) uprintf(#v ": %d\n", v) -#define uprint_val_hex8(v) uprintf(#v ": %X\n", v) -#define uprint_val_hex16(v) uprintf(#v ": %02X\n", v) -#define uprint_val_hex32(v) uprintf(#v ": %04lX\n", v) -#define uprint_val_bin8(v) uprintf(#v ": %08b\n", v) -#define uprint_val_bin16(v) uprintf(#v ": %016b\n", v) -#define uprint_val_bin32(v) uprintf(#v ": %032lb\n", v) -#define uprint_val_bin_reverse8(v) uprintf(#v ": %08b\n", bitrev(v)) -#define uprint_val_bin_reverse16(v) uprintf(#v ": %016b\n", bitrev16(v)) -#define uprint_val_bin_reverse32(v) uprintf(#v ": %032lb\n", bitrev32(v)) diff --git a/tmk_core/common/printf.c b/tmk_core/common/printf.c deleted file mode 100644 index e8440e55ee..0000000000 --- a/tmk_core/common/printf.c +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2011 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#include -#include "sendchar.h" - -// bind lib/printf to console interface - sendchar - -static int8_t null_sendchar_func(uint8_t c) { return 0; } -static sendchar_func_t func = null_sendchar_func; - -void print_set_sendchar(sendchar_func_t send) { func = send; } - -void _putchar(char character) { func(character); } diff --git a/tmk_core/common/sendchar.h b/tmk_core/common/sendchar.h deleted file mode 100644 index edcddaa6bb..0000000000 --- a/tmk_core/common/sendchar.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2011 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int8_t (*sendchar_func_t)(uint8_t c); - -/* transmit a character. return 0 on success, -1 on error. */ -int8_t sendchar(uint8_t c); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/sendchar_null.c b/tmk_core/common/sendchar_null.c deleted file mode 100644 index fb67f70866..0000000000 --- a/tmk_core/common/sendchar_null.c +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2011 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#include "sendchar.h" - -__attribute__((weak)) int8_t sendchar(uint8_t c) { return 0; } diff --git a/tmk_core/common/sendchar_uart.c b/tmk_core/common/sendchar_uart.c deleted file mode 100644 index 2fc48bafff..0000000000 --- a/tmk_core/common/sendchar_uart.c +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2011 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#include "uart.h" -#include "sendchar.h" - -int8_t sendchar(uint8_t c) { - uart_putchar(c); - return 0; -} -- cgit v1.2.3 From 7e983796e18e7401c062c158f23966aeb7b1405b Mon Sep 17 00:00:00 2001 From: Pete Sevander Date: Fri, 6 Aug 2021 02:44:57 +0300 Subject: Process combos earlier & overlapping combos (#8591) * Combo processing improvements. Now it is possible to use ModTap and LayerTap keys as part of combos. Overlapping combos also don't trigger all the combos, just exactly the one that you press. New settings: - COMBO_MUST_HOLD_MODS - COMBO_MOD_TERM - COMBO_TERM_PER_COMBO - COMBO_MUST_HOLD_PER_COMBO - COMBO_STRICT_TIMER - COMBO_NO_TIMER * Remove the size flags from combo_t struct boolean members. This in the end actually saves space as the members are accessed so many times. The amount of operations needed to access the bits uses more memory than setting the size saves. * Fix `process_combo_key_release` not called correctly with tap-only combos * Fix not passing a pointer when NO_ACTION_TAPPING is defined. * Docs for `COMBO_ONLY_FROM_LAYER` * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update quantum/process_keycode/process_combo.c Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Add `EXTRA_SHORT_COMBOS` option. Stuff combo's `disabled` and `active` flags into `state`. Possibly can save some space. * Add more examples and clarify things with dict management system. - Simple examples now has a combo that has modifiers included. - The slightly more advanced examples now are actually more advanced instead of just `tap_code16()`. - Added a note that `COMBO_ACTION`s are not needed anymore as you can just use custom keycodes. - Added a note that the `g/keymap_combo.h` macros use the `process_combo_event` function and that it is not usable in one's keymap afterwards. * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Change "the" combo action example to "email" example. * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Fix sneaky infinite loop with `combo_disable()` No need to call `dump_key_buffer` when disabling combos because the buffer is either being dumped if a combo-key was pressed, or the buffer is empty if a non-combo-key is pressed. * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> Co-authored-by: Drashna Jaelre --- tmk_core/common/action.c | 37 ++++++++++++++++++++++++++++++++++-- tmk_core/common/action.h | 5 +++++ tmk_core/common/action_tapping.c | 41 ++++++++++++++++++++++++++-------------- tmk_core/common/action_tapping.h | 1 + 4 files changed, 68 insertions(+), 16 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index bd41d28b66..d19fd2a045 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -55,6 +55,8 @@ __attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrec __attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; } #endif +__attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) { return true; } + #ifndef TAP_CODE_DELAY # define TAP_CODE_DELAY 0 #endif @@ -106,9 +108,13 @@ void action_exec(keyevent_t event) { #endif #ifndef NO_ACTION_TAPPING - action_tapping_process(record); + if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { + action_tapping_process(record); + } #else - process_record(&record); + if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { + process_record(&record); + } if (!IS_NOEVENT(record.event)) { dprint("processed: "); debug_record(record); @@ -206,7 +212,16 @@ void process_record(keyrecord_t *record) { } void process_record_handler(keyrecord_t *record) { +#ifdef COMBO_ENABLE + action_t action; + if (record->keycode) { + action = action_for_keycode(record->keycode); + } else { + action = store_or_get_action(record->event.pressed, record->event.key); + } +#else action_t action = store_or_get_action(record->event.pressed, record->event.key); +#endif dprint("ACTION: "); debug_action(action); #ifndef NO_ACTION_LAYER @@ -990,6 +1005,24 @@ bool is_tap_key(keypos_t key) { return is_tap_action(action); } +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +bool is_tap_record(keyrecord_t *record) { +#ifdef COMBO_ENABLE + action_t action; + if (record->keycode) { + action = action_for_keycode(record->keycode); + } else { + action = layer_switch_get_action(record->event.key); + } +#else + action_t action = layer_switch_get_action(record->event.key); +#endif + return is_tap_action(action); +} + /** \brief Utilities for actions. (FIXME: Needs better description) * * FIXME: Needs documentation. diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 8cb4722c6e..3d357b33b8 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -53,6 +53,9 @@ typedef struct { #ifndef NO_ACTION_TAPPING tap_t tap; #endif +#ifdef COMBO_ENABLE + uint16_t keycode; +#endif } keyrecord_t; /* Execute action per keyevent */ @@ -60,6 +63,7 @@ void action_exec(keyevent_t event); /* action for key */ action_t action_for_key(uint8_t layer, keypos_t key); +action_t action_for_keycode(uint16_t keycode); /* macro */ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); @@ -111,6 +115,7 @@ void clear_keyboard_but_mods(void); void clear_keyboard_but_mods_and_keys(void); void layer_switch(uint8_t new_layer); bool is_tap_key(keypos_t key); +bool is_tap_record(keyrecord_t *record); bool is_tap_action(action_t action); #ifndef NO_ACTION_TAPPING diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c index 56044e096d..1701ae4717 100644 --- a/tmk_core/common/action_tapping.c +++ b/tmk_core/common/action_tapping.c @@ -18,11 +18,16 @@ # define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed) # define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) # define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) +#ifndef COMBO_ENABLE +# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key))) +#else +# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode) +#endif __attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; } # ifdef TAPPING_TERM_PER_KEY -# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_event_keycode(tapping_key.event, false), &tapping_key)) +# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_record_keycode(&tapping_key, false), &tapping_key)) # else # define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM) # endif @@ -103,7 +108,7 @@ bool process_tapping(keyrecord_t *keyp) { if (IS_TAPPING_PRESSED()) { if (WITHIN_TAPPING_TERM(event)) { if (tapping_key.tap.count == 0) { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { // first tap! debug("Tapping: First tap(0->1).\n"); tapping_key.tap.count = 1; @@ -122,14 +127,14 @@ bool process_tapping(keyrecord_t *keyp) { # if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) else if ((( # ifdef TAPPING_TERM_PER_KEY - get_tapping_term(get_event_keycode(tapping_key.event, false), keyp) + get_tapping_term(get_record_keycode(&tapping_key, false), keyp) # else TAPPING_TERM # endif >= 500) # ifdef PERMISSIVE_HOLD_PER_KEY - || get_permissive_hold(get_event_keycode(tapping_key.event, false), keyp) + || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp) # elif defined(PERMISSIVE_HOLD) || true # endif @@ -177,7 +182,7 @@ bool process_tapping(keyrecord_t *keyp) { } // tap_count > 0 else { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n"); @@ -186,11 +191,15 @@ bool process_tapping(keyrecord_t *keyp) { tapping_key = *keyp; debug_tapping_key(); return true; - } else if (is_tap_key(event.key) && event.pressed) { + } else if (is_tap_record(keyp) && event.pressed) { if (tapping_key.tap.count > 1) { debug("Tapping: Start new tap with releasing last tap(>1).\n"); // unregister key - process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false}); + process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, +#ifdef COMBO_ENABLE + .keycode = tapping_key.keycode, +#endif + }); } else { debug("Tapping: Start while last tap(1).\n"); } @@ -218,17 +227,21 @@ bool process_tapping(keyrecord_t *keyp) { debug_tapping_key(); return false; } else { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { debug("Tapping: End. last timeout tap release(>0)."); keyp->tap = tapping_key.tap; process_record(keyp); tapping_key = (keyrecord_t){}; return true; - } else if (is_tap_key(event.key) && event.pressed) { + } else if (is_tap_record(keyp) && event.pressed) { if (tapping_key.tap.count > 1) { debug("Tapping: Start new tap with releasing last timeout tap(>1).\n"); // unregister key - process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false}); + process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, +#ifdef COMBO_ENABLE + .keycode = tapping_key.keycode, +#endif + }); } else { debug("Tapping: Start while last timeout tap(1).\n"); } @@ -248,12 +261,12 @@ bool process_tapping(keyrecord_t *keyp) { } else if (IS_TAPPING_RELEASED()) { if (WITHIN_TAPPING_TERM(event)) { if (event.pressed) { - if (IS_TAPPING_KEY(event.key)) { + if (IS_TAPPING_RECORD(keyp)) { //# ifndef TAPPING_FORCE_HOLD # if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY) if ( # ifdef TAPPING_FORCE_HOLD_PER_KEY - !get_tapping_force_hold(get_event_keycode(tapping_key.event, false), keyp) && + !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) && # endif !tapping_key.tap.interrupted && tapping_key.tap.count > 0) { // sequential tap. @@ -271,7 +284,7 @@ bool process_tapping(keyrecord_t *keyp) { // FIX: start new tap again tapping_key = *keyp; return true; - } else if (is_tap_key(event.key)) { + } else if (is_tap_record(keyp)) { // Sequential tap can be interfered with other tap key. debug("Tapping: Start with interfering other tap.\n"); tapping_key = *keyp; @@ -303,7 +316,7 @@ bool process_tapping(keyrecord_t *keyp) { } // not tapping state else { - if (event.pressed && is_tap_key(event.key)) { + if (event.pressed && is_tap_record(keyp)) { debug("Tapping: Start(Press tap key).\n"); tapping_key = *keyp; process_record_tap_hint(&tapping_key); diff --git a/tmk_core/common/action_tapping.h b/tmk_core/common/action_tapping.h index 893ccb1ce1..7de8049c7f 100644 --- a/tmk_core/common/action_tapping.h +++ b/tmk_core/common/action_tapping.h @@ -30,6 +30,7 @@ along with this program. If not, see . #define WAITING_BUFFER_SIZE 8 #ifndef NO_ACTION_TAPPING +uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache); uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache); void action_tapping_process(keyrecord_t record); -- cgit v1.2.3 From c588d232cb97904400b048db923ee86e5bf9abcc Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Fri, 6 Aug 2021 06:53:38 +0100 Subject: Avoid name conflicts with usb_hid Arduino code (#13870) * Avoid name conflicts with usb_hid Arduino code * Fix tests --- tmk_core/common/arm_atsam/platform.h | 18 ------------------ tmk_core/common/arm_atsam/platform_deps.h | 18 ++++++++++++++++++ tmk_core/common/avr/platform.h | 20 -------------------- tmk_core/common/avr/platform_deps.h | 20 ++++++++++++++++++++ tmk_core/common/chibios/platform.h | 19 ------------------- tmk_core/common/chibios/platform_deps.h | 19 +++++++++++++++++++ tmk_core/common/test/platform_deps.h | 18 ++++++++++++++++++ 7 files changed, 75 insertions(+), 57 deletions(-) delete mode 100644 tmk_core/common/arm_atsam/platform.h create mode 100644 tmk_core/common/arm_atsam/platform_deps.h delete mode 100644 tmk_core/common/avr/platform.h create mode 100644 tmk_core/common/avr/platform_deps.h delete mode 100644 tmk_core/common/chibios/platform.h create mode 100644 tmk_core/common/chibios/platform_deps.h create mode 100644 tmk_core/common/test/platform_deps.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/arm_atsam/platform.h b/tmk_core/common/arm_atsam/platform.h deleted file mode 100644 index f296d1d535..0000000000 --- a/tmk_core/common/arm_atsam/platform.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2021 QMK - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 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 . - */ -#pragma once - -// here just to please the build diff --git a/tmk_core/common/arm_atsam/platform_deps.h b/tmk_core/common/arm_atsam/platform_deps.h new file mode 100644 index 0000000000..f296d1d535 --- /dev/null +++ b/tmk_core/common/arm_atsam/platform_deps.h @@ -0,0 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +// here just to please the build diff --git a/tmk_core/common/avr/platform.h b/tmk_core/common/avr/platform.h deleted file mode 100644 index 45d9dcebfa..0000000000 --- a/tmk_core/common/avr/platform.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2021 QMK - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 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 . - */ -#pragma once - -#include -#include -#include diff --git a/tmk_core/common/avr/platform_deps.h b/tmk_core/common/avr/platform_deps.h new file mode 100644 index 0000000000..45d9dcebfa --- /dev/null +++ b/tmk_core/common/avr/platform_deps.h @@ -0,0 +1,20 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include +#include +#include diff --git a/tmk_core/common/chibios/platform.h b/tmk_core/common/chibios/platform.h deleted file mode 100644 index 8243dcec53..0000000000 --- a/tmk_core/common/chibios/platform.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright 2021 QMK - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 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 . - */ -#pragma once - -#include -#include "chibios_config.h" diff --git a/tmk_core/common/chibios/platform_deps.h b/tmk_core/common/chibios/platform_deps.h new file mode 100644 index 0000000000..8243dcec53 --- /dev/null +++ b/tmk_core/common/chibios/platform_deps.h @@ -0,0 +1,19 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include +#include "chibios_config.h" diff --git a/tmk_core/common/test/platform_deps.h b/tmk_core/common/test/platform_deps.h new file mode 100644 index 0000000000..f296d1d535 --- /dev/null +++ b/tmk_core/common/test/platform_deps.h @@ -0,0 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +// here just to please the build -- cgit v1.2.3 From 610035dce8f4f7010779e61e1cb590eebc8cea46 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sat, 7 Aug 2021 02:16:26 +0300 Subject: Add HOLD_ON_OTHER_KEY_PRESS option for dual-role keys (#9404) * Add HOLD_ON_OTHER_KEY_PRESS option for dual-role keys Implement an additional option for dual-role keys which converts the dual-role key press into a hold action immediately when another key is pressed (this is different from the existing PERMISSIVE_HOLD option, which selects the hold action when another key is tapped (pressed and then released) while the dual-role key is pressed). The Mod-Tap keys already behave in a similar way, unless the IGNORE_MOD_TAP_INTERRUPT option is enabled (but with some additional delays); the added option makes this behavior available for all other kinds of dual-role keys. * [Docs] Update tap-hold docs for HOLD_ON_OTHER_KEY_PRESS Document the newly added HOLD_ON_OTHER_KEY_PRESS option and update the documentation for closely related options (PERMISSIVE_HOLD and IGNORE_MOD_TAP_INTERRUPT). Use Layer Tap instead of Mod Tap in examples for PERMISSIVE_HOLD and HOLD_ON_OTHER_KEY_PRESS, because the effect of using these options with Mod Tap keys is mostly invisible without IGNORE_MOD_TAP_INTERRUPT. Add comments before return statements in sample implementations of `get_ignore_mod_tap_interrupt()`, `get_hold_on_other_key_press()` and `get_permissive_hold()`. Thanks to @Erovia and @precondition for comments and suggestions to improve the documentation. --- tmk_core/common/action_tapping.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'tmk_core/common') diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c index 1701ae4717..36839f9faf 100644 --- a/tmk_core/common/action_tapping.c +++ b/tmk_core/common/action_tapping.c @@ -40,6 +40,10 @@ __attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t __attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { return false; } # endif +# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; } +# endif + static keyrecord_t tapping_key = {}; static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; static uint8_t waiting_buffer_head = 0; @@ -175,6 +179,19 @@ bool process_tapping(keyrecord_t *keyp) { // set interrupted flag when other key preesed during tapping if (event.pressed) { tapping_key.tap.interrupted = true; +# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) +# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) + if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp)) +# endif + { + debug("Tapping: End. No tap. Interfered by pressed key\n"); + process_record(&tapping_key); + tapping_key = (keyrecord_t){}; + debug_tapping_key(); + // enqueue + return false; + } +# endif } // enqueue return false; -- cgit v1.2.3 From 2bc8215ce5f5c7473bb75de95cef4ab468d7e837 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Mon, 16 Aug 2021 17:28:12 +0100 Subject: Unify behaviour of wait on AVR (#14025) --- tmk_core/common/avr/_wait.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/avr/_wait.h b/tmk_core/common/avr/_wait.h index 56eb316faf..ae1a25131a 100644 --- a/tmk_core/common/avr/_wait.h +++ b/tmk_core/common/avr/_wait.h @@ -17,8 +17,26 @@ #include -#define wait_ms(ms) _delay_ms(ms) -#define wait_us(us) _delay_us(us) +#define wait_ms(ms) \ + do { \ + if (__builtin_constant_p(ms)) { \ + _delay_ms(ms); \ + } else { \ + for (uint16_t i = ms; i > 0; i--) { \ + _delay_ms(1); \ + } \ + } \ + } while (0) +#define wait_us(us) \ + do { \ + if (__builtin_constant_p(us)) { \ + _delay_us(us); \ + } else { \ + for (uint16_t i = us; i > 0; i--) { \ + _delay_us(1); \ + } \ + } \ + } while (0) /* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. * But here's more margin to make it two clocks. */ -- cgit v1.2.3 From 75b49aff56436c57a424e622c91f6d80e1d0ecc2 Mon Sep 17 00:00:00 2001 From: a-chol Date: Tue, 17 Aug 2021 20:52:44 +0200 Subject: Digitizer HID interface : absolute coordinates for mouse cursor (#12851) * Add digitizer HID interface for setting the mouse cursor position at absolute screen coordinates. Tested on Pro Micro, Proton C and Blackpill. * Update docs/feature_digitizer.md Co-authored-by: Ryan * Update tmk_core/protocol/usb_descriptor.c Co-authored-by: Ryan * Add missing copyrights Add V-USB support * Add support for digitizer dedicated endpoint for lufa and chibios. Fix formatting issues Move digitizer_task definition to the feature's base implementation file * Run cformat on modified files * Change digitizer report usage to Digitizer instead of Pen to avoid pointer disappearing on Windows. * Update tmk_core/protocol/vusb/vusb.c Co-authored-by: Ryan * Run cformat from docker image * Remove send_digitizer from host_driver_t and instead rely on the declaration being the interface to the implementation in each HW-specific usb implementation. * Fix build : send_digitizer shouldn't be static in vusb and add weak-linkage implementation for tests without usb implementation * Change digitizer user interface to match pointing device's * Update documentation with new API Co-authored-by: a-chol Co-authored-by: Ryan --- tmk_core/common/host.c | 19 +++++++++++++++++++ tmk_core/common/host_driver.h | 2 ++ tmk_core/common/keyboard.c | 7 +++++++ tmk_core/common/report.h | 14 +++++++++++++- 4 files changed, 41 insertions(+), 1 deletion(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c index a8b391e893..f0c396b189 100644 --- a/tmk_core/common/host.c +++ b/tmk_core/common/host.c @@ -22,6 +22,7 @@ along with this program. If not, see . #include "host.h" #include "util.h" #include "debug.h" +#include "digitizer.h" #ifdef NKRO_ENABLE # include "keycode_config.h" @@ -103,6 +104,24 @@ void host_consumer_send(uint16_t report) { (*driver->send_consumer)(report); } +void host_digitizer_send(digitizer_t *digitizer) { + if (!driver) return; + + report_digitizer_t report = { +#ifdef DIGITIZER_SHARED_EP + .report_id = REPORT_ID_DIGITIZER, +#endif + .tip = digitizer->tipswitch & 0x1, + .inrange = digitizer->inrange & 0x1, + .x = (uint16_t)(digitizer->x * 0x7FFF), + .y = (uint16_t)(digitizer->y * 0x7FFF), + }; + + send_digitizer(&report); +} + +__attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} + uint16_t host_last_system_report(void) { return last_system_report; } uint16_t host_last_consumer_report(void) { return last_consumer_report; } diff --git a/tmk_core/common/host_driver.h b/tmk_core/common/host_driver.h index f34a220530..2aebca043d 100644 --- a/tmk_core/common/host_driver.h +++ b/tmk_core/common/host_driver.h @@ -30,3 +30,5 @@ typedef struct { void (*send_system)(uint16_t); void (*send_consumer)(uint16_t); } host_driver_t; + +void send_digitizer(report_digitizer_t *report); \ No newline at end of file diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 28fa97bc8f..fcc51973fd 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -106,6 +106,9 @@ along with this program. If not, see . #if defined(CRC_ENABLE) # include "crc.h" #endif +#ifdef DIGITIZER_ENABLE +# include "digitizer.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { return last_input_modification_time; } @@ -537,6 +540,10 @@ MATRIX_LOOP_END: joystick_task(); #endif +#ifdef DIGITIZER_ENABLE + digitizer_task(); +#endif + // update LED if (led_status != host_keyboard_leds()) { led_status = host_keyboard_leds(); diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index db6370657d..f2223e8063 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h @@ -30,7 +30,8 @@ enum hid_report_ids { REPORT_ID_SYSTEM, REPORT_ID_CONSUMER, REPORT_ID_NKRO, - REPORT_ID_JOYSTICK + REPORT_ID_JOYSTICK, + REPORT_ID_DIGITIZER }; /* Mouse buttons */ @@ -205,6 +206,17 @@ typedef struct { int8_t h; } __attribute__((packed)) report_mouse_t; +typedef struct { +#ifdef DIGITIZER_SHARED_EP + uint8_t report_id; +#endif + uint8_t tip : 1; + uint8_t inrange : 1; + uint8_t pad2 : 6; + uint16_t x; + uint16_t y; +} __attribute__((packed)) report_digitizer_t; + typedef struct { #if JOYSTICK_AXES_COUNT > 0 # if JOYSTICK_AXES_RESOLUTION > 8 -- cgit v1.2.3 From 96e2b13d1de227cdc2b918fb0292bd832d346a25 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Wed, 18 Aug 2021 00:11:07 +0100 Subject: Begin to carve out platform/protocol API - Single main loop (#13843) * Begin to carve out platform/protocol API * Fix up after rebase --- tmk_core/common/arm_atsam/platform.c | 21 +++++++++++++++++++++ tmk_core/common/avr/platform.c | 21 +++++++++++++++++++++ tmk_core/common/chibios/platform.c | 22 ++++++++++++++++++++++ tmk_core/common/test/platform.c | 21 +++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 tmk_core/common/arm_atsam/platform.c create mode 100644 tmk_core/common/avr/platform.c create mode 100644 tmk_core/common/chibios/platform.c create mode 100644 tmk_core/common/test/platform.c (limited to 'tmk_core/common') diff --git a/tmk_core/common/arm_atsam/platform.c b/tmk_core/common/arm_atsam/platform.c new file mode 100644 index 0000000000..3e35b4fe4c --- /dev/null +++ b/tmk_core/common/arm_atsam/platform.c @@ -0,0 +1,21 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 "platform_deps.h" + +void platform_setup(void) { + // do nothing +} diff --git a/tmk_core/common/avr/platform.c b/tmk_core/common/avr/platform.c new file mode 100644 index 0000000000..3e35b4fe4c --- /dev/null +++ b/tmk_core/common/avr/platform.c @@ -0,0 +1,21 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 "platform_deps.h" + +void platform_setup(void) { + // do nothing +} diff --git a/tmk_core/common/chibios/platform.c b/tmk_core/common/chibios/platform.c new file mode 100644 index 0000000000..d4a229f278 --- /dev/null +++ b/tmk_core/common/chibios/platform.c @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 "platform_deps.h" + +void platform_setup(void) { + halInit(); + chSysInit(); +} \ No newline at end of file diff --git a/tmk_core/common/test/platform.c b/tmk_core/common/test/platform.c new file mode 100644 index 0000000000..8ddceeda8f --- /dev/null +++ b/tmk_core/common/test/platform.c @@ -0,0 +1,21 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 "platform_deps.h" + +void platform_setup(void) { + // do nothing +} \ No newline at end of file -- cgit v1.2.3 From b8e913c8db73ebf890e4604ee41991a34354a600 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Wed, 18 Aug 2021 00:18:58 +0100 Subject: Migrate platform independent code from tmk_core -> quantum (#13673) * Migrate action|keyboard|keycode|eeconfig from tmk_core -> quantum --- tmk_core/common/action.c | 1126 -------------------------------------- tmk_core/common/action.h | 132 ----- tmk_core/common/action_code.h | 308 ----------- tmk_core/common/action_layer.c | 279 ---------- tmk_core/common/action_layer.h | 147 ----- tmk_core/common/action_macro.c | 93 ---- tmk_core/common/action_macro.h | 123 ----- tmk_core/common/action_tapping.c | 456 --------------- tmk_core/common/action_tapping.h | 42 -- tmk_core/common/action_util.c | 455 --------------- tmk_core/common/action_util.h | 105 ---- tmk_core/common/eeconfig.c | 211 ------- tmk_core/common/eeconfig.h | 113 ---- tmk_core/common/keyboard.c | 565 ------------------- tmk_core/common/keyboard.h | 90 --- tmk_core/common/keycode.h | 560 ------------------- 16 files changed, 4805 deletions(-) delete mode 100644 tmk_core/common/action.c delete mode 100644 tmk_core/common/action.h delete mode 100644 tmk_core/common/action_code.h delete mode 100644 tmk_core/common/action_layer.c delete mode 100644 tmk_core/common/action_layer.h delete mode 100644 tmk_core/common/action_macro.c delete mode 100644 tmk_core/common/action_macro.h delete mode 100644 tmk_core/common/action_tapping.c delete mode 100644 tmk_core/common/action_tapping.h delete mode 100644 tmk_core/common/action_util.c delete mode 100644 tmk_core/common/action_util.h delete mode 100644 tmk_core/common/eeconfig.c delete mode 100644 tmk_core/common/eeconfig.h delete mode 100644 tmk_core/common/keyboard.c delete mode 100644 tmk_core/common/keyboard.h delete mode 100644 tmk_core/common/keycode.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c deleted file mode 100644 index d19fd2a045..0000000000 --- a/tmk_core/common/action.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* -Copyright 2012,2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#include "host.h" -#include "keycode.h" -#include "keyboard.h" -#include "mousekey.h" -#include "command.h" -#include "led.h" -#include "action_layer.h" -#include "action_tapping.h" -#include "action_macro.h" -#include "action_util.h" -#include "action.h" -#include "wait.h" - -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" -#endif - -#ifdef DEBUG_ACTION -# include "debug.h" -#else -# include "nodebug.h" -#endif - -#ifdef POINTING_DEVICE_ENABLE -# include "pointing_device.h" -#endif - -int tp_buttons; - -#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) -int retro_tapping_counter = 0; -#endif - -#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY -__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; } -#endif - -#ifdef RETRO_TAPPING_PER_KEY -__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; } -#endif - -__attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) { return true; } - -#ifndef TAP_CODE_DELAY -# define TAP_CODE_DELAY 0 -#endif -#ifndef TAP_HOLD_CAPS_DELAY -# define TAP_HOLD_CAPS_DELAY 80 -#endif -/** \brief Called to execute an action. - * - * FIXME: Needs documentation. - */ -void action_exec(keyevent_t event) { - if (!IS_NOEVENT(event)) { - dprint("\n---- action_exec: start -----\n"); - dprint("EVENT: "); - debug_event(event); - dprintln(); -#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) - retro_tapping_counter++; -#endif - } - - if (event.pressed) { - // clear the potential weak mods left by previously pressed keys - clear_weak_mods(); - } - -#ifdef SWAP_HANDS_ENABLE - if (!IS_NOEVENT(event)) { - process_hand_swap(&event); - } -#endif - - keyrecord_t record = {.event = event}; - -#ifndef NO_ACTION_ONESHOT -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - if (has_oneshot_layer_timed_out()) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } - if (has_oneshot_mods_timed_out()) { - clear_oneshot_mods(); - } -# ifdef SWAP_HANDS_ENABLE - if (has_oneshot_swaphands_timed_out()) { - clear_oneshot_swaphands(); - } -# endif -# endif -#endif - -#ifndef NO_ACTION_TAPPING - if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { - action_tapping_process(record); - } -#else - if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { - process_record(&record); - } - if (!IS_NOEVENT(record.event)) { - dprint("processed: "); - debug_record(record); - dprintln(); - } -#endif -} - -#ifdef SWAP_HANDS_ENABLE -bool swap_hands = false; -bool swap_held = false; - -/** \brief Process Hand Swap - * - * FIXME: Needs documentation. - */ -void process_hand_swap(keyevent_t *event) { - static swap_state_row_t swap_state[MATRIX_ROWS]; - - keypos_t pos = event->key; - swap_state_row_t col_bit = (swap_state_row_t)1 << pos.col; - bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit); - - if (do_swap) { - event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); - event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); - swap_state[pos.row] |= col_bit; - } else { - swap_state[pos.row] &= ~(col_bit); - } -} -#endif - -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) -bool disable_action_cache = false; - -void process_record_nocache(keyrecord_t *record) { - disable_action_cache = true; - process_record(record); - disable_action_cache = false; -} -#else -void process_record_nocache(keyrecord_t *record) { process_record(record); } -#endif - -__attribute__((weak)) bool process_record_quantum(keyrecord_t *record) { return true; } - -__attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {} - -#ifndef NO_ACTION_TAPPING -/** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress. - * - * FIXME: Needs documentation. - */ -void process_record_tap_hint(keyrecord_t *record) { - action_t action = layer_switch_get_action(record->event.key); - - switch (action.kind.id) { -# ifdef SWAP_HANDS_ENABLE - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case OP_SH_ONESHOT: - break; - case OP_SH_TAP_TOGGLE: - default: - swap_hands = !swap_hands; - swap_held = true; - } - break; -# endif - } -} -#endif - -/** \brief Take a key event (key press or key release) and processes it. - * - * FIXME: Needs documentation. - */ -void process_record(keyrecord_t *record) { - if (IS_NOEVENT(record->event)) { - return; - } - - if (!process_record_quantum(record)) { -#ifndef NO_ACTION_ONESHOT - if (is_oneshot_layer_active() && record->event.pressed) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } -#endif - return; - } - - process_record_handler(record); - post_process_record_quantum(record); -} - -void process_record_handler(keyrecord_t *record) { -#ifdef COMBO_ENABLE - action_t action; - if (record->keycode) { - action = action_for_keycode(record->keycode); - } else { - action = store_or_get_action(record->event.pressed, record->event.key); - } -#else - action_t action = store_or_get_action(record->event.pressed, record->event.key); -#endif - dprint("ACTION: "); - debug_action(action); -#ifndef NO_ACTION_LAYER - dprint(" layer_state: "); - layer_debug(); - dprint(" default_layer_state: "); - default_layer_debug(); -#endif - dprintln(); - - process_action(record, action); -} - -#if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) -void register_button(bool pressed, enum mouse_buttons button) { -# ifdef PS2_MOUSE_ENABLE - tp_buttons = pressed ? tp_buttons | button : tp_buttons & ~button; -# endif -# ifdef POINTING_DEVICE_ENABLE - report_mouse_t currentReport = pointing_device_get_report(); - currentReport.buttons = pressed ? currentReport.buttons | button : currentReport.buttons & ~button; - pointing_device_set_report(currentReport); -# endif -} -#endif - -/** \brief Take an action and processes it. - * - * FIXME: Needs documentation. - */ -void process_action(keyrecord_t *record, action_t action) { - keyevent_t event = record->event; -#ifndef NO_ACTION_TAPPING - uint8_t tap_count = record->tap.count; -#endif - -#ifndef NO_ACTION_ONESHOT - bool do_release_oneshot = false; - // notice we only clear the one shot layer if the pressed key is not a modifier. - if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code)) -# ifdef SWAP_HANDS_ENABLE - && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT) -# endif - ) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - do_release_oneshot = !is_oneshot_layer_active(); - } -#endif - - switch (action.kind.id) { - /* Key and Mods */ - case ACT_LMODS: - case ACT_RMODS: { - uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : action.key.mods << 4; - if (event.pressed) { - if (mods) { - if (IS_MOD(action.key.code) || action.key.code == KC_NO) { - // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless. - // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT). - // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO). - add_mods(mods); - } else { - add_weak_mods(mods); - } - send_keyboard_report(); - } - register_code(action.key.code); - } else { - unregister_code(action.key.code); - if (mods) { - if (IS_MOD(action.key.code) || action.key.code == KC_NO) { - del_mods(mods); - } else { - del_weak_mods(mods); - } - send_keyboard_report(); - } - } - } break; -#ifndef NO_ACTION_TAPPING - case ACT_LMODS_TAP: - case ACT_RMODS_TAP: { - uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods << 4; - switch (action.layer_tap.code) { -# ifndef NO_ACTION_ONESHOT - case MODS_ONESHOT: - // Oneshot modifier - if (event.pressed) { - if (tap_count == 0) { - dprint("MODS_TAP: Oneshot: 0\n"); - register_mods(mods | get_oneshot_mods()); - } else if (tap_count == 1) { - dprint("MODS_TAP: Oneshot: start\n"); - set_oneshot_mods(mods | get_oneshot_mods()); -# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - } else if (tap_count == ONESHOT_TAP_TOGGLE) { - dprint("MODS_TAP: Toggling oneshot"); - clear_oneshot_mods(); - set_oneshot_locked_mods(mods); - register_mods(mods); -# endif - } else { - register_mods(mods | get_oneshot_mods()); - } - } else { - if (tap_count == 0) { - clear_oneshot_mods(); - unregister_mods(mods); - } else if (tap_count == 1) { - // Retain Oneshot mods -# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - if (mods & get_mods()) { - clear_oneshot_locked_mods(); - clear_oneshot_mods(); - unregister_mods(mods); - } - } else if (tap_count == ONESHOT_TAP_TOGGLE) { - // Toggle Oneshot Layer -# endif - } else { - clear_oneshot_mods(); - unregister_mods(mods); - } - } - break; -# endif - case MODS_TAP_TOGGLE: - if (event.pressed) { - if (tap_count <= TAPPING_TOGGLE) { - register_mods(mods); - } - } else { - if (tap_count < TAPPING_TOGGLE) { - unregister_mods(mods); - } - } - break; - default: - if (event.pressed) { - if (tap_count > 0) { -# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY) - if ( -# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY - !get_ignore_mod_tap_interrupt(get_event_keycode(record->event, false), record) && -# endif - record->tap.interrupted) { - dprint("mods_tap: tap: cancel: add_mods\n"); - // ad hoc: set 0 to cancel tap - record->tap.count = 0; - register_mods(mods); - } else -# endif - { - dprint("MODS_TAP: Tap: register_code\n"); - register_code(action.key.code); - } - } else { - dprint("MODS_TAP: No tap: add_mods\n"); - register_mods(mods); - } - } else { - if (tap_count > 0) { - dprint("MODS_TAP: Tap: unregister_code\n"); - if (action.layer_tap.code == KC_CAPS) { - wait_ms(TAP_HOLD_CAPS_DELAY); - } else { - wait_ms(TAP_CODE_DELAY); - } - unregister_code(action.key.code); - } else { - dprint("MODS_TAP: No tap: add_mods\n"); - unregister_mods(mods); - } - } - break; - } - } break; -#endif -#ifdef EXTRAKEY_ENABLE - /* other HID usage */ - case ACT_USAGE: - switch (action.usage.page) { - case PAGE_SYSTEM: - if (event.pressed) { - host_system_send(action.usage.code); - } else { - host_system_send(0); - } - break; - case PAGE_CONSUMER: - if (event.pressed) { - host_consumer_send(action.usage.code); - } else { - host_consumer_send(0); - } - break; - } - break; -#endif -#ifdef MOUSEKEY_ENABLE - /* Mouse key */ - case ACT_MOUSEKEY: - if (event.pressed) { - mousekey_on(action.key.code); - } else { - mousekey_off(action.key.code); - } - switch (action.key.code) { -# if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) -# ifdef POINTING_DEVICE_ENABLE - case KC_MS_BTN1 ... KC_MS_BTN8: -# else - case KC_MS_BTN1 ... KC_MS_BTN3: -# endif - register_button(event.pressed, MOUSE_BTN_MASK(action.key.code - KC_MS_BTN1)); - break; -# endif - default: - mousekey_send(); - break; - } - break; -#endif -#ifndef NO_ACTION_LAYER - case ACT_LAYER: - if (action.layer_bitop.on == 0) { - /* Default Layer Bitwise Operation */ - if (!event.pressed) { - uint8_t shift = action.layer_bitop.part * 4; - layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; - layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; - switch (action.layer_bitop.op) { - case OP_BIT_AND: - default_layer_and(bits | mask); - break; - case OP_BIT_OR: - default_layer_or(bits | mask); - break; - case OP_BIT_XOR: - default_layer_xor(bits | mask); - break; - case OP_BIT_SET: - default_layer_set(bits | mask); - break; - } - } - } else { - /* Layer Bitwise Operation */ - if (event.pressed ? (action.layer_bitop.on & ON_PRESS) : (action.layer_bitop.on & ON_RELEASE)) { - uint8_t shift = action.layer_bitop.part * 4; - layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; - layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; - switch (action.layer_bitop.op) { - case OP_BIT_AND: - layer_and(bits | mask); - break; - case OP_BIT_OR: - layer_or(bits | mask); - break; - case OP_BIT_XOR: - layer_xor(bits | mask); - break; - case OP_BIT_SET: - layer_state_set(bits | mask); - break; - } - } - } - break; - case ACT_LAYER_MODS: - if (event.pressed) { - layer_on(action.layer_mods.layer); - register_mods(action.layer_mods.mods); - } else { - unregister_mods(action.layer_mods.mods); - layer_off(action.layer_mods.layer); - } - break; -# ifndef NO_ACTION_TAPPING - case ACT_LAYER_TAP: - case ACT_LAYER_TAP_EXT: - switch (action.layer_tap.code) { - case OP_TAP_TOGGLE: - /* tap toggle */ - if (event.pressed) { - if (tap_count < TAPPING_TOGGLE) { - layer_invert(action.layer_tap.val); - } - } else { - if (tap_count <= TAPPING_TOGGLE) { - layer_invert(action.layer_tap.val); - } - } - break; - case OP_ON_OFF: - event.pressed ? layer_on(action.layer_tap.val) : layer_off(action.layer_tap.val); - break; - case OP_OFF_ON: - event.pressed ? layer_off(action.layer_tap.val) : layer_on(action.layer_tap.val); - break; - case OP_SET_CLEAR: - event.pressed ? layer_move(action.layer_tap.val) : layer_clear(); - break; -# ifndef NO_ACTION_ONESHOT - case OP_ONESHOT: - // Oneshot modifier -# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - do_release_oneshot = false; - if (event.pressed) { - del_mods(get_oneshot_locked_mods()); - if (get_oneshot_layer_state() == ONESHOT_TOGGLED) { - reset_oneshot_layer(); - layer_off(action.layer_tap.val); - break; - } else if (tap_count < ONESHOT_TAP_TOGGLE) { - layer_on(action.layer_tap.val); - set_oneshot_layer(action.layer_tap.val, ONESHOT_START); - } - } else { - add_mods(get_oneshot_locked_mods()); - if (tap_count >= ONESHOT_TAP_TOGGLE) { - reset_oneshot_layer(); - clear_oneshot_locked_mods(); - set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED); - } else { - clear_oneshot_layer_state(ONESHOT_PRESSED); - } - } -# else - if (event.pressed) { - layer_on(action.layer_tap.val); - set_oneshot_layer(action.layer_tap.val, ONESHOT_START); - } else { - clear_oneshot_layer_state(ONESHOT_PRESSED); - if (tap_count > 1) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } - } -# endif - break; -# endif - default: - /* tap key */ - if (event.pressed) { - if (tap_count > 0) { - dprint("KEYMAP_TAP_KEY: Tap: register_code\n"); - register_code(action.layer_tap.code); - } else { - dprint("KEYMAP_TAP_KEY: No tap: On on press\n"); - layer_on(action.layer_tap.val); - } - } else { - if (tap_count > 0) { - dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n"); - if (action.layer_tap.code == KC_CAPS) { - wait_ms(TAP_HOLD_CAPS_DELAY); - } else { - wait_ms(TAP_CODE_DELAY); - } - unregister_code(action.layer_tap.code); - } else { - dprint("KEYMAP_TAP_KEY: No tap: Off on release\n"); - layer_off(action.layer_tap.val); - } - } - break; - } - break; -# endif -#endif - /* Extentions */ -#ifndef NO_ACTION_MACRO - case ACT_MACRO: - action_macro_play(action_get_macro(record, action.func.id, action.func.opt)); - break; -#endif -#ifdef SWAP_HANDS_ENABLE - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case OP_SH_TOGGLE: - if (event.pressed) { - swap_hands = !swap_hands; - } - break; - case OP_SH_ON_OFF: - swap_hands = event.pressed; - break; - case OP_SH_OFF_ON: - swap_hands = !event.pressed; - break; - case OP_SH_ON: - if (!event.pressed) { - swap_hands = true; - } - break; - case OP_SH_OFF: - if (!event.pressed) { - swap_hands = false; - } - break; -# ifndef NO_ACTION_ONESHOT - case OP_SH_ONESHOT: - if (event.pressed) { - set_oneshot_swaphands(); - } else { - release_oneshot_swaphands(); - } - break; -# endif - -# ifndef NO_ACTION_TAPPING - case OP_SH_TAP_TOGGLE: - /* tap toggle */ - - if (event.pressed) { - if (swap_held) { - swap_held = false; - } else { - swap_hands = !swap_hands; - } - } else { - if (tap_count < TAPPING_TOGGLE) { - swap_hands = !swap_hands; - } - } - break; - default: - /* tap key */ - if (tap_count > 0) { - if (swap_held) { - swap_hands = !swap_hands; // undo hold set up in _tap_hint - swap_held = false; - } - if (event.pressed) { - register_code(action.swap.code); - } else { - wait_ms(TAP_CODE_DELAY); - unregister_code(action.swap.code); - *record = (keyrecord_t){}; // hack: reset tap mode - } - } else { - if (swap_held && !event.pressed) { - swap_hands = !swap_hands; // undo hold set up in _tap_hint - swap_held = false; - } - } -# endif - } -#endif -#ifndef NO_ACTION_FUNCTION - case ACT_FUNCTION: - action_function(record, action.func.id, action.func.opt); - break; -#endif - default: - break; - } - -#ifndef NO_ACTION_LAYER - // if this event is a layer action, update the leds - switch (action.kind.id) { - case ACT_LAYER: - case ACT_LAYER_MODS: -# ifndef NO_ACTION_TAPPING - case ACT_LAYER_TAP: - case ACT_LAYER_TAP_EXT: -# endif - led_set(host_keyboard_leds()); - break; - default: - break; - } -#endif - -#ifndef NO_ACTION_TAPPING -# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) - if (!is_tap_action(action)) { - retro_tapping_counter = 0; - } else { - if (event.pressed) { - if (tap_count > 0) { - retro_tapping_counter = 0; - } - } else { - if (tap_count > 0) { - retro_tapping_counter = 0; - } else { - if ( -# ifdef RETRO_TAPPING_PER_KEY - get_retro_tapping(get_event_keycode(record->event, false), record) && -# endif - retro_tapping_counter == 2) { - tap_code(action.layer_tap.code); - } - retro_tapping_counter = 0; - } - } - } -# endif -#endif - -#ifdef SWAP_HANDS_ENABLE -# ifndef NO_ACTION_ONESHOT - if (event.pressed && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)) { - use_oneshot_swaphands(); - } -# endif -#endif - -#ifndef NO_ACTION_ONESHOT - /* Because we switch layers after a oneshot event, we need to release the - * key before we leave the layer or no key up event will be generated. - */ - if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED)) { - record->event.pressed = false; - layer_on(get_oneshot_layer()); - process_record(record); - layer_off(get_oneshot_layer()); - } -#endif -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void register_code(uint8_t code) { - if (code == KC_NO) { - return; - } -#ifdef LOCKING_SUPPORT_ENABLE - else if (KC_LOCKING_CAPS == code) { -# ifdef LOCKING_RESYNC_ENABLE - // Resync: ignore if caps lock already is on - if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) return; -# endif - add_key(KC_CAPSLOCK); - send_keyboard_report(); - wait_ms(100); - del_key(KC_CAPSLOCK); - send_keyboard_report(); - } - - else if (KC_LOCKING_NUM == code) { -# ifdef LOCKING_RESYNC_ENABLE - if (host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)) return; -# endif - add_key(KC_NUMLOCK); - send_keyboard_report(); - wait_ms(100); - del_key(KC_NUMLOCK); - send_keyboard_report(); - } - - else if (KC_LOCKING_SCROLL == code) { -# ifdef LOCKING_RESYNC_ENABLE - if (host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK)) return; -# endif - add_key(KC_SCROLLLOCK); - send_keyboard_report(); - wait_ms(100); - del_key(KC_SCROLLLOCK); - send_keyboard_report(); - } -#endif - - else if IS_KEY (code) { - // TODO: should push command_proc out of this block? - if (command_proc(code)) return; - -#ifndef NO_ACTION_ONESHOT -/* TODO: remove - if (oneshot_state.mods && !oneshot_state.disabled) { - uint8_t tmp_mods = get_mods(); - add_mods(oneshot_state.mods); - - add_key(code); - send_keyboard_report(); - - set_mods(tmp_mods); - send_keyboard_report(); - oneshot_cancel(); - } else -*/ -#endif - { - // Force a new key press if the key is already pressed - // without this, keys with the same keycode, but different - // modifiers will be reported incorrectly, see issue #1708 - if (is_key_pressed(keyboard_report, code)) { - del_key(code); - send_keyboard_report(); - } - add_key(code); - send_keyboard_report(); - } - } else if IS_MOD (code) { - add_mods(MOD_BIT(code)); - send_keyboard_report(); - } -#ifdef EXTRAKEY_ENABLE - else if IS_SYSTEM (code) { - host_system_send(KEYCODE2SYSTEM(code)); - } else if IS_CONSUMER (code) { - host_consumer_send(KEYCODE2CONSUMER(code)); - } -#endif -#ifdef MOUSEKEY_ENABLE - else if IS_MOUSEKEY (code) { - mousekey_on(code); - mousekey_send(); - } -#endif -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void unregister_code(uint8_t code) { - if (code == KC_NO) { - return; - } -#ifdef LOCKING_SUPPORT_ENABLE - else if (KC_LOCKING_CAPS == code) { -# ifdef LOCKING_RESYNC_ENABLE - // Resync: ignore if caps lock already is off - if (!(host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK))) return; -# endif - add_key(KC_CAPSLOCK); - send_keyboard_report(); - del_key(KC_CAPSLOCK); - send_keyboard_report(); - } - - else if (KC_LOCKING_NUM == code) { -# ifdef LOCKING_RESYNC_ENABLE - if (!(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK))) return; -# endif - add_key(KC_NUMLOCK); - send_keyboard_report(); - del_key(KC_NUMLOCK); - send_keyboard_report(); - } - - else if (KC_LOCKING_SCROLL == code) { -# ifdef LOCKING_RESYNC_ENABLE - if (!(host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK))) return; -# endif - add_key(KC_SCROLLLOCK); - send_keyboard_report(); - del_key(KC_SCROLLLOCK); - send_keyboard_report(); - } -#endif - - else if IS_KEY (code) { - del_key(code); - send_keyboard_report(); - } else if IS_MOD (code) { - del_mods(MOD_BIT(code)); - send_keyboard_report(); - } else if IS_SYSTEM (code) { - host_system_send(0); - } else if IS_CONSUMER (code) { - host_consumer_send(0); - } -#ifdef MOUSEKEY_ENABLE - else if IS_MOUSEKEY (code) { - mousekey_off(code); - mousekey_send(); - } -#endif -} - -/** \brief Tap a keycode with a delay. - * - * \param code The basic keycode to tap. - * \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it. - */ -void tap_code_delay(uint8_t code, uint16_t delay) { - register_code(code); - for (uint16_t i = delay; i > 0; i--) { - wait_ms(1); - } - unregister_code(code); -} - -/** \brief Tap a keycode with the default delay. - * - * \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined. - */ -void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); } - -/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately. - * - * \param mods A bitfield of modifiers to register. - */ -void register_mods(uint8_t mods) { - if (mods) { - add_mods(mods); - send_keyboard_report(); - } -} - -/** \brief Removes the given physically pressed modifiers and sends a keyboard report immediately. - * - * \param mods A bitfield of modifiers to unregister. - */ -void unregister_mods(uint8_t mods) { - if (mods) { - del_mods(mods); - send_keyboard_report(); - } -} - -/** \brief Adds the given weak modifiers and sends a keyboard report immediately. - * - * \param mods A bitfield of modifiers to register. - */ -void register_weak_mods(uint8_t mods) { - if (mods) { - add_weak_mods(mods); - send_keyboard_report(); - } -} - -/** \brief Removes the given weak modifiers and sends a keyboard report immediately. - * - * \param mods A bitfield of modifiers to unregister. - */ -void unregister_weak_mods(uint8_t mods) { - if (mods) { - del_weak_mods(mods); - send_keyboard_report(); - } -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void clear_keyboard(void) { - clear_mods(); - clear_keyboard_but_mods(); -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void clear_keyboard_but_mods(void) { - clear_keys(); - clear_keyboard_but_mods_and_keys(); -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void clear_keyboard_but_mods_and_keys() { -#ifdef EXTRAKEY_ENABLE - host_system_send(0); - host_consumer_send(0); -#endif - clear_weak_mods(); - clear_macro_mods(); - send_keyboard_report(); -#ifdef MOUSEKEY_ENABLE - mousekey_clear(); - mousekey_send(); -#endif -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -bool is_tap_key(keypos_t key) { - action_t action = layer_switch_get_action(key); - return is_tap_action(action); -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -bool is_tap_record(keyrecord_t *record) { -#ifdef COMBO_ENABLE - action_t action; - if (record->keycode) { - action = action_for_keycode(record->keycode); - } else { - action = layer_switch_get_action(record->event.key); - } -#else - action_t action = layer_switch_get_action(record->event.key); -#endif - return is_tap_action(action); -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -bool is_tap_action(action_t action) { - switch (action.kind.id) { - case ACT_LMODS_TAP: - case ACT_RMODS_TAP: - case ACT_LAYER_TAP: - case ACT_LAYER_TAP_EXT: - switch (action.layer_tap.code) { - case KC_NO ... KC_RGUI: - case OP_TAP_TOGGLE: - case OP_ONESHOT: - return true; - } - return false; - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case KC_NO ... KC_RGUI: - case OP_SH_TAP_TOGGLE: - return true; - } - return false; - case ACT_MACRO: - case ACT_FUNCTION: - if (action.func.opt & FUNC_TAP) { - return true; - } - return false; - } - return false; -} - -/** \brief Debug print (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void debug_event(keyevent_t event) { dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time); } -/** \brief Debug print (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void debug_record(keyrecord_t record) { - debug_event(record.event); -#ifndef NO_ACTION_TAPPING - dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' ')); -#endif -} - -/** \brief Debug print (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void debug_action(action_t action) { - switch (action.kind.id) { - case ACT_LMODS: - dprint("ACT_LMODS"); - break; - case ACT_RMODS: - dprint("ACT_RMODS"); - break; - case ACT_LMODS_TAP: - dprint("ACT_LMODS_TAP"); - break; - case ACT_RMODS_TAP: - dprint("ACT_RMODS_TAP"); - break; - case ACT_USAGE: - dprint("ACT_USAGE"); - break; - case ACT_MOUSEKEY: - dprint("ACT_MOUSEKEY"); - break; - case ACT_LAYER: - dprint("ACT_LAYER"); - break; - case ACT_LAYER_MODS: - dprint("ACT_LAYER_MODS"); - break; - case ACT_LAYER_TAP: - dprint("ACT_LAYER_TAP"); - break; - case ACT_LAYER_TAP_EXT: - dprint("ACT_LAYER_TAP_EXT"); - break; - case ACT_MACRO: - dprint("ACT_MACRO"); - break; - case ACT_FUNCTION: - dprint("ACT_FUNCTION"); - break; - case ACT_SWAP_HANDS: - dprint("ACT_SWAP_HANDS"); - break; - default: - dprint("UNKNOWN"); - break; - } - dprintf("[%X:%02X]", action.kind.param >> 8, action.kind.param & 0xff); -} diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h deleted file mode 100644 index 3d357b33b8..0000000000 --- a/tmk_core/common/action.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright 2012,2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#include -#include -#include "keyboard.h" -#include "keycode.h" -#include "action_code.h" -#include "action_macro.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Disable macro and function features when LTO is enabled, since they break */ -#ifdef LTO_ENABLE -# ifndef NO_ACTION_MACRO -# define NO_ACTION_MACRO -# endif -# ifndef NO_ACTION_FUNCTION -# define NO_ACTION_FUNCTION -# endif -#endif - -/* tapping count and state */ -typedef struct { - bool interrupted : 1; - bool reserved2 : 1; - bool reserved1 : 1; - bool reserved0 : 1; - uint8_t count : 4; -} tap_t; - -/* Key event container for recording */ -typedef struct { - keyevent_t event; -#ifndef NO_ACTION_TAPPING - tap_t tap; -#endif -#ifdef COMBO_ENABLE - uint16_t keycode; -#endif -} keyrecord_t; - -/* Execute action per keyevent */ -void action_exec(keyevent_t event); - -/* action for key */ -action_t action_for_key(uint8_t layer, keypos_t key); -action_t action_for_keycode(uint16_t keycode); - -/* macro */ -const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); - -/* user defined special function */ -void action_function(keyrecord_t *record, uint8_t id, uint8_t opt); - -/* keyboard-specific key event (pre)processing */ -bool process_record_quantum(keyrecord_t *record); - -/* Utilities for actions. */ -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) -extern bool disable_action_cache; -#endif - -/* Code for handling one-handed key modifiers. */ -#ifdef SWAP_HANDS_ENABLE -extern bool swap_hands; -extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; -# if (MATRIX_COLS <= 8) -typedef uint8_t swap_state_row_t; -# elif (MATRIX_COLS <= 16) -typedef uint16_t swap_state_row_t; -# elif (MATRIX_COLS <= 32) -typedef uint32_t swap_state_row_t; -# else -# error "MATRIX_COLS: invalid value" -# endif - -void process_hand_swap(keyevent_t *record); -#endif - -void process_record_nocache(keyrecord_t *record); -void process_record(keyrecord_t *record); -void process_record_handler(keyrecord_t *record); -void post_process_record_quantum(keyrecord_t *record); -void process_action(keyrecord_t *record, action_t action); -void register_code(uint8_t code); -void unregister_code(uint8_t code); -void tap_code(uint8_t code); -void tap_code_delay(uint8_t code, uint16_t delay); -void register_mods(uint8_t mods); -void unregister_mods(uint8_t mods); -void register_weak_mods(uint8_t mods); -void unregister_weak_mods(uint8_t mods); -// void set_mods(uint8_t mods); -void clear_keyboard(void); -void clear_keyboard_but_mods(void); -void clear_keyboard_but_mods_and_keys(void); -void layer_switch(uint8_t new_layer); -bool is_tap_key(keypos_t key); -bool is_tap_record(keyrecord_t *record); -bool is_tap_action(action_t action); - -#ifndef NO_ACTION_TAPPING -void process_record_tap_hint(keyrecord_t *record); -#endif - -/* debug */ -void debug_event(keyevent_t event); -void debug_record(keyrecord_t record); -void debug_action(action_t action); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h deleted file mode 100644 index eb18c36ae8..0000000000 --- a/tmk_core/common/action_code.h +++ /dev/null @@ -1,308 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -/** \brief Action codes - * - * 16bit code: action_kind(4bit) + action_parameter(12bit) - * - * Key Actions(00xx) - * ----------------- - * ACT_MODS(000r): - * 000r|0000|0000 0000 No action code - * 000r|0000|0000 0001 Transparent code - * 000r|0000| keycode Key - * 000r|mods|0000 0000 Modifiers - * 000r|mods| keycode Modifiers+Key(Modified key) - * r: Left/Right flag(Left:0, Right:1) - * - * ACT_MODS_TAP(001r): - * 001r|mods|0000 0000 Modifiers with OneShot - * 001r|mods|0000 0001 Modifiers with tap toggle - * 001r|mods|0000 00xx (reserved) - * 001r|mods| keycode Modifiers with Tap Key(Dual role) - * - * Other Keys(01xx) - * ---------------- - * ACT_USAGE(0100): TODO: Not needed? - * 0100|00| usage(10) System control(0x80) - General Desktop page(0x01) - * 0100|01| usage(10) Consumer control(0x01) - Consumer page(0x0C) - * 0100|10| usage(10) (reserved) - * 0100|11| usage(10) (reserved) - * - * ACT_MOUSEKEY(0101): TODO: Merge these two actions to conserve space? - * 0101|xxxx| keycode Mouse key - * - * ACT_SWAP_HANDS(0110): - * 0110|xxxx| keycode Swap hands (keycode on tap, or options) - * - * 0111|xxxx xxxx xxxx (reserved) - * - * Layer Actions(10xx) - * ------------------- - * ACT_LAYER(1000): - * 1000|oo00|pppE BBBB Default Layer Bitwise operation - * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET) - * ppp: 4-bit chunk part(0-7) - * EBBBB: bits and extra bit - * 1000|ooee|pppE BBBB Layer Bitwise Operation - * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET) - * ppp: 4-bit chunk part(0-7) - * EBBBB: bits and extra bit - * ee: on event(01:press, 10:release, 11:both) - * - * ACT_LAYER_MODS(1001): - * 1001|LLLL| mods Layer with modifiers held - * - * ACT_LAYER_TAP(101x): - * 101E|LLLL| keycode On/Off with tap key (0x00-DF)[TAP] - * 101E|LLLL|1110 mods On/Off with modifiers (0xE0-EF)[NOT TAP] - * 101E|LLLL|1111 0000 Invert with tap toggle (0xF0) [TAP] - * 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP] - * 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP] - * 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP] - * 101E|LLLL|1111 0100 One Shot Layer (0xF4) [TAP] - * 101E|LLLL|1111 xxxx Reserved (0xF5-FF) - * ELLLL: layer 0-31(E: extra bit for layer 16-31) - * - * Extensions(11xx) - * ---------------- - * ACT_MACRO(1100): - * 1100|opt | id(8) Macro play? - * 1100|1111| id(8) Macro record? - * - * 1101|xxxx xxxx xxxx (reserved) - * 1110|xxxx xxxx xxxx (reserved) - * - * ACT_FUNCTION(1111): - * 1111| address(12) Function? - * 1111|opt | id(8) Function? - */ -enum action_kind_id { - /* Key Actions */ - ACT_MODS = 0b0000, - ACT_LMODS = 0b0000, - ACT_RMODS = 0b0001, - ACT_MODS_TAP = 0b0010, - ACT_LMODS_TAP = 0b0010, - ACT_RMODS_TAP = 0b0011, - /* Other Keys */ - ACT_USAGE = 0b0100, - ACT_MOUSEKEY = 0b0101, - /* One-hand Support */ - ACT_SWAP_HANDS = 0b0110, - /* Layer Actions */ - ACT_LAYER = 0b1000, - ACT_LAYER_MODS = 0b1001, - ACT_LAYER_TAP = 0b1010, /* Layer 0-15 */ - ACT_LAYER_TAP_EXT = 0b1011, /* Layer 16-31 */ - /* Extensions */ - ACT_MACRO = 0b1100, - ACT_FUNCTION = 0b1111 -}; - -/** \brief Action Code Struct - * - * NOTE: - * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15). - * AVR looks like a little endian in avr-gcc. - * Not portable across compiler/endianness? - * - * Byte order and bit order of 0x1234: - * Big endian: Little endian: - * -------------------- -------------------- - * FEDC BA98 7654 3210 0123 4567 89AB CDEF - * 0001 0010 0011 0100 0010 1100 0100 1000 - * 0x12 0x34 0x34 0x12 - */ -typedef union { - uint16_t code; - struct action_kind { - uint16_t param : 12; - uint8_t id : 4; - } kind; - struct action_key { - uint8_t code : 8; - uint8_t mods : 4; - uint8_t kind : 4; - } key; - struct action_layer_bitop { - uint8_t bits : 4; - uint8_t xbit : 1; - uint8_t part : 3; - uint8_t on : 2; - uint8_t op : 2; - uint8_t kind : 4; - } layer_bitop; - struct action_layer_mods { - uint8_t mods : 8; - uint8_t layer : 4; - uint8_t kind : 4; - } layer_mods; - struct action_layer_tap { - uint8_t code : 8; - uint8_t val : 5; - uint8_t kind : 3; - } layer_tap; - struct action_usage { - uint16_t code : 10; - uint8_t page : 2; - uint8_t kind : 4; - } usage; - struct action_function { - uint8_t id : 8; - uint8_t opt : 4; - uint8_t kind : 4; - } func; - struct action_swap { - uint8_t code : 8; - uint8_t opt : 4; - uint8_t kind : 4; - } swap; -} action_t; - -/* action utility */ -#define ACTION_NO 0 -#define ACTION_TRANSPARENT 1 -#define ACTION(kind, param) ((kind) << 12 | (param)) - -/** \brief Key Actions - * - * Mod bits: 43210 - * bit 0 ||||+- Control - * bit 1 |||+-- Shift - * bit 2 ||+--- Alt - * bit 3 |+---- Gui - * bit 4 +----- LR flag(Left:0, Right:1) - */ -enum mods_bit { - MOD_LCTL = 0x01, - MOD_LSFT = 0x02, - MOD_LALT = 0x04, - MOD_LGUI = 0x08, - MOD_RCTL = 0x11, - MOD_RSFT = 0x12, - MOD_RALT = 0x14, - MOD_RGUI = 0x18, -}; -enum mods_codes { - MODS_ONESHOT = 0x00, - MODS_TAP_TOGGLE = 0x01, -}; -#define ACTION_KEY(key) ACTION(ACT_MODS, (key)) -#define ACTION_MODS(mods) ACTION(ACT_MODS, ((mods)&0x1f) << 8 | 0) -#define ACTION_MODS_KEY(mods, key) ACTION(ACT_MODS, ((mods)&0x1f) << 8 | (key)) -#define ACTION_MODS_TAP_KEY(mods, key) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | (key)) -#define ACTION_MODS_ONESHOT(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | MODS_ONESHOT) -#define ACTION_MODS_TAP_TOGGLE(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | MODS_TAP_TOGGLE) - -/** \brief Other Keys - */ -enum usage_pages { PAGE_SYSTEM, PAGE_CONSUMER }; -#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM << 10 | (id)) -#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER << 10 | (id)) -#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key) - -/** \brief Layer Actions - */ -enum layer_param_on { - ON_PRESS = 1, - ON_RELEASE = 2, - ON_BOTH = 3, -}; - -/** \brief Layer Actions - */ -enum layer_param_bit_op { - OP_BIT_AND = 0, - OP_BIT_OR = 1, - OP_BIT_XOR = 2, - OP_BIT_SET = 3, -}; - -/** \brief Layer Actions - */ -enum layer_param_tap_op { - OP_TAP_TOGGLE = 0xF0, - OP_ON_OFF, - OP_OFF_ON, - OP_SET_CLEAR, - OP_ONESHOT, -}; -#define ACTION_LAYER_BITOP(op, part, bits, on) ACTION(ACT_LAYER, (op) << 10 | (on) << 8 | (part) << 5 | ((bits)&0x1f)) -#define ACTION_LAYER_TAP(layer, key) ACTION(ACT_LAYER_TAP, (layer) << 8 | (key)) -/* Default Layer */ -#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4)) -/* Layer Operation */ -#define ACTION_LAYER_CLEAR(on) ACTION_LAYER_BIT_AND(0, 0, (on)) -#define ACTION_LAYER_MOMENTARY(layer) ACTION_LAYER_ON_OFF(layer) -#define ACTION_LAYER_TOGGLE(layer) ACTION_LAYER_INVERT(layer, ON_RELEASE) -#define ACTION_LAYER_INVERT(layer, on) ACTION_LAYER_BIT_XOR((layer) / 4, 1 << ((layer) % 4), (on)) -#define ACTION_LAYER_ON(layer, on) ACTION_LAYER_BIT_OR((layer) / 4, 1 << ((layer) % 4), (on)) -#define ACTION_LAYER_OFF(layer, on) ACTION_LAYER_BIT_AND((layer) / 4, ~(1 << ((layer) % 4)), (on)) -#define ACTION_LAYER_SET(layer, on) ACTION_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4), (on)) -#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF) -#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON) -#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR) -#define ACTION_LAYER_ONESHOT(layer) ACTION_LAYER_TAP((layer), OP_ONESHOT) -#define ACTION_LAYER_MODS(layer, mods) ACTION(ACT_LAYER_MODS, (layer) << 8 | (mods)) -/* With Tapping */ -#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key)) -#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE) -/* Bitwise Operation */ -#define ACTION_LAYER_BIT_AND(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on)) -#define ACTION_LAYER_BIT_OR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), (on)) -#define ACTION_LAYER_BIT_XOR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on)) -#define ACTION_LAYER_BIT_SET(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on)) -/* Default Layer Bitwise Operation */ -#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0) -#define ACTION_DEFAULT_LAYER_BIT_OR(part, bits) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), 0) -#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0) -#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0) - -/* Macro */ -#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id)) -#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP << 8 | (id)) -#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt) << 8 | (id)) -/* Function */ -enum function_opts { - FUNC_TAP = 0x8, /* indciates function is tappable */ -}; -#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id)) -#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP << 8 | (id)) -#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt) << 8 | (id)) -/* OneHand Support */ -enum swap_hands_param_tap_op { - OP_SH_TOGGLE = 0xF0, - OP_SH_TAP_TOGGLE, - OP_SH_ON_OFF, - OP_SH_OFF_ON, - OP_SH_OFF, - OP_SH_ON, - OP_SH_ONESHOT, -}; - -#define ACTION_SWAP_HANDS() ACTION_SWAP_HANDS_ON_OFF() -#define ACTION_SWAP_HANDS_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TOGGLE) -#define ACTION_SWAP_HANDS_TAP_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TAP_TOGGLE) -#define ACTION_SWAP_HANDS_ONESHOT() ACTION(ACT_SWAP_HANDS, OP_SH_ONESHOT) -#define ACTION_SWAP_HANDS_TAP_KEY(key) ACTION(ACT_SWAP_HANDS, key) -#define ACTION_SWAP_HANDS_ON_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_ON_OFF) -#define ACTION_SWAP_HANDS_OFF_ON() ACTION(ACT_SWAP_HANDS, OP_SH_OFF_ON) -#define ACTION_SWAP_HANDS_ON() ACTION(ACT_SWAP_HANDS, OP_SH_ON) -#define ACTION_SWAP_HANDS_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_OFF) diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c deleted file mode 100644 index ed1a4bd20d..0000000000 --- a/tmk_core/common/action_layer.c +++ /dev/null @@ -1,279 +0,0 @@ -#include -#include "keyboard.h" -#include "action.h" -#include "util.h" -#include "action_layer.h" - -#ifdef DEBUG_ACTION -# include "debug.h" -#else -# include "nodebug.h" -#endif - -/** \brief Default Layer State - */ -layer_state_t default_layer_state = 0; - -/** \brief Default Layer State Set At user Level - * - * Run user code on default layer state change - */ -__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state) { return state; } - -/** \brief Default Layer State Set At Keyboard Level - * - * Run keyboard code on default layer state change - */ -__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state) { return default_layer_state_set_user(state); } - -/** \brief Default Layer State Set - * - * Static function to set the default layer state, prints debug info and clears keys - */ -static void default_layer_state_set(layer_state_t state) { - state = default_layer_state_set_kb(state); - debug("default_layer_state: "); - default_layer_debug(); - debug(" to "); - default_layer_state = state; - default_layer_debug(); - debug("\n"); -#ifdef STRICT_LAYER_RELEASE - clear_keyboard_but_mods(); // To avoid stuck keys -#else - clear_keyboard_but_mods_and_keys(); // Don't reset held keys -#endif -} - -/** \brief Default Layer Print - * - * Print out the hex value of the 32-bit default layer state, as well as the value of the highest bit. - */ -void default_layer_debug(void) { dprintf("%08lX(%u)", default_layer_state, get_highest_layer(default_layer_state)); } - -/** \brief Default Layer Set - * - * Sets the default layer state. - */ -void default_layer_set(layer_state_t state) { default_layer_state_set(state); } - -#ifndef NO_ACTION_LAYER -/** \brief Default Layer Or - * - * Turns on the default layer based on matching bits between specifed layer and existing layer state - */ -void default_layer_or(layer_state_t state) { default_layer_state_set(default_layer_state | state); } -/** \brief Default Layer And - * - * Turns on default layer based on matching enabled bits between specifed layer and existing layer state - */ -void default_layer_and(layer_state_t state) { default_layer_state_set(default_layer_state & state); } -/** \brief Default Layer Xor - * - * Turns on default layer based on non-matching bits between specifed layer and existing layer state - */ -void default_layer_xor(layer_state_t state) { default_layer_state_set(default_layer_state ^ state); } -#endif - -#ifndef NO_ACTION_LAYER -/** \brief Keymap Layer State - */ -layer_state_t layer_state = 0; - -/** \brief Layer state set user - * - * Runs user code on layer state change - */ -__attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) { return state; } - -/** \brief Layer state set keyboard - * - * Runs keyboard code on layer state change - */ -__attribute__((weak)) layer_state_t layer_state_set_kb(layer_state_t state) { return layer_state_set_user(state); } - -/** \brief Layer state set - * - * Sets the layer to match the specifed state (a bitmask) - */ -void layer_state_set(layer_state_t state) { - state = layer_state_set_kb(state); - dprint("layer_state: "); - layer_debug(); - dprint(" to "); - layer_state = state; - layer_debug(); - dprintln(); -# ifdef STRICT_LAYER_RELEASE - clear_keyboard_but_mods(); // To avoid stuck keys -# else - clear_keyboard_but_mods_and_keys(); // Don't reset held keys -# endif -} - -/** \brief Layer clear - * - * Turn off all layers - */ -void layer_clear(void) { layer_state_set(0); } - -/** \brief Layer state is - * - * Return whether the given state is on (it might still be shadowed by a higher state, though) - */ -bool layer_state_is(uint8_t layer) { return layer_state_cmp(layer_state, layer); } - -/** \brief Layer state compare - * - * Used for comparing layers {mostly used for unit testing} - */ -bool layer_state_cmp(layer_state_t cmp_layer_state, uint8_t layer) { - if (!cmp_layer_state) { - return layer == 0; - } - return (cmp_layer_state & ((layer_state_t)1 << layer)) != 0; -} - -/** \brief Layer move - * - * Turns on the given layer and turn off all other layers - */ -void layer_move(uint8_t layer) { layer_state_set((layer_state_t)1 << layer); } - -/** \brief Layer on - * - * Turns on given layer - */ -void layer_on(uint8_t layer) { layer_state_set(layer_state | ((layer_state_t)1 << layer)); } - -/** \brief Layer off - * - * Turns off given layer - */ -void layer_off(uint8_t layer) { layer_state_set(layer_state & ~((layer_state_t)1 << layer)); } - -/** \brief Layer invert - * - * Toggle the given layer (set it if it's unset, or unset it if it's set) - */ -void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ ((layer_state_t)1 << layer)); } - -/** \brief Layer or - * - * Turns on layers based on matching bits between specifed layer and existing layer state - */ -void layer_or(layer_state_t state) { layer_state_set(layer_state | state); } -/** \brief Layer and - * - * Turns on layers based on matching enabled bits between specifed layer and existing layer state - */ -void layer_and(layer_state_t state) { layer_state_set(layer_state & state); } -/** \brief Layer xor - * - * Turns on layers based on non-matching bits between specifed layer and existing layer state - */ -void layer_xor(layer_state_t state) { layer_state_set(layer_state ^ state); } - -/** \brief Layer debug printing - * - * Print out the hex value of the 32-bit layer state, as well as the value of the highest bit. - */ -void layer_debug(void) { dprintf("%08lX(%u)", layer_state, get_highest_layer(layer_state)); } -#endif - -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) -/** \brief source layer cache - */ - -uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}}; - -/** \brief update source layers cache - * - * Updates the cached keys when changing layers - */ -void update_source_layers_cache(keypos_t key, uint8_t layer) { - const uint8_t key_number = key.col + (key.row * MATRIX_COLS); - const uint8_t storage_row = key_number / 8; - const uint8_t storage_bit = key_number % 8; - - for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { - source_layers_cache[storage_row][bit_number] ^= (-((layer & (1U << bit_number)) != 0) ^ source_layers_cache[storage_row][bit_number]) & (1U << storage_bit); - } -} - -/** \brief read source layers cache - * - * reads the cached keys stored when the layer was changed - */ -uint8_t read_source_layers_cache(keypos_t key) { - const uint8_t key_number = key.col + (key.row * MATRIX_COLS); - const uint8_t storage_row = key_number / 8; - const uint8_t storage_bit = key_number % 8; - uint8_t layer = 0; - - for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { - layer |= ((source_layers_cache[storage_row][bit_number] & (1U << storage_bit)) != 0) << bit_number; - } - - return layer; -} -#endif - -/** \brief Store or get action (FIXME: Needs better summary) - * - * Make sure the action triggered when the key is released is the same - * one as the one triggered on press. It's important for the mod keys - * when the layer is switched after the down event but before the up - * event as they may get stuck otherwise. - */ -action_t store_or_get_action(bool pressed, keypos_t key) { -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) - if (disable_action_cache) { - return layer_switch_get_action(key); - } - - uint8_t layer; - - if (pressed) { - layer = layer_switch_get_layer(key); - update_source_layers_cache(key, layer); - } else { - layer = read_source_layers_cache(key); - } - return action_for_key(layer, key); -#else - return layer_switch_get_action(key); -#endif -} - -/** \brief Layer switch get layer - * - * Gets the layer based on key info - */ -uint8_t layer_switch_get_layer(keypos_t key) { -#ifndef NO_ACTION_LAYER - action_t action; - action.code = ACTION_TRANSPARENT; - - layer_state_t layers = layer_state | default_layer_state; - /* check top layer first */ - for (int8_t i = MAX_LAYER - 1; i >= 0; i--) { - if (layers & ((layer_state_t)1 << i)) { - action = action_for_key(i, key); - if (action.code != ACTION_TRANSPARENT) { - return i; - } - } - } - /* fall back to layer 0 */ - return 0; -#else - return get_highest_layer(default_layer_state); -#endif -} - -/** \brief Layer switch get layer - * - * Gets action code based on key position - */ -action_t layer_switch_get_action(keypos_t key) { return action_for_key(layer_switch_get_layer(key), key); } diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h deleted file mode 100644 index b87d096eed..0000000000 --- a/tmk_core/common/action_layer.h +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#include -#include "keyboard.h" -#include "action.h" - -#ifdef DYNAMIC_KEYMAP_ENABLE -# ifndef DYNAMIC_KEYMAP_LAYER_COUNT -# define DYNAMIC_KEYMAP_LAYER_COUNT 4 -# endif -# if DYNAMIC_KEYMAP_LAYER_COUNT <= 8 -# ifndef LAYER_STATE_8BIT -# define LAYER_STATE_8BIT -# endif -# elif DYNAMIC_KEYMAP_LAYER_COUNT <= 16 -# ifndef LAYER_STATE_16BIT -# define LAYER_STATE_16BIT -# endif -# else -# ifndef LAYER_STATE_32BIT -# define LAYER_STATE_32BIT -# endif -# endif -#endif - -#if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT) -# define LAYER_STATE_32BIT -#endif - -#if defined(LAYER_STATE_8BIT) -typedef uint8_t layer_state_t; -# define MAX_LAYER_BITS 3 -# ifndef MAX_LAYER -# define MAX_LAYER 8 -# endif -# define get_highest_layer(state) biton(state) -#elif defined(LAYER_STATE_16BIT) -typedef uint16_t layer_state_t; -# define MAX_LAYER_BITS 4 -# ifndef MAX_LAYER -# define MAX_LAYER 16 -# endif -# define get_highest_layer(state) biton16(state) -#elif defined(LAYER_STATE_32BIT) -typedef uint32_t layer_state_t; -# define MAX_LAYER_BITS 5 -# ifndef MAX_LAYER -# define MAX_LAYER 32 -# endif -# define get_highest_layer(state) biton32(state) -#else -# error Layer Mask size not specified. HOW?! -#endif - -/* - * Default Layer - */ -extern layer_state_t default_layer_state; -void default_layer_debug(void); -void default_layer_set(layer_state_t state); - -__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state); -__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state); - -#ifndef NO_ACTION_LAYER -/* bitwise operation */ -void default_layer_or(layer_state_t state); -void default_layer_and(layer_state_t state); -void default_layer_xor(layer_state_t state); -#else -# define default_layer_or(state) -# define default_layer_and(state) -# define default_layer_xor(state) -#endif - -/* - * Keymap Layer - */ -#ifndef NO_ACTION_LAYER -extern layer_state_t layer_state; - -void layer_state_set(layer_state_t state); -bool layer_state_is(uint8_t layer); -bool layer_state_cmp(layer_state_t layer1, uint8_t layer2); - -void layer_debug(void); -void layer_clear(void); -void layer_move(uint8_t layer); -void layer_on(uint8_t layer); -void layer_off(uint8_t layer); -void layer_invert(uint8_t layer); -/* bitwise operation */ -void layer_or(layer_state_t state); -void layer_and(layer_state_t state); -void layer_xor(layer_state_t state); -layer_state_t layer_state_set_user(layer_state_t state); -layer_state_t layer_state_set_kb(layer_state_t state); -#else -# define layer_state 0 - -# define layer_state_set(layer) -# define layer_state_is(layer) (layer == 0) -# define layer_state_cmp(state, layer) (state == 0 ? layer == 0 : (state & (layer_state_t)1 << layer) != 0) - -# define layer_debug() -# define layer_clear() -# define layer_move(layer) (void)layer -# define layer_on(layer) (void)layer -# define layer_off(layer) (void)layer -# define layer_invert(layer) (void)layer -# define layer_or(state) (void)state -# define layer_and(state) (void)state -# define layer_xor(state) (void)state -# define layer_state_set_kb(state) (void)state -# define layer_state_set_user(state) (void)state -#endif - -/* pressed actions cache */ -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) - -void update_source_layers_cache(keypos_t key, uint8_t layer); -uint8_t read_source_layers_cache(keypos_t key); -#endif -action_t store_or_get_action(bool pressed, keypos_t key); - -/* return the topmost non-transparent layer currently associated with key */ -uint8_t layer_switch_get_layer(keypos_t key); - -/* return action depending on current layer status */ -action_t layer_switch_get_action(keypos_t key); diff --git a/tmk_core/common/action_macro.c b/tmk_core/common/action_macro.c deleted file mode 100644 index 92228c0ba8..0000000000 --- a/tmk_core/common/action_macro.c +++ /dev/null @@ -1,93 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#include "action.h" -#include "action_util.h" -#include "action_macro.h" -#include "wait.h" - -#ifdef DEBUG_ACTION -# include "debug.h" -#else -# include "nodebug.h" -#endif - -#ifndef NO_ACTION_MACRO - -# define MACRO_READ() (macro = MACRO_GET(macro_p++)) -/** \brief Action Macro Play - * - * FIXME: Needs doc - */ -void action_macro_play(const macro_t *macro_p) { - macro_t macro = END; - uint8_t interval = 0; - - if (!macro_p) return; - while (true) { - switch (MACRO_READ()) { - case KEY_DOWN: - MACRO_READ(); - dprintf("KEY_DOWN(%02X)\n", macro); - if (IS_MOD(macro)) { - add_macro_mods(MOD_BIT(macro)); - send_keyboard_report(); - } else { - register_code(macro); - } - break; - case KEY_UP: - MACRO_READ(); - dprintf("KEY_UP(%02X)\n", macro); - if (IS_MOD(macro)) { - del_macro_mods(MOD_BIT(macro)); - send_keyboard_report(); - } else { - unregister_code(macro); - } - break; - case WAIT: - MACRO_READ(); - dprintf("WAIT(%u)\n", macro); - { - uint8_t ms = macro; - while (ms--) wait_ms(1); - } - break; - case INTERVAL: - interval = MACRO_READ(); - dprintf("INTERVAL(%u)\n", interval); - break; - case 0x04 ... 0x73: - dprintf("DOWN(%02X)\n", macro); - register_code(macro); - break; - case 0x84 ... 0xF3: - dprintf("UP(%02X)\n", macro); - unregister_code(macro & 0x7F); - break; - case END: - default: - return; - } - // interval - { - uint8_t ms = interval; - while (ms--) wait_ms(1); - } - } -} -#endif diff --git a/tmk_core/common/action_macro.h b/tmk_core/common/action_macro.h deleted file mode 100644 index 685e2c6ffc..0000000000 --- a/tmk_core/common/action_macro.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#include -#include "progmem.h" - -typedef uint8_t macro_t; - -#define MACRO_NONE (macro_t *)0 -#define MACRO(...) \ - ({ \ - static const macro_t __m[] PROGMEM = {__VA_ARGS__}; \ - &__m[0]; \ - }) -#define MACRO_GET(p) pgm_read_byte(p) - -// Sends press when the macro key is pressed, release when release, or tap_macro when the key has been tapped -#define MACRO_TAP_HOLD(record, press, release, tap_macro) (((record)->event.pressed) ? (((record)->tap.count <= 0 || (record)->tap.interrupted) ? (press) : MACRO_NONE) : (((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (tap_macro) : (release))) - -// Holds down the modifier mod when the macro key is held, or sends macro instead when tapped -#define MACRO_TAP_HOLD_MOD(record, macro, mod) MACRO_TAP_HOLD(record, (MACRO(D(mod), END)), MACRO(U(mod), END), macro) - -// Holds down the modifier mod when the macro key is held, or pressed a shifted key when tapped (eg: shift+3 for #) -#define MACRO_TAP_SHFT_KEY_HOLD_MOD(record, key, mod) MACRO_TAP_HOLD_MOD(record, (MACRO(I(10), D(LSFT), T(key), U(LSFT), END)), mod) - -// Momentary switch layer when held, sends macro if tapped -#define MACRO_TAP_HOLD_LAYER(record, macro, layer) \ - (((record)->event.pressed) ? (((record)->tap.count <= 0 || (record)->tap.interrupted) ? ({ \ - layer_on((layer)); \ - MACRO_NONE; \ - }) \ - : MACRO_NONE) \ - : (((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (macro) : ({ \ - layer_off((layer)); \ - MACRO_NONE; \ - }))) - -// Momentary switch layer when held, presses a shifted key when tapped (eg: shift+3 for #) -#define MACRO_TAP_SHFT_KEY_HOLD_LAYER(record, key, layer) MACRO_TAP_HOLD_LAYER(record, MACRO(I(10), D(LSFT), T(key), U(LSFT), END), layer) - -#ifndef NO_ACTION_MACRO -void action_macro_play(const macro_t *macro_p); -#else -# define action_macro_play(macro) -#endif - -/* Macro commands - * code(0x04-73) // key down(1byte) - * code(0x04-73) | 0x80 // key up(1byte) - * { KEY_DOWN, code(0x04-0xff) } // key down(2bytes) - * { KEY_UP, code(0x04-0xff) } // key up(2bytes) - * WAIT // wait milli-seconds - * INTERVAL // set interval between macro commands - * END // stop macro execution - * - * Ideas(Not implemented): - * modifiers - * system usage - * consumer usage - * unicode usage - * function call - * conditionals - * loop - */ -enum macro_command_id { - /* 0x00 - 0x03 */ - END = 0x00, - KEY_DOWN, - KEY_UP, - - /* 0x04 - 0x73 (reserved for keycode down) */ - - /* 0x74 - 0x83 */ - WAIT = 0x74, - INTERVAL, - - /* 0x84 - 0xf3 (reserved for keycode up) */ - - /* 0xf4 - 0xff */ -}; - -/* TODO: keycode:0x04-0x73 can be handled by 1byte command else 2bytes are needed - * if keycode between 0x04 and 0x73 - * keycode / (keycode|0x80) - * else - * {KEY_DOWN, keycode} / {KEY_UP, keycode} - */ -#define DOWN(key) KEY_DOWN, (key) -#define UP(key) KEY_UP, (key) -#define TYPE(key) DOWN(key), UP(key) -#define WAIT(ms) WAIT, (ms) -#define INTERVAL(ms) INTERVAL, (ms) - -/* key down */ -#define D(key) DOWN(KC_##key) -/* key up */ -#define U(key) UP(KC_##key) -/* key type */ -#define T(key) TYPE(KC_##key) -/* wait */ -#define W(ms) WAIT(ms) -/* interval */ -#define I(ms) INTERVAL(ms) - -/* for backward comaptibility */ -#define MD(key) DOWN(KC_##key) -#define MU(key) UP(KC_##key) diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c deleted file mode 100644 index 36839f9faf..0000000000 --- a/tmk_core/common/action_tapping.c +++ /dev/null @@ -1,456 +0,0 @@ -#include -#include -#include "action.h" -#include "action_layer.h" -#include "action_tapping.h" -#include "keycode.h" -#include "timer.h" - -#ifdef DEBUG_ACTION -# include "debug.h" -#else -# include "nodebug.h" -#endif - -#ifndef NO_ACTION_TAPPING - -# define IS_TAPPING() !IS_NOEVENT(tapping_key.event) -# define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed) -# define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) -# define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) -#ifndef COMBO_ENABLE -# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key))) -#else -# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode) -#endif - -__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; } - -# ifdef TAPPING_TERM_PER_KEY -# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_record_keycode(&tapping_key, false), &tapping_key)) -# else -# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM) -# endif - -# ifdef TAPPING_FORCE_HOLD_PER_KEY -__attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { return false; } -# endif - -# ifdef PERMISSIVE_HOLD_PER_KEY -__attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { return false; } -# endif - -# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY -__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; } -# endif - -static keyrecord_t tapping_key = {}; -static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; -static uint8_t waiting_buffer_head = 0; -static uint8_t waiting_buffer_tail = 0; - -static bool process_tapping(keyrecord_t *record); -static bool waiting_buffer_enq(keyrecord_t record); -static void waiting_buffer_clear(void); -static bool waiting_buffer_typed(keyevent_t event); -static bool waiting_buffer_has_anykey_pressed(void); -static void waiting_buffer_scan_tap(void); -static void debug_tapping_key(void); -static void debug_waiting_buffer(void); - -/** \brief Action Tapping Process - * - * FIXME: Needs doc - */ -void action_tapping_process(keyrecord_t record) { - if (process_tapping(&record)) { - if (!IS_NOEVENT(record.event)) { - debug("processed: "); - debug_record(record); - debug("\n"); - } - } else { - if (!waiting_buffer_enq(record)) { - // clear all in case of overflow. - debug("OVERFLOW: CLEAR ALL STATES\n"); - clear_keyboard(); - waiting_buffer_clear(); - tapping_key = (keyrecord_t){}; - } - } - - // process waiting_buffer - if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) { - debug("---- action_exec: process waiting_buffer -----\n"); - } - for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { - if (process_tapping(&waiting_buffer[waiting_buffer_tail])) { - debug("processed: waiting_buffer["); - debug_dec(waiting_buffer_tail); - debug("] = "); - debug_record(waiting_buffer[waiting_buffer_tail]); - debug("\n\n"); - } else { - break; - } - } - if (!IS_NOEVENT(record.event)) { - debug("\n"); - } -} - -/** \brief Tapping - * - * Rule: Tap key is typed(pressed and released) within TAPPING_TERM. - * (without interfering by typing other key) - */ -/* return true when key event is processed or consumed. */ -bool process_tapping(keyrecord_t *keyp) { - keyevent_t event = keyp->event; - - // if tapping - if (IS_TAPPING_PRESSED()) { - if (WITHIN_TAPPING_TERM(event)) { - if (tapping_key.tap.count == 0) { - if (IS_TAPPING_RECORD(keyp) && !event.pressed) { - // first tap! - debug("Tapping: First tap(0->1).\n"); - tapping_key.tap.count = 1; - debug_tapping_key(); - process_record(&tapping_key); - - // copy tapping state - keyp->tap = tapping_key.tap; - // enqueue - return false; - } - /* Process a key typed within TAPPING_TERM - * This can register the key before settlement of tapping, - * useful for long TAPPING_TERM but may prevent fast typing. - */ -# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) - else if ((( -# ifdef TAPPING_TERM_PER_KEY - get_tapping_term(get_record_keycode(&tapping_key, false), keyp) -# else - TAPPING_TERM -# endif - >= 500) - -# ifdef PERMISSIVE_HOLD_PER_KEY - || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp) -# elif defined(PERMISSIVE_HOLD) - || true -# endif - ) && - IS_RELEASED(event) && waiting_buffer_typed(event)) { - debug("Tapping: End. No tap. Interfered by typing key\n"); - process_record(&tapping_key); - tapping_key = (keyrecord_t){}; - debug_tapping_key(); - // enqueue - return false; - } -# endif - /* Process release event of a key pressed before tapping starts - * Without this unexpected repeating will occur with having fast repeating setting - * https://github.com/tmk/tmk_keyboard/issues/60 - */ - else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) { - // Modifier should be retained till end of this tapping. - action_t action = layer_switch_get_action(event.key); - switch (action.kind.id) { - case ACT_LMODS: - case ACT_RMODS: - if (action.key.mods && !action.key.code) return false; - if (IS_MOD(action.key.code)) return false; - break; - case ACT_LMODS_TAP: - case ACT_RMODS_TAP: - if (action.key.mods && keyp->tap.count == 0) return false; - if (IS_MOD(action.key.code)) return false; - break; - } - // Release of key should be process immediately. - debug("Tapping: release event of a key pressed before tapping\n"); - process_record(keyp); - return true; - } else { - // set interrupted flag when other key preesed during tapping - if (event.pressed) { - tapping_key.tap.interrupted = true; -# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) -# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) - if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp)) -# endif - { - debug("Tapping: End. No tap. Interfered by pressed key\n"); - process_record(&tapping_key); - tapping_key = (keyrecord_t){}; - debug_tapping_key(); - // enqueue - return false; - } -# endif - } - // enqueue - return false; - } - } - // tap_count > 0 - else { - if (IS_TAPPING_RECORD(keyp) && !event.pressed) { - debug("Tapping: Tap release("); - debug_dec(tapping_key.tap.count); - debug(")\n"); - keyp->tap = tapping_key.tap; - process_record(keyp); - tapping_key = *keyp; - debug_tapping_key(); - return true; - } else if (is_tap_record(keyp) && event.pressed) { - if (tapping_key.tap.count > 1) { - debug("Tapping: Start new tap with releasing last tap(>1).\n"); - // unregister key - process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, -#ifdef COMBO_ENABLE - .keycode = tapping_key.keycode, -#endif - }); - } else { - debug("Tapping: Start while last tap(1).\n"); - } - tapping_key = *keyp; - waiting_buffer_scan_tap(); - debug_tapping_key(); - return true; - } else { - if (!IS_NOEVENT(event)) { - debug("Tapping: key event while last tap(>0).\n"); - } - process_record(keyp); - return true; - } - } - } - // after TAPPING_TERM - else { - if (tapping_key.tap.count == 0) { - debug("Tapping: End. Timeout. Not tap(0): "); - debug_event(event); - debug("\n"); - process_record(&tapping_key); - tapping_key = (keyrecord_t){}; - debug_tapping_key(); - return false; - } else { - if (IS_TAPPING_RECORD(keyp) && !event.pressed) { - debug("Tapping: End. last timeout tap release(>0)."); - keyp->tap = tapping_key.tap; - process_record(keyp); - tapping_key = (keyrecord_t){}; - return true; - } else if (is_tap_record(keyp) && event.pressed) { - if (tapping_key.tap.count > 1) { - debug("Tapping: Start new tap with releasing last timeout tap(>1).\n"); - // unregister key - process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, -#ifdef COMBO_ENABLE - .keycode = tapping_key.keycode, -#endif - }); - } else { - debug("Tapping: Start while last timeout tap(1).\n"); - } - tapping_key = *keyp; - waiting_buffer_scan_tap(); - debug_tapping_key(); - return true; - } else { - if (!IS_NOEVENT(event)) { - debug("Tapping: key event while last timeout tap(>0).\n"); - } - process_record(keyp); - return true; - } - } - } - } else if (IS_TAPPING_RELEASED()) { - if (WITHIN_TAPPING_TERM(event)) { - if (event.pressed) { - if (IS_TAPPING_RECORD(keyp)) { -//# ifndef TAPPING_FORCE_HOLD -# if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY) - if ( -# ifdef TAPPING_FORCE_HOLD_PER_KEY - !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) && -# endif - !tapping_key.tap.interrupted && tapping_key.tap.count > 0) { - // sequential tap. - keyp->tap = tapping_key.tap; - if (keyp->tap.count < 15) keyp->tap.count += 1; - debug("Tapping: Tap press("); - debug_dec(keyp->tap.count); - debug(")\n"); - process_record(keyp); - tapping_key = *keyp; - debug_tapping_key(); - return true; - } -# endif - // FIX: start new tap again - tapping_key = *keyp; - return true; - } else if (is_tap_record(keyp)) { - // Sequential tap can be interfered with other tap key. - debug("Tapping: Start with interfering other tap.\n"); - tapping_key = *keyp; - waiting_buffer_scan_tap(); - debug_tapping_key(); - return true; - } else { - // should none in buffer - // FIX: interrupted when other key is pressed - tapping_key.tap.interrupted = true; - process_record(keyp); - return true; - } - } else { - if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n"); - process_record(keyp); - return true; - } - } else { - // FIX: process_action here? - // timeout. no sequential tap. - debug("Tapping: End(Timeout after releasing last tap): "); - debug_event(event); - debug("\n"); - tapping_key = (keyrecord_t){}; - debug_tapping_key(); - return false; - } - } - // not tapping state - else { - if (event.pressed && is_tap_record(keyp)) { - debug("Tapping: Start(Press tap key).\n"); - tapping_key = *keyp; - process_record_tap_hint(&tapping_key); - waiting_buffer_scan_tap(); - debug_tapping_key(); - return true; - } else { - process_record(keyp); - return true; - } - } -} - -/** \brief Waiting buffer enq - * - * FIXME: Needs docs - */ -bool waiting_buffer_enq(keyrecord_t record) { - if (IS_NOEVENT(record.event)) { - return true; - } - - if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) { - debug("waiting_buffer_enq: Over flow.\n"); - return false; - } - - waiting_buffer[waiting_buffer_head] = record; - waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE; - - debug("waiting_buffer_enq: "); - debug_waiting_buffer(); - return true; -} - -/** \brief Waiting buffer clear - * - * FIXME: Needs docs - */ -void waiting_buffer_clear(void) { - waiting_buffer_head = 0; - waiting_buffer_tail = 0; -} - -/** \brief Waiting buffer typed - * - * FIXME: Needs docs - */ -bool waiting_buffer_typed(keyevent_t event) { - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) { - return true; - } - } - return false; -} - -/** \brief Waiting buffer has anykey pressed - * - * FIXME: Needs docs - */ -__attribute__((unused)) bool waiting_buffer_has_anykey_pressed(void) { - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - if (waiting_buffer[i].event.pressed) return true; - } - return false; -} - -/** \brief Scan buffer for tapping - * - * FIXME: Needs docs - */ -void waiting_buffer_scan_tap(void) { - // tapping already is settled - if (tapping_key.tap.count > 0) return; - // invalid state: tapping_key released && tap.count == 0 - if (!tapping_key.event.pressed) return; - - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - if (IS_TAPPING_KEY(waiting_buffer[i].event.key) && !waiting_buffer[i].event.pressed && WITHIN_TAPPING_TERM(waiting_buffer[i].event)) { - tapping_key.tap.count = 1; - waiting_buffer[i].tap.count = 1; - process_record(&tapping_key); - - debug("waiting_buffer_scan_tap: found at ["); - debug_dec(i); - debug("]\n"); - debug_waiting_buffer(); - return; - } - } -} - -/** \brief Tapping key debug print - * - * FIXME: Needs docs - */ -static void debug_tapping_key(void) { - debug("TAPPING_KEY="); - debug_record(tapping_key); - debug("\n"); -} - -/** \brief Waiting buffer debug print - * - * FIXME: Needs docs - */ -static void debug_waiting_buffer(void) { - debug("{ "); - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - debug("["); - debug_dec(i); - debug("]="); - debug_record(waiting_buffer[i]); - debug(" "); - } - debug("}\n"); -} - -#endif diff --git a/tmk_core/common/action_tapping.h b/tmk_core/common/action_tapping.h deleted file mode 100644 index 7de8049c7f..0000000000 --- a/tmk_core/common/action_tapping.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -/* period of tapping(ms) */ -#ifndef TAPPING_TERM -# define TAPPING_TERM 200 -#endif - -/* tap count needed for toggling a feature */ -#ifndef TAPPING_TOGGLE -# define TAPPING_TOGGLE 5 -#endif - -#define WAITING_BUFFER_SIZE 8 - -#ifndef NO_ACTION_TAPPING -uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache); -uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache); -void action_tapping_process(keyrecord_t record); - -uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record); -bool get_permissive_hold(uint16_t keycode, keyrecord_t *record); -bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record); -bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record); -bool get_retro_tapping(uint16_t keycode, keyrecord_t *record); -#endif diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c deleted file mode 100644 index 2b3c00cba0..0000000000 --- a/tmk_core/common/action_util.c +++ /dev/null @@ -1,455 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#include "host.h" -#include "report.h" -#include "debug.h" -#include "action_util.h" -#include "action_layer.h" -#include "timer.h" -#include "keycode_config.h" - -extern keymap_config_t keymap_config; - -static uint8_t real_mods = 0; -static uint8_t weak_mods = 0; -static uint8_t macro_mods = 0; -#ifdef KEY_OVERRIDE_ENABLE -static uint8_t weak_override_mods = 0; -static uint8_t suppressed_mods = 0; -#endif - -#ifdef USB_6KRO_ENABLE -# define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) -# define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) -# define RO_INC(a) RO_ADD(a, 1) -# define RO_DEC(a) RO_SUB(a, 1) -static int8_t cb_head = 0; -static int8_t cb_tail = 0; -static int8_t cb_count = 0; -#endif - -// TODO: pointer variable is not needed -// report_keyboard_t keyboard_report = {}; -report_keyboard_t *keyboard_report = &(report_keyboard_t){}; - -extern inline void add_key(uint8_t key); -extern inline void del_key(uint8_t key); -extern inline void clear_keys(void); - -#ifndef NO_ACTION_ONESHOT -static uint8_t oneshot_mods = 0; -static uint8_t oneshot_locked_mods = 0; -uint8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; } -void set_oneshot_locked_mods(uint8_t mods) { - if (mods != oneshot_locked_mods) { - oneshot_locked_mods = mods; - oneshot_locked_mods_changed_kb(oneshot_locked_mods); - } -} -void clear_oneshot_locked_mods(void) { - if (oneshot_locked_mods) { - oneshot_locked_mods = 0; - oneshot_locked_mods_changed_kb(oneshot_locked_mods); - } -} -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) -static uint16_t oneshot_time = 0; -bool has_oneshot_mods_timed_out(void) { return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; } -# else -bool has_oneshot_mods_timed_out(void) { return false; } -# endif -#endif - -/* oneshot layer */ -#ifndef NO_ACTION_ONESHOT -/** \brief oneshot_layer_data bits - * LLLL LSSS - * where: - * L => are layer bits - * S => oneshot state bits - */ -static int8_t oneshot_layer_data = 0; - -inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; } -inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; } - -# ifdef SWAP_HANDS_ENABLE -enum { - SHO_OFF, - SHO_ACTIVE, // Swap hands button was pressed, and we didn't send any swapped keys yet - SHO_PRESSED, // Swap hands button is currently pressed - SHO_USED, // Swap hands button is still pressed, and we already sent swapped keys -} swap_hands_oneshot = SHO_OFF; -# endif - -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) -static uint16_t oneshot_layer_time = 0; -inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); } -# ifdef SWAP_HANDS_ENABLE -static uint16_t oneshot_swaphands_time = 0; -inline bool has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= ONESHOT_TIMEOUT && (swap_hands_oneshot == SHO_ACTIVE); } -# endif -# endif - -# ifdef SWAP_HANDS_ENABLE - -void set_oneshot_swaphands(void) { - swap_hands_oneshot = SHO_PRESSED; - swap_hands = true; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_swaphands_time = timer_read(); - if (oneshot_layer_time != 0) { - oneshot_layer_time = oneshot_swaphands_time; - } -# endif -} - -void release_oneshot_swaphands(void) { - if (swap_hands_oneshot == SHO_PRESSED) { - swap_hands_oneshot = SHO_ACTIVE; - } - if (swap_hands_oneshot == SHO_USED) { - clear_oneshot_swaphands(); - } -} - -void use_oneshot_swaphands(void) { - if (swap_hands_oneshot == SHO_PRESSED) { - swap_hands_oneshot = SHO_USED; - } - if (swap_hands_oneshot == SHO_ACTIVE) { - clear_oneshot_swaphands(); - } -} - -void clear_oneshot_swaphands(void) { - swap_hands_oneshot = SHO_OFF; - swap_hands = false; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_swaphands_time = 0; -# endif -} - -# endif - -/** \brief Set oneshot layer - * - * FIXME: needs doc - */ -void set_oneshot_layer(uint8_t layer, uint8_t state) { - if (!keymap_config.oneshot_disable) { - oneshot_layer_data = layer << 3 | state; - layer_on(layer); -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_layer_time = timer_read(); -# endif - oneshot_layer_changed_kb(get_oneshot_layer()); - } else { - layer_on(layer); - } -} -/** \brief Reset oneshot layer - * - * FIXME: needs doc - */ -void reset_oneshot_layer(void) { - oneshot_layer_data = 0; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_layer_time = 0; -# endif - oneshot_layer_changed_kb(get_oneshot_layer()); -} -/** \brief Clear oneshot layer - * - * FIXME: needs doc - */ -void clear_oneshot_layer_state(oneshot_fullfillment_t state) { - uint8_t start_state = oneshot_layer_data; - oneshot_layer_data &= ~state; - if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) { - layer_off(get_oneshot_layer()); - reset_oneshot_layer(); - } -} -/** \brief Is oneshot layer active - * - * FIXME: needs doc - */ -bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); } - -/** \brief set oneshot - * - * FIXME: needs doc - */ -void oneshot_set(bool active) { - if (keymap_config.oneshot_disable != active) { - keymap_config.oneshot_disable = active; - eeconfig_update_keymap(keymap_config.raw); - dprintf("Oneshot: active: %d\n", active); - } -} - -/** \brief toggle oneshot - * - * FIXME: needs doc - */ -void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); } - -/** \brief enable oneshot - * - * FIXME: needs doc - */ -void oneshot_enable(void) { oneshot_set(true); } - -/** \brief disable oneshot - * - * FIXME: needs doc - */ -void oneshot_disable(void) { oneshot_set(false); } - -bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; } - -#endif - -/** \brief Send keyboard report - * - * FIXME: needs doc - */ -void send_keyboard_report(void) { - keyboard_report->mods = real_mods; - keyboard_report->mods |= weak_mods; - keyboard_report->mods |= macro_mods; - -#ifndef NO_ACTION_ONESHOT - if (oneshot_mods) { -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - if (has_oneshot_mods_timed_out()) { - dprintf("Oneshot: timeout\n"); - clear_oneshot_mods(); - } -# endif - keyboard_report->mods |= oneshot_mods; - if (has_anykey(keyboard_report)) { - clear_oneshot_mods(); - } - } - -#endif - -#ifdef KEY_OVERRIDE_ENABLE - // These need to be last to be able to properly control key overrides - keyboard_report->mods &= ~suppressed_mods; - keyboard_report->mods |= weak_override_mods; -#endif - - host_keyboard_send(keyboard_report); -} - -/** \brief Get mods - * - * FIXME: needs doc - */ -uint8_t get_mods(void) { return real_mods; } -/** \brief add mods - * - * FIXME: needs doc - */ -void add_mods(uint8_t mods) { real_mods |= mods; } -/** \brief del mods - * - * FIXME: needs doc - */ -void del_mods(uint8_t mods) { real_mods &= ~mods; } -/** \brief set mods - * - * FIXME: needs doc - */ -void set_mods(uint8_t mods) { real_mods = mods; } -/** \brief clear mods - * - * FIXME: needs doc - */ -void clear_mods(void) { real_mods = 0; } - -/** \brief get weak mods - * - * FIXME: needs doc - */ -uint8_t get_weak_mods(void) { return weak_mods; } -/** \brief add weak mods - * - * FIXME: needs doc - */ -void add_weak_mods(uint8_t mods) { weak_mods |= mods; } -/** \brief del weak mods - * - * FIXME: needs doc - */ -void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; } -/** \brief set weak mods - * - * FIXME: needs doc - */ -void set_weak_mods(uint8_t mods) { weak_mods = mods; } -/** \brief clear weak mods - * - * FIXME: needs doc - */ -void clear_weak_mods(void) { weak_mods = 0; } - -#ifdef KEY_OVERRIDE_ENABLE -/** \brief set weak mods used by key overrides. DO not call this manually - */ -void set_weak_override_mods(uint8_t mods) { weak_override_mods = mods; } -/** \brief clear weak mods used by key overrides. DO not call this manually - */ -void clear_weak_override_mods(void) { weak_override_mods = 0; } - -/** \brief set suppressed mods used by key overrides. DO not call this manually - */ -void set_suppressed_override_mods(uint8_t mods) { suppressed_mods = mods; } -/** \brief clear suppressed mods used by key overrides. DO not call this manually - */ -void clear_suppressed_override_mods(void) { suppressed_mods = 0; } -#endif - -/* macro modifier */ -/** \brief get macro mods - * - * FIXME: needs doc - */ -uint8_t get_macro_mods(void) { return macro_mods; } -/** \brief add macro mods - * - * FIXME: needs doc - */ -void add_macro_mods(uint8_t mods) { macro_mods |= mods; } -/** \brief del macro mods - * - * FIXME: needs doc - */ -void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; } -/** \brief set macro mods - * - * FIXME: needs doc - */ -void set_macro_mods(uint8_t mods) { macro_mods = mods; } -/** \brief clear macro mods - * - * FIXME: needs doc - */ -void clear_macro_mods(void) { macro_mods = 0; } - -#ifndef NO_ACTION_ONESHOT -/** \brief get oneshot mods - * - * FIXME: needs doc - */ -uint8_t get_oneshot_mods(void) { return oneshot_mods; } - -void add_oneshot_mods(uint8_t mods) { - if ((oneshot_mods & mods) != mods) { -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = timer_read(); -# endif - oneshot_mods |= mods; - oneshot_mods_changed_kb(mods); - } -} - -void del_oneshot_mods(uint8_t mods) { - if (oneshot_mods & mods) { - oneshot_mods &= ~mods; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = oneshot_mods ? timer_read() : 0; -# endif - oneshot_mods_changed_kb(oneshot_mods); - } -} - -/** \brief set oneshot mods - * - * FIXME: needs doc - */ -void set_oneshot_mods(uint8_t mods) { - if (!keymap_config.oneshot_disable) { - if (oneshot_mods != mods) { -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = timer_read(); -# endif - oneshot_mods = mods; - oneshot_mods_changed_kb(mods); - } - } -} - -/** \brief clear oneshot mods - * - * FIXME: needs doc - */ -void clear_oneshot_mods(void) { - if (oneshot_mods) { - oneshot_mods = 0; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = 0; -# endif - oneshot_mods_changed_kb(oneshot_mods); - } -} -#endif - -/** \brief Called when the one shot modifiers have been changed. - * - * \param mods Contains the active modifiers active after the change. - */ -__attribute__((weak)) void oneshot_locked_mods_changed_user(uint8_t mods) {} - -/** \brief Called when the locked one shot modifiers have been changed. - * - * \param mods Contains the active modifiers active after the change. - */ -__attribute__((weak)) void oneshot_locked_mods_changed_kb(uint8_t mods) { oneshot_locked_mods_changed_user(mods); } - -/** \brief Called when the one shot modifiers have been changed. - * - * \param mods Contains the active modifiers active after the change. - */ -__attribute__((weak)) void oneshot_mods_changed_user(uint8_t mods) {} - -/** \brief Called when the one shot modifiers have been changed. - * - * \param mods Contains the active modifiers active after the change. - */ -__attribute__((weak)) void oneshot_mods_changed_kb(uint8_t mods) { oneshot_mods_changed_user(mods); } - -/** \brief Called when the one shot layers have been changed. - * - * \param layer Contains the layer that is toggled on, or zero when toggled off. - */ -__attribute__((weak)) void oneshot_layer_changed_user(uint8_t layer) {} - -/** \brief Called when the one shot layers have been changed. - * - * \param layer Contains the layer that is toggled on, or zero when toggled off. - */ -__attribute__((weak)) void oneshot_layer_changed_kb(uint8_t layer) { oneshot_layer_changed_user(layer); } - -/** \brief inspect keyboard state - * - * FIXME: needs doc - */ -uint8_t has_anymod(void) { return bitpop(real_mods); } diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h deleted file mode 100644 index f2b3897ae5..0000000000 --- a/tmk_core/common/action_util.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#include -#include "report.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern report_keyboard_t *keyboard_report; - -void send_keyboard_report(void); - -/* key */ -inline void add_key(uint8_t key) { add_key_to_report(keyboard_report, key); } - -inline void del_key(uint8_t key) { del_key_from_report(keyboard_report, key); } - -inline void clear_keys(void) { clear_keys_from_report(keyboard_report); } - -/* modifier */ -uint8_t get_mods(void); -void add_mods(uint8_t mods); -void del_mods(uint8_t mods); -void set_mods(uint8_t mods); -void clear_mods(void); - -/* weak modifier */ -uint8_t get_weak_mods(void); -void add_weak_mods(uint8_t mods); -void del_weak_mods(uint8_t mods); -void set_weak_mods(uint8_t mods); -void clear_weak_mods(void); - -/* macro modifier */ -uint8_t get_macro_mods(void); -void add_macro_mods(uint8_t mods); -void del_macro_mods(uint8_t mods); -void set_macro_mods(uint8_t mods); -void clear_macro_mods(void); - -/* oneshot modifier */ -uint8_t get_oneshot_mods(void); -void add_oneshot_mods(uint8_t mods); -void del_oneshot_mods(uint8_t mods); -void set_oneshot_mods(uint8_t mods); -void clear_oneshot_mods(void); -bool has_oneshot_mods_timed_out(void); - -uint8_t get_oneshot_locked_mods(void); -void set_oneshot_locked_mods(uint8_t mods); -void clear_oneshot_locked_mods(void); - -typedef enum { ONESHOT_PRESSED = 0b01, ONESHOT_OTHER_KEY_PRESSED = 0b10, ONESHOT_START = 0b11, ONESHOT_TOGGLED = 0b100 } oneshot_fullfillment_t; -void set_oneshot_layer(uint8_t layer, uint8_t state); -uint8_t get_oneshot_layer(void); -void clear_oneshot_layer_state(oneshot_fullfillment_t state); -void reset_oneshot_layer(void); -bool is_oneshot_layer_active(void); -uint8_t get_oneshot_layer_state(void); -bool has_oneshot_layer_timed_out(void); -bool has_oneshot_swaphands_timed_out(void); - -void oneshot_locked_mods_changed_user(uint8_t mods); -void oneshot_locked_mods_changed_kb(uint8_t mods); -void oneshot_mods_changed_user(uint8_t mods); -void oneshot_mods_changed_kb(uint8_t mods); -void oneshot_layer_changed_user(uint8_t layer); -void oneshot_layer_changed_kb(uint8_t layer); - -void oneshot_toggle(void); -void oneshot_enable(void); -void oneshot_disable(void); -bool is_oneshot_enabled(void); - -/* inspect */ -uint8_t has_anymod(void); - -#ifdef SWAP_HANDS_ENABLE -void set_oneshot_swaphands(void); -void release_oneshot_swaphands(void); -void use_oneshot_swaphands(void); -void clear_oneshot_swaphands(void); -#endif - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c deleted file mode 100644 index ffa56ab56d..0000000000 --- a/tmk_core/common/eeconfig.c +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include -#include "eeprom.h" -#include "eeconfig.h" -#include "action_layer.h" - -#ifdef STM32_EEPROM_ENABLE -# include -# include "eeprom_stm32.h" -#endif - -#if defined(EEPROM_DRIVER) -# include "eeprom_driver.h" -#endif - -#if defined(HAPTIC_ENABLE) -# include "haptic.h" -#endif - -/** \brief eeconfig enable - * - * FIXME: needs doc - */ -__attribute__((weak)) void eeconfig_init_user(void) { - // Reset user EEPROM value to blank, rather than to a set value - eeconfig_update_user(0); -} - -__attribute__((weak)) void eeconfig_init_kb(void) { - // Reset Keyboard EEPROM value to blank, rather than to a set value - eeconfig_update_kb(0); - - eeconfig_init_user(); -} - -/* - * FIXME: needs doc - */ -void eeconfig_init_quantum(void) { -#ifdef STM32_EEPROM_ENABLE - EEPROM_Erase(); -#endif -#if defined(EEPROM_DRIVER) - eeprom_driver_erase(); -#endif - eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); - eeprom_update_byte(EECONFIG_DEBUG, 0); - eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0); - default_layer_state = 0; - eeprom_update_byte(EECONFIG_KEYMAP_LOWER_BYTE, 0); - eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, 0); - eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0); - eeprom_update_byte(EECONFIG_BACKLIGHT, 0); - eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default - eeprom_update_dword(EECONFIG_RGBLIGHT, 0); - eeprom_update_byte(EECONFIG_STENOMODE, 0); - eeprom_update_dword(EECONFIG_HAPTIC, 0); - eeprom_update_byte(EECONFIG_VELOCIKEY, 0); - eeprom_update_dword(EECONFIG_RGB_MATRIX, 0); - eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0); - - // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS - // within the emulated eeprom via dfu-util or another tool -#if defined INIT_EE_HANDS_LEFT -# pragma message "Faking EE_HANDS for left hand" - eeprom_update_byte(EECONFIG_HANDEDNESS, 1); -#elif defined INIT_EE_HANDS_RIGHT -# pragma message "Faking EE_HANDS for right hand" - eeprom_update_byte(EECONFIG_HANDEDNESS, 0); -#endif - -#if defined(HAPTIC_ENABLE) - haptic_reset(); -#else - // this is used in case haptic is disabled, but we still want sane defaults - // in the haptic configuration eeprom. All zero will trigger a haptic_reset - // when a haptic-enabled firmware is loaded onto the keyboard. - eeprom_update_dword(EECONFIG_HAPTIC, 0); -#endif - - eeconfig_init_kb(); -} - -/** \brief eeconfig initialization - * - * FIXME: needs doc - */ -void eeconfig_init(void) { eeconfig_init_quantum(); } - -/** \brief eeconfig enable - * - * FIXME: needs doc - */ -void eeconfig_enable(void) { eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); } - -/** \brief eeconfig disable - * - * FIXME: needs doc - */ -void eeconfig_disable(void) { -#ifdef STM32_EEPROM_ENABLE - EEPROM_Erase(); -#endif -#if defined(EEPROM_DRIVER) - eeprom_driver_erase(); -#endif - eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); -} - -/** \brief eeconfig is enabled - * - * FIXME: needs doc - */ -bool eeconfig_is_enabled(void) { return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER); } - -/** \brief eeconfig is disabled - * - * FIXME: needs doc - */ -bool eeconfig_is_disabled(void) { return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF); } - -/** \brief eeconfig read debug - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); } -/** \brief eeconfig update debug - * - * FIXME: needs doc - */ -void eeconfig_update_debug(uint8_t val) { eeprom_update_byte(EECONFIG_DEBUG, val); } - -/** \brief eeconfig read default layer - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); } -/** \brief eeconfig update default layer - * - * FIXME: needs doc - */ -void eeconfig_update_default_layer(uint8_t val) { eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); } - -/** \brief eeconfig read keymap - * - * FIXME: needs doc - */ -uint16_t eeconfig_read_keymap(void) { return (eeprom_read_byte(EECONFIG_KEYMAP_LOWER_BYTE) | (eeprom_read_byte(EECONFIG_KEYMAP_UPPER_BYTE) << 8)); } -/** \brief eeconfig update keymap - * - * FIXME: needs doc - */ -void eeconfig_update_keymap(uint16_t val) { - eeprom_update_byte(EECONFIG_KEYMAP_LOWER_BYTE, val & 0xFF); - eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, (val >> 8) & 0xFF); -} - -/** \brief eeconfig read audio - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO); } -/** \brief eeconfig update audio - * - * FIXME: needs doc - */ -void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); } - -/** \brief eeconfig read kb - * - * FIXME: needs doc - */ -uint32_t eeconfig_read_kb(void) { return eeprom_read_dword(EECONFIG_KEYBOARD); } -/** \brief eeconfig update kb - * - * FIXME: needs doc - */ -void eeconfig_update_kb(uint32_t val) { eeprom_update_dword(EECONFIG_KEYBOARD, val); } - -/** \brief eeconfig read user - * - * FIXME: needs doc - */ -uint32_t eeconfig_read_user(void) { return eeprom_read_dword(EECONFIG_USER); } -/** \brief eeconfig update user - * - * FIXME: needs doc - */ -void eeconfig_update_user(uint32_t val) { eeprom_update_dword(EECONFIG_USER, val); } - -/** \brief eeconfig read haptic - * - * FIXME: needs doc - */ -uint32_t eeconfig_read_haptic(void) { return eeprom_read_dword(EECONFIG_HAPTIC); } -/** \brief eeconfig update haptic - * - * FIXME: needs doc - */ -void eeconfig_update_haptic(uint32_t val) { eeprom_update_dword(EECONFIG_HAPTIC, val); } - -/** \brief eeconfig read split handedness - * - * FIXME: needs doc - */ -bool eeconfig_read_handedness(void) { return !!eeprom_read_byte(EECONFIG_HANDEDNESS); } -/** \brief eeconfig update split handedness - * - * FIXME: needs doc - */ -void eeconfig_update_handedness(bool val) { eeprom_update_byte(EECONFIG_HANDEDNESS, !!val); } diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h deleted file mode 100644 index a88071729d..0000000000 --- a/tmk_core/common/eeconfig.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -Copyright 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#include -#include - -#ifndef EECONFIG_MAGIC_NUMBER -# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA // When changing, decrement this value to avoid future re-init issues -#endif -#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF - -/* EEPROM parameter address */ -#define EECONFIG_MAGIC (uint16_t *)0 -#define EECONFIG_DEBUG (uint8_t *)2 -#define EECONFIG_DEFAULT_LAYER (uint8_t *)3 -#define EECONFIG_KEYMAP (uint8_t *)4 -#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5 -#define EECONFIG_BACKLIGHT (uint8_t *)6 -#define EECONFIG_AUDIO (uint8_t *)7 -#define EECONFIG_RGBLIGHT (uint32_t *)8 -#define EECONFIG_UNICODEMODE (uint8_t *)12 -#define EECONFIG_STENOMODE (uint8_t *)13 -// EEHANDS for two handed boards -#define EECONFIG_HANDEDNESS (uint8_t *)14 -#define EECONFIG_KEYBOARD (uint32_t *)15 -#define EECONFIG_USER (uint32_t *)19 -#define EECONFIG_VELOCIKEY (uint8_t *)23 - -#define EECONFIG_HAPTIC (uint32_t *)24 - -// Mutually exclusive -#define EECONFIG_LED_MATRIX (uint32_t *)28 -#define EECONFIG_RGB_MATRIX (uint32_t *)28 -// Speed & Flags -#define EECONFIG_LED_MATRIX_EXTENDED (uint16_t *)32 -#define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32 - -// TODO: Combine these into a single word and single block of EEPROM -#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 -// Size of EEPROM being used, other code can refer to this for available EEPROM -#define EECONFIG_SIZE 35 -/* debug bit */ -#define EECONFIG_DEBUG_ENABLE (1 << 0) -#define EECONFIG_DEBUG_MATRIX (1 << 1) -#define EECONFIG_DEBUG_KEYBOARD (1 << 2) -#define EECONFIG_DEBUG_MOUSE (1 << 3) - -/* keyconf bit */ -#define EECONFIG_KEYMAP_SWAP_CONTROL_CAPSLOCK (1 << 0) -#define EECONFIG_KEYMAP_CAPSLOCK_TO_CONTROL (1 << 1) -#define EECONFIG_KEYMAP_SWAP_LALT_LGUI (1 << 2) -#define EECONFIG_KEYMAP_SWAP_RALT_RGUI (1 << 3) -#define EECONFIG_KEYMAP_NO_GUI (1 << 4) -#define EECONFIG_KEYMAP_SWAP_GRAVE_ESC (1 << 5) -#define EECONFIG_KEYMAP_SWAP_BACKSLASH_BACKSPACE (1 << 6) -#define EECONFIG_KEYMAP_NKRO (1 << 7) - -#define EECONFIG_KEYMAP_LOWER_BYTE EECONFIG_KEYMAP - -bool eeconfig_is_enabled(void); -bool eeconfig_is_disabled(void); - -void eeconfig_init(void); -void eeconfig_init_quantum(void); -void eeconfig_init_kb(void); -void eeconfig_init_user(void); - -void eeconfig_enable(void); - -void eeconfig_disable(void); - -uint8_t eeconfig_read_debug(void); -void eeconfig_update_debug(uint8_t val); - -uint8_t eeconfig_read_default_layer(void); -void eeconfig_update_default_layer(uint8_t val); - -uint16_t eeconfig_read_keymap(void); -void eeconfig_update_keymap(uint16_t val); - -#ifdef AUDIO_ENABLE -uint8_t eeconfig_read_audio(void); -void eeconfig_update_audio(uint8_t val); -#endif - -uint32_t eeconfig_read_kb(void); -void eeconfig_update_kb(uint32_t val); -uint32_t eeconfig_read_user(void); -void eeconfig_update_user(uint32_t val); - -#ifdef HAPTIC_ENABLE -uint32_t eeconfig_read_haptic(void); -void eeconfig_update_haptic(uint32_t val); -#endif - -bool eeconfig_read_handedness(void); -void eeconfig_update_handedness(bool val); diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c deleted file mode 100644 index fcc51973fd..0000000000 --- a/tmk_core/common/keyboard.c +++ /dev/null @@ -1,565 +0,0 @@ -/* -Copyright 2011, 2012, 2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include -#include "keyboard.h" -#include "matrix.h" -#include "keymap.h" -#include "host.h" -#include "led.h" -#include "keycode.h" -#include "timer.h" -#include "sync_timer.h" -#include "print.h" -#include "debug.h" -#include "command.h" -#include "util.h" -#include "sendchar.h" -#include "eeconfig.h" -#include "action_layer.h" -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" -#endif -#ifdef MOUSEKEY_ENABLE -# include "mousekey.h" -#endif -#ifdef PS2_MOUSE_ENABLE -# include "ps2_mouse.h" -#endif -#ifdef SERIAL_MOUSE_ENABLE -# include "serial_mouse.h" -#endif -#ifdef ADB_MOUSE_ENABLE -# include "adb.h" -#endif -#ifdef RGBLIGHT_ENABLE -# include "rgblight.h" -#endif -#ifdef LED_MATRIX_ENABLE -# include "led_matrix.h" -#endif -#ifdef RGB_MATRIX_ENABLE -# include "rgb_matrix.h" -#endif -#ifdef ENCODER_ENABLE -# include "encoder.h" -#endif -#ifdef STENO_ENABLE -# include "process_steno.h" -#endif -#ifdef SERIAL_LINK_ENABLE -# include "serial_link/system/serial_link.h" -#endif -#ifdef VISUALIZER_ENABLE -# include "visualizer/visualizer.h" -#endif -#ifdef POINTING_DEVICE_ENABLE -# include "pointing_device.h" -#endif -#ifdef MIDI_ENABLE -# include "process_midi.h" -#endif -#ifdef JOYSTICK_ENABLE -# include "process_joystick.h" -#endif -#ifdef HD44780_ENABLE -# include "hd44780.h" -#endif -#ifdef QWIIC_ENABLE -# include "qwiic.h" -#endif -#ifdef OLED_DRIVER_ENABLE -# include "oled_driver.h" -#endif -#ifdef ST7565_ENABLE -# include "st7565.h" -#endif -#ifdef VELOCIKEY_ENABLE -# include "velocikey.h" -#endif -#ifdef VIA_ENABLE -# include "via.h" -#endif -#ifdef DIP_SWITCH_ENABLE -# include "dip_switch.h" -#endif -#ifdef STM32_EEPROM_ENABLE -# include "eeprom_stm32.h" -#endif -#ifdef EEPROM_DRIVER -# include "eeprom_driver.h" -#endif -#if defined(CRC_ENABLE) -# include "crc.h" -#endif -#ifdef DIGITIZER_ENABLE -# include "digitizer.h" -#endif - -static uint32_t last_input_modification_time = 0; -uint32_t last_input_activity_time(void) { return last_input_modification_time; } -uint32_t last_input_activity_elapsed(void) { return timer_elapsed32(last_input_modification_time); } - -static uint32_t last_matrix_modification_time = 0; -uint32_t last_matrix_activity_time(void) { return last_matrix_modification_time; } -uint32_t last_matrix_activity_elapsed(void) { return timer_elapsed32(last_matrix_modification_time); } -void last_matrix_activity_trigger(void) { last_matrix_modification_time = last_input_modification_time = timer_read32(); } - -static uint32_t last_encoder_modification_time = 0; -uint32_t last_encoder_activity_time(void) { return last_encoder_modification_time; } -uint32_t last_encoder_activity_elapsed(void) { return timer_elapsed32(last_encoder_modification_time); } -void last_encoder_activity_trigger(void) { last_encoder_modification_time = last_input_modification_time = timer_read32(); } - -// Only enable this if console is enabled to print to -#if defined(DEBUG_MATRIX_SCAN_RATE) -static uint32_t matrix_timer = 0; -static uint32_t matrix_scan_count = 0; -static uint32_t last_matrix_scan_count = 0; - -void matrix_scan_perf_task(void) { - matrix_scan_count++; - - uint32_t timer_now = timer_read32(); - if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) { -# if defined(CONSOLE_ENABLE) - dprintf("matrix scan frequency: %lu\n", matrix_scan_count); -# endif - last_matrix_scan_count = matrix_scan_count; - matrix_timer = timer_now; - matrix_scan_count = 0; - } -} - -uint32_t get_matrix_scan_rate(void) { return last_matrix_scan_count; } -#else -# define matrix_scan_perf_task() -#endif - -#ifdef MATRIX_HAS_GHOST -extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; -static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata) { - matrix_row_t out = 0; - for (uint8_t col = 0; col < MATRIX_COLS; col++) { - // read each key in the row data and check if the keymap defines it as a real key - if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1 << col))) { - // this creates new row data, if a key is defined in the keymap, it will be set here - out |= 1 << col; - } - } - return out; -} - -static inline bool popcount_more_than_one(matrix_row_t rowdata) { - rowdata &= rowdata - 1; // if there are less than two bits (keys) set, rowdata will become zero - return rowdata; -} - -static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) { - /* No ghost exists when less than 2 keys are down on the row. - If there are "active" blanks in the matrix, the key can't be pressed by the user, - there is no doubt as to which keys are really being pressed. - The ghosts will be ignored, they are KC_NO. */ - rowdata = get_real_keys(row, rowdata); - if ((popcount_more_than_one(rowdata)) == 0) { - return false; - } - /* Ghost occurs when the row shares a column line with other row, - and two columns are read on each row. Blanks in the matrix don't matter, - so they are filtered out. - If there are two or more real keys pressed and they match columns with - at least two of another row's real keys, the row will be ignored. Keep in mind, - we are checking one row at a time, not all of them at once. - */ - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)) { - return true; - } - } - return false; -} - -#endif - -void disable_jtag(void) { -// To use PF4-7 (PC2-5 on ATmega32A), disable JTAG by writing JTD bit twice within four cycles. -#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) - MCUCR |= _BV(JTD); - MCUCR |= _BV(JTD); -#elif defined(__AVR_ATmega32A__) - MCUCSR |= _BV(JTD); - MCUCSR |= _BV(JTD); -#endif -} - -/** \brief matrix_setup - * - * FIXME: needs doc - */ -__attribute__((weak)) void matrix_setup(void) {} - -/** \brief keyboard_pre_init_user - * - * FIXME: needs doc - */ -__attribute__((weak)) void keyboard_pre_init_user(void) {} - -/** \brief keyboard_pre_init_kb - * - * FIXME: needs doc - */ -__attribute__((weak)) void keyboard_pre_init_kb(void) { keyboard_pre_init_user(); } - -/** \brief keyboard_post_init_user - * - * FIXME: needs doc - */ - -__attribute__((weak)) void keyboard_post_init_user() {} - -/** \brief keyboard_post_init_kb - * - * FIXME: needs doc - */ - -__attribute__((weak)) void keyboard_post_init_kb(void) { keyboard_post_init_user(); } - -/** \brief keyboard_setup - * - * FIXME: needs doc - */ -void keyboard_setup(void) { -#ifndef NO_JTAG_DISABLE - disable_jtag(); -#endif - print_set_sendchar(sendchar); -#ifdef STM32_EEPROM_ENABLE - EEPROM_Init(); -#endif -#ifdef EEPROM_DRIVER - eeprom_driver_init(); -#endif - matrix_setup(); - keyboard_pre_init_kb(); -} - -/** \brief is_keyboard_master - * - * FIXME: needs doc - */ -__attribute__((weak)) bool is_keyboard_master(void) { return true; } - -/** \brief is_keyboard_left - * - * FIXME: needs doc - */ -__attribute__((weak)) bool is_keyboard_left(void) { return true; } - -/** \brief should_process_keypress - * - * Override this function if you have a condition where keypresses processing should change: - * - splits where the slave side needs to process for rgb/oled functionality - */ -__attribute__((weak)) bool should_process_keypress(void) { return is_keyboard_master(); } - -/** \brief housekeeping_task_kb - * - * Override this function if you have a need to execute code for every keyboard main loop iteration. - * This is specific to keyboard-level functionality. - */ -__attribute__((weak)) void housekeeping_task_kb(void) {} - -/** \brief housekeeping_task_user - * - * Override this function if you have a need to execute code for every keyboard main loop iteration. - * This is specific to user/keymap-level functionality. - */ -__attribute__((weak)) void housekeeping_task_user(void) {} - -/** \brief housekeeping_task - * - * Invokes hooks for executing code after QMK is done after each loop iteration. - */ -void housekeeping_task(void) { - housekeeping_task_kb(); - housekeeping_task_user(); -} - -/** \brief keyboard_init - * - * FIXME: needs doc - */ -void keyboard_init(void) { - timer_init(); - sync_timer_init(); - matrix_init(); -#if defined(CRC_ENABLE) - crc_init(); -#endif -#ifdef VIA_ENABLE - via_init(); -#endif -#ifdef QWIIC_ENABLE - qwiic_init(); -#endif -#ifdef OLED_DRIVER_ENABLE - oled_init(OLED_ROTATION_0); -#endif -#ifdef ST7565_ENABLE - st7565_init(DISPLAY_ROTATION_0); -#endif -#ifdef PS2_MOUSE_ENABLE - ps2_mouse_init(); -#endif -#ifdef SERIAL_MOUSE_ENABLE - serial_mouse_init(); -#endif -#ifdef ADB_MOUSE_ENABLE - adb_mouse_init(); -#endif -#ifdef BACKLIGHT_ENABLE - backlight_init(); -#endif -#ifdef RGBLIGHT_ENABLE - rgblight_init(); -#endif -#ifdef ENCODER_ENABLE - encoder_init(); -#endif -#ifdef STENO_ENABLE - steno_init(); -#endif -#ifdef POINTING_DEVICE_ENABLE - pointing_device_init(); -#endif -#if defined(NKRO_ENABLE) && defined(FORCE_NKRO) - keymap_config.nkro = 1; - eeconfig_update_keymap(keymap_config.raw); -#endif -#ifdef DIP_SWITCH_ENABLE - dip_switch_init(); -#endif - -#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE) - debug_enable = true; -#endif - - keyboard_post_init_kb(); /* Always keep this last */ -} - -/** \brief key_event_task - * - * This function is responsible for calling into other systems when they need to respond to electrical switch press events. - * This is differnet than keycode events as no layer processing, or filtering occurs. - */ -void switch_events(uint8_t row, uint8_t col, bool pressed) { -#if defined(LED_MATRIX_ENABLE) - process_led_matrix(row, col, pressed); -#endif -#if defined(RGB_MATRIX_ENABLE) - process_rgb_matrix(row, col, pressed); -#endif -} - -/** \brief Keyboard task: Do keyboard routine jobs - * - * Do routine keyboard jobs: - * - * * scan matrix - * * handle mouse movements - * * run visualizer code - * * handle midi commands - * * light LEDs - * - * This is repeatedly called as fast as possible. - */ -void keyboard_task(void) { - static matrix_row_t matrix_prev[MATRIX_ROWS]; - static uint8_t led_status = 0; - matrix_row_t matrix_row = 0; - matrix_row_t matrix_change = 0; -#ifdef QMK_KEYS_PER_SCAN - uint8_t keys_processed = 0; -#endif -#ifdef ENCODER_ENABLE - bool encoders_changed = false; -#endif - - uint8_t matrix_changed = matrix_scan(); - if (matrix_changed) last_matrix_activity_trigger(); - - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row = matrix_get_row(r); - matrix_change = matrix_row ^ matrix_prev[r]; - if (matrix_change) { -#ifdef MATRIX_HAS_GHOST - if (has_ghost_in_row(r, matrix_row)) { - continue; - } -#endif - if (debug_matrix) matrix_print(); - matrix_row_t col_mask = 1; - for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) { - if (matrix_change & col_mask) { - if (should_process_keypress()) { - action_exec((keyevent_t){ - .key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */ - }); - } - // record a processed key - matrix_prev[r] ^= col_mask; - - switch_events(r, c, (matrix_row & col_mask)); - -#ifdef QMK_KEYS_PER_SCAN - // only jump out if we have processed "enough" keys. - if (++keys_processed >= QMK_KEYS_PER_SCAN) -#endif - // process a key per task call - goto MATRIX_LOOP_END; - } - } - } - } - // call with pseudo tick event when no real key event. -#ifdef QMK_KEYS_PER_SCAN - // we can get here with some keys processed now. - if (!keys_processed) -#endif - action_exec(TICK); - -MATRIX_LOOP_END: - -#ifdef DEBUG_MATRIX_SCAN_RATE - matrix_scan_perf_task(); -#endif - -#if defined(RGBLIGHT_ENABLE) - rgblight_task(); -#endif - -#ifdef LED_MATRIX_ENABLE - led_matrix_task(); -#endif -#ifdef RGB_MATRIX_ENABLE - rgb_matrix_task(); -#endif - -#if defined(BACKLIGHT_ENABLE) -# if defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS) - backlight_task(); -# endif -#endif - -#ifdef ENCODER_ENABLE - encoders_changed = encoder_read(); - if (encoders_changed) last_encoder_activity_trigger(); -#endif - -#ifdef QWIIC_ENABLE - qwiic_task(); -#endif - -#ifdef OLED_DRIVER_ENABLE - oled_task(); -# ifndef OLED_DISABLE_TIMEOUT - // Wake up oled if user is using those fabulous keys or spinning those encoders! -# ifdef ENCODER_ENABLE - if (matrix_changed || encoders_changed) oled_on(); -# else - if (matrix_changed) oled_on(); -# endif -# endif -#endif - -#ifdef ST7565_ENABLE - st7565_task(); -# ifndef ST7565_DISABLE_TIMEOUT - // Wake up display if user is using those fabulous keys or spinning those encoders! -# ifdef ENCODER_ENABLE - if (matrix_changed || encoders_changed) st7565_on(); -# else - if (matrix_changed) st7565_on(); -# endif -# endif -#endif - -#ifdef MOUSEKEY_ENABLE - // mousekey repeat & acceleration - mousekey_task(); -#endif - -#ifdef PS2_MOUSE_ENABLE - ps2_mouse_task(); -#endif - -#ifdef SERIAL_MOUSE_ENABLE - serial_mouse_task(); -#endif - -#ifdef ADB_MOUSE_ENABLE - adb_mouse_task(); -#endif - -#ifdef SERIAL_LINK_ENABLE - serial_link_update(); -#endif - -#ifdef VISUALIZER_ENABLE - visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds()); -#endif - -#ifdef POINTING_DEVICE_ENABLE - pointing_device_task(); -#endif - -#ifdef MIDI_ENABLE - midi_task(); -#endif - -#ifdef VELOCIKEY_ENABLE - if (velocikey_enabled()) { - velocikey_decelerate(); - } -#endif - -#ifdef JOYSTICK_ENABLE - joystick_task(); -#endif - -#ifdef DIGITIZER_ENABLE - digitizer_task(); -#endif - - // update LED - if (led_status != host_keyboard_leds()) { - led_status = host_keyboard_leds(); - keyboard_set_leds(led_status); - } -} - -/** \brief keyboard set leds - * - * FIXME: needs doc - */ -void keyboard_set_leds(uint8_t leds) { - if (debug_keyboard) { - debug("keyboard_set_led: "); - debug_hex8(leds); - debug("\n"); - } - led_set(leds); -} diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h deleted file mode 100644 index 08f4e84f94..0000000000 --- a/tmk_core/common/keyboard.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2011,2012,2013 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* key matrix position */ -typedef struct { - uint8_t col; - uint8_t row; -} keypos_t; - -/* key event */ -typedef struct { - keypos_t key; - bool pressed; - uint16_t time; -} keyevent_t; - -/* equivalent test of keypos_t */ -#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col) - -/* Rules for No Event: - * 1) (time == 0) to handle (keyevent_t){} as empty event - * 2) Matrix(255, 255) to make TICK event available - */ -static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); } -static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); } -static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) && !event.pressed); } - -/* Tick event */ -#define TICK \ - (keyevent_t) { .key = (keypos_t){.row = 255, .col = 255}, .pressed = false, .time = (timer_read() | 1) } - -/* it runs once at early stage of startup before keyboard_init. */ -void keyboard_setup(void); -/* it runs once after initializing host side protocol, debug and MCU peripherals. */ -void keyboard_init(void); -/* it runs repeatedly in main loop */ -void keyboard_task(void); -/* it runs when host LED status is updated */ -void keyboard_set_leds(uint8_t leds); -/* it runs whenever code has to behave differently on a slave */ -bool is_keyboard_master(void); -/* it runs whenever code has to behave differently on left vs right split */ -bool is_keyboard_left(void); - -void keyboard_pre_init_kb(void); -void keyboard_pre_init_user(void); -void keyboard_post_init_kb(void); -void keyboard_post_init_user(void); - -void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol -void housekeeping_task_kb(void); // To be overridden by keyboard-level code -void housekeeping_task_user(void); // To be overridden by user/keymap-level code - -uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity -uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity - -uint32_t last_matrix_activity_time(void); // Timestamp of the last matrix activity -uint32_t last_matrix_activity_elapsed(void); // Number of milliseconds since the last matrix activity - -uint32_t last_encoder_activity_time(void); // Timestamp of the last encoder activity -uint32_t last_encoder_activity_elapsed(void); // Number of milliseconds since the last encoder activity - -uint32_t get_matrix_scan_rate(void); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/keycode.h b/tmk_core/common/keycode.h deleted file mode 100644 index 8facabd818..0000000000 --- a/tmk_core/common/keycode.h +++ /dev/null @@ -1,560 +0,0 @@ -/* -Copyright 2011,2012 Jun Wako - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* - * Keycodes based on HID Keyboard/Keypad Usage Page (0x07) plus media keys from Generic Desktop Page (0x01) and Consumer Page (0x0C) - * - * See https://web.archive.org/web/20060218214400/http://www.usb.org/developers/devclass_docs/Hut1_12.pdf - * or http://www.usb.org/developers/hidpage/Hut1_12v2.pdf (older) - */ - -#pragma once - -/* FIXME: Add doxygen comments here */ - -#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED) -#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF) -#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL) -#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI) - -#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF)) -#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE) -#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_BRID) - -#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31) - -#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2) -#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT) -#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN8) -#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT) -#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2) - -#define MOD_BIT(code) (1 << MOD_INDEX(code)) -#define MOD_INDEX(code) ((code)&0x07) - -#define MOD_MASK_CTRL (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL)) -#define MOD_MASK_SHIFT (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) -#define MOD_MASK_ALT (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) -#define MOD_MASK_GUI (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI)) -#define MOD_MASK_CS (MOD_MASK_CTRL | MOD_MASK_SHIFT) -#define MOD_MASK_CA (MOD_MASK_CTRL | MOD_MASK_ALT) -#define MOD_MASK_CG (MOD_MASK_CTRL | MOD_MASK_GUI) -#define MOD_MASK_SA (MOD_MASK_SHIFT | MOD_MASK_ALT) -#define MOD_MASK_SG (MOD_MASK_SHIFT | MOD_MASK_GUI) -#define MOD_MASK_AG (MOD_MASK_ALT | MOD_MASK_GUI) -#define MOD_MASK_CSA (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT) -#define MOD_MASK_CSG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_GUI) -#define MOD_MASK_CAG (MOD_MASK_CTRL | MOD_MASK_ALT | MOD_MASK_GUI) -#define MOD_MASK_SAG (MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI) -#define MOD_MASK_CSAG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI) - -#define FN_BIT(code) (1 << FN_INDEX(code)) -#define FN_INDEX(code) ((code)-KC_FN0) -#define FN_MIN KC_FN0 -#define FN_MAX KC_FN31 - -/* - * Short names for ease of definition of keymap - */ -/* Transparent */ -#define KC_TRANSPARENT 0x01 -#define KC_TRNS KC_TRANSPARENT - -/* Punctuation */ -#define KC_ENT KC_ENTER -#define KC_ESC KC_ESCAPE -#define KC_BSPC KC_BSPACE -#define KC_SPC KC_SPACE -#define KC_MINS KC_MINUS -#define KC_EQL KC_EQUAL -#define KC_LBRC KC_LBRACKET -#define KC_RBRC KC_RBRACKET -#define KC_BSLS KC_BSLASH -#define KC_NUHS KC_NONUS_HASH -#define KC_SCLN KC_SCOLON -#define KC_QUOT KC_QUOTE -#define KC_GRV KC_GRAVE -#define KC_COMM KC_COMMA -#define KC_SLSH KC_SLASH -#define KC_NUBS KC_NONUS_BSLASH - -/* Lock Keys */ -#define KC_CLCK KC_CAPSLOCK -#define KC_CAPS KC_CAPSLOCK -#define KC_SLCK KC_SCROLLLOCK -#define KC_NLCK KC_NUMLOCK -#define KC_LCAP KC_LOCKING_CAPS -#define KC_LNUM KC_LOCKING_NUM -#define KC_LSCR KC_LOCKING_SCROLL - -/* Commands */ -#define KC_PSCR KC_PSCREEN -#define KC_PAUS KC_PAUSE -#define KC_BRK KC_PAUSE -#define KC_INS KC_INSERT -#define KC_DEL KC_DELETE -#define KC_PGDN KC_PGDOWN -#define KC_RGHT KC_RIGHT -#define KC_APP KC_APPLICATION -#define KC_EXEC KC_EXECUTE -#define KC_SLCT KC_SELECT -#define KC_AGIN KC_AGAIN -#define KC_PSTE KC_PASTE -#define KC_ERAS KC_ALT_ERASE -#define KC_CLR KC_CLEAR - -/* Keypad */ -#define KC_PSLS KC_KP_SLASH -#define KC_PAST KC_KP_ASTERISK -#define KC_PMNS KC_KP_MINUS -#define KC_PPLS KC_KP_PLUS -#define KC_PENT KC_KP_ENTER -#define KC_P1 KC_KP_1 -#define KC_P2 KC_KP_2 -#define KC_P3 KC_KP_3 -#define KC_P4 KC_KP_4 -#define KC_P5 KC_KP_5 -#define KC_P6 KC_KP_6 -#define KC_P7 KC_KP_7 -#define KC_P8 KC_KP_8 -#define KC_P9 KC_KP_9 -#define KC_P0 KC_KP_0 -#define KC_PDOT KC_KP_DOT -#define KC_PEQL KC_KP_EQUAL -#define KC_PCMM KC_KP_COMMA - -/* Japanese specific */ -#define KC_ZKHK KC_GRAVE -#define KC_RO KC_INT1 -#define KC_KANA KC_INT2 -#define KC_JYEN KC_INT3 -#define KC_HENK KC_INT4 -#define KC_MHEN KC_INT5 - -/* Korean specific */ -#define KC_HAEN KC_LANG1 -#define KC_HANJ KC_LANG2 - -/* Modifiers */ -#define KC_LCTL KC_LCTRL -#define KC_LSFT KC_LSHIFT -#define KC_LOPT KC_LALT -#define KC_LCMD KC_LGUI -#define KC_LWIN KC_LGUI -#define KC_RCTL KC_RCTRL -#define KC_RSFT KC_RSHIFT -#define KC_ALGR KC_RALT -#define KC_ROPT KC_RALT -#define KC_RCMD KC_RGUI -#define KC_RWIN KC_RGUI - -/* Generic Desktop Page (0x01) */ -#define KC_PWR KC_SYSTEM_POWER -#define KC_SLEP KC_SYSTEM_SLEEP -#define KC_WAKE KC_SYSTEM_WAKE - -/* Consumer Page (0x0C) */ -#define KC_MUTE KC_AUDIO_MUTE -#define KC_VOLU KC_AUDIO_VOL_UP -#define KC_VOLD KC_AUDIO_VOL_DOWN -#define KC_MNXT KC_MEDIA_NEXT_TRACK -#define KC_MPRV KC_MEDIA_PREV_TRACK -#define KC_MSTP KC_MEDIA_STOP -#define KC_MPLY KC_MEDIA_PLAY_PAUSE -#define KC_MSEL KC_MEDIA_SELECT -#define KC_EJCT KC_MEDIA_EJECT -#define KC_CALC KC_CALCULATOR -#define KC_MYCM KC_MY_COMPUTER -#define KC_WSCH KC_WWW_SEARCH -#define KC_WHOM KC_WWW_HOME -#define KC_WBAK KC_WWW_BACK -#define KC_WFWD KC_WWW_FORWARD -#define KC_WSTP KC_WWW_STOP -#define KC_WREF KC_WWW_REFRESH -#define KC_WFAV KC_WWW_FAVORITES -#define KC_MFFD KC_MEDIA_FAST_FORWARD -#define KC_MRWD KC_MEDIA_REWIND -#define KC_BRIU KC_BRIGHTNESS_UP -#define KC_BRID KC_BRIGHTNESS_DOWN - -/* System Specific */ -#define KC_BRMU KC_PAUSE -#define KC_BRMD KC_SCROLLLOCK - -/* Mouse Keys */ -#define KC_MS_U KC_MS_UP -#define KC_MS_D KC_MS_DOWN -#define KC_MS_L KC_MS_LEFT -#define KC_MS_R KC_MS_RIGHT -#define KC_BTN1 KC_MS_BTN1 -#define KC_BTN2 KC_MS_BTN2 -#define KC_BTN3 KC_MS_BTN3 -#define KC_BTN4 KC_MS_BTN4 -#define KC_BTN5 KC_MS_BTN5 -#define KC_BTN6 KC_MS_BTN6 -#define KC_BTN7 KC_MS_BTN7 -#define KC_BTN8 KC_MS_BTN8 -#define KC_WH_U KC_MS_WH_UP -#define KC_WH_D KC_MS_WH_DOWN -#define KC_WH_L KC_MS_WH_LEFT -#define KC_WH_R KC_MS_WH_RIGHT -#define KC_ACL0 KC_MS_ACCEL0 -#define KC_ACL1 KC_MS_ACCEL1 -#define KC_ACL2 KC_MS_ACCEL2 - -/* Keyboard/Keypad Page (0x07) */ -enum hid_keyboard_keypad_usage { - KC_NO = 0x00, - KC_ROLL_OVER, - KC_POST_FAIL, - KC_UNDEFINED, - KC_A, - KC_B, - KC_C, - KC_D, - KC_E, - KC_F, - KC_G, - KC_H, - KC_I, - KC_J, - KC_K, - KC_L, - KC_M, // 0x10 - KC_N, - KC_O, - KC_P, - KC_Q, - KC_R, - KC_S, - KC_T, - KC_U, - KC_V, - KC_W, - KC_X, - KC_Y, - KC_Z, - KC_1, - KC_2, - KC_3, // 0x20 - KC_4, - KC_5, - KC_6, - KC_7, - KC_8, - KC_9, - KC_0, - KC_ENTER, - KC_ESCAPE, - KC_BSPACE, - KC_TAB, - KC_SPACE, - KC_MINUS, - KC_EQUAL, - KC_LBRACKET, - KC_RBRACKET, // 0x30 - KC_BSLASH, - KC_NONUS_HASH, - KC_SCOLON, - KC_QUOTE, - KC_GRAVE, - KC_COMMA, - KC_DOT, - KC_SLASH, - KC_CAPSLOCK, - KC_F1, - KC_F2, - KC_F3, - KC_F4, - KC_F5, - KC_F6, - KC_F7, // 0x40 - KC_F8, - KC_F9, - KC_F10, - KC_F11, - KC_F12, - KC_PSCREEN, - KC_SCROLLLOCK, - KC_PAUSE, - KC_INSERT, - KC_HOME, - KC_PGUP, - KC_DELETE, - KC_END, - KC_PGDOWN, - KC_RIGHT, - KC_LEFT, // 0x50 - KC_DOWN, - KC_UP, - KC_NUMLOCK, - KC_KP_SLASH, - KC_KP_ASTERISK, - KC_KP_MINUS, - KC_KP_PLUS, - KC_KP_ENTER, - KC_KP_1, - KC_KP_2, - KC_KP_3, - KC_KP_4, - KC_KP_5, - KC_KP_6, - KC_KP_7, - KC_KP_8, // 0x60 - KC_KP_9, - KC_KP_0, - KC_KP_DOT, - KC_NONUS_BSLASH, - KC_APPLICATION, - KC_POWER, - KC_KP_EQUAL, - KC_F13, - KC_F14, - KC_F15, - KC_F16, - KC_F17, - KC_F18, - KC_F19, - KC_F20, - KC_F21, // 0x70 - KC_F22, - KC_F23, - KC_F24, - KC_EXECUTE, - KC_HELP, - KC_MENU, - KC_SELECT, - KC_STOP, - KC_AGAIN, - KC_UNDO, - KC_CUT, - KC_COPY, - KC_PASTE, - KC_FIND, - KC__MUTE, - KC__VOLUP, // 0x80 - KC__VOLDOWN, - KC_LOCKING_CAPS, - KC_LOCKING_NUM, - KC_LOCKING_SCROLL, - KC_KP_COMMA, - KC_KP_EQUAL_AS400, - KC_INT1, - KC_INT2, - KC_INT3, - KC_INT4, - KC_INT5, - KC_INT6, - KC_INT7, - KC_INT8, - KC_INT9, - KC_LANG1, // 0x90 - KC_LANG2, - KC_LANG3, - KC_LANG4, - KC_LANG5, - KC_LANG6, - KC_LANG7, - KC_LANG8, - KC_LANG9, - KC_ALT_ERASE, - KC_SYSREQ, - KC_CANCEL, - KC_CLEAR, - KC_PRIOR, - KC_RETURN, - KC_SEPARATOR, - KC_OUT, // 0xA0 - KC_OPER, - KC_CLEAR_AGAIN, - KC_CRSEL, - KC_EXSEL, - -#if 0 - // *************************************************************** - // These keycodes are present in the HID spec, but are * - // nonfunctional on modern OSes. QMK uses this range (0xA5-0xDF) * - // for the media and function keys instead - see below. * - // *************************************************************** - - KC_KP_00 = 0xB0, - KC_KP_000, - KC_THOUSANDS_SEPARATOR, - KC_DECIMAL_SEPARATOR, - KC_CURRENCY_UNIT, - KC_CURRENCY_SUB_UNIT, - KC_KP_LPAREN, - KC_KP_RPAREN, - KC_KP_LCBRACKET, - KC_KP_RCBRACKET, - KC_KP_TAB, - KC_KP_BSPACE, - KC_KP_A, - KC_KP_B, - KC_KP_C, - KC_KP_D, - KC_KP_E, //0xC0 - KC_KP_F, - KC_KP_XOR, - KC_KP_HAT, - KC_KP_PERC, - KC_KP_LT, - KC_KP_GT, - KC_KP_AND, - KC_KP_LAZYAND, - KC_KP_OR, - KC_KP_LAZYOR, - KC_KP_COLON, - KC_KP_HASH, - KC_KP_SPACE, - KC_KP_ATMARK, - KC_KP_EXCLAMATION, - KC_KP_MEM_STORE, //0xD0 - KC_KP_MEM_RECALL, - KC_KP_MEM_CLEAR, - KC_KP_MEM_ADD, - KC_KP_MEM_SUB, - KC_KP_MEM_MUL, - KC_KP_MEM_DIV, - KC_KP_PLUS_MINUS, - KC_KP_CLEAR, - KC_KP_CLEAR_ENTRY, - KC_KP_BINARY, - KC_KP_OCTAL, - KC_KP_DECIMAL, - KC_KP_HEXADECIMAL, -#endif - - /* Modifiers */ - KC_LCTRL = 0xE0, - KC_LSHIFT, - KC_LALT, - KC_LGUI, - KC_RCTRL, - KC_RSHIFT, - KC_RALT, - KC_RGUI - - // ********************************************** - // * 0xF0-0xFF are unallocated in the HID spec. * - // * QMK uses these for Mouse Keys - see below. * - // ********************************************** -}; - -/* Media and Function keys */ -enum internal_special_keycodes { - /* Generic Desktop Page (0x01) */ - KC_SYSTEM_POWER = 0xA5, - KC_SYSTEM_SLEEP, - KC_SYSTEM_WAKE, - - /* Consumer Page (0x0C) */ - KC_AUDIO_MUTE, - KC_AUDIO_VOL_UP, - KC_AUDIO_VOL_DOWN, - KC_MEDIA_NEXT_TRACK, - KC_MEDIA_PREV_TRACK, - KC_MEDIA_STOP, - KC_MEDIA_PLAY_PAUSE, - KC_MEDIA_SELECT, - KC_MEDIA_EJECT, // 0xB0 - KC_MAIL, - KC_CALCULATOR, - KC_MY_COMPUTER, - KC_WWW_SEARCH, - KC_WWW_HOME, - KC_WWW_BACK, - KC_WWW_FORWARD, - KC_WWW_STOP, - KC_WWW_REFRESH, - KC_WWW_FAVORITES, - KC_MEDIA_FAST_FORWARD, - KC_MEDIA_REWIND, - KC_BRIGHTNESS_UP, - KC_BRIGHTNESS_DOWN, - - /* Fn keys */ - KC_FN0 = 0xC0, - KC_FN1, - KC_FN2, - KC_FN3, - KC_FN4, - KC_FN5, - KC_FN6, - KC_FN7, - KC_FN8, - KC_FN9, - KC_FN10, - KC_FN11, - KC_FN12, - KC_FN13, - KC_FN14, - KC_FN15, - KC_FN16, // 0xD0 - KC_FN17, - KC_FN18, - KC_FN19, - KC_FN20, - KC_FN21, - KC_FN22, - KC_FN23, - KC_FN24, - KC_FN25, - KC_FN26, - KC_FN27, - KC_FN28, - KC_FN29, - KC_FN30, - KC_FN31 -}; - -enum mouse_keys { -/* Mouse Buttons */ -#ifdef VIA_ENABLE - KC_MS_UP = 0xF0, -#else - KC_MS_UP = 0xED, -#endif - KC_MS_DOWN, - KC_MS_LEFT, - KC_MS_RIGHT, // 0xF0 - KC_MS_BTN1, - KC_MS_BTN2, - KC_MS_BTN3, - KC_MS_BTN4, - KC_MS_BTN5, -#ifdef VIA_ENABLE - KC_MS_BTN6 = KC_MS_BTN5, - KC_MS_BTN7 = KC_MS_BTN5, - KC_MS_BTN8 = KC_MS_BTN5, -#else - KC_MS_BTN6, - KC_MS_BTN7, - KC_MS_BTN8, -#endif - - /* Mouse Wheel */ - KC_MS_WH_UP, - KC_MS_WH_DOWN, - KC_MS_WH_LEFT, - KC_MS_WH_RIGHT, - - /* Acceleration */ - KC_MS_ACCEL0, - KC_MS_ACCEL1, - KC_MS_ACCEL2 // 0xFF -}; -- cgit v1.2.3 From 0a1bf7f6aa6e44557041e03f6e58df5a180c6d79 Mon Sep 17 00:00:00 2001 From: Simon Arlott <70171+nomis@users.noreply.github.com> Date: Fri, 20 Aug 2021 00:31:23 +0100 Subject: Support using a timer for wait_us() on ChibiOS-based boards (#12211) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Support using a timer for wait_us() on ChibiOS-based boards (#12198) There are spare GPT timers that can be used to get a more accurate wait_ms() time. This is required for the matrix scan unselect delay (30µs) to be shorter than the system tick rate of 100µs. This is limited to the maximum GPT duration of 65535 so values above that will automatically use the previous implementation based on the system tick. Using a specific timer means it can't be shared by another thread at the same time so when wait_us() is called from anything other than the main thread it will use the system tick implementation too. * Update tmk_core/common/chibios/wait.c * Update tmk_core/common/chibios/wait.c Co-authored-by: Joel Challis --- tmk_core/common/chibios/_wait.c | 89 ++++++++++++++++++++++++++++++++++++++++ tmk_core/common/chibios/_wait.h | 24 ++++++----- tmk_core/common/chibios/wait.c | 90 ++++++++++------------------------------- 3 files changed, 125 insertions(+), 78 deletions(-) create mode 100644 tmk_core/common/chibios/_wait.c (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/_wait.c b/tmk_core/common/chibios/_wait.c new file mode 100644 index 0000000000..1fbea2dd5e --- /dev/null +++ b/tmk_core/common/chibios/_wait.c @@ -0,0 +1,89 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ + +#ifndef __OPTIMIZE__ +# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" +#endif + +#define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" + +__attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ + /* The argument n must be a constant expression. + * That way, compiler optimization will remove unnecessary code. */ + if (n < 1) { + return; + } + if (n > 8) { + unsigned int n8 = n / 8; + n = n - n8 * 8; + switch (n8) { + case 16: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 15: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 14: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 13: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 12: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 11: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 10: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 9: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 8: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 7: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 6: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 5: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 4: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 3: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 2: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 1: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 0: + break; + } + } + switch (n) { + case 8: + asm volatile("nop" ::: "memory"); + case 7: + asm volatile("nop" ::: "memory"); + case 6: + asm volatile("nop" ::: "memory"); + case 5: + asm volatile("nop" ::: "memory"); + case 4: + asm volatile("nop" ::: "memory"); + case 3: + asm volatile("nop" ::: "memory"); + case 2: + asm volatile("nop" ::: "memory"); + case 1: + asm volatile("nop" ::: "memory"); + case 0: + break; + } +} diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h index 5bface53e1..4a5172536b 100644 --- a/tmk_core/common/chibios/_wait.h +++ b/tmk_core/common/chibios/_wait.h @@ -16,6 +16,7 @@ #pragma once #include +#include /* chThdSleepX of zero maps to infinite - so we map to a tiny delay to still yield */ #define wait_ms(ms) \ @@ -26,14 +27,19 @@ chThdSleepMicroseconds(1); \ } \ } while (0) -#define wait_us(us) \ - do { \ - if (us != 0) { \ - chThdSleepMicroseconds(us); \ - } else { \ - chThdSleepMicroseconds(1); \ - } \ - } while (0) + +#ifdef WAIT_US_TIMER +void wait_us(uint16_t duration); +#else +# define wait_us(us) \ + do { \ + if (us != 0) { \ + chThdSleepMicroseconds(us); \ + } else { \ + chThdSleepMicroseconds(1); \ + } \ + } while (0) +#endif /* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus * to which the GPIO is connected. @@ -46,7 +52,7 @@ * (A fairly large value of 0.25 microseconds is set.) */ -#include "wait.c" +#include "_wait.c" #ifndef GPIO_INPUT_PIN_DELAY # define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) diff --git a/tmk_core/common/chibios/wait.c b/tmk_core/common/chibios/wait.c index c6270fd95e..56fd6ffcec 100644 --- a/tmk_core/common/chibios/wait.c +++ b/tmk_core/common/chibios/wait.c @@ -14,76 +14,28 @@ * along with this program. If not, see . */ -#ifndef __OPTIMIZE__ -# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" -#endif +#include +#include -#define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" +#include "_wait.h" -__attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ - /* The argument n must be a constant expression. - * That way, compiler optimization will remove unnecessary code. */ - if (n < 1) { - return; - } - if (n > 8) { - unsigned int n8 = n / 8; - n = n - n8 * 8; - switch (n8) { - case 16: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 15: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 14: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 13: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 12: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 11: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 10: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 9: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 8: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 7: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 6: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 5: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 4: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 3: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 2: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 1: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 0: - break; - } +#ifdef WAIT_US_TIMER +void wait_us(uint16_t duration) { + static const GPTConfig gpt_cfg = {1000000, NULL, 0, 0}; /* 1MHz timer, no callback */ + + if (duration == 0) { + duration = 1; } - switch (n) { - case 8: - asm volatile("nop" ::: "memory"); - case 7: - asm volatile("nop" ::: "memory"); - case 6: - asm volatile("nop" ::: "memory"); - case 5: - asm volatile("nop" ::: "memory"); - case 4: - asm volatile("nop" ::: "memory"); - case 3: - asm volatile("nop" ::: "memory"); - case 2: - asm volatile("nop" ::: "memory"); - case 1: - asm volatile("nop" ::: "memory"); - case 0: - break; + + /* + * Only use this timer on the main thread; + * other threads need to use their own timer. + */ + if (chThdGetSelfX() == &ch.mainthread && duration < (1ULL << (sizeof(gptcnt_t) * 8))) { + gptStart(&WAIT_US_TIMER, &gpt_cfg); + gptPolledDelay(&WAIT_US_TIMER, duration); + } else { + chThdSleepMicroseconds(duration); } -} \ No newline at end of file +} +#endif -- cgit v1.2.3 From e756a21636149ad47c19c659d04be93cf3071dab Mon Sep 17 00:00:00 2001 From: Donald Kjer Date: Mon, 23 Aug 2021 15:15:34 -0700 Subject: eeprom_stm32: implement high density wear leveling (#12567) * eeprom_stm32: implement wear leveling Update EECONFIG_MAGIC_NUMBER eeprom_stm32: check emulated eeprom size is large enough * eeprom_stm32: Increasing simulated EEPROM density on stm32 * Adding utility script to decode emulated eeprom * Adding unit tests * Applying qmk cformat changes * cleaned up flash mocking * Fix for stm32eeprom_parser.py checking via signature with wrong base * Fix for nk65 keyboard Co-authored-by: Ilya Zhuravlev Co-authored-by: zvecr --- tmk_core/common/chibios/eeprom_stm32.c | 802 ++++++++++++++++++++++++---- tmk_core/common/chibios/eeprom_stm32.h | 61 +-- tmk_core/common/chibios/flash_stm32.h | 7 +- tmk_core/common/test/eeprom_stm32_tests.cpp | 438 +++++++++++++++ tmk_core/common/test/flash_stm32_mock.c | 50 ++ tmk_core/common/test/rules.mk | 23 + tmk_core/common/test/testlist.mk | 1 + 7 files changed, 1206 insertions(+), 176 deletions(-) create mode 100644 tmk_core/common/test/eeprom_stm32_tests.cpp create mode 100644 tmk_core/common/test/flash_stm32_mock.c create mode 100644 tmk_core/common/test/rules.mk create mode 100644 tmk_core/common/test/testlist.mk (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c index ea51989728..5bf852fde1 100644 --- a/tmk_core/common/chibios/eeprom_stm32.c +++ b/tmk_core/common/chibios/eeprom_stm32.c @@ -14,185 +14,751 @@ * Artur F. * * Modifications for QMK and STM32F303 by Yiancar + * Modifications to add flash wear leveling by Ilya Zhuravlev + * Modifications to increase flash density by Don Kjer */ #include -#include +#include +#include "debug.h" #include "eeprom_stm32.h" -/***************************************************************************** - * Allows to use the internal flash to store non volatile data. To initialize - * the functionality use the EEPROM_Init() function. Be sure that by reprogramming - * of the controller just affected pages will be deleted. In other case the non - * volatile data will be lost. - ******************************************************************************/ +#include "flash_stm32.h" + +/* + * We emulate eeprom by writing a snapshot compacted view of eeprom contents, + * followed by a write log of any change since that snapshot: + * + * === SIMULATED EEPROM CONTENTS === + * + * ┌─ Compacted ┬ Write Log ─┐ + * │............│[BYTE][BYTE]│ + * │FFFF....FFFF│[WRD0][WRD1]│ + * │FFFFFFFFFFFF│[WORD][NEXT]│ + * │....FFFFFFFF│[BYTE][WRD0]│ + * ├────────────┼────────────┤ + * └──PAGE_BASE │ │ + * PAGE_LAST─┴─WRITE_BASE │ + * WRITE_LAST ┘ + * + * Compacted contents are the 1's complement of the actual EEPROM contents. + * e.g. An 'FFFF' represents a '0000' value. + * + * The size of the 'compacted' area is equal to the size of the 'emulated' eeprom. + * The size of the compacted-area and write log are configurable, and the combined + * size of Compacted + WriteLog is a multiple FEE_PAGE_SIZE, which is MCU dependent. + * Simulated Eeprom contents are located at the end of available flash space. + * + * The following configuration defines can be set: + * + * FEE_DENSITY_PAGES # Total number of pages to use for eeprom simulation (Compact + Write log) + * FEE_DENSITY_BYTES # Size of simulated eeprom. (Defaults to half the space allocated by FEE_DENSITY_PAGES) + * NOTE: The current implementation does not include page swapping, + * and FEE_DENSITY_BYTES will consume that amount of RAM as a cached view of actual EEPROM contents. + * + * The maximum size of FEE_DENSITY_BYTES is currently 16384. The write log size equals + * FEE_DENSITY_PAGES * FEE_PAGE_SIZE - FEE_DENSITY_BYTES. + * The larger the write log, the less frequently the compacted area needs to be rewritten. + * + * + * *** General Algorithm *** + * + * During initialization: + * The contents of the Compacted-flash area are loaded and the 1's complement value + * is cached into memory (e.g. 0xFFFF in Flash represents 0x0000 in cache). + * Write log entries are processed until a 0xFFFF is reached. + * Each log entry updates a byte or word in the cache. + * + * During reads: + * EEPROM contents are given back directly from the cache in memory. + * + * During writes: + * The contents of the cache is updated first. + * If the Compacted-flash area corresponding to the write address is unprogrammed, the 1's complement of the value is written directly into Compacted-flash + * Otherwise: + * If the write log is full, erase both the Compacted-flash area and the Write log, then write cached contents to the Compacted-flash area. + * Otherwise a Write log entry is constructed and appended to the next free position in the Write log. + * + * + * *** Write Log Structure *** + * + * Write log entries allow for optimized byte writes to addresses below 128. Writing 0 or 1 words are also optimized when word-aligned. + * + * === WRITE LOG ENTRY FORMATS === + * + * ╔═══ Byte-Entry ══╗ + * ║0XXXXXXX║YYYYYYYY║ + * ║ └──┬──┘║└──┬───┘║ + * ║ Address║ Value ║ + * ╚════════╩════════╝ + * 0 <= Address < 0x80 (128) + * + * ╔ Word-Encoded 0 ╗ + * ║100XXXXXXXXXXXXX║ + * ║ │└─────┬─────┘║ + * ║ │Address >> 1 ║ + * ║ └── Value: 0 ║ + * ╚════════════════╝ + * 0 <= Address <= 0x3FFE (16382) + * + * ╔ Word-Encoded 1 ╗ + * ║101XXXXXXXXXXXXX║ + * ║ │└─────┬─────┘║ + * ║ │Address >> 1 ║ + * ║ └── Value: 1 ║ + * ╚════════════════╝ + * 0 <= Address <= 0x3FFE (16382) + * + * ╔═══ Reserved ═══╗ + * ║110XXXXXXXXXXXXX║ + * ╚════════════════╝ + * + * ╔═══════════ Word-Next ═══════════╗ + * ║111XXXXXXXXXXXXX║YYYYYYYYYYYYYYYY║ + * ║ └─────┬─────┘║└───────┬──────┘║ + * ║(Address-128)>>1║ ~Value ║ + * ╚════════════════╩════════════════╝ + * ( 0 <= Address < 0x0080 (128): Reserved) + * 0x80 <= Address <= 0x3FFE (16382) + * + * Write Log entry ranges: + * 0x0000 ... 0x7FFF - Byte-Entry; address is (Entry & 0x7F00) >> 4; value is (Entry & 0xFF) + * 0x8000 ... 0x9FFF - Word-Encoded 0; address is (Entry & 0x1FFF) << 1; value is 0 + * 0xA000 ... 0xBFFF - Word-Encoded 1; address is (Entry & 0x1FFF) << 1; value is 1 + * 0xC000 ... 0xDFFF - Reserved + * 0xE000 ... 0xFFBF - Word-Next; address is (Entry & 0x1FFF) << 1 + 0x80; value is ~(Next_Entry) + * 0xFFC0 ... 0xFFFE - Reserved + * 0xFFFF - Unprogrammed + * + */ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Functions -----------------------------------------------------------------*/ +/* These bits are used for optimizing encoding of bytes, 0 and 1 */ +#define FEE_WORD_ENCODING 0x8000 +#define FEE_VALUE_NEXT 0x6000 +#define FEE_VALUE_RESERVED 0x4000 +#define FEE_VALUE_ENCODED 0x2000 +#define FEE_BYTE_RANGE 0x80 + +// HACK ALERT. This definition may not match your processor +// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc +#if defined(EEPROM_EMU_STM32F303xC) +# define MCU_STM32F303CC +#elif defined(EEPROM_EMU_STM32F103xB) +# define MCU_STM32F103RB +#elif defined(EEPROM_EMU_STM32F072xB) +# define MCU_STM32F072CB +#elif defined(EEPROM_EMU_STM32F042x6) +# define MCU_STM32F042K6 +#elif !defined(FEE_PAGE_SIZE) || !defined(FEE_DENSITY_PAGES) || !defined(FEE_MCU_FLASH_SIZE) +# error "not implemented." +#endif + +#if !defined(FEE_PAGE_SIZE) || !defined(FEE_DENSITY_PAGES) +# if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6) +# ifndef FEE_PAGE_SIZE +# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte +# endif +# ifndef FEE_DENSITY_PAGES +# define FEE_DENSITY_PAGES 2 // How many pages are used +# endif +# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB) +# ifndef FEE_PAGE_SIZE +# define FEE_PAGE_SIZE 0x800 // Page size = 2KByte +# endif +# ifndef FEE_DENSITY_PAGES +# define FEE_DENSITY_PAGES 4 // How many pages are used +# endif +# else +# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." +# endif +#endif + +#ifndef FEE_MCU_FLASH_SIZE +# if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB) +# define FEE_MCU_FLASH_SIZE 128 // Size in Kb +# elif defined(MCU_STM32F042K6) +# define FEE_MCU_FLASH_SIZE 32 // Size in Kb +# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) +# define FEE_MCU_FLASH_SIZE 512 // Size in Kb +# elif defined(MCU_STM32F103RD) +# define FEE_MCU_FLASH_SIZE 384 // Size in Kb +# elif defined(MCU_STM32F303CC) +# define FEE_MCU_FLASH_SIZE 256 // Size in Kb +# else +# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." +# endif +#endif + +#define FEE_XSTR(x) FEE_STR(x) +#define FEE_STR(x) #x + +/* Size of combined compacted eeprom and write log pages */ +#define FEE_DENSITY_MAX_SIZE (FEE_DENSITY_PAGES * FEE_PAGE_SIZE) +/* Addressable range 16KByte: 0 <-> (0x1FFF << 1) */ +#define FEE_ADDRESS_MAX_SIZE 0x4000 + +#ifndef EEPROM_START_ADDRESS /* *TODO: Get rid of this check */ +# if FEE_DENSITY_MAX_SIZE > (FEE_MCU_FLASH_SIZE * 1024) +# pragma message FEE_XSTR(FEE_DENSITY_MAX_SIZE) " > " FEE_XSTR(FEE_MCU_FLASH_SIZE * 1024) +# error emulated eeprom: FEE_DENSITY_PAGES is greater than available flash size +# endif +#endif + +/* Size of emulated eeprom */ +#ifdef FEE_DENSITY_BYTES +# if (FEE_DENSITY_BYTES > FEE_DENSITY_MAX_SIZE) +# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " > " FEE_XSTR(FEE_DENSITY_MAX_SIZE) +# error emulated eeprom: FEE_DENSITY_BYTES exceeds FEE_DENSITY_MAX_SIZE +# endif +# if (FEE_DENSITY_BYTES == FEE_DENSITY_MAX_SIZE) +# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " == " FEE_XSTR(FEE_DENSITY_MAX_SIZE) +# warning emulated eeprom: FEE_DENSITY_BYTES leaves no room for a write log. This will greatly increase the flash wear rate! +# endif +# if FEE_DENSITY_BYTES > FEE_ADDRESS_MAX_SIZE +# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " > " FEE_XSTR(FEE_ADDRESS_MAX_SIZE) +# error emulated eeprom: FEE_DENSITY_BYTES is greater than FEE_ADDRESS_MAX_SIZE allows +# endif +# if ((FEE_DENSITY_BYTES) % 2) == 1 +# error emulated eeprom: FEE_DENSITY_BYTES must be even +# endif +#else +/* Default to half of allocated space used for emulated eeprom, half for write log */ +# define FEE_DENSITY_BYTES (FEE_DENSITY_PAGES * FEE_PAGE_SIZE / 2) +#endif + +/* Size of write log */ +#define FEE_WRITE_LOG_BYTES (FEE_DENSITY_PAGES * FEE_PAGE_SIZE - FEE_DENSITY_BYTES) + +/* Start of the emulated eeprom compacted flash area */ +#ifndef FEE_FLASH_BASE +# define FEE_FLASH_BASE 0x8000000 +#endif +#define FEE_PAGE_BASE_ADDRESS ((uintptr_t)(FEE_FLASH_BASE) + FEE_MCU_FLASH_SIZE * 1024 - FEE_WRITE_LOG_BYTES - FEE_DENSITY_BYTES) +/* End of the emulated eeprom compacted flash area */ +#define FEE_PAGE_LAST_ADDRESS (FEE_PAGE_BASE_ADDRESS + FEE_DENSITY_BYTES) +/* Start of the emulated eeprom write log */ +#define FEE_WRITE_LOG_BASE_ADDRESS FEE_PAGE_LAST_ADDRESS +/* End of the emulated eeprom write log */ +#define FEE_WRITE_LOG_LAST_ADDRESS (FEE_WRITE_LOG_BASE_ADDRESS + FEE_WRITE_LOG_BYTES) + +/* Flash word value after erase */ +#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) + +#if defined(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) && (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= FEE_DENSITY_BYTES) +# error emulated eeprom: DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is greater than the FEE_DENSITY_BYTES available +#endif + +/* In-memory contents of emulated eeprom for faster access */ +/* *TODO: Implement page swapping */ +static uint16_t WordBuf[FEE_DENSITY_BYTES / 2]; +static uint8_t *DataBuf = (uint8_t *)WordBuf; + +/* Pointer to the first available slot within the write log */ +static uint16_t *empty_slot; + +// #define DEBUG_EEPROM_OUTPUT + +/* + * Debug print utils + */ + +#if defined(DEBUG_EEPROM_OUTPUT) + +# define debug_eeprom debug_enable +# define eeprom_println(s) println(s) +# define eeprom_printf(fmt, ...) xprintf(fmt, ##__VA_ARGS__); + +#else /* NO_DEBUG */ + +# define debug_eeprom false +# define eeprom_println(s) +# define eeprom_printf(fmt, ...) + +#endif /* NO_DEBUG */ + +void print_eeprom(void) { +#ifndef NO_DEBUG + int empty_rows = 0; + for (uint16_t i = 0; i < FEE_DENSITY_BYTES; i++) { + if (i % 16 == 0) { + if (i >= FEE_DENSITY_BYTES - 16) { + /* Make sure we display the last row */ + empty_rows = 0; + } + /* Check if this row is uninitialized */ + ++empty_rows; + for (uint16_t j = 0; j < 16; j++) { + if (DataBuf[i + j]) { + empty_rows = 0; + break; + } + } + if (empty_rows > 1) { + /* Repeat empty row */ + if (empty_rows == 2) { + /* Only display the first repeat empty row */ + println("*"); + } + i += 15; + continue; + } + xprintf("%04x", i); + } + if (i % 8 == 0) print(" "); + + xprintf(" %02x", DataBuf[i]); + if ((i + 1) % 16 == 0) { + println(""); + } + } +#endif +} -uint8_t DataBuf[FEE_PAGE_SIZE]; -/***************************************************************************** - * Delete Flash Space used for user Data, deletes the whole space between - * RW_PAGE_BASE_ADDRESS and the last uC Flash Page - ******************************************************************************/ uint16_t EEPROM_Init(void) { - // unlock flash - FLASH_Unlock(); + /* Load emulated eeprom contents from compacted flash into memory */ + uint16_t *src = (uint16_t *)FEE_PAGE_BASE_ADDRESS; + uint16_t *dest = (uint16_t *)DataBuf; + for (; src < (uint16_t *)FEE_PAGE_LAST_ADDRESS; ++src, ++dest) { + *dest = ~*src; + } + + if (debug_eeprom) { + println("EEPROM_Init Compacted Pages:"); + print_eeprom(); + println("EEPROM_Init Write Log:"); + } + + /* Replay write log */ + uint16_t *log_addr; + for (log_addr = (uint16_t *)FEE_WRITE_LOG_BASE_ADDRESS; log_addr < (uint16_t *)FEE_WRITE_LOG_LAST_ADDRESS; ++log_addr) { + uint16_t address = *log_addr; + if (address == FEE_EMPTY_WORD) { + break; + } + /* Check for lowest 128-bytes optimization */ + if (!(address & FEE_WORD_ENCODING)) { + uint8_t bvalue = (uint8_t)address; + address >>= 8; + DataBuf[address] = bvalue; + eeprom_printf("DataBuf[0x%02x] = 0x%02x;\n", address, bvalue); + } else { + uint16_t wvalue; + /* Check if value is in next word */ + if ((address & FEE_VALUE_NEXT) == FEE_VALUE_NEXT) { + /* Read value from next word */ + if (++log_addr >= (uint16_t *)FEE_WRITE_LOG_LAST_ADDRESS) { + break; + } + wvalue = ~*log_addr; + if (!wvalue) { + eeprom_printf("Incomplete write at log_addr: 0x%04x;\n", (uint32_t)log_addr); + /* Possibly incomplete write. Ignore and continue */ + continue; + } + address &= 0x1FFF; + address <<= 1; + /* Writes to addresses less than 128 are byte log entries */ + address += FEE_BYTE_RANGE; + } else { + /* Reserved for future use */ + if (address & FEE_VALUE_RESERVED) { + eeprom_printf("Reserved encoded value at log_addr: 0x%04x;\n", (uint32_t)log_addr); + continue; + } + /* Optimization for 0 or 1 values. */ + wvalue = (address & FEE_VALUE_ENCODED) >> 13; + address &= 0x1FFF; + address <<= 1; + } + if (address < FEE_DENSITY_BYTES) { + eeprom_printf("DataBuf[0x%04x] = 0x%04x;\n", address, wvalue); + *(uint16_t *)(&DataBuf[address]) = wvalue; + } else { + eeprom_printf("DataBuf[0x%04x] cannot be set to 0x%04x [BAD ADDRESS]\n", address, wvalue); + } + } + } - // Clear Flags - // FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR); + empty_slot = log_addr; + + if (debug_eeprom) { + println("EEPROM_Init Final DataBuf:"); + print_eeprom(); + } return FEE_DENSITY_BYTES; } -/***************************************************************************** - * Erase the whole reserved Flash Space used for user Data - ******************************************************************************/ -void EEPROM_Erase(void) { - int page_num = 0; - // delete all pages from specified start page to the last page - do { +/* Clear flash contents (doesn't touch in-memory DataBuf) */ +static void eeprom_clear(void) { + FLASH_Unlock(); + + for (uint16_t page_num = 0; page_num < FEE_DENSITY_PAGES; ++page_num) { + eeprom_printf("FLASH_ErasePage(0x%04x)\n", (uint32_t)(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE))); FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE)); - page_num++; - } while (page_num < FEE_DENSITY_PAGES); + } + + FLASH_Lock(); + + empty_slot = (uint16_t *)FEE_WRITE_LOG_BASE_ADDRESS; + eeprom_printf("eeprom_clear empty_slot: 0x%08x\n", (uint32_t)empty_slot); } -/***************************************************************************** - * Writes once data byte to flash on specified address. If a byte is already - * written, the whole page must be copied to a buffer, the byte changed and - * the manipulated buffer written after PageErase. - *******************************************************************************/ -uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) { - FLASH_Status FlashStatus = FLASH_COMPLETE; - uint32_t page; - int i; +/* Erase emulated eeprom */ +void EEPROM_Erase(void) { + eeprom_println("EEPROM_Erase"); + /* Erase compacted pages and write log */ + eeprom_clear(); + /* re-initialize to reset DataBuf */ + EEPROM_Init(); +} - // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages) - if (Address > FEE_DENSITY_BYTES) { - return 0; +/* Compact write log */ +static uint8_t eeprom_compact(void) { + /* Erase compacted pages and write log */ + eeprom_clear(); + + FLASH_Unlock(); + + FLASH_Status final_status = FLASH_COMPLETE; + + /* Write emulated eeprom contents from memory to compacted flash */ + uint16_t *src = (uint16_t *)DataBuf; + uintptr_t dest = FEE_PAGE_BASE_ADDRESS; + uint16_t value; + for (; dest < FEE_PAGE_LAST_ADDRESS; ++src, dest += 2) { + value = *src; + if (value) { + eeprom_printf("FLASH_ProgramHalfWord(0x%04x, 0x%04x)\n", (uint32_t)dest, ~value); + FLASH_Status status = FLASH_ProgramHalfWord(dest, ~value); + if (status != FLASH_COMPLETE) final_status = status; + } } - // calculate which page is affected (Pagenum1/Pagenum2...PagenumN) - page = FEE_ADDR_OFFSET(Address) / FEE_PAGE_SIZE; + FLASH_Lock(); - // if current data is 0xFF, the byte is empty, just overwrite with the new one - if ((*(__IO uint16_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) { - FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte)); + if (debug_eeprom) { + println("eeprom_compacted:"); + print_eeprom(); + } + + return final_status; +} + +static uint8_t eeprom_write_direct_entry(uint16_t Address) { + /* Check if we can just write this directly to the compacted flash area */ + uintptr_t directAddress = FEE_PAGE_BASE_ADDRESS + (Address & 0xFFFE); + if (*(uint16_t *)directAddress == FEE_EMPTY_WORD) { + /* Write the value directly to the compacted area without a log entry */ + uint16_t value = ~*(uint16_t *)(&DataBuf[Address & 0xFFFE]); + /* Early exit if a write isn't needed */ + if (value == FEE_EMPTY_WORD) return FLASH_COMPLETE; + + FLASH_Unlock(); + + eeprom_printf("FLASH_ProgramHalfWord(0x%08x, 0x%04x) [DIRECT]\n", (uint32_t)directAddress, value); + FLASH_Status status = FLASH_ProgramHalfWord(directAddress, value); + + FLASH_Lock(); + return status; + } + return 0; +} + +static uint8_t eeprom_write_log_word_entry(uint16_t Address) { + FLASH_Status final_status = FLASH_COMPLETE; + + uint16_t value = *(uint16_t *)(&DataBuf[Address]); + eeprom_printf("eeprom_write_log_word_entry(0x%04x): 0x%04x\n", Address, value); + + /* MSB signifies the lowest 128-byte optimization is not in effect */ + uint16_t encoding = FEE_WORD_ENCODING; + uint8_t entry_size; + if (value <= 1) { + encoding |= value << 13; + entry_size = 2; } else { - // Copy Page to a buffer - memcpy(DataBuf, (uint8_t *)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page + encoding |= FEE_VALUE_NEXT; + entry_size = 4; + /* Writes to addresses less than 128 are byte log entries */ + Address -= FEE_BYTE_RANGE; + } + + /* if we can't find an empty spot, we must compact emulated eeprom */ + if (empty_slot > (uint16_t *)(FEE_WRITE_LOG_LAST_ADDRESS - entry_size)) { + /* compact the write log into the compacted flash area */ + return eeprom_compact(); + } + + /* Word log writes should be word-aligned. Take back a bit */ + Address >>= 1; + Address |= encoding; + + /* ok we found a place let's write our data */ + FLASH_Unlock(); + + /* address */ + eeprom_printf("FLASH_ProgramHalfWord(0x%08x, 0x%04x)\n", (uint32_t)empty_slot, Address); + final_status = FLASH_ProgramHalfWord((uintptr_t)empty_slot++, Address); + + /* value */ + if (encoding == (FEE_WORD_ENCODING | FEE_VALUE_NEXT)) { + eeprom_printf("FLASH_ProgramHalfWord(0x%08x, 0x%04x)\n", (uint32_t)empty_slot, ~value); + FLASH_Status status = FLASH_ProgramHalfWord((uintptr_t)empty_slot++, ~value); + if (status != FLASH_COMPLETE) final_status = status; + } + + FLASH_Lock(); - // check if new data is differ to current data, return if not, proceed if yes - if (DataByte == *(__IO uint8_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) { - return 0; + return final_status; +} + +static uint8_t eeprom_write_log_byte_entry(uint16_t Address) { + eeprom_printf("eeprom_write_log_byte_entry(0x%04x): 0x%02x\n", Address, DataBuf[Address]); + + /* if couldn't find an empty spot, we must compact emulated eeprom */ + if (empty_slot >= (uint16_t *)FEE_WRITE_LOG_LAST_ADDRESS) { + /* compact the write log into the compacted flash area */ + return eeprom_compact(); + } + + /* ok we found a place let's write our data */ + FLASH_Unlock(); + + /* Pack address and value into the same word */ + uint16_t value = (Address << 8) | DataBuf[Address]; + + /* write to flash */ + eeprom_printf("FLASH_ProgramHalfWord(0x%08x, 0x%04x)\n", (uint32_t)empty_slot, value); + FLASH_Status status = FLASH_ProgramHalfWord((uintptr_t)empty_slot++, value); + + FLASH_Lock(); + + return status; +} + +uint8_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) { + /* if the address is out-of-bounds, do nothing */ + if (Address >= FEE_DENSITY_BYTES) { + eeprom_printf("EEPROM_WriteDataByte(0x%04x, 0x%02x) [BAD ADDRESS]\n", Address, DataByte); + return FLASH_BAD_ADDRESS; + } + + /* if the value is the same, don't bother writing it */ + if (DataBuf[Address] == DataByte) { + eeprom_printf("EEPROM_WriteDataByte(0x%04x, 0x%02x) [SKIP SAME]\n", Address, DataByte); + return 0; + } + + /* keep DataBuf cache in sync */ + DataBuf[Address] = DataByte; + eeprom_printf("EEPROM_WriteDataByte DataBuf[0x%04x] = 0x%02x\n", Address, DataBuf[Address]); + + /* perform the write into flash memory */ + /* First, attempt to write directly into the compacted flash area */ + FLASH_Status status = eeprom_write_direct_entry(Address); + if (!status) { + /* Otherwise append to the write log */ + if (Address < FEE_BYTE_RANGE) { + status = eeprom_write_log_byte_entry(Address); + } else { + status = eeprom_write_log_word_entry(Address & 0xFFFE); } + } + if (status != 0 && status != FLASH_COMPLETE) { + eeprom_printf("EEPROM_WriteDataByte [STATUS == %d]\n", status); + } + return status; +} - // manipulate desired data byte in temp data array if new byte is differ to the current - DataBuf[FEE_ADDR_OFFSET(Address) % FEE_PAGE_SIZE] = DataByte; +uint8_t EEPROM_WriteDataWord(uint16_t Address, uint16_t DataWord) { + /* if the address is out-of-bounds, do nothing */ + if (Address >= FEE_DENSITY_BYTES) { + eeprom_printf("EEPROM_WriteDataWord(0x%04x, 0x%04x) [BAD ADDRESS]\n", Address, DataWord); + return FLASH_BAD_ADDRESS; + } - // Erase Page - FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)); + /* Check for word alignment */ + FLASH_Status final_status = FLASH_COMPLETE; + if (Address % 2) { + final_status = EEPROM_WriteDataByte(Address, DataWord); + FLASH_Status status = EEPROM_WriteDataByte(Address + 1, DataWord >> 8); + if (status != FLASH_COMPLETE) final_status = status; + if (final_status != 0 && final_status != FLASH_COMPLETE) { + eeprom_printf("EEPROM_WriteDataWord [STATUS == %d]\n", final_status); + } + return final_status; + } + + /* if the value is the same, don't bother writing it */ + uint16_t oldValue = *(uint16_t *)(&DataBuf[Address]); + if (oldValue == DataWord) { + eeprom_printf("EEPROM_WriteDataWord(0x%04x, 0x%04x) [SKIP SAME]\n", Address, DataWord); + return 0; + } + + /* keep DataBuf cache in sync */ + *(uint16_t *)(&DataBuf[Address]) = DataWord; + eeprom_printf("EEPROM_WriteDataWord DataBuf[0x%04x] = 0x%04x\n", Address, *(uint16_t *)(&DataBuf[Address])); - // Write new data (whole page) to flash if data has been changed - for (i = 0; i < (FEE_PAGE_SIZE / 2); i++) { - if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) { - FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)])); + /* perform the write into flash memory */ + /* First, attempt to write directly into the compacted flash area */ + final_status = eeprom_write_direct_entry(Address); + if (!final_status) { + /* Otherwise append to the write log */ + /* Check if we need to fall back to byte write */ + if (Address < FEE_BYTE_RANGE) { + final_status = FLASH_COMPLETE; + /* Only write a byte if it has changed */ + if ((uint8_t)oldValue != (uint8_t)DataWord) { + final_status = eeprom_write_log_byte_entry(Address); } + FLASH_Status status = FLASH_COMPLETE; + /* Only write a byte if it has changed */ + if ((oldValue >> 8) != (DataWord >> 8)) { + status = eeprom_write_log_byte_entry(Address + 1); + } + if (status != FLASH_COMPLETE) final_status = status; + } else { + final_status = eeprom_write_log_word_entry(Address); } } - return FlashStatus; + if (final_status != 0 && final_status != FLASH_COMPLETE) { + eeprom_printf("EEPROM_WriteDataWord [STATUS == %d]\n", final_status); + } + return final_status; } -/***************************************************************************** - * Read once data byte from a specified address. - *******************************************************************************/ + uint8_t EEPROM_ReadDataByte(uint16_t Address) { uint8_t DataByte = 0xFF; - // Get Byte from specified address - DataByte = (*(__IO uint8_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))); + if (Address < FEE_DENSITY_BYTES) { + DataByte = DataBuf[Address]; + } + + eeprom_printf("EEPROM_ReadDataByte(0x%04x): 0x%02x\n", Address, DataByte); return DataByte; } +uint16_t EEPROM_ReadDataWord(uint16_t Address) { + uint16_t DataWord = 0xFFFF; + + if (Address < FEE_DENSITY_BYTES - 1) { + /* Check word alignment */ + if (Address % 2) { + DataWord = DataBuf[Address] | (DataBuf[Address + 1] << 8); + } else { + DataWord = *(uint16_t *)(&DataBuf[Address]); + } + } + + eeprom_printf("EEPROM_ReadDataWord(0x%04x): 0x%04x\n", Address, DataWord); + + return DataWord; +} + /***************************************************************************** * Wrap library in AVR style functions. *******************************************************************************/ -uint8_t eeprom_read_byte(const uint8_t *Address) { - const uint16_t p = (const uint32_t)Address; - return EEPROM_ReadDataByte(p); -} +uint8_t eeprom_read_byte(const uint8_t *Address) { return EEPROM_ReadDataByte((const uintptr_t)Address); } -void eeprom_write_byte(uint8_t *Address, uint8_t Value) { - uint16_t p = (uint32_t)Address; - EEPROM_WriteDataByte(p, Value); -} +void eeprom_write_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); } -void eeprom_update_byte(uint8_t *Address, uint8_t Value) { - uint16_t p = (uint32_t)Address; - EEPROM_WriteDataByte(p, Value); -} +void eeprom_update_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); } -uint16_t eeprom_read_word(const uint16_t *Address) { - const uint16_t p = (const uint32_t)Address; - return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8); -} +uint16_t eeprom_read_word(const uint16_t *Address) { return EEPROM_ReadDataWord((const uintptr_t)Address); } -void eeprom_write_word(uint16_t *Address, uint16_t Value) { - uint16_t p = (uint32_t)Address; - EEPROM_WriteDataByte(p, (uint8_t)Value); - EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8)); -} +void eeprom_write_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); } -void eeprom_update_word(uint16_t *Address, uint16_t Value) { - uint16_t p = (uint32_t)Address; - EEPROM_WriteDataByte(p, (uint8_t)Value); - EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8)); -} +void eeprom_update_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); } uint32_t eeprom_read_dword(const uint32_t *Address) { - const uint16_t p = (const uint32_t)Address; - return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8) | (EEPROM_ReadDataByte(p + 2) << 16) | (EEPROM_ReadDataByte(p + 3) << 24); + const uint16_t p = (const uintptr_t)Address; + /* Check word alignment */ + if (p % 2) { + /* Not aligned */ + return (uint32_t)EEPROM_ReadDataByte(p) | (uint32_t)(EEPROM_ReadDataWord(p + 1) << 8) | (uint32_t)(EEPROM_ReadDataByte(p + 3) << 24); + } else { + /* Aligned */ + return EEPROM_ReadDataWord(p) | (EEPROM_ReadDataWord(p + 2) << 16); + } } void eeprom_write_dword(uint32_t *Address, uint32_t Value) { - uint16_t p = (const uint32_t)Address; - EEPROM_WriteDataByte(p, (uint8_t)Value); - EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8)); - EEPROM_WriteDataByte(p + 2, (uint8_t)(Value >> 16)); - EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24)); -} - -void eeprom_update_dword(uint32_t *Address, uint32_t Value) { - uint16_t p = (const uint32_t)Address; - uint32_t existingValue = EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8) | (EEPROM_ReadDataByte(p + 2) << 16) | (EEPROM_ReadDataByte(p + 3) << 24); - if (Value != existingValue) { + uint16_t p = (const uintptr_t)Address; + /* Check word alignment */ + if (p % 2) { + /* Not aligned */ EEPROM_WriteDataByte(p, (uint8_t)Value); - EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8)); - EEPROM_WriteDataByte(p + 2, (uint8_t)(Value >> 16)); + EEPROM_WriteDataWord(p + 1, (uint16_t)(Value >> 8)); EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24)); + } else { + /* Aligned */ + EEPROM_WriteDataWord(p, (uint16_t)Value); + EEPROM_WriteDataWord(p + 2, (uint16_t)(Value >> 16)); } } +void eeprom_update_dword(uint32_t *Address, uint32_t Value) { eeprom_write_dword(Address, Value); } + void eeprom_read_block(void *buf, const void *addr, size_t len) { - const uint8_t *p = (const uint8_t *)addr; + const uint8_t *src = (const uint8_t *)addr; uint8_t * dest = (uint8_t *)buf; - while (len--) { - *dest++ = eeprom_read_byte(p++); + + /* Check word alignment */ + if (len && (uintptr_t)src % 2) { + /* Read the unaligned first byte */ + *dest++ = eeprom_read_byte(src++); + --len; + } + + uint16_t value; + bool aligned = ((uintptr_t)dest % 2 == 0); + while (len > 1) { + value = eeprom_read_word((uint16_t *)src); + if (aligned) { + *(uint16_t *)dest = value; + dest += 2; + } else { + *dest++ = value; + *dest++ = value >> 8; + } + src += 2; + len -= 2; + } + if (len) { + *dest = eeprom_read_byte(src); } } void eeprom_write_block(const void *buf, void *addr, size_t len) { - uint8_t * p = (uint8_t *)addr; - const uint8_t *src = (const uint8_t *)buf; - while (len--) { - eeprom_write_byte(p++, *src++); + uint8_t * dest = (uint8_t *)addr; + const uint8_t *src = (const uint8_t *)buf; + + /* Check word alignment */ + if (len && (uintptr_t)dest % 2) { + /* Write the unaligned first byte */ + eeprom_write_byte(dest++, *src++); + --len; } -} -void eeprom_update_block(const void *buf, void *addr, size_t len) { - uint8_t * p = (uint8_t *)addr; - const uint8_t *src = (const uint8_t *)buf; - while (len--) { - eeprom_write_byte(p++, *src++); + uint16_t value; + bool aligned = ((uintptr_t)src % 2 == 0); + while (len > 1) { + if (aligned) { + value = *(uint16_t *)src; + } else { + value = *(uint8_t *)src | (*(uint8_t *)(src + 1) << 8); + } + eeprom_write_word((uint16_t *)dest, value); + dest += 2; + src += 2; + len -= 2; + } + + if (len) { + eeprom_write_byte(dest, *src); } } + +void eeprom_update_block(const void *buf, void *addr, size_t len) { eeprom_write_block(buf, addr, len); } diff --git a/tmk_core/common/chibios/eeprom_stm32.h b/tmk_core/common/chibios/eeprom_stm32.h index 4dac7c1b59..8fcfb556b8 100644 --- a/tmk_core/common/chibios/eeprom_stm32.h +++ b/tmk_core/common/chibios/eeprom_stm32.h @@ -23,62 +23,11 @@ #pragma once -#include -#include -#include "flash_stm32.h" - -// HACK ALERT. This definition may not match your processor -// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc -#if defined(EEPROM_EMU_STM32F303xC) -# define MCU_STM32F303CC -#elif defined(EEPROM_EMU_STM32F103xB) -# define MCU_STM32F103RB -#elif defined(EEPROM_EMU_STM32F072xB) -# define MCU_STM32F072CB -#elif defined(EEPROM_EMU_STM32F042x6) -# define MCU_STM32F042K6 -#else -# error "not implemented." -#endif - -#ifndef EEPROM_PAGE_SIZE -# if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6) -# define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte -# define FEE_DENSITY_PAGES 2 // How many pages are used -# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB) -# define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte -# define FEE_DENSITY_PAGES 4 // How many pages are used -# else -# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." -# endif -#endif - -#ifndef EEPROM_START_ADDRESS -# if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB) -# define FEE_MCU_FLASH_SIZE 128 // Size in Kb -# elif defined(MCU_STM32F042K6) -# define FEE_MCU_FLASH_SIZE 32 // Size in Kb -# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) -# define FEE_MCU_FLASH_SIZE 512 // Size in Kb -# elif defined(MCU_STM32F103RD) -# define FEE_MCU_FLASH_SIZE 384 // Size in Kb -# elif defined(MCU_STM32F303CC) -# define FEE_MCU_FLASH_SIZE 256 // Size in Kb -# else -# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." -# endif -#endif - -// DONT CHANGE -// Choose location for the first EEPROM Page address on the top of flash -#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE)) -#define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1) -#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES)) -#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) -#define FEE_ADDR_OFFSET(Address) (Address * 2) // 1Byte per Word will be saved to preserve Flash - -// Use this function to initialize the functionality uint16_t EEPROM_Init(void); void EEPROM_Erase(void); -uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte); +uint8_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte); +uint8_t EEPROM_WriteDataWord(uint16_t Address, uint16_t DataWord); uint8_t EEPROM_ReadDataByte(uint16_t Address); +uint16_t EEPROM_ReadDataWord(uint16_t Address); + +void print_eeprom(void); diff --git a/tmk_core/common/chibios/flash_stm32.h b/tmk_core/common/chibios/flash_stm32.h index 90d5bff47e..9c6a7cc50f 100644 --- a/tmk_core/common/chibios/flash_stm32.h +++ b/tmk_core/common/chibios/flash_stm32.h @@ -22,8 +22,11 @@ extern "C" { #endif -#include -#include +#include + +#ifdef FLASH_STM32_MOCKED +extern uint8_t FlashBuf[MOCK_FLASH_SIZE]; +#endif typedef enum { FLASH_BUSY = 1, FLASH_ERROR_PG, FLASH_ERROR_WRP, FLASH_ERROR_OPT, FLASH_COMPLETE, FLASH_TIMEOUT, FLASH_BAD_ADDRESS } FLASH_Status; diff --git a/tmk_core/common/test/eeprom_stm32_tests.cpp b/tmk_core/common/test/eeprom_stm32_tests.cpp new file mode 100644 index 0000000000..aa84492b87 --- /dev/null +++ b/tmk_core/common/test/eeprom_stm32_tests.cpp @@ -0,0 +1,438 @@ +/* Copyright 2021 by Don Kjer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "gtest/gtest.h" + +extern "C" { +#include "flash_stm32.h" +#include "eeprom_stm32.h" +#include "eeprom.h" +} + +/* Mock Flash Parameters: + * + * === Large Layout === + * flash size: 65536 + * page size: 2048 + * density pages: 16 + * Simulated EEPROM size: 16384 + * + * FlashBuf Layout: + * [Unused | Compact | Write Log ] + * [0......|32768......|49152......65535] + * + * === Tiny Layout === + * flash size: 1024 + * page size: 512 + * density pages: 1 + * Simulated EEPROM size: 256 + * + * FlashBuf Layout: + * [Unused | Compact | Write Log ] + * [0......|512......|768......1023] + * + */ + +#define EEPROM_SIZE (FEE_PAGE_SIZE * FEE_DENSITY_PAGES / 2) +#define LOG_SIZE EEPROM_SIZE +#define LOG_BASE (MOCK_FLASH_SIZE - LOG_SIZE) +#define EEPROM_BASE (LOG_BASE - EEPROM_SIZE) + +/* Log encoding helpers */ +#define BYTE_VALUE(addr, value) (((addr) << 8) | (value)) +#define WORD_ZERO(addr) (0x8000 | ((addr) >> 1)) +#define WORD_ONE(addr) (0xA000 | ((addr) >> 1)) +#define WORD_NEXT(addr) (0xE000 | (((addr)-0x80) >> 1)) + +class EepromStm32Test : public testing::Test { + public: + EepromStm32Test() {} + ~EepromStm32Test() {} + + protected: + void SetUp() override { EEPROM_Erase(); } + + void TearDown() override { +#ifdef EEPROM_DEBUG + dumpEepromDataBuf(); +#endif + } +}; + +TEST_F(EepromStm32Test, TestErase) { + EEPROM_WriteDataByte(0, 0x42); + EEPROM_Erase(); + EXPECT_EQ(EEPROM_ReadDataByte(0), 0); + EXPECT_EQ(EEPROM_ReadDataByte(1), 0); +} + +TEST_F(EepromStm32Test, TestReadGarbage) { + uint8_t garbage = 0x3c; + for (int i = 0; i < MOCK_FLASH_SIZE; ++i) { + garbage ^= 0xa3; + garbage += i; + FlashBuf[i] = garbage; + } + EEPROM_Init(); // Just verify we don't crash +} + +TEST_F(EepromStm32Test, TestWriteBadAddress) { + EXPECT_EQ(EEPROM_WriteDataByte(EEPROM_SIZE, 0x42), FLASH_BAD_ADDRESS); + EXPECT_EQ(EEPROM_WriteDataWord(EEPROM_SIZE - 1, 0xbeef), FLASH_BAD_ADDRESS); + EXPECT_EQ(EEPROM_WriteDataWord(EEPROM_SIZE, 0xbeef), FLASH_BAD_ADDRESS); +} + +TEST_F(EepromStm32Test, TestReadBadAddress) { + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE), 0xFF); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 1), 0xFFFF); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE), 0xFFFF); + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0); + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 3)), 0xFF000000); + EXPECT_EQ(eeprom_read_dword((uint32_t*)EEPROM_SIZE), 0xFFFFFFFF); +} + +TEST_F(EepromStm32Test, TestReadByte) { + /* Direct compacted-area baseline: Address < 0x80 */ + FlashBuf[EEPROM_BASE + 2] = ~0xef; + FlashBuf[EEPROM_BASE + 3] = ~0xbe; + /* Direct compacted-area baseline: Address >= 0x80 */ + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 2] = ~0x78; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 1] = ~0x56; + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataByte(2), 0xef); + EXPECT_EQ(EEPROM_ReadDataByte(3), 0xbe); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 2), 0x78); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 1), 0x56); + /* Write Log byte value */ + FlashBuf[LOG_BASE] = 0x65; + FlashBuf[LOG_BASE + 1] = 3; + /* Write Log word value */ + *(uint16_t*)&FlashBuf[LOG_BASE + 2] = WORD_NEXT(EEPROM_SIZE - 2); + *(uint16_t*)&FlashBuf[LOG_BASE + 4] = ~0x9abc; + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataByte(2), 0xef); + EXPECT_EQ(EEPROM_ReadDataByte(3), 0x65); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 2), 0xbc); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 1), 0x9a); +} + +TEST_F(EepromStm32Test, TestWriteByte) { + /* Direct compacted-area baseline: Address < 0x80 */ + EEPROM_WriteDataByte(2, 0xef); + EEPROM_WriteDataByte(3, 0xbe); + /* Direct compacted-area baseline: Address >= 0x80 */ + EEPROM_WriteDataByte(EEPROM_SIZE - 2, 0x78); + EEPROM_WriteDataByte(EEPROM_SIZE - 1, 0x56); + /* Check values */ + /* First write in each aligned word should have been direct */ + EXPECT_EQ(FlashBuf[EEPROM_BASE + 2], (uint8_t)~0xef); + EXPECT_EQ(FlashBuf[EEPROM_BASE + EEPROM_SIZE - 2], (uint8_t)~0x78); + + /* Second write per aligned word requires a log entry */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE], BYTE_VALUE(3, 0xbe)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 2], WORD_NEXT(EEPROM_SIZE - 1)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 4], (uint16_t)~0x5678); +} + +TEST_F(EepromStm32Test, TestByteRoundTrip) { + /* Direct compacted-area: Address < 0x80 */ + EEPROM_WriteDataWord(0, 0xdead); + EEPROM_WriteDataByte(2, 0xef); + EEPROM_WriteDataByte(3, 0xbe); + /* Direct compacted-area: Address >= 0x80 */ + EEPROM_WriteDataByte(EEPROM_SIZE - 2, 0x78); + EEPROM_WriteDataByte(EEPROM_SIZE - 1, 0x56); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataByte(0), 0xad); + EXPECT_EQ(EEPROM_ReadDataByte(1), 0xde); + EXPECT_EQ(EEPROM_ReadDataByte(2), 0xef); + EXPECT_EQ(EEPROM_ReadDataByte(3), 0xbe); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 2), 0x78); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 1), 0x56); + /* Write log entries */ + EEPROM_WriteDataByte(2, 0x80); + EEPROM_WriteDataByte(EEPROM_SIZE - 2, 0x3c); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataByte(2), 0x80); + EXPECT_EQ(EEPROM_ReadDataByte(3), 0xbe); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 2), 0x3c); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 1), 0x56); +} + +TEST_F(EepromStm32Test, TestReadWord) { + /* Direct compacted-area baseline: Address < 0x80 */ + FlashBuf[EEPROM_BASE + 0] = ~0xad; + FlashBuf[EEPROM_BASE + 1] = ~0xde; + /* Direct compacted-area baseline: Address >= 0x80 */ + FlashBuf[EEPROM_BASE + 200] = ~0xcd; + FlashBuf[EEPROM_BASE + 201] = ~0xab; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 4] = ~0x34; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 3] = ~0x12; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 2] = ~0x78; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 1] = ~0x56; + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0), 0xdead); + EXPECT_EQ(EEPROM_ReadDataWord(200), 0xabcd); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 4), 0x1234); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 2), 0x5678); + /* Write Log word zero-encoded */ + *(uint16_t*)&FlashBuf[LOG_BASE] = WORD_ZERO(200); + /* Write Log word one-encoded */ + *(uint16_t*)&FlashBuf[LOG_BASE + 2] = WORD_ONE(EEPROM_SIZE - 4); + /* Write Log word value */ + *(uint16_t*)&FlashBuf[LOG_BASE + 4] = WORD_NEXT(EEPROM_SIZE - 2); + *(uint16_t*)&FlashBuf[LOG_BASE + 6] = ~0x9abc; + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(200), 0); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 4), 1); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 2), 0x9abc); +} + +TEST_F(EepromStm32Test, TestWriteWord) { + /* Direct compacted-area: Address < 0x80 */ + EEPROM_WriteDataWord(0, 0xdead); // Aligned + EEPROM_WriteDataWord(3, 0xbeef); // Unaligned + /* Direct compacted-area: Address >= 0x80 */ + EEPROM_WriteDataWord(200, 0xabcd); // Aligned + EEPROM_WriteDataWord(203, 0x9876); // Unaligned + EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0x1234); + EEPROM_WriteDataWord(EEPROM_SIZE - 2, 0x5678); + /* Write Log word zero-encoded */ + EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0); + /* Write Log word one-encoded */ + EEPROM_WriteDataWord(EEPROM_SIZE - 2, 1); + /* Write Log word value aligned */ + EEPROM_WriteDataWord(200, 0x4321); // Aligned + /* Write Log word value unaligned */ + EEPROM_WriteDataByte(202, 0x3c); // Set neighboring byte + EEPROM_WriteDataWord(203, 0xcdef); // Unaligned + /* Check values */ + /* Direct compacted-area */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE], (uint16_t)~0xdead); + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE + 3], (uint16_t)~0xbeef); + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE + 200], (uint16_t)~0xabcd); + EXPECT_EQ(FlashBuf[EEPROM_BASE + 203], (uint8_t)~0x76); + EXPECT_EQ(FlashBuf[EEPROM_BASE + 204], (uint8_t)~0x98); + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE + EEPROM_SIZE - 4], (uint16_t)~0x1234); + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE + EEPROM_SIZE - 2], (uint16_t)~0x5678); + /* Write Log word zero-encoded */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE], WORD_ZERO(EEPROM_SIZE - 4)); + /* Write Log word one-encoded */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 2], WORD_ONE(EEPROM_SIZE - 2)); + /* Write Log word value aligned */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 4], WORD_NEXT(200)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 6], (uint16_t)~0x4321); + /* Write Log word value unaligned */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 8], WORD_NEXT(202)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 10], (uint16_t)~0x763c); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 12], WORD_NEXT(202)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 14], (uint16_t)~0xef3c); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 16], WORD_NEXT(204)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 18], (uint16_t)~0x00cd); +} + +TEST_F(EepromStm32Test, TestWordRoundTrip) { + /* Direct compacted-area: Address < 0x80 */ + EEPROM_WriteDataWord(0, 0xdead); // Aligned + EEPROM_WriteDataWord(3, 0xbeef); // Unaligned + /* Direct compacted-area: Address >= 0x80 */ + EEPROM_WriteDataWord(200, 0xabcd); // Aligned + EEPROM_WriteDataWord(203, 0x9876); // Unaligned + EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0x1234); + EEPROM_WriteDataWord(EEPROM_SIZE - 2, 0x5678); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0), 0xdead); + EXPECT_EQ(EEPROM_ReadDataWord(3), 0xbeef); + EXPECT_EQ(EEPROM_ReadDataWord(200), 0xabcd); + EXPECT_EQ(EEPROM_ReadDataWord(203), 0x9876); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 4), 0x1234); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 2), 0x5678); + + /* Write Log word zero-encoded */ + EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0); + /* Write Log word one-encoded */ + EEPROM_WriteDataWord(EEPROM_SIZE - 2, 1); + /* Write Log word value aligned */ + EEPROM_WriteDataWord(200, 0x4321); // Aligned + /* Write Log word value unaligned */ + EEPROM_WriteDataByte(202, 0x3c); // Set neighboring byte + EEPROM_WriteDataWord(203, 0xcdef); // Unaligned + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(200), 0x4321); + EXPECT_EQ(EEPROM_ReadDataByte(202), 0x3c); + EXPECT_EQ(EEPROM_ReadDataWord(203), 0xcdef); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 4), 0); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 2), 1); +} + +TEST_F(EepromStm32Test, TestByteWordBoundary) { + /* Direct compacted-area write */ + EEPROM_WriteDataWord(0x7e, 0xdead); + EEPROM_WriteDataWord(0x80, 0xbeef); + /* Byte log entry */ + EEPROM_WriteDataByte(0x7f, 0x3c); + /* Word log entry */ + EEPROM_WriteDataByte(0x80, 0x18); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0x7e), 0x3cad); + EXPECT_EQ(EEPROM_ReadDataWord(0x80), 0xbe18); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE], BYTE_VALUE(0x7f, 0x3c)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 2], WORD_NEXT(0x80)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 4], (uint16_t)~0xbe18); + /* Byte log entries */ + EEPROM_WriteDataWord(0x7e, 0xcafe); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0x7e), 0xcafe); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 6], BYTE_VALUE(0x7e, 0xfe)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 8], BYTE_VALUE(0x7f, 0xca)); + /* Byte and Word log entries */ + EEPROM_WriteDataWord(0x7f, 0xba5e); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0x7f), 0xba5e); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 10], BYTE_VALUE(0x7f, 0x5e)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 12], WORD_NEXT(0x80)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 14], (uint16_t)~0xbeba); + /* Word log entry */ + EEPROM_WriteDataWord(0x80, 0xf00d); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0x80), 0xf00d); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 16], WORD_NEXT(0x80)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 18], (uint16_t)~0xf00d); +} + +TEST_F(EepromStm32Test, TestDWordRoundTrip) { + /* Direct compacted-area: Address < 0x80 */ + eeprom_write_dword((uint32_t*)0, 0xdeadbeef); // Aligned + eeprom_write_dword((uint32_t*)9, 0x12345678); // Unaligned + /* Direct compacted-area: Address >= 0x80 */ + eeprom_write_dword((uint32_t*)200, 0xfacef00d); + eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 4), 0xba5eba11); // Aligned + eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 9), 0xcafed00d); // Unaligned + /* Check direct values */ + EEPROM_Init(); + EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdeadbeef); + EXPECT_EQ(eeprom_read_dword((uint32_t*)9), 0x12345678); + EXPECT_EQ(eeprom_read_dword((uint32_t*)200), 0xfacef00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0xba5eba11); // Aligned + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 9)), 0xcafed00d); // Unaligned + /* Write Log byte encoded */ + eeprom_write_dword((uint32_t*)0, 0xdecafbad); + eeprom_write_dword((uint32_t*)9, 0x87654321); + /* Write Log word encoded */ + eeprom_write_dword((uint32_t*)200, 1); + /* Write Log word value aligned */ + eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 4), 0xdeadc0de); // Aligned + eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 9), 0x6789abcd); // Unaligned + /* Check log values */ + EEPROM_Init(); + EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdecafbad); + EXPECT_EQ(eeprom_read_dword((uint32_t*)9), 0x87654321); + EXPECT_EQ(eeprom_read_dword((uint32_t*)200), 1); + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0xdeadc0de); // Aligned + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 9)), 0x6789abcd); // Unaligned +} + +TEST_F(EepromStm32Test, TestBlockRoundTrip) { + char src0[] = "0123456789abcdef"; + void* src1 = (void*)&src0[1]; + /* Various alignments of src & dst, Address < 0x80 */ + eeprom_write_block(src0, (void*)0, sizeof(src0)); + eeprom_write_block(src0, (void*)21, sizeof(src0)); + eeprom_write_block(src1, (void*)40, sizeof(src0) - 1); + eeprom_write_block(src1, (void*)61, sizeof(src0) - 1); + /* Various alignments of src & dst, Address >= 0x80 */ + eeprom_write_block(src0, (void*)140, sizeof(src0)); + eeprom_write_block(src0, (void*)161, sizeof(src0)); + eeprom_write_block(src1, (void*)180, sizeof(src0) - 1); + eeprom_write_block(src1, (void*)201, sizeof(src0) - 1); + + /* Check values */ + EEPROM_Init(); + + char dstBuf[256] = {0}; + char* dst0a = (char*)dstBuf; + char* dst0b = (char*)&dstBuf[20]; + char* dst1a = (char*)&dstBuf[41]; + char* dst1b = (char*)&dstBuf[61]; + char* dst0c = (char*)&dstBuf[80]; + char* dst0d = (char*)&dstBuf[100]; + char* dst1c = (char*)&dstBuf[121]; + char* dst1d = (char*)&dstBuf[141]; + eeprom_read_block((void*)dst0a, (void*)0, sizeof(src0)); + eeprom_read_block((void*)dst0b, (void*)21, sizeof(src0)); + eeprom_read_block((void*)dst1a, (void*)40, sizeof(src0) - 1); + eeprom_read_block((void*)dst1b, (void*)61, sizeof(src0) - 1); + eeprom_read_block((void*)dst0c, (void*)140, sizeof(src0)); + eeprom_read_block((void*)dst0d, (void*)161, sizeof(src0)); + eeprom_read_block((void*)dst1c, (void*)180, sizeof(src0) - 1); + eeprom_read_block((void*)dst1d, (void*)201, sizeof(src0) - 1); + EXPECT_EQ(strcmp((char*)src0, dst0a), 0); + EXPECT_EQ(strcmp((char*)src0, dst0b), 0); + EXPECT_EQ(strcmp((char*)src0, dst0c), 0); + EXPECT_EQ(strcmp((char*)src0, dst0d), 0); + EXPECT_EQ(strcmp((char*)src1, dst1a), 0); + EXPECT_EQ(strcmp((char*)src1, dst1b), 0); + EXPECT_EQ(strcmp((char*)src1, dst1c), 0); + EXPECT_EQ(strcmp((char*)src1, dst1d), 0); +} + +TEST_F(EepromStm32Test, TestCompaction) { + /* Direct writes */ + eeprom_write_dword((uint32_t*)0, 0xdeadbeef); + eeprom_write_byte((uint8_t*)4, 0x3c); + eeprom_write_word((uint16_t*)6, 0xd00d); + eeprom_write_dword((uint32_t*)150, 0xcafef00d); + eeprom_write_dword((uint32_t*)200, 0x12345678); + /* Fill write log entries */ + uint32_t i; + uint32_t val = 0xd8453c6b; + for (i = 0; i < (LOG_SIZE / (sizeof(uint32_t) * 2)); i++) { + val ^= 0x593ca5b3; + val += i; + eeprom_write_dword((uint32_t*)200, val); + } + /* Check values pre-compaction */ + EEPROM_Init(); + EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdeadbeef); + EXPECT_EQ(eeprom_read_byte((uint8_t*)4), 0x3c); + EXPECT_EQ(eeprom_read_word((uint16_t*)6), 0xd00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)150), 0xcafef00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)200), val); + EXPECT_NE(*(uint16_t*)&FlashBuf[LOG_BASE], 0xFFFF); + EXPECT_NE(*(uint16_t*)&FlashBuf[LOG_BASE + LOG_SIZE - 2], 0xFFFF); + /* Run compaction */ + eeprom_write_byte((uint8_t*)4, 0x1f); + EEPROM_Init(); + EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdeadbeef); + EXPECT_EQ(eeprom_read_byte((uint8_t*)4), 0x1f); + EXPECT_EQ(eeprom_read_word((uint16_t*)6), 0xd00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)150), 0xcafef00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)200), val); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE], 0xFFFF); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + LOG_SIZE - 2], 0xFFFF); +} diff --git a/tmk_core/common/test/flash_stm32_mock.c b/tmk_core/common/test/flash_stm32_mock.c new file mode 100644 index 0000000000..1b81d81f9a --- /dev/null +++ b/tmk_core/common/test/flash_stm32_mock.c @@ -0,0 +1,50 @@ +/* Copyright 2021 by Don Kjer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include "flash_stm32.h" + +uint8_t FlashBuf[MOCK_FLASH_SIZE] = {0}; + +static bool flash_locked = true; + +FLASH_Status FLASH_ErasePage(uint32_t Page_Address) { + if (flash_locked) return FLASH_ERROR_WRP; + Page_Address -= (uintptr_t)FlashBuf; + Page_Address -= (Page_Address % FEE_PAGE_SIZE); + if (Page_Address >= MOCK_FLASH_SIZE) return FLASH_BAD_ADDRESS; + memset(&FlashBuf[Page_Address], '\xff', FEE_PAGE_SIZE); + return FLASH_COMPLETE; +} + +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) { + if (flash_locked) return FLASH_ERROR_WRP; + Address -= (uintptr_t)FlashBuf; + if (Address >= MOCK_FLASH_SIZE) return FLASH_BAD_ADDRESS; + uint16_t oldData = *(uint16_t*)&FlashBuf[Address]; + if (oldData == 0xFFFF || Data == 0) { + *(uint16_t*)&FlashBuf[Address] = Data; + return FLASH_COMPLETE; + } else { + return FLASH_ERROR_PG; + } +} + +FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) { return FLASH_COMPLETE; } +void FLASH_Unlock(void) { flash_locked = false; } +void FLASH_Lock(void) { flash_locked = true; } +void FLASH_ClearFlag(uint32_t FLASH_FLAG) {} diff --git a/tmk_core/common/test/rules.mk b/tmk_core/common/test/rules.mk new file mode 100644 index 0000000000..e47e5880c5 --- /dev/null +++ b/tmk_core/common/test/rules.mk @@ -0,0 +1,23 @@ +eeprom_stm32_DEFS := -DFLASH_STM32_MOCKED -DNO_PRINT -DFEE_FLASH_BASE=FlashBuf +eeprom_stm32_tiny_DEFS := $(eeprom_stm32_DEFS) \ + -DFEE_MCU_FLASH_SIZE=1 \ + -DMOCK_FLASH_SIZE=1024 \ + -DFEE_PAGE_SIZE=512 \ + -DFEE_DENSITY_PAGES=1 +eeprom_stm32_large_DEFS := $(eeprom_stm32_DEFS) \ + -DFEE_MCU_FLASH_SIZE=64 \ + -DMOCK_FLASH_SIZE=65536 \ + -DFEE_PAGE_SIZE=2048 \ + -DFEE_DENSITY_PAGES=16 + +eeprom_stm32_INC := \ + $(TMK_PATH)/common/chibios/ +eeprom_stm32_tiny_INC := $(eeprom_stm32_INC) +eeprom_stm32_large_INC := $(eeprom_stm32_INC) + +eeprom_stm32_SRC := \ + $(TMK_PATH)/common/test/eeprom_stm32_tests.cpp \ + $(TMK_PATH)/common/test/flash_stm32_mock.c \ + $(TMK_PATH)/common/chibios/eeprom_stm32.c +eeprom_stm32_tiny_SRC := $(eeprom_stm32_SRC) +eeprom_stm32_large_SRC := $(eeprom_stm32_SRC) diff --git a/tmk_core/common/test/testlist.mk b/tmk_core/common/test/testlist.mk new file mode 100644 index 0000000000..51a9638bb9 --- /dev/null +++ b/tmk_core/common/test/testlist.mk @@ -0,0 +1 @@ +TEST_LIST += eeprom_stm32_tiny eeprom_stm32_large -- cgit v1.2.3 From c9c60d227e38abdf08ca86bcdad3a0cac2579e3f Mon Sep 17 00:00:00 2001 From: Takeshi ISHII <2170248+mtei@users.noreply.github.com> Date: Tue, 24 Aug 2021 22:34:24 +0900 Subject: add wait_cpuclock() macro for AVR and CPU_CLOCK macro (#12755) --- tmk_core/common/avr/_wait.h | 4 +++- tmk_core/common/chibios/_wait.h | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/avr/_wait.h b/tmk_core/common/avr/_wait.h index ae1a25131a..683db6ae57 100644 --- a/tmk_core/common/avr/_wait.h +++ b/tmk_core/common/avr/_wait.h @@ -37,6 +37,8 @@ } \ } \ } while (0) +#define wait_cpuclock(n) __builtin_avr_delay_cycles(n) +#define CPU_CLOCK F_CPU /* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. * But here's more margin to make it two clocks. */ @@ -44,4 +46,4 @@ # define GPIO_INPUT_PIN_DELAY 2 #endif -#define waitInputPinDelay() __builtin_avr_delay_cycles(GPIO_INPUT_PIN_DELAY) +#define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h index 4a5172536b..b740afbd24 100644 --- a/tmk_core/common/chibios/_wait.h +++ b/tmk_core/common/chibios/_wait.h @@ -41,6 +41,10 @@ void wait_us(uint16_t duration); } while (0) #endif +#include "_wait.c" + +#define CPU_CLOCK STM32_SYSCLK + /* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus * to which the GPIO is connected. * The connected buses differ depending on the various series of MCUs. @@ -51,11 +55,8 @@ void wait_us(uint16_t duration); * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. * (A fairly large value of 0.25 microseconds is set.) */ - -#include "_wait.c" - #ifndef GPIO_INPUT_PIN_DELAY -# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) +# define GPIO_INPUT_PIN_DELAY (CPU_CLOCK / 1000000L / 4) #endif #define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) -- cgit v1.2.3 From f2c9e82e5b3887ed28c3a5c68d27c4efaca54201 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Tue, 31 Aug 2021 00:25:41 +0100 Subject: cherry pick tidy up (#14244) --- tmk_core/common/chibios/eeprom_stm32.c | 12 +++++------- tmk_core/common/chibios/flash_stm32.c | 31 +------------------------------ tmk_core/common/chibios/flash_stm32.h | 1 - tmk_core/common/test/flash_stm32_mock.c | 1 - 4 files changed, 6 insertions(+), 39 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c index 5bf852fde1..64d7d79ba0 100644 --- a/tmk_core/common/chibios/eeprom_stm32.c +++ b/tmk_core/common/chibios/eeprom_stm32.c @@ -20,6 +20,7 @@ #include #include +#include "util.h" #include "debug.h" #include "eeprom_stm32.h" #include "flash_stm32.h" @@ -188,9 +189,6 @@ # endif #endif -#define FEE_XSTR(x) FEE_STR(x) -#define FEE_STR(x) #x - /* Size of combined compacted eeprom and write log pages */ #define FEE_DENSITY_MAX_SIZE (FEE_DENSITY_PAGES * FEE_PAGE_SIZE) /* Addressable range 16KByte: 0 <-> (0x1FFF << 1) */ @@ -198,7 +196,7 @@ #ifndef EEPROM_START_ADDRESS /* *TODO: Get rid of this check */ # if FEE_DENSITY_MAX_SIZE > (FEE_MCU_FLASH_SIZE * 1024) -# pragma message FEE_XSTR(FEE_DENSITY_MAX_SIZE) " > " FEE_XSTR(FEE_MCU_FLASH_SIZE * 1024) +# pragma message STR(FEE_DENSITY_MAX_SIZE) " > " STR(FEE_MCU_FLASH_SIZE * 1024) # error emulated eeprom: FEE_DENSITY_PAGES is greater than available flash size # endif #endif @@ -206,15 +204,15 @@ /* Size of emulated eeprom */ #ifdef FEE_DENSITY_BYTES # if (FEE_DENSITY_BYTES > FEE_DENSITY_MAX_SIZE) -# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " > " FEE_XSTR(FEE_DENSITY_MAX_SIZE) +# pragma message STR(FEE_DENSITY_BYTES) " > " STR(FEE_DENSITY_MAX_SIZE) # error emulated eeprom: FEE_DENSITY_BYTES exceeds FEE_DENSITY_MAX_SIZE # endif # if (FEE_DENSITY_BYTES == FEE_DENSITY_MAX_SIZE) -# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " == " FEE_XSTR(FEE_DENSITY_MAX_SIZE) +# pragma message STR(FEE_DENSITY_BYTES) " == " STR(FEE_DENSITY_MAX_SIZE) # warning emulated eeprom: FEE_DENSITY_BYTES leaves no room for a write log. This will greatly increase the flash wear rate! # endif # if FEE_DENSITY_BYTES > FEE_ADDRESS_MAX_SIZE -# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " > " FEE_XSTR(FEE_ADDRESS_MAX_SIZE) +# pragma message STR(FEE_DENSITY_BYTES) " > " STR(FEE_ADDRESS_MAX_SIZE) # error emulated eeprom: FEE_DENSITY_BYTES is greater than FEE_ADDRESS_MAX_SIZE allows # endif # if ((FEE_DENSITY_BYTES) % 2) == 1 diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c index 66f2b13768..6b80ff71c3 100644 --- a/tmk_core/common/chibios/flash_stm32.c +++ b/tmk_core/common/chibios/flash_stm32.c @@ -16,22 +16,7 @@ * Modifications for QMK and STM32F303 by Yiancar */ -#if defined(EEPROM_EMU_STM32F303xC) -# define STM32F303xC -# include "stm32f3xx.h" -#elif defined(EEPROM_EMU_STM32F103xB) -# define STM32F103xB -# include "stm32f1xx.h" -#elif defined(EEPROM_EMU_STM32F072xB) -# define STM32F072xB -# include "stm32f0xx.h" -#elif defined(EEPROM_EMU_STM32F042x6) -# define STM32F042x6 -# include "stm32f0xx.h" -#else -# error "not implemented." -#endif - +#include #include "flash_stm32.h" #if defined(EEPROM_EMU_STM32F103xB) @@ -177,17 +162,3 @@ void FLASH_Lock(void) { /* Set the Lock Bit to lock the FPEC and the FCR */ FLASH->CR |= FLASH_CR_LOCK; } - -/** - * @brief Clears the FLASH's pending flags. - * @param FLASH_FLAG: specifies the FLASH flags to clear. - * This parameter can be any combination of the following values: - * @arg FLASH_FLAG_PGERR: FLASH Programming error flag flag - * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag - * @arg FLASH_FLAG_EOP: FLASH End of Programming flag - * @retval None - */ -void FLASH_ClearFlag(uint32_t FLASH_FLAG) { - /* Clear the flags */ - FLASH->SR = FLASH_FLAG; -} diff --git a/tmk_core/common/chibios/flash_stm32.h b/tmk_core/common/chibios/flash_stm32.h index 9c6a7cc50f..6c66642ec5 100644 --- a/tmk_core/common/chibios/flash_stm32.h +++ b/tmk_core/common/chibios/flash_stm32.h @@ -38,7 +38,6 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); void FLASH_Unlock(void); void FLASH_Lock(void); -void FLASH_ClearFlag(uint32_t FLASH_FLAG); #ifdef __cplusplus } diff --git a/tmk_core/common/test/flash_stm32_mock.c b/tmk_core/common/test/flash_stm32_mock.c index 1b81d81f9a..222a004bc7 100644 --- a/tmk_core/common/test/flash_stm32_mock.c +++ b/tmk_core/common/test/flash_stm32_mock.c @@ -47,4 +47,3 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) { FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) { return FLASH_COMPLETE; } void FLASH_Unlock(void) { flash_locked = false; } void FLASH_Lock(void) { flash_locked = true; } -void FLASH_ClearFlag(uint32_t FLASH_FLAG) {} -- cgit v1.2.3 From 8d6d8cfadfd1522b3dd2cc8ac1ce7393b45bbe64 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 5 Sep 2021 21:36:43 +0100 Subject: Tidy up defines within STM EEPROM emulation (#14275) * Tidy up defines within stm eeprom emulation * Fix tests * Resolve todo * Still use page notion in clear * Remove more f4 refs --- tmk_core/common/chibios/eeprom_stm32.c | 110 ++++++++++------------------ tmk_core/common/chibios/eeprom_stm32_defs.h | 61 +++++++++++++++ tmk_core/common/test/eeprom_stm32_tests.cpp | 2 +- tmk_core/common/test/hal.h | 18 +++++ tmk_core/common/test/rules.mk | 4 +- 5 files changed, 119 insertions(+), 76 deletions(-) create mode 100644 tmk_core/common/chibios/eeprom_stm32_defs.h create mode 100644 tmk_core/common/test/hal.h (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c index 64d7d79ba0..1fdf8c1e29 100644 --- a/tmk_core/common/chibios/eeprom_stm32.c +++ b/tmk_core/common/chibios/eeprom_stm32.c @@ -51,13 +51,13 @@ * * The following configuration defines can be set: * - * FEE_DENSITY_PAGES # Total number of pages to use for eeprom simulation (Compact + Write log) - * FEE_DENSITY_BYTES # Size of simulated eeprom. (Defaults to half the space allocated by FEE_DENSITY_PAGES) + * FEE_PAGE_COUNT # Total number of pages to use for eeprom simulation (Compact + Write log) + * FEE_DENSITY_BYTES # Size of simulated eeprom. (Defaults to half the space allocated by FEE_PAGE_COUNT) * NOTE: The current implementation does not include page swapping, * and FEE_DENSITY_BYTES will consume that amount of RAM as a cached view of actual EEPROM contents. * * The maximum size of FEE_DENSITY_BYTES is currently 16384. The write log size equals - * FEE_DENSITY_PAGES * FEE_PAGE_SIZE - FEE_DENSITY_BYTES. + * FEE_PAGE_COUNT * FEE_PAGE_SIZE - FEE_DENSITY_BYTES. * The larger the write log, the less frequently the compacted area needs to be rewritten. * * @@ -132,6 +132,11 @@ * */ +#include "eeprom_stm32_defs.h" +#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT) || !defined(FEE_MCU_FLASH_SIZE) || !defined(FEE_PAGE_BASE_ADDRESS) +# error "not implemented." +#endif + /* These bits are used for optimizing encoding of bytes, 0 and 1 */ #define FEE_WORD_ENCODING 0x8000 #define FEE_VALUE_NEXT 0x6000 @@ -139,65 +144,19 @@ #define FEE_VALUE_ENCODED 0x2000 #define FEE_BYTE_RANGE 0x80 -// HACK ALERT. This definition may not match your processor -// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc -#if defined(EEPROM_EMU_STM32F303xC) -# define MCU_STM32F303CC -#elif defined(EEPROM_EMU_STM32F103xB) -# define MCU_STM32F103RB -#elif defined(EEPROM_EMU_STM32F072xB) -# define MCU_STM32F072CB -#elif defined(EEPROM_EMU_STM32F042x6) -# define MCU_STM32F042K6 -#elif !defined(FEE_PAGE_SIZE) || !defined(FEE_DENSITY_PAGES) || !defined(FEE_MCU_FLASH_SIZE) -# error "not implemented." -#endif - -#if !defined(FEE_PAGE_SIZE) || !defined(FEE_DENSITY_PAGES) -# if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6) -# ifndef FEE_PAGE_SIZE -# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte -# endif -# ifndef FEE_DENSITY_PAGES -# define FEE_DENSITY_PAGES 2 // How many pages are used -# endif -# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB) -# ifndef FEE_PAGE_SIZE -# define FEE_PAGE_SIZE 0x800 // Page size = 2KByte -# endif -# ifndef FEE_DENSITY_PAGES -# define FEE_DENSITY_PAGES 4 // How many pages are used -# endif -# else -# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." -# endif -#endif +/* Addressable range 16KByte: 0 <-> (0x1FFF << 1) */ +#define FEE_ADDRESS_MAX_SIZE 0x4000 -#ifndef FEE_MCU_FLASH_SIZE -# if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB) -# define FEE_MCU_FLASH_SIZE 128 // Size in Kb -# elif defined(MCU_STM32F042K6) -# define FEE_MCU_FLASH_SIZE 32 // Size in Kb -# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) -# define FEE_MCU_FLASH_SIZE 512 // Size in Kb -# elif defined(MCU_STM32F103RD) -# define FEE_MCU_FLASH_SIZE 384 // Size in Kb -# elif defined(MCU_STM32F303CC) -# define FEE_MCU_FLASH_SIZE 256 // Size in Kb -# else -# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." -# endif -#endif +/* Flash word value after erase */ +#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) /* Size of combined compacted eeprom and write log pages */ -#define FEE_DENSITY_MAX_SIZE (FEE_DENSITY_PAGES * FEE_PAGE_SIZE) -/* Addressable range 16KByte: 0 <-> (0x1FFF << 1) */ -#define FEE_ADDRESS_MAX_SIZE 0x4000 +#define FEE_DENSITY_MAX_SIZE (FEE_PAGE_COUNT * FEE_PAGE_SIZE) -#ifndef EEPROM_START_ADDRESS /* *TODO: Get rid of this check */ +#ifndef FEE_MCU_FLASH_SIZE_IGNORE_CHECK /* *TODO: Get rid of this check */ # if FEE_DENSITY_MAX_SIZE > (FEE_MCU_FLASH_SIZE * 1024) # pragma message STR(FEE_DENSITY_MAX_SIZE) " > " STR(FEE_MCU_FLASH_SIZE * 1024) -# error emulated eeprom: FEE_DENSITY_PAGES is greater than available flash size +# error emulated eeprom: FEE_DENSITY_MAX_SIZE is greater than available flash size # endif #endif @@ -220,27 +179,32 @@ # endif #else /* Default to half of allocated space used for emulated eeprom, half for write log */ -# define FEE_DENSITY_BYTES (FEE_DENSITY_PAGES * FEE_PAGE_SIZE / 2) +# define FEE_DENSITY_BYTES (FEE_PAGE_COUNT * FEE_PAGE_SIZE / 2) #endif /* Size of write log */ -#define FEE_WRITE_LOG_BYTES (FEE_DENSITY_PAGES * FEE_PAGE_SIZE - FEE_DENSITY_BYTES) +#ifdef FEE_WRITE_LOG_BYTES +# if ((FEE_DENSITY_BYTES + FEE_WRITE_LOG_BYTES) > FEE_DENSITY_MAX_SIZE) +# pragma message STR(FEE_DENSITY_BYTES) " + " STR(FEE_WRITE_LOG_BYTES) " > " STR(FEE_DENSITY_MAX_SIZE) +# error emulated eeprom: FEE_WRITE_LOG_BYTES exceeds remaining FEE_DENSITY_MAX_SIZE +# endif +# if ((FEE_WRITE_LOG_BYTES) % 2) == 1 +# error emulated eeprom: FEE_WRITE_LOG_BYTES must be even +# endif +#else +/* Default to use all remaining space */ +# define FEE_WRITE_LOG_BYTES (FEE_PAGE_COUNT * FEE_PAGE_SIZE - FEE_DENSITY_BYTES) +#endif /* Start of the emulated eeprom compacted flash area */ -#ifndef FEE_FLASH_BASE -# define FEE_FLASH_BASE 0x8000000 -#endif -#define FEE_PAGE_BASE_ADDRESS ((uintptr_t)(FEE_FLASH_BASE) + FEE_MCU_FLASH_SIZE * 1024 - FEE_WRITE_LOG_BYTES - FEE_DENSITY_BYTES) +#define FEE_COMPACTED_BASE_ADDRESS FEE_PAGE_BASE_ADDRESS /* End of the emulated eeprom compacted flash area */ -#define FEE_PAGE_LAST_ADDRESS (FEE_PAGE_BASE_ADDRESS + FEE_DENSITY_BYTES) +#define FEE_COMPACTED_LAST_ADDRESS (FEE_COMPACTED_BASE_ADDRESS + FEE_DENSITY_BYTES) /* Start of the emulated eeprom write log */ -#define FEE_WRITE_LOG_BASE_ADDRESS FEE_PAGE_LAST_ADDRESS +#define FEE_WRITE_LOG_BASE_ADDRESS FEE_COMPACTED_LAST_ADDRESS /* End of the emulated eeprom write log */ #define FEE_WRITE_LOG_LAST_ADDRESS (FEE_WRITE_LOG_BASE_ADDRESS + FEE_WRITE_LOG_BYTES) -/* Flash word value after erase */ -#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) - #if defined(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) && (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= FEE_DENSITY_BYTES) # error emulated eeprom: DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is greater than the FEE_DENSITY_BYTES available #endif @@ -313,9 +277,9 @@ void print_eeprom(void) { uint16_t EEPROM_Init(void) { /* Load emulated eeprom contents from compacted flash into memory */ - uint16_t *src = (uint16_t *)FEE_PAGE_BASE_ADDRESS; + uint16_t *src = (uint16_t *)FEE_COMPACTED_BASE_ADDRESS; uint16_t *dest = (uint16_t *)DataBuf; - for (; src < (uint16_t *)FEE_PAGE_LAST_ADDRESS; ++src, ++dest) { + for (; src < (uint16_t *)FEE_COMPACTED_LAST_ADDRESS; ++src, ++dest) { *dest = ~*src; } @@ -390,7 +354,7 @@ uint16_t EEPROM_Init(void) { static void eeprom_clear(void) { FLASH_Unlock(); - for (uint16_t page_num = 0; page_num < FEE_DENSITY_PAGES; ++page_num) { + for (uint16_t page_num = 0; page_num < FEE_PAGE_COUNT; ++page_num) { eeprom_printf("FLASH_ErasePage(0x%04x)\n", (uint32_t)(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE))); FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE)); } @@ -421,9 +385,9 @@ static uint8_t eeprom_compact(void) { /* Write emulated eeprom contents from memory to compacted flash */ uint16_t *src = (uint16_t *)DataBuf; - uintptr_t dest = FEE_PAGE_BASE_ADDRESS; + uintptr_t dest = FEE_COMPACTED_BASE_ADDRESS; uint16_t value; - for (; dest < FEE_PAGE_LAST_ADDRESS; ++src, dest += 2) { + for (; dest < FEE_COMPACTED_LAST_ADDRESS; ++src, dest += 2) { value = *src; if (value) { eeprom_printf("FLASH_ProgramHalfWord(0x%04x, 0x%04x)\n", (uint32_t)dest, ~value); @@ -444,7 +408,7 @@ static uint8_t eeprom_compact(void) { static uint8_t eeprom_write_direct_entry(uint16_t Address) { /* Check if we can just write this directly to the compacted flash area */ - uintptr_t directAddress = FEE_PAGE_BASE_ADDRESS + (Address & 0xFFFE); + uintptr_t directAddress = FEE_COMPACTED_BASE_ADDRESS + (Address & 0xFFFE); if (*(uint16_t *)directAddress == FEE_EMPTY_WORD) { /* Write the value directly to the compacted area without a log entry */ uint16_t value = ~*(uint16_t *)(&DataBuf[Address & 0xFFFE]); diff --git a/tmk_core/common/chibios/eeprom_stm32_defs.h b/tmk_core/common/chibios/eeprom_stm32_defs.h new file mode 100644 index 0000000000..a775ec201a --- /dev/null +++ b/tmk_core/common/chibios/eeprom_stm32_defs.h @@ -0,0 +1,61 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +#include + +#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT) +# if defined(STM32F103xB) || defined(STM32F042x6) +# ifndef FEE_PAGE_SIZE +# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte +# endif +# ifndef FEE_PAGE_COUNT +# define FEE_PAGE_COUNT 2 // How many pages are used +# endif +# elif defined(STM32F103xE) || defined(STM32F303xC) || defined(STM32F072xB) +# ifndef FEE_PAGE_SIZE +# define FEE_PAGE_SIZE 0x800 // Page size = 2KByte +# endif +# ifndef FEE_PAGE_COUNT +# define FEE_PAGE_COUNT 4 // How many pages are used +# endif +# endif +#endif + +#if !defined(FEE_MCU_FLASH_SIZE) +# if defined(STM32F042x6) +# define FEE_MCU_FLASH_SIZE 32 // Size in Kb +# elif defined(STM32F103xB) || defined(STM32F072xB) +# define FEE_MCU_FLASH_SIZE 128 // Size in Kb +# elif defined(STM32F303xC) +# define FEE_MCU_FLASH_SIZE 256 // Size in Kb +# elif defined(STM32F103xE) +# define FEE_MCU_FLASH_SIZE 512 // Size in Kb +# endif +#endif + +/* Start of the emulated eeprom */ +#if !defined(FEE_PAGE_BASE_ADDRESS) +# if 0 +/* TODO: Add support for F4 */ +# else +# ifndef FEE_FLASH_BASE +# define FEE_FLASH_BASE 0x8000000 +# endif +/* Default to end of flash */ +# define FEE_PAGE_BASE_ADDRESS ((uintptr_t)(FEE_FLASH_BASE) + FEE_MCU_FLASH_SIZE * 1024 - (FEE_PAGE_COUNT * FEE_PAGE_SIZE)) +# endif +#endif diff --git a/tmk_core/common/test/eeprom_stm32_tests.cpp b/tmk_core/common/test/eeprom_stm32_tests.cpp index aa84492b87..5bc8d87900 100644 --- a/tmk_core/common/test/eeprom_stm32_tests.cpp +++ b/tmk_core/common/test/eeprom_stm32_tests.cpp @@ -46,7 +46,7 @@ extern "C" { * */ -#define EEPROM_SIZE (FEE_PAGE_SIZE * FEE_DENSITY_PAGES / 2) +#define EEPROM_SIZE (FEE_PAGE_SIZE * FEE_PAGE_COUNT / 2) #define LOG_SIZE EEPROM_SIZE #define LOG_BASE (MOCK_FLASH_SIZE - LOG_SIZE) #define EEPROM_BASE (LOG_BASE - EEPROM_SIZE) diff --git a/tmk_core/common/test/hal.h b/tmk_core/common/test/hal.h new file mode 100644 index 0000000000..2d268ad54c --- /dev/null +++ b/tmk_core/common/test/hal.h @@ -0,0 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ +#pragma once + +// Just here to please eeprom tests diff --git a/tmk_core/common/test/rules.mk b/tmk_core/common/test/rules.mk index e47e5880c5..48632a095b 100644 --- a/tmk_core/common/test/rules.mk +++ b/tmk_core/common/test/rules.mk @@ -3,12 +3,12 @@ eeprom_stm32_tiny_DEFS := $(eeprom_stm32_DEFS) \ -DFEE_MCU_FLASH_SIZE=1 \ -DMOCK_FLASH_SIZE=1024 \ -DFEE_PAGE_SIZE=512 \ - -DFEE_DENSITY_PAGES=1 + -DFEE_PAGE_COUNT=1 eeprom_stm32_large_DEFS := $(eeprom_stm32_DEFS) \ -DFEE_MCU_FLASH_SIZE=64 \ -DMOCK_FLASH_SIZE=65536 \ -DFEE_PAGE_SIZE=2048 \ - -DFEE_DENSITY_PAGES=16 + -DFEE_PAGE_COUNT=16 eeprom_stm32_INC := \ $(TMK_PATH)/common/chibios/ -- cgit v1.2.3 From 1a494da288509d162593aaa07f4f9ca36b6b3dbd Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 5 Sep 2021 23:56:10 +0100 Subject: Fix eeprom for Durgod boards (#14324) --- tmk_core/common/chibios/eeprom_stm32_defs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/chibios/eeprom_stm32_defs.h b/tmk_core/common/chibios/eeprom_stm32_defs.h index a775ec201a..22b4ab858e 100644 --- a/tmk_core/common/chibios/eeprom_stm32_defs.h +++ b/tmk_core/common/chibios/eeprom_stm32_defs.h @@ -25,7 +25,7 @@ # ifndef FEE_PAGE_COUNT # define FEE_PAGE_COUNT 2 // How many pages are used # endif -# elif defined(STM32F103xE) || defined(STM32F303xC) || defined(STM32F072xB) +# elif defined(STM32F103xE) || defined(STM32F303xC) || defined(STM32F072xB) || defined(STM32F070xB) # ifndef FEE_PAGE_SIZE # define FEE_PAGE_SIZE 0x800 // Page size = 2KByte # endif @@ -38,7 +38,7 @@ #if !defined(FEE_MCU_FLASH_SIZE) # if defined(STM32F042x6) # define FEE_MCU_FLASH_SIZE 32 // Size in Kb -# elif defined(STM32F103xB) || defined(STM32F072xB) +# elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) # define FEE_MCU_FLASH_SIZE 128 // Size in Kb # elif defined(STM32F303xC) # define FEE_MCU_FLASH_SIZE 256 // Size in Kb -- cgit v1.2.3 From 02ab7b1888e6572178543ca0b944e4fa14cdf974 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Wed, 29 Sep 2021 11:37:11 -0700 Subject: [Core] Fix "6kro enable" and clarify naming (#14563) * Fix USB_6KRO_ENABLE compilation errors * Add info to docs * Rename define to be more accurate * Remove unused rule * Refixe docs --- tmk_core/common/report.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'tmk_core/common') diff --git a/tmk_core/common/report.c b/tmk_core/common/report.c index 1bcb6f2adb..2a7fc006c4 100644 --- a/tmk_core/common/report.c +++ b/tmk_core/common/report.c @@ -21,6 +21,16 @@ #include "util.h" #include +#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE +# define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) +# define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) +# define RO_INC(a) RO_ADD(a, 1) +# define RO_DEC(a) RO_SUB(a, 1) +static int8_t cb_head = 0; +static int8_t cb_tail = 0; +static int8_t cb_count = 0; +#endif + /** \brief has_anykey * * FIXME: Needs doc @@ -54,7 +64,7 @@ uint8_t get_first_key(report_keyboard_t* keyboard_report) { return i << 3 | biton(keyboard_report->nkro.bits[i]); } #endif -#ifdef USB_6KRO_ENABLE +#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE uint8_t i = cb_head; do { if (keyboard_report->keys[i] != 0) { @@ -99,7 +109,7 @@ bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key) { * FIXME: Needs doc */ void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { -#ifdef USB_6KRO_ENABLE +#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE int8_t i = cb_head; int8_t empty = -1; if (cb_count) { @@ -166,7 +176,7 @@ void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { * FIXME: Needs doc */ void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { -#ifdef USB_6KRO_ENABLE +#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE uint8_t i = cb_head; if (cb_count) { do { -- cgit v1.2.3