diff options
Diffstat (limited to 'quantum')
69 files changed, 1603 insertions, 694 deletions
diff --git a/quantum/action.c b/quantum/action.c index 29822c39e9..8dae32b2cb 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -1011,9 +1011,7 @@ __attribute__((weak)) void unregister_code(uint8_t code) { */ __attribute__((weak)) void tap_code_delay(uint8_t code, uint16_t delay) { register_code(code); - for (uint16_t i = delay; i > 0; i--) { - wait_ms(1); - } + wait_ms(delay); unregister_code(code); } diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index 28c8267517..c1a1500493 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -17,6 +17,7 @@ #include "audio.h" #include "eeconfig.h" #include "timer.h" +#include "debug.h" #include "wait.h" #include "util.h" @@ -62,6 +63,13 @@ * the internal state of the audio system does its calculations with the later - ms */ +#ifndef AUDIO_DEFAULT_ON +# define AUDIO_DEFAULT_ON true +#endif +#ifndef AUDIO_DEFAULT_CLICKY_ON +# define AUDIO_DEFAULT_CLICKY_ON true +#endif + #ifndef AUDIO_TONE_STACKSIZE # define AUDIO_TONE_STACKSIZE 8 #endif @@ -117,32 +125,31 @@ void eeconfig_update_audio_current(void) { eeconfig_update_audio(audio_config.raw); } +void eeconfig_update_audio_default(void) { + audio_config.valid = true; + audio_config.enable = AUDIO_DEFAULT_ON; + audio_config.clicky_enable = AUDIO_DEFAULT_CLICKY_ON; + eeconfig_update_audio(audio_config.raw); +} + void audio_init(void) { if (audio_initialized) { return; } - // Check EEPROM -#ifdef EEPROM_ENABLE - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } audio_config.raw = eeconfig_read_audio(); -#else // EEPROM settings - audio_config.enable = true; -# ifdef AUDIO_CLICKY_ON - audio_config.clicky_enable = true; -# endif -#endif // EEPROM settings + if (!audio_config.valid) { + dprintf("audio_init audio_config.valid = 0. Write default values to EEPROM.\n"); + eeconfig_update_audio_default(); + } for (uint8_t i = 0; i < AUDIO_TONE_STACKSIZE; i++) { tones[i] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0}; } - if (!audio_initialized) { - audio_driver_initialize(); - audio_initialized = true; - } + audio_driver_initialize(); + audio_initialized = true; + stop_all_notes(); #ifndef AUDIO_INIT_DELAY audio_startup(); diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index a4a908b43c..eb0bedc6f9 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -33,7 +33,8 @@ typedef union { struct { bool enable : 1; bool clicky_enable : 1; - uint8_t level : 6; + bool valid : 1; + uint8_t reserved : 5; }; } audio_config_t; diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c index e89b34696c..eb64dd71e8 100644 --- a/quantum/backlight/backlight.c +++ b/quantum/backlight/backlight.c @@ -42,20 +42,26 @@ backlight_config_t backlight_config; static uint8_t breathing_period = BREATHING_PERIOD; #endif +static void backlight_check_config(void) { + /* Add some out of bound checks for backlight config */ + + if (backlight_config.level > BACKLIGHT_LEVELS) { + backlight_config.level = BACKLIGHT_LEVELS; + } +} + /** \brief Backlight initialization * * FIXME: needs doc */ void backlight_init(void) { - /* check signature */ - if (!eeconfig_is_enabled()) { - eeconfig_init(); - eeconfig_update_backlight_default(); - } backlight_config.raw = eeconfig_read_backlight(); - if (backlight_config.level > BACKLIGHT_LEVELS) { - backlight_config.level = BACKLIGHT_LEVELS; + if (!backlight_config.valid) { + dprintf("backlight_init backlight_config.valid = 0. Write default values to EEPROM.\n"); + eeconfig_update_backlight_default(); } + backlight_check_config(); + backlight_set(backlight_config.enable ? backlight_config.level : 0); } @@ -183,6 +189,7 @@ void eeconfig_update_backlight_current(void) { } void eeconfig_update_backlight_default(void) { + backlight_config.valid = true; backlight_config.enable = BACKLIGHT_DEFAULT_ON; backlight_config.breathing = BACKLIGHT_DEFAULT_BREATHING; backlight_config.level = BACKLIGHT_DEFAULT_LEVEL; diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h index 85812bff3a..c34fb5858d 100644 --- a/quantum/backlight/backlight.h +++ b/quantum/backlight/backlight.h @@ -39,7 +39,7 @@ typedef union { struct { bool enable : 1; bool breathing : 1; - uint8_t reserved : 1; // Reserved for possible future backlight modes + bool valid : 1; uint8_t level : 5; }; } backlight_config_t; diff --git a/quantum/bootmagic/bootmagic_lite.c b/quantum/bootmagic/bootmagic.c index efce6bfd12..efce6bfd12 100644 --- a/quantum/bootmagic/bootmagic_lite.c +++ b/quantum/bootmagic/bootmagic.c diff --git a/quantum/bootmagic/bootmagic.h b/quantum/bootmagic/bootmagic.h index db826025ce..4b5f5f7c5e 100644 --- a/quantum/bootmagic/bootmagic.h +++ b/quantum/bootmagic/bootmagic.h @@ -15,8 +15,11 @@ */ #pragma once -#if defined(BOOTMAGIC_LITE) -# include "bootmagic_lite.h" +#ifndef BOOTMAGIC_LITE_COLUMN +# define BOOTMAGIC_LITE_COLUMN 0 +#endif +#ifndef BOOTMAGIC_LITE_ROW +# define BOOTMAGIC_LITE_ROW 0 #endif void bootmagic(void); diff --git a/quantum/bootmagic/bootmagic_lite.h b/quantum/bootmagic/bootmagic_lite.h deleted file mode 100644 index 17777e6b4a..0000000000 --- a/quantum/bootmagic/bootmagic_lite.h +++ /dev/null @@ -1,25 +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 <http://www.gnu.org/licenses/>. - */ -#pragma once - -#ifndef BOOTMAGIC_LITE_COLUMN -# define BOOTMAGIC_LITE_COLUMN 0 -#endif -#ifndef BOOTMAGIC_LITE_ROW -# define BOOTMAGIC_LITE_ROW 0 -#endif - -void bootmagic_lite(void); diff --git a/quantum/bootmagic/magic.c b/quantum/bootmagic/magic.c deleted file mode 100644 index d68df3fa58..0000000000 --- a/quantum/bootmagic/magic.c +++ /dev/null @@ -1,54 +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 <http://www.gnu.org/licenses/>. - */ -#include <stdint.h> -#include <stdbool.h> -#include "wait.h" -#include "matrix.h" -#include "bootloader.h" -#include "debug.h" -#include "keycode_config.h" -#include "host.h" -#include "action_layer.h" -#include "eeconfig.h" -#include "bootmagic.h" - -keymap_config_t keymap_config; - -__attribute__((weak)) void bootmagic(void) {} - -/** \brief Magic - * - * FIXME: Needs doc - */ -void magic(void) { - /* check signature */ - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } - - /* init globals */ - debug_config.raw = eeconfig_read_debug(); - keymap_config.raw = eeconfig_read_keymap(); - - bootmagic(); - - /* read here just incase bootmagic process changed its value */ - layer_state_t default_layer = (layer_state_t)eeconfig_read_default_layer(); - default_layer_set(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/quantum/bootmagic/magic.h b/quantum/bootmagic/magic.h deleted file mode 100644 index 2c3969b85c..0000000000 --- a/quantum/bootmagic/magic.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 <http://www.gnu.org/licenses/>. - */ -#pragma once - -void magic(void); diff --git a/quantum/dip_switch.c b/quantum/dip_switch.c index 6e254578d1..e901f3e0c4 100644 --- a/quantum/dip_switch.c +++ b/quantum/dip_switch.c @@ -19,8 +19,6 @@ #include <string.h> // for memcpy #include "dip_switch.h" -#include "gpio.h" -#include "util.h" #ifdef SPLIT_KEYBOARD # include "split_common/split_util.h" @@ -35,24 +33,17 @@ #endif #ifdef DIP_SWITCH_PINS -# define NUMBER_OF_DIP_SWITCHES (ARRAY_SIZE(dip_switch_pad)) static pin_t dip_switch_pad[] = DIP_SWITCH_PINS; #endif #ifdef DIP_SWITCH_MATRIX_GRID -typedef struct matrix_index_t { - uint8_t row; - uint8_t col; -} matrix_index_t; - -# define NUMBER_OF_DIP_SWITCHES (ARRAY_SIZE(dip_switch_pad)) -static matrix_index_t dip_switch_pad[] = DIP_SWITCH_MATRIX_GRID; -extern bool peek_matrix(uint8_t row_index, uint8_t col_index, bool read_raw); -static uint16_t scan_count; +static matrix_intersection_t dip_switch_pad[] = DIP_SWITCH_MATRIX_GRID; +extern bool peek_matrix(uint8_t row_index, uint8_t col_index, bool read_raw); +static uint16_t scan_count; #endif /* DIP_SWITCH_MATRIX_GRID */ -static bool dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0}; -static bool last_dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0}; +static bool dip_switch_state[NUM_DIP_SWITCHES] = {0}; +static bool last_dip_switch_state[NUM_DIP_SWITCHES] = {0}; __attribute__((weak)) bool dip_switch_update_user(uint8_t index, bool active) { return true; @@ -70,17 +61,39 @@ __attribute__((weak)) bool dip_switch_update_mask_kb(uint32_t state) { return dip_switch_update_mask_user(state); } +#ifdef DIP_SWITCH_MAP_ENABLE +# include "keymap_introspection.h" +# include "action.h" + +# ifndef DIP_SWITCH_MAP_KEY_DELAY +# define DIP_SWITCH_MAP_KEY_DELAY TAP_CODE_DELAY +# endif + +static void dip_switch_exec_mapping(uint8_t index, bool on) { + // The delays below cater for Windows and its wonderful requirements. + action_exec(on ? MAKE_DIPSWITCH_ON_EVENT(index, true) : MAKE_DIPSWITCH_OFF_EVENT(index, true)); +# if DIP_SWITCH_MAP_KEY_DELAY > 0 + wait_ms(DIP_SWITCH_MAP_KEY_DELAY); +# endif // DIP_SWITCH_MAP_KEY_DELAY > 0 + + action_exec(on ? MAKE_DIPSWITCH_ON_EVENT(index, false) : MAKE_DIPSWITCH_OFF_EVENT(index, false)); +# if DIP_SWITCH_MAP_KEY_DELAY > 0 + wait_ms(DIP_SWITCH_MAP_KEY_DELAY); +# endif // DIP_SWITCH_MAP_KEY_DELAY > 0 +} +#endif // DIP_SWITCH_MAP_ENABLE + void dip_switch_init(void) { #ifdef DIP_SWITCH_PINS # if defined(SPLIT_KEYBOARD) && defined(DIP_SWITCH_PINS_RIGHT) if (!isLeftHand) { const pin_t dip_switch_pad_right[] = DIP_SWITCH_PINS_RIGHT; - for (uint8_t i = 0; i < NUMBER_OF_DIP_SWITCHES; i++) { + for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) { dip_switch_pad[i] = dip_switch_pad_right[i]; } } # endif - for (uint8_t i = 0; i < NUMBER_OF_DIP_SWITCHES; i++) { + for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) { setPinInputHigh(dip_switch_pad[i]); } dip_switch_read(true); @@ -108,7 +121,7 @@ void dip_switch_read(bool forced) { } #endif - for (uint8_t i = 0; i < NUMBER_OF_DIP_SWITCHES; i++) { + for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) { #ifdef DIP_SWITCH_PINS dip_switch_state[i] = !readPin(dip_switch_pad[i]); #endif @@ -118,11 +131,21 @@ void dip_switch_read(bool forced) { dip_switch_mask |= dip_switch_state[i] << i; if (last_dip_switch_state[i] != dip_switch_state[i] || forced) { has_dip_state_changed = true; +#ifndef DIP_SWITCH_MAP_ENABLE dip_switch_update_kb(i, dip_switch_state[i]); +#else + dip_switch_exec_mapping(i, dip_switch_state[i]); +#endif } } if (has_dip_state_changed) { +#ifndef DIP_SWITCH_MAP_ENABLE dip_switch_update_mask_kb(dip_switch_mask); +#endif memcpy(last_dip_switch_state, dip_switch_state, sizeof(dip_switch_state)); } } + +void dip_switch_task(void) { + dip_switch_read(false); +} diff --git a/quantum/dip_switch.h b/quantum/dip_switch.h index 6e79dcb0bf..7629859359 100644 --- a/quantum/dip_switch.h +++ b/quantum/dip_switch.h @@ -20,11 +20,36 @@ #include <stdbool.h> #include <stdint.h> +#include "gpio.h" +#include "util.h" + +#if defined(DIP_SWITCH_PINS) +# define NUM_DIP_SWITCHES ARRAY_SIZE(((pin_t[])DIP_SWITCH_PINS)) +#elif defined(DIP_SWITCH_MATRIX_GRID) +typedef struct matrix_intersection_t { + uint8_t row; + uint8_t col; +} matrix_intersection_t; +# define NUM_DIP_SWITCHES ARRAY_SIZE(((matrix_intersection_t[])DIP_SWITCH_MATRIX_GRID)) +#endif + +#ifndef NUM_DIP_SWITCHES +# define NUM_DIP_SWITCHES 0 +#endif bool dip_switch_update_kb(uint8_t index, bool active); bool dip_switch_update_user(uint8_t index, bool active); bool dip_switch_update_mask_user(uint32_t state); bool dip_switch_update_mask_kb(uint32_t state); -void dip_switch_init(void); void dip_switch_read(bool forced); + +void dip_switch_init(void); +void dip_switch_task(void); + +#ifdef DIP_SWITCH_MAP_ENABLE +# define NUM_DIP_STATES 2 +# define DIP_SWITCH_OFF_ON(off, on) \ + { (off), (on) } +extern const uint16_t dip_switch_map[NUM_DIP_SWITCHES][NUM_DIP_STATES]; +#endif // DIP_SWITCH_MAP_ENABLE diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c index d9eea13758..2d2180b4b4 100644 --- a/quantum/eeconfig.c +++ b/quantum/eeconfig.c @@ -54,7 +54,7 @@ void eeconfig_init_quantum(void) { // Enable oneshot and autocorrect by default: 0b0001 0100 0000 0000 eeprom_update_word(EECONFIG_KEYMAP, 0x1400); eeprom_update_byte(EECONFIG_BACKLIGHT, 0); - eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default + eeprom_update_byte(EECONFIG_AUDIO, 0); eeprom_update_dword(EECONFIG_RGBLIGHT, 0); eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, 0); eeprom_update_byte(EECONFIG_UNUSED, 0); diff --git a/quantum/encoder/tests/mock.c b/quantum/encoder/tests/mock.c index 61f2f8294d..1524e61ca4 100644 --- a/quantum/encoder/tests/mock.c +++ b/quantum/encoder/tests/mock.c @@ -19,14 +19,14 @@ bool pins[32] = {0}; bool pinIsInputHigh[32] = {0}; -uint8_t mockSetPinInputHigh(pin_t pin) { +uint8_t mock_set_pin_input_high(pin_t pin) { // dprintf("Setting pin %d input high.", pin); pins[pin] = true; pinIsInputHigh[pin] = true; return 0; } -bool mockReadPin(pin_t pin) { +bool mock_read_pin(pin_t pin) { return pins[pin]; } diff --git a/quantum/encoder/tests/mock.h b/quantum/encoder/tests/mock.h index 80c336b5ef..28774b82ab 100644 --- a/quantum/encoder/tests/mock.h +++ b/quantum/encoder/tests/mock.h @@ -24,11 +24,11 @@ typedef uint8_t pin_t; extern bool pins[]; extern bool pinIsInputHigh[]; -#define setPinInputHigh(pin) (mockSetPinInputHigh(pin)) -#define readPin(pin) (mockReadPin(pin)) +#define gpio_set_pin_input_high(pin) (mock_set_pin_input_high(pin)) +#define gpio_read_pin(pin) (mock_read_pin(pin)) -uint8_t mockSetPinInputHigh(pin_t pin); +uint8_t mock_set_pin_input_high(pin_t pin); -bool mockReadPin(pin_t pin); +bool mock_read_pin(pin_t pin); bool setPin(pin_t pin, bool val); diff --git a/quantum/encoder/tests/mock_split.c b/quantum/encoder/tests/mock_split.c index 5cc6cd19e1..f024c2058d 100644 --- a/quantum/encoder/tests/mock_split.c +++ b/quantum/encoder/tests/mock_split.c @@ -19,14 +19,14 @@ bool pins[32] = {0}; bool pinIsInputHigh[32] = {0}; -uint8_t mockSetPinInputHigh(pin_t pin) { +uint8_t mock_set_pin_input_high(pin_t pin) { // dprintf("Setting pin %d input high.", pin); pins[pin] = true; pinIsInputHigh[pin] = true; return 0; } -bool mockReadPin(pin_t pin) { +bool mock_read_pin(pin_t pin) { return pins[pin]; } diff --git a/quantum/encoder/tests/mock_split.h b/quantum/encoder/tests/mock_split.h index 2fc12f1830..8b4a141078 100644 --- a/quantum/encoder/tests/mock_split.h +++ b/quantum/encoder/tests/mock_split.h @@ -28,11 +28,11 @@ void encoder_update_raw(uint8_t* slave_state); extern bool pins[]; extern bool pinIsInputHigh[]; -#define setPinInputHigh(pin) (mockSetPinInputHigh(pin)) -#define readPin(pin) (mockReadPin(pin)) +#define gpio_set_pin_input_high(pin) (mock_set_pin_input_high(pin)) +#define gpio_read_pin(pin) (mock_read_pin(pin)) -uint8_t mockSetPinInputHigh(pin_t pin); +uint8_t mock_set_pin_input_high(pin_t pin); -bool mockReadPin(pin_t pin); +bool mock_read_pin(pin_t pin); bool setPin(pin_t pin, bool val); diff --git a/quantum/joystick.c b/quantum/joystick.c index 02818e4acd..3e9edeb8e2 100644 --- a/quantum/joystick.c +++ b/quantum/joystick.c @@ -15,10 +15,12 @@ */ #include "joystick.h" - -#include "analog.h" #include "wait.h" +#if defined(JOYSTICK_ANALOG) +# include "analog.h" +#endif + joystick_t joystick_state = { .buttons = {0}, .axes = @@ -31,21 +33,47 @@ joystick_t joystick_state = { }; // array defining the reading of analog values for each axis -__attribute__((weak)) joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {}; +__attribute__((weak)) joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = { +#if JOYSTICK_AXIS_COUNT > 0 + [0 ...(JOYSTICK_AXIS_COUNT - 1)] = JOYSTICK_AXIS_VIRTUAL +#endif +}; -__attribute__((weak)) void joystick_task(void) { - joystick_read_axes(); +__attribute__((weak)) void joystick_axis_init(uint8_t axis) { + if (axis >= JOYSTICK_AXIS_COUNT) return; + +#if defined(JOYSTICK_ANALOG) + setPinInput(joystick_axes[axis].input_pin); +#endif +} + +__attribute__((weak)) uint16_t joystick_axis_sample(uint8_t axis) { + if (axis >= JOYSTICK_AXIS_COUNT) return 0; + +#if defined(JOYSTICK_ANALOG) + return analogReadPin(joystick_axes[axis].input_pin); +#else + // default to resting position + return joystick_axes[axis].mid_digit; +#endif +} + +static inline bool is_virtual_axis(uint8_t axis) { + return joystick_axes[axis].input_pin == NO_PIN; } void joystick_flush(void) { - if (joystick_state.dirty) { - host_joystick_send(&joystick_state); - joystick_state.dirty = false; - } + if (!joystick_state.dirty) return; + + // TODO: host.h? + void host_joystick_send(joystick_t * joystick); + host_joystick_send(&joystick_state); + joystick_state.dirty = false; } void register_joystick_button(uint8_t button) { if (button >= JOYSTICK_BUTTON_COUNT) return; + joystick_state.buttons[button / 8] |= 1 << (button % 8); joystick_state.dirty = true; joystick_flush(); @@ -53,6 +81,7 @@ void register_joystick_button(uint8_t button) { void unregister_joystick_button(uint8_t button) { if (button >= JOYSTICK_BUTTON_COUNT) return; + joystick_state.buttons[button / 8] &= ~(1 << (button % 8)); joystick_state.dirty = true; joystick_flush(); @@ -61,37 +90,7 @@ void unregister_joystick_button(uint8_t button) { int16_t joystick_read_axis(uint8_t axis) { if (axis >= JOYSTICK_AXIS_COUNT) return 0; - // disable pull-up resistor - writePinLow(joystick_axes[axis].input_pin); - - // if pin was a pull-up input, we need to uncharge it by turning it low - // before making it a low input - setPinOutput(joystick_axes[axis].input_pin); - - wait_us(10); - - if (joystick_axes[axis].output_pin != JS_VIRTUAL_AXIS) { - setPinOutput(joystick_axes[axis].output_pin); - writePinHigh(joystick_axes[axis].output_pin); - } - - if (joystick_axes[axis].ground_pin != JS_VIRTUAL_AXIS) { - setPinOutput(joystick_axes[axis].ground_pin); - writePinLow(joystick_axes[axis].ground_pin); - } - - wait_us(10); - - setPinInput(joystick_axes[axis].input_pin); - - wait_us(10); - -#if defined(ANALOG_JOYSTICK_ENABLE) && (defined(__AVR__) || defined(PROTOCOL_CHIBIOS)) - int16_t axis_val = analogReadPin(joystick_axes[axis].input_pin); -#else - // default to resting position - int16_t axis_val = joystick_axes[axis].mid_digit; -#endif + int16_t axis_val = joystick_axis_sample(axis); // test the converted value against the lower range int32_t ref = joystick_axes[axis].mid_digit; @@ -111,10 +110,22 @@ int16_t joystick_read_axis(uint8_t axis) { return ranged_val; } +void joystick_init_axes(void) { +#if JOYSTICK_AXIS_COUNT > 0 + for (int i = 0; i < JOYSTICK_AXIS_COUNT; ++i) { + if (is_virtual_axis(i)) { + continue; + } + + joystick_axis_init(i); + } +#endif +} + void joystick_read_axes(void) { #if JOYSTICK_AXIS_COUNT > 0 for (int i = 0; i < JOYSTICK_AXIS_COUNT; ++i) { - if (joystick_axes[i].input_pin == JS_VIRTUAL_AXIS) { + if (is_virtual_axis(i)) { continue; } @@ -133,3 +144,11 @@ void joystick_set_axis(uint8_t axis, int16_t value) { joystick_state.dirty = true; } } + +void joystick_init(void) { + joystick_init_axes(); +} + +void joystick_task(void) { + joystick_read_axes(); +} diff --git a/quantum/joystick.h b/quantum/joystick.h index 5de4ba66c6..5a69ceac64 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -52,24 +52,15 @@ #define JOYSTICK_MAX_VALUE ((1L << (JOYSTICK_AXIS_RESOLUTION - 1)) - 1) -// configure on input_pin of the joystick_axes array entry to JS_VIRTUAL_AXIS -// to prevent it from being read from the ADC. This allows outputing forged axis value. -// -#define JS_VIRTUAL_AXIS 0xFF - +// configure on input_pin of the joystick_axes array entry to NO_PIN +// to prevent it from being read from the ADC. This allows outputting forged axis value. #define JOYSTICK_AXIS_VIRTUAL \ - { JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, 0, 1023 } + { NO_PIN, 0, JOYSTICK_MAX_VALUE / 2, JOYSTICK_MAX_VALUE } #define JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH) \ - { JS_VIRTUAL_AXIS, INPUT_PIN, JS_VIRTUAL_AXIS, LOW, REST, HIGH } -#define JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH) \ - { OUTPUT_PIN, INPUT_PIN, JS_VIRTUAL_AXIS, LOW, REST, HIGH } -#define JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH) \ - { OUTPUT_PIN, INPUT_PIN, GROUND_PIN, LOW, REST, HIGH } + { INPUT_PIN, LOW, REST, HIGH } typedef struct { - pin_t output_pin; pin_t input_pin; - pin_t ground_pin; // the AVR ADC offers 10 bit precision, with significant bits on the higher part uint16_t min_digit; @@ -87,6 +78,14 @@ typedef struct { extern joystick_t joystick_state; +/** + * \brief Handle the initialization of the subsystem. + */ +void joystick_init(void); + +/** + * \brief Handle various subsystem background tasks. + */ void joystick_task(void); /** @@ -117,6 +116,9 @@ void unregister_joystick_button(uint8_t button); */ int16_t joystick_read_axis(uint8_t axis); +/** + * \brief Sample and process the all axis. + */ void joystick_read_axes(void); /** @@ -127,6 +129,4 @@ void joystick_read_axes(void); */ void joystick_set_axis(uint8_t axis, int16_t value); -void host_joystick_send(joystick_t *joystick); - /** \} */ diff --git a/quantum/keyboard.c b/quantum/keyboard.c index 86a1a9fea3..1d6657c230 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "keycode_config.h" #include "matrix.h" #include "keymap_introspection.h" -#include "magic.h" #include "host.h" #include "led.h" #include "keycode.h" @@ -33,6 +32,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "sendchar.h" #include "eeconfig.h" #include "action_layer.h" +#ifdef BOOTMAGIC_ENABLE +# include "bootmagic.h" +#endif #ifdef AUDIO_ENABLE # include "audio.h" #endif @@ -135,6 +137,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef WPM_ENABLE # include "wpm.h" #endif +#ifdef OS_DETECTION_ENABLE +# include "os_detection.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { @@ -370,28 +375,30 @@ void housekeeping_task(void) { housekeeping_task_user(); } -/** \brief Init tasks previously located in matrix_init_quantum +/** \brief quantum_init * - * TODO: rationalise against keyboard_init and current split role + * Init global state */ void quantum_init(void) { - magic(); - led_init_ports(); -#ifdef BACKLIGHT_ENABLE - backlight_init_ports(); -#endif -#ifdef AUDIO_ENABLE - audio_init(); -#endif -#ifdef LED_MATRIX_ENABLE - led_matrix_init(); -#endif -#ifdef RGB_MATRIX_ENABLE - rgb_matrix_init(); -#endif -#if defined(UNICODE_COMMON_ENABLE) - unicode_input_mode_init(); + /* check signature */ + if (!eeconfig_is_enabled()) { + eeconfig_init(); + } + + /* init globals */ + debug_config.raw = eeconfig_read_debug(); + keymap_config.raw = eeconfig_read_keymap(); + +#ifdef BOOTMAGIC_ENABLE + bootmagic(); #endif + + /* read here just incase bootmagic process changed its value */ + layer_state_t default_layer = (layer_state_t)eeconfig_read_default_layer(); + default_layer_set(default_layer); + + /* Also initialize layer state to trigger callback functions for layer_state */ + layer_state_set_kb((layer_state_t)layer_state); } /** \brief keyboard_init @@ -412,6 +419,22 @@ void keyboard_init(void) { #endif matrix_init(); quantum_init(); + led_init_ports(); +#ifdef BACKLIGHT_ENABLE + backlight_init_ports(); +#endif +#ifdef AUDIO_ENABLE + audio_init(); +#endif +#ifdef LED_MATRIX_ENABLE + led_matrix_init(); +#endif +#ifdef RGB_MATRIX_ENABLE + rgb_matrix_init(); +#endif +#if defined(UNICODE_COMMON_ENABLE) + unicode_input_mode_init(); +#endif #if defined(CRC_ENABLE) crc_init(); #endif @@ -440,6 +463,9 @@ void keyboard_init(void) { #ifdef DIP_SWITCH_ENABLE dip_switch_init(); #endif +#ifdef JOYSTICK_ENABLE + joystick_init(); +#endif #ifdef SLEEP_LED_ENABLE sleep_led_init(); #endif @@ -615,7 +641,7 @@ void quantum_task(void) { #endif #ifdef DIP_SWITCH_ENABLE - dip_switch_read(false); + dip_switch_task(); #endif #ifdef AUTO_SHIFT_ENABLE @@ -718,4 +744,8 @@ void keyboard_task(void) { #endif led_task(); + +#ifdef OS_DETECTION_ENABLE + os_detection_task(); +#endif } diff --git a/quantum/keyboard.h b/quantum/keyboard.h index 5ea57815a7..0f39fde682 100644 --- a/quantum/keyboard.h +++ b/quantum/keyboard.h @@ -32,7 +32,7 @@ typedef struct { uint8_t row; } keypos_t; -typedef enum keyevent_type_t { TICK_EVENT = 0, KEY_EVENT = 1, ENCODER_CW_EVENT = 2, ENCODER_CCW_EVENT = 3, COMBO_EVENT = 4 } keyevent_type_t; +typedef enum keyevent_type_t { TICK_EVENT = 0, KEY_EVENT = 1, ENCODER_CW_EVENT = 2, ENCODER_CCW_EVENT = 3, COMBO_EVENT = 4, DIP_SWITCH_ON_EVENT = 5, DIP_SWITCH_OFF_EVENT = 6 } keyevent_type_t; /* key event */ typedef struct { @@ -48,6 +48,8 @@ typedef struct { /* special keypos_t entries */ #define KEYLOC_ENCODER_CW 253 #define KEYLOC_ENCODER_CCW 252 +#define KEYLOC_DIP_SWITCH_ON 251 +#define KEYLOC_DIP_SWITCH_OFF 250 static inline bool IS_NOEVENT(const keyevent_t event) { return event.type == TICK_EVENT; @@ -64,6 +66,9 @@ static inline bool IS_COMBOEVENT(const keyevent_t event) { static inline bool IS_ENCODEREVENT(const keyevent_t event) { return event.type == ENCODER_CW_EVENT || event.type == ENCODER_CCW_EVENT; } +static inline bool IS_DIPSWITCHEVENT(const keyevent_t event) { + return event.type == DIP_SWITCH_ON_EVENT || event.type == DIP_SWITCH_OFF_EVENT; +} /* Common keypos_t object factory */ #define MAKE_KEYPOS(row_num, col_num) ((keypos_t){.row = (row_num), .col = (col_num)}) @@ -92,6 +97,12 @@ static inline bool IS_ENCODEREVENT(const keyevent_t event) { # define MAKE_ENCODER_CCW_EVENT(enc_id, press) MAKE_EVENT(KEYLOC_ENCODER_CCW, (enc_id), (press), ENCODER_CCW_EVENT) #endif // ENCODER_MAP_ENABLE +#ifdef DIP_SWITCH_MAP_ENABLE +/* Dip Switch events */ +# define MAKE_DIPSWITCH_ON_EVENT(switch_id, press) MAKE_EVENT(KEYLOC_DIP_SWITCH_ON, (switch_id), (press), DIP_SWITCH_ON_EVENT) +# define MAKE_DIPSWITCH_OFF_EVENT(switch_id, press) MAKE_EVENT(KEYLOC_DIP_SWITCH_OFF, (switch_id), (press), DIP_SWITCH_OFF_EVENT) +#endif // DIP_SWITCH_MAP_ENABLE + /* 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. */ diff --git a/quantum/keycode_config.c b/quantum/keycode_config.c index 864488a65c..cbfbcc8140 100644 --- a/quantum/keycode_config.c +++ b/quantum/keycode_config.c @@ -16,6 +16,8 @@ #include "keycode_config.h" +keymap_config_t keymap_config; + /** \brief keycode_config * * This function is used to check a specific keycode against the bootmagic config, diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 91e47a72ee..abdcd5c7ba 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -29,6 +29,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # include "encoder.h" #endif +#ifdef DIP_SWITCH_MAP_ENABLE +# include "dip_switch.h" +#endif + #ifdef BACKLIGHT_ENABLE # include "backlight.h" #endif @@ -204,5 +208,13 @@ __attribute__((weak)) uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key return keycode_at_encodermap_location(layer, key.col, false); } #endif // ENCODER_MAP_ENABLE +#ifdef DIP_SWITCH_MAP_ENABLE + else if (key.row == KEYLOC_DIP_SWITCH_ON && key.col < NUM_DIP_SWITCHES) { + return keycode_at_dip_switch_map_location(key.col, true); + } else if (key.row == KEYLOC_DIP_SWITCH_OFF && key.col < NUM_DIP_SWITCHES) { + return keycode_at_dip_switch_map_location(key.col, false); + } +#endif // DIP_SWITCH_MAP_ENABLE + return KC_NO; } diff --git a/quantum/keymap_extras/keymap_canadian_french.h b/quantum/keymap_extras/keymap_canadian_french.h new file mode 100644 index 0000000000..63c9166a31 --- /dev/null +++ b/quantum/keymap_extras/keymap_canadian_french.h @@ -0,0 +1,122 @@ +// Copyright 2024 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +/******************************************************************************* + 88888888888 888 d8b .d888 d8b 888 d8b + 888 888 Y8P d88P" Y8P 888 Y8P + 888 888 888 888 + 888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b + 888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K + 888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b. + 888 888 888 888 X88 888 888 888 Y8b. 888 X88 + 888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P' + 888 888 + 888 888 + 888 888 + .d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888 + d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888 + 888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888 + Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888 + "Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888 + 888 + Y8b d88P + "Y88P" +*******************************************************************************/ + +#pragma once +#include "keycodes.h" +// clang-format off + +// Aliases +#define FR_HASH KC_GRV // # +#define FR_1 KC_1 // 1 +#define FR_2 KC_2 // 2 +#define FR_3 KC_3 // 3 +#define FR_4 KC_4 // 4 +#define FR_5 KC_5 // 5 +#define FR_6 KC_6 // 6 +#define FR_7 KC_7 // 7 +#define FR_8 KC_8 // 8 +#define FR_9 KC_9 // 9 +#define FR_0 KC_0 // 0 +#define FR_MINS KC_MINS // - +#define FR_EQL KC_EQL // = +#define FR_Q KC_Q // Q +#define FR_W KC_W // W +#define FR_E KC_E // E +#define FR_R KC_R // R +#define FR_T KC_T // T +#define FR_Y KC_Y // Y +#define FR_U KC_U // U +#define FR_I KC_I // I +#define FR_O KC_O // O +#define FR_P KC_P // P +#define FR_DCIR KC_LBRC // ^ (dead) +#define FR_CEDL KC_RBRC // ¸ (dead) +#define FR_A KC_A // A +#define FR_S KC_S // S +#define FR_D KC_D // D +#define FR_F KC_F // F +#define FR_G KC_G // G +#define FR_H KC_H // H +#define FR_J KC_J // J +#define FR_K KC_K // K +#define FR_L KC_L // L +#define FR_SCLN KC_SCLN // ; +#define FR_DGRV KC_QUOT // ` (dead) +#define FR_LABK KC_NUHS // < +#define FR_LDAQ KC_NUBS // « +#define FR_Z KC_Z // Z +#define FR_X KC_X // X +#define FR_C KC_C // C +#define FR_V KC_V // V +#define FR_B KC_B // B +#define FR_N KC_N // N +#define FR_M KC_M // M +#define FR_COMM KC_COMM // , +#define FR_DOT KC_DOT // . +#define FR_EACU KC_SLSH // É +#define FR_PIPE S(FR_HASH) // | +#define FR_EXLM S(FR_1) // ! +#define FR_DQUO S(FR_2) // " +#define FR_SLSH S(FR_3) // / +#define FR_DLR S(FR_4) // $ +#define FR_PERC S(FR_5) // % +#define FR_QUES S(FR_6) // ? +#define FR_AMPR S(FR_7) // & +#define FR_ASTR S(FR_8) // * +#define FR_LPRN S(FR_9) // ( +#define FR_RPRN S(FR_0) // ) +#define FR_UNDS S(FR_MINS) // _ +#define FR_PLUS S(FR_EQL) // + +#define FR_DIAE S(FR_CEDL) // ¨ (dead) +#define FR_COLN S(FR_SCLN) // : +#define FR_RABK S(FR_LABK) // > +#define FR_RDAQ S(FR_LDAQ) // » +#define FR_QUOT S(FR_COMM) // ' +#define FR_BSLS ALGR(FR_HASH) // (backslash) +#define FR_PLMN ALGR(FR_1) // ± +#define FR_AT ALGR(FR_2) // @ +#define FR_PND ALGR(FR_3) // £ +#define FR_CENT ALGR(FR_4) // ¢ +#define FR_CURR ALGR(FR_5) // ¤ +#define FR_NOT ALGR(FR_6) // ¬ +#define FR_BRKP ALGR(FR_7) // ¦ +#define FR_SUP2 ALGR(FR_8) // ² +#define FR_SUP3 ALGR(FR_9) // ³ +#define FR_QRTR ALGR(FR_0) // ¼ +#define FR_HALF ALGR(FR_MINS) // ½ +#define FR_TQTR ALGR(FR_EQL) // ¾ +#define FR_SECT ALGR(FR_O) // § +#define FR_PARA ALGR(FR_P) // ¶ +#define FR_LBRC ALGR(FR_DCIR) // [ +#define FR_RBRC ALGR(FR_CEDL) // ] +#define FR_TILD ALGR(FR_SCLN) // ~ +#define FR_LCBR ALGR(FR_DGRV) // { +#define FR_RCBR ALGR(FR_LABK) // } +#define FR_DEG ALGR(FR_LDAQ) // ° +#define FR_MICR ALGR(FR_M) // µ +#define FR_MACR ALGR(FR_COMM) // ¯ +#define FR_SHYP ALGR(FR_DOT) //  (soft hyphen) +#define FR_ACUT ALGR(FR_EACU) // ´ (dead) + diff --git a/quantum/keymap_extras/keymap_spanish_latin_america.h b/quantum/keymap_extras/keymap_spanish_latin_america.h new file mode 100644 index 0000000000..0ade828793 --- /dev/null +++ b/quantum/keymap_extras/keymap_spanish_latin_america.h @@ -0,0 +1,105 @@ +// Copyright 2024 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +/******************************************************************************* + 88888888888 888 d8b .d888 d8b 888 d8b + 888 888 Y8P d88P" Y8P 888 Y8P + 888 888 888 888 + 888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b + 888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K + 888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b. + 888 888 888 888 X88 888 888 888 Y8b. 888 X88 + 888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P' + 888 888 + 888 888 + 888 888 + .d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888 + d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888 + 888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888 + Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888 + "Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888 + 888 + Y8b d88P + "Y88P" +*******************************************************************************/ + +#pragma once +#include "keycodes.h" +// clang-format off + +// Aliases +#define ES_PIPE KC_GRV // | +#define ES_1 KC_1 // 1 +#define ES_2 KC_2 // 2 +#define ES_3 KC_3 // 3 +#define ES_4 KC_4 // 4 +#define ES_5 KC_5 // 5 +#define ES_6 KC_6 // 6 +#define ES_7 KC_7 // 7 +#define ES_8 KC_8 // 8 +#define ES_9 KC_9 // 9 +#define ES_0 KC_0 // 0 +#define ES_QUOT KC_MINS // ' +#define ES_IQUE KC_EQL // ¿ +#define ES_Q KC_Q // Q +#define ES_W KC_W // W +#define ES_E KC_E // E +#define ES_R KC_R // R +#define ES_T KC_T // T +#define ES_Y KC_Y // Y +#define ES_U KC_U // U +#define ES_I KC_I // I +#define ES_O KC_O // O +#define ES_P KC_P // P +#define ES_ACUT KC_LBRC // ´ (dead) +#define ES_PLUS KC_RBRC // + +#define ES_A KC_A // A +#define ES_S KC_S // S +#define ES_D KC_D // D +#define ES_F KC_F // F +#define ES_G KC_G // G +#define ES_H KC_H // H +#define ES_J KC_J // J +#define ES_K KC_K // K +#define ES_L KC_L // L +#define ES_NTIL KC_SCLN // Ñ +#define ES_LCBR KC_QUOT // { +#define ES_RCBR KC_NUHS // } +#define ES_LABK KC_NUBS // < +#define ES_Z KC_Z // Z +#define ES_X KC_X // X +#define ES_C KC_C // C +#define ES_V KC_V // V +#define ES_B KC_B // B +#define ES_N KC_N // N +#define ES_M KC_M // M +#define ES_COMM KC_COMM // , +#define ES_DOT KC_DOT // . +#define ES_MINS KC_SLSH // - +#define ES_MORD S(ES_PIPE) // ° +#define ES_EXLM S(ES_1) // ! +#define ES_DQUO S(ES_2) // " +#define ES_NUMB S(ES_3) // # +#define ES_DLR S(ES_4) // $ +#define ES_PERC S(ES_5) // % +#define ES_AMPR S(ES_6) // & +#define ES_SLSH S(ES_7) // / +#define ES_LPRN S(ES_8) // ( +#define ES_RPRN S(ES_9) // ) +#define ES_EQL S(ES_0) // = +#define ES_QUES S(ES_QUOT) // ? +#define ES_IEXL S(ES_IQUE) // ¡ +#define ES_DIAE S(ES_ACUT) // ¨ (dead) +#define ES_ASTR S(ES_PLUS) // * +#define ES_LBRC S(ES_LCBR) // [ +#define ES_RBRC S(ES_RCBR) // ] +#define ES_RABK S(ES_LABK) // > +#define ES_SCLN S(ES_COMM) // ; +#define ES_COLN S(ES_DOT) // : +#define ES_UNDS S(ES_MINS) // _ +#define ES_NOT ALGR(ES_PIPE) // ¬ +#define ES_BSLS ALGR(ES_QUOT) // (backslash) +#define ES_AT ALGR(ES_Q) // @ +#define ES_TILD ALGR(ES_PLUS) // ~ +#define ES_CIRC ALGR(ES_LCBR) // ^ + diff --git a/quantum/keymap_extras/sendstring_canadian_french.h b/quantum/keymap_extras/sendstring_canadian_french.h new file mode 100644 index 0000000000..2abba3a9d3 --- /dev/null +++ b/quantum/keymap_extras/sendstring_canadian_french.h @@ -0,0 +1,120 @@ +/* Copyright 2023 Nebuleon + * + * 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 <http://www.gnu.org/licenses/>. + */ + +// Sendstring lookup tables for Canadian French layouts + +#pragma once + +#include "keymap_canadian_french.h" +#include "send_string.h" + +// clang-format off + +const uint8_t ascii_to_shift_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 1, 1, 0, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 0, 0, 0, 1), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 1, 0, 0, 0, 1, 1), + KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 0, 0, 0, 0, 1), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 1, 0, 0, 0) +}; + +const uint8_t ascii_to_altgr_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 1, 1, 1, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 1, 0, 1, 1, 0) +}; + +const uint8_t ascii_to_dead_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 1, 0), + KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0) +}; + +const uint8_t ascii_to_keycode_lut[128] PROGMEM = { + // NUL SOH STX ETX EOT ENQ ACK BEL + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // BS TAB LF VT FF CR SO SI + KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // DLE DC1 DC2 DC3 DC4 NAK SYN ETB + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // CAN EM SUB ESC FS GS RS US + XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + + // ! " # $ % & ' + KC_SPC, FR_1, FR_2, FR_HASH, FR_4, FR_5, FR_7, FR_COMM, + // ( ) * + , - . / + FR_9, FR_0, FR_8, FR_EQL, FR_COMM, FR_MINS, FR_DOT, FR_3, + // 0 1 2 3 4 5 6 7 + FR_0, FR_1, FR_2, FR_3, FR_4, FR_5, FR_6, FR_7, + // 8 9 : ; < = > ? + FR_8, FR_9, FR_SCLN, FR_SCLN, FR_LABK, FR_EQL, FR_LABK, FR_6, + // @ A B C D E F G + FR_2, FR_A, FR_B, FR_C, FR_D, FR_E, FR_F, FR_G, + // H I J K L M N O + FR_H, FR_I, FR_J, FR_K, FR_L, FR_M, FR_N, FR_O, + // P Q R S T U V W + FR_P, FR_Q, FR_R, FR_S, FR_T, FR_U, FR_V, FR_W, + // X Y Z [ \ ] ^ _ + FR_X, FR_Y, FR_Z, FR_DCIR, FR_HASH, FR_CEDL, FR_DCIR, FR_MINS, + // ` a b c d e f g + FR_DGRV, FR_A, FR_B, FR_C, FR_D, FR_E, FR_F, FR_G, + // h i j k l m n o + FR_H, FR_I, FR_J, FR_K, FR_L, FR_M, FR_N, FR_O, + // p q r s t u v w + FR_P, FR_Q, FR_R, FR_S, FR_T, FR_U, FR_V, FR_W, + // x y z { | } ~ DEL + FR_X, FR_Y, FR_Z, FR_DGRV, FR_HASH, FR_LABK, FR_SCLN, KC_DEL +}; diff --git a/quantum/keymap_extras/sendstring_spanish_latin_america.h b/quantum/keymap_extras/sendstring_spanish_latin_america.h new file mode 100644 index 0000000000..3bfdf7d5cb --- /dev/null +++ b/quantum/keymap_extras/sendstring_spanish_latin_america.h @@ -0,0 +1,120 @@ +/* Copyright 2023 Juan David DÃaz + * + * 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 <http://www.gnu.org/licenses/>. + */ + +// Sendstring lookup tables for Latam Spanish layouts + +#pragma once + +#include "send_string.h" +#include "keymap_spanish_latin_america.h" + +// clang-format off + +const uint8_t ascii_to_shift_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 1, 1, 0, 1, 1, 1, 0), + KCLUT_ENTRY(1, 1, 1, 0, 0, 0, 0, 1), + KCLUT_ENTRY(0, 0, 1, 1, 0, 1, 1, 0), + KCLUT_ENTRY(0, 0, 1, 1, 0, 1, 1, 1), + KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), + KCLUT_ENTRY(1, 1, 1, 1, 0, 1, 0, 1), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0) +}; + +const uint8_t ascii_to_altgr_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 1, 0, 1, 0), + KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 1, 0) +}; + +const uint8_t ascii_to_dead_lut[16] PROGMEM = { + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 1, 0), + KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0) +}; + +const uint8_t ascii_to_keycode_lut[128] PROGMEM = { + // NUL SOH STX ETX EOT ENQ ACK BEL + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // BS TAB LF VT FF CR SO SI + KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // DLE DC1 DC2 DC3 DC4 NAK SYN ETB + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + // CAN EM SUB ESC FS GS RS US + XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + + // ! " # $ % & ' + KC_SPC, ES_1, ES_2, ES_3, ES_4, ES_5, ES_6, ES_QUOT, + // ( ) * + , - . / + ES_8, ES_9, ES_PLUS, ES_PLUS, ES_COMM, ES_MINS, ES_DOT, ES_7, + // 0 1 2 3 4 5 6 7 + ES_0, ES_1, ES_2, ES_3, ES_4, ES_5, ES_6, ES_7, + // 8 9 : ; < = > ? + ES_8, ES_9, ES_DOT, ES_COMM, ES_LABK, ES_0, ES_LABK, ES_QUOT, + // @ A B C D E F G + ES_Q, ES_A, ES_B, ES_C, ES_D, ES_E, ES_F, ES_G, + // H I J K L M N O + ES_H, ES_I, ES_J, ES_K, ES_L, ES_M, ES_N, ES_O, + // P Q R S T U V W + ES_P, ES_Q, ES_R, ES_S, ES_T, ES_U, ES_V, ES_W, + // X Y Z [ \ ] ^ _ + ES_X, ES_Y, ES_Z, ES_LCBR, ES_QUOT, ES_RCBR, ES_LCBR, ES_MINS, + // ` a b c d e f g + ES_RCBR, ES_A, ES_B, ES_C, ES_D, ES_E, ES_F, ES_G, + // h i j k l m n o + ES_H, ES_I, ES_J, ES_K, ES_L, ES_M, ES_N, ES_O, + // p q r s t u v w + ES_P, ES_Q, ES_R, ES_S, ES_T, ES_U, ES_V, ES_W, + // x y z { | } ~ DEL + ES_X, ES_Y, ES_Z, ES_LCBR, ES_PIPE, ES_RCBR, ES_PLUS, KC_DEL +}; diff --git a/quantum/keymap_introspection.c b/quantum/keymap_introspection.c index e4a01d2e9a..71e3b429ea 100644 --- a/quantum/keymap_introspection.c +++ b/quantum/keymap_introspection.c @@ -72,6 +72,24 @@ __attribute__((weak)) uint16_t keycode_at_encodermap_location(uint8_t layer_num, #endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Dip Switch mapping + +#if defined(DIP_SWITCH_ENABLE) && defined(DIP_SWITCH_MAP_ENABLE) + +uint16_t keycode_at_dip_switch_map_location_raw(uint8_t switch_idx, bool on) { + if (switch_idx < NUM_DIP_SWITCHES) { + return pgm_read_word(&dip_switch_map[switch_idx][!!on]); + } + return KC_TRNS; +} + +uint16_t keycode_at_dip_switch_map_location(uint8_t switch_idx, bool on) { + return keycode_at_dip_switch_map_location_raw(switch_idx, on); +} + +#endif // defined(DIP_SWITCH_ENABLE) && defined(DIP_SWITCH_MAP_ENABLE) + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Combos #if defined(COMBO_ENABLE) diff --git a/quantum/keymap_introspection.h b/quantum/keymap_introspection.h index 2012a2b8cc..f7516bf42a 100644 --- a/quantum/keymap_introspection.h +++ b/quantum/keymap_introspection.h @@ -36,6 +36,18 @@ uint16_t keycode_at_encodermap_location(uint8_t layer_num, uint8_t encoder_idx, #endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Dip Switch mapping + +#if defined(DIP_SWITCH_ENABLE) && defined(DIP_SWITCH_MAP_ENABLE) + +// Get the keycode for the dip_switch mapping location, stored in firmware rather than any other persistent storage +uint16_t keycode_at_dip_switch_map_location_raw(uint8_t switch_idx, bool on); +// Get the keycode for the dip_switch mapping location, potentially stored dynamically +uint16_t keycode_at_dip_switch_map_location(uint8_t switch_idx, bool on); + +#endif // defined(DIP_SWITCH_ENABLE) && defined(DIP_SWITCH_MAP_ENABLE) + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Combos #if defined(COMBO_ENABLE) diff --git a/quantum/led.c b/quantum/led.c index 8d86374a6f..1e7ee9db76 100644 --- a/quantum/led.c +++ b/quantum/led.c @@ -183,9 +183,7 @@ void led_task(void) { last_led_modification_time = timer_read32(); if (debug_keyboard) { - debug("led_task: "); - debug_hex8(led_status); - debug("\n"); + dprintf("led_task: %02X\n", led_status); } led_set(led_status); } diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c index 4d67a295df..c0fb4c810b 100644 --- a/quantum/led_matrix/led_matrix.c +++ b/quantum/led_matrix/led_matrix.c @@ -74,9 +74,6 @@ static uint8_t led_last_enable = UINT8_MAX; static uint8_t led_last_effect = UINT8_MAX; static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; static led_task_states led_task_state = SYNCING; -#if LED_MATRIX_TIMEOUT > 0 -static uint32_t led_anykey_timer; -#endif // LED_MATRIX_TIMEOUT > 0 // double buffers static uint32_t led_timer_buffer; @@ -101,7 +98,7 @@ void eeconfig_update_led_matrix_default(void) { led_matrix_eeconfig.mode = LED_MATRIX_DEFAULT_MODE; led_matrix_eeconfig.val = LED_MATRIX_DEFAULT_VAL; led_matrix_eeconfig.speed = LED_MATRIX_DEFAULT_SPD; - led_matrix_eeconfig.flags = LED_FLAG_ALL; + led_matrix_eeconfig.flags = LED_MATRIX_DEFAULT_FLAGS; eeconfig_flush_led_matrix(true); } @@ -114,6 +111,16 @@ void eeconfig_debug_led_matrix(void) { dprintf("led_matrix_eeconfig.flags = %d\n", led_matrix_eeconfig.flags); } +void led_matrix_reload_from_eeprom(void) { + led_matrix_disable_noeeprom(); + /* Reset back to what we have in eeprom */ + eeconfig_init_led_matrix(); + eeconfig_debug_led_matrix(); // display current eeprom values + if (led_matrix_eeconfig.enable) { + led_matrix_mode_noeeprom(led_matrix_eeconfig.mode); + } +} + __attribute__((weak)) uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; } @@ -156,9 +163,6 @@ void process_led_matrix(uint8_t row, uint8_t col, bool pressed) { #ifndef LED_MATRIX_SPLIT if (!is_keyboard_master()) return; #endif -#if LED_MATRIX_TIMEOUT > 0 - led_anykey_timer = 0; -#endif // LED_MATRIX_TIMEOUT > 0 #ifdef LED_MATRIX_KEYREACTIVE_ENABLED uint8_t led[LED_HITS_TO_REMEMBER]; @@ -208,22 +212,11 @@ static bool led_matrix_none(effect_params_t *params) { } static void led_task_timers(void) { -#if defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_MATRIX_TIMEOUT > 0 +#if defined(LED_MATRIX_KEYREACTIVE_ENABLED) uint32_t deltaTime = sync_timer_elapsed32(led_timer_buffer); -#endif // defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_MATRIX_TIMEOUT > 0 +#endif // defined(LED_MATRIX_KEYREACTIVE_ENABLED) led_timer_buffer = sync_timer_read32(); - // Update double buffer timers -#if LED_MATRIX_TIMEOUT > 0 - if (led_anykey_timer < UINT32_MAX) { - if (UINT32_MAX - deltaTime < led_anykey_timer) { - led_anykey_timer = UINT32_MAX; - } else { - led_anykey_timer += deltaTime; - } - } -#endif // LED_MATRIX_TIMEOUT > 0 - // Update double buffer last hit timers #ifdef LED_MATRIX_KEYREACTIVE_ENABLED uint8_t count = last_hit_buffer.count; @@ -329,7 +322,7 @@ void led_matrix_task(void) { // while suspended and just do a software shutdown. This is a cheap hack for now. bool suspend_backlight = suspend_state || #if LED_MATRIX_TIMEOUT > 0 - (led_anykey_timer > (uint32_t)LED_MATRIX_TIMEOUT) || + (last_input_activity_elapsed() > (uint32_t)LED_MATRIX_TIMEOUT) || #endif // LED_MATRIX_TIMEOUT > 0 false; @@ -432,12 +425,6 @@ void led_matrix_init(void) { } #endif // LED_MATRIX_KEYREACTIVE_ENABLED - if (!eeconfig_is_enabled()) { - dprintf("led_matrix_init_drivers eeconfig is not enabled.\n"); - eeconfig_init(); - eeconfig_update_led_matrix_default(); - } - eeconfig_init_led_matrix(); if (!led_matrix_eeconfig.mode) { dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n"); @@ -447,7 +434,7 @@ void led_matrix_init(void) { } void led_matrix_set_suspend_state(bool state) { -#ifdef LED_DISABLE_WHEN_USB_SUSPENDED +#ifdef LED_MATRIX_SLEEP if (state && !suspend_state && is_keyboard_master()) { // only run if turning off, and only once led_task_render(0); // turn off all LEDs when suspending led_task_flush(0); // and actually flash led state to LEDs diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h index c903a230f4..941d42aeca 100644 --- a/quantum/led_matrix/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h @@ -23,32 +23,9 @@ #include <stdint.h> #include <stdbool.h> #include "led_matrix_types.h" +#include "led_matrix_drivers.h" #include "keyboard.h" -#if defined(LED_MATRIX_IS31FL3218) -# include "is31fl3218-simple.h" -#elif defined(LED_MATRIX_IS31FL3731) -# include "is31fl3731-simple.h" -#endif -#ifdef LED_MATRIX_IS31FL3733 -# include "is31fl3733-simple.h" -#endif -#ifdef LED_MATRIX_IS31FL3736 -# include "is31fl3736-simple.h" -#endif -#ifdef LED_MATRIX_IS31FL3737 -# include "is31fl3737-simple.h" -#endif -#ifdef LED_MATRIX_IS31FL3741 -# include "is31fl3741-simple.h" -#endif -#if defined(IS31FLCOMMON) -# include "is31flcommon.h" -#endif -#ifdef LED_MATRIX_SNLED27351 -# include "snled27351-simple.h" -#endif - #ifndef LED_MATRIX_TIMEOUT # define LED_MATRIX_TIMEOUT 0 #endif @@ -81,6 +58,10 @@ # define LED_MATRIX_DEFAULT_SPD UINT8_MAX / 2 #endif +#ifndef LED_MATRIX_DEFAULT_FLAGS +# define LED_MATRIX_DEFAULT_FLAGS LED_FLAG_ALL +#endif + #ifndef LED_MATRIX_LED_FLUSH_LIMIT # define LED_MATRIX_LED_FLUSH_LIMIT 16 #endif @@ -159,6 +140,8 @@ bool led_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max); void led_matrix_init(void); +void led_matrix_reload_from_eeprom(void); + void led_matrix_set_suspend_state(bool state); bool led_matrix_get_suspend_state(void); void led_matrix_toggle(void); @@ -193,18 +176,6 @@ led_flags_t led_matrix_get_flags(void); void led_matrix_set_flags(led_flags_t flags); void led_matrix_set_flags_noeeprom(led_flags_t flags); -typedef struct { - /* Perform any initialisation required for the other driver functions to work. */ - void (*init)(void); - - /* Set the brightness of a single LED in the buffer. */ - void (*set_value)(int index, uint8_t value); - /* Set the brightness of all LEDS on the keyboard in the buffer. */ - void (*set_value_all)(uint8_t value); - /* Flush any buffered changes to the hardware. */ - void (*flush)(void); -} led_matrix_driver_t; - static inline bool led_matrix_check_finished_leds(uint8_t led_idx) { #if defined(LED_MATRIX_SPLIT) if (is_keyboard_left()) { @@ -217,8 +188,6 @@ static inline bool led_matrix_check_finished_leds(uint8_t led_idx) { #endif } -extern const led_matrix_driver_t led_matrix_driver; - extern led_eeconfig_t led_matrix_eeconfig; extern uint32_t g_led_timer; diff --git a/quantum/led_matrix/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c index 117bed9851..2e80bd0375 100644 --- a/quantum/led_matrix/led_matrix_drivers.c +++ b/quantum/led_matrix/led_matrix_drivers.c @@ -15,7 +15,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "led_matrix.h" +#include "led_matrix_drivers.h" /* Each driver needs to define a struct: * @@ -33,6 +33,14 @@ const led_matrix_driver_t led_matrix_driver = { .set_value_all = is31fl3218_set_value_all, }; +#elif defined(LED_MATRIX_IS31FL3729) +const led_matrix_driver_t led_matrix_driver = { + .init = is31fl3729_init_drivers, + .flush = is31fl3729_flush, + .set_value = is31fl3729_set_value, + .set_value_all = is31fl3729_set_value_all, +}; + #elif defined(LED_MATRIX_IS31FL3731) const led_matrix_driver_t led_matrix_driver = { .init = is31fl3731_init_drivers, @@ -73,12 +81,36 @@ const led_matrix_driver_t led_matrix_driver = { .set_value_all = is31fl3741_set_value_all, }; -#elif defined(IS31FLCOMMON) +#elif defined(LED_MATRIX_IS31FL3742A) +const led_matrix_driver_t led_matrix_driver = { + .init = is31fl3742a_init_drivers, + .flush = is31fl3742a_flush, + .set_value = is31fl3742a_set_value, + .set_value_all = is31fl3742a_set_value_all, +}; + +#elif defined(LED_MATRIX_IS31FL3743A) +const led_matrix_driver_t led_matrix_driver = { + .init = is31fl3743a_init_drivers, + .flush = is31fl3743a_flush, + .set_value = is31fl3743a_set_value, + .set_value_all = is31fl3743a_set_value_all, +}; + +#elif defined(LED_MATRIX_IS31FL3745) +const led_matrix_driver_t led_matrix_driver = { + .init = is31fl3745_init_drivers, + .flush = is31fl3745_flush, + .set_value = is31fl3745_set_value, + .set_value_all = is31fl3745_set_value_all, +}; + +#elif defined(LED_MATRIX_IS31FL3746A) const led_matrix_driver_t led_matrix_driver = { - .init = IS31FL_simple_init_drivers, - .flush = IS31FL_common_flush, - .set_value = IS31FL_simple_set_brightness, - .set_value_all = IS31FL_simple_set_brigntness_all, + .init = is31fl3746a_init_drivers, + .flush = is31fl3746a_flush, + .set_value = is31fl3746a_set_value, + .set_value_all = is31fl3746a_set_value_all, }; #elif defined(LED_MATRIX_SNLED27351) diff --git a/quantum/led_matrix/led_matrix_drivers.h b/quantum/led_matrix/led_matrix_drivers.h new file mode 100644 index 0000000000..a961784a62 --- /dev/null +++ b/quantum/led_matrix/led_matrix_drivers.h @@ -0,0 +1,46 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <stdint.h> + +#if defined(LED_MATRIX_IS31FL3218) +# include "is31fl3218-mono.h" +#elif defined(LED_MATRIX_IS31FL3729) +# include "is31fl3729-mono.h" +#elif defined(LED_MATRIX_IS31FL3731) +# include "is31fl3731-mono.h" +#elif defined(LED_MATRIX_IS31FL3733) +# include "is31fl3733-mono.h" +#elif defined(LED_MATRIX_IS31FL3736) +# include "is31fl3736-mono.h" +#elif defined(LED_MATRIX_IS31FL3737) +# include "is31fl3737-mono.h" +#elif defined(LED_MATRIX_IS31FL3741) +# include "is31fl3741-mono.h" +#elif defined(LED_MATRIX_IS31FL3742A) +# include "is31fl3742a-mono.h" +#elif defined(LED_MATRIX_IS31FL3743A) +# include "is31fl3743a-mono.h" +#elif defined(LED_MATRIX_IS31FL3745) +# include "is31fl3745-mono.h" +#elif defined(LED_MATRIX_IS31FL3746A) +# include "is31fl3746a-mono.h" +#elif defined(LED_MATRIX_SNLED27351) +# include "snled27351-mono.h" +#endif + +typedef struct { + /* Perform any initialisation required for the other driver functions to work. */ + void (*init)(void); + + /* Set the brightness of a single LED in the buffer. */ + void (*set_value)(int index, uint8_t value); + /* Set the brightness of all LEDS on the keyboard in the buffer. */ + void (*set_value_all)(uint8_t value); + /* Flush any buffered changes to the hardware. */ + void (*flush)(void); +} led_matrix_driver_t; + +extern const led_matrix_driver_t led_matrix_driver; diff --git a/quantum/logging/debug.h b/quantum/logging/debug.h index 8415310356..d0590474c0 100644 --- a/quantum/logging/debug.h +++ b/quantum/logging/debug.h @@ -17,6 +17,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #pragma once +#ifndef PROTOCOL_ARM_ATSAM +# include <stdio.h> +#endif + #include <stdbool.h> #include "print.h" @@ -54,116 +58,14 @@ extern debug_config_t debug_config; * 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 %d: %s\n", __FILE__, __LINE__, 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); \ +# define dprintf(fmt, ...) \ + do { \ + if (debug_config.enable) xprintf(fmt, ##__VA_ARGS__); \ } 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 */ + +#define dprint(s) dprintf(s) +#define dprintln(s) dprintf(s "\r\n") +#define dmsg(s) dprintf("%s at %d: %s\n", __FILE__, __LINE__, s) diff --git a/quantum/logging/print.h b/quantum/logging/print.h index 4c4195de50..984bc10758 100644 --- a/quantum/logging/print.h +++ b/quantum/logging/print.h @@ -52,40 +52,27 @@ void print_set_sendchar(sendchar_func_t func); # 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") +# include "printf.h" // // Fall back to lib/printf/printf.h # 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 +# endif +#else // Remove print defines -# define print(s) -# define println(s) +# undef xprintf # define xprintf(fmt, ...) -# define uprintf(fmt, ...) -# define uprint(s) -# define uprintln(s) +#endif -#endif /* NO_PRINT */ +// Resolve before USER_PRINT can remove +#define uprintf xprintf #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(s) xprintf(s) +#define println(s) xprintf(s "\r\n") + #define print_dec(i) xprintf("%u", i) #define print_decs(i) xprintf("%d", i) /* hex */ @@ -121,6 +108,9 @@ void print_set_sendchar(sendchar_func_t func); // // !!! DO NOT USE USER PRINT CALLS IN THE BODY OF QMK/TMK !!! +#define uprint(s) uprintf(s) +#define uprintln(s) uprintf(s "\r\n") + /* decimal */ #define uprint_dec(i) uprintf("%u", i) #define uprint_decs(i) uprintf("%d", i) diff --git a/quantum/os_detection.c b/quantum/os_detection.c index e606227136..b674f05b35 100644 --- a/quantum/os_detection.c +++ b/quantum/os_detection.c @@ -16,20 +16,25 @@ #include "os_detection.h" -#include <string.h> +#ifdef OS_DETECTION_ENABLE -#ifdef OS_DETECTION_DEBUG_ENABLE -# include "eeconfig.h" -# include "eeprom.h" -# include "print.h" +# include <string.h> +# include "timer.h" +# ifdef OS_DETECTION_KEYBOARD_RESET +# include "quantum.h" +# endif -# define STORED_USB_SETUPS 50 -# define EEPROM_USER_OFFSET (uint8_t*)EECONFIG_SIZE +# ifdef OS_DETECTION_DEBUG_ENABLE +# include "eeconfig.h" +# include "eeprom.h" +# include "print.h" -uint16_t usb_setups[STORED_USB_SETUPS]; -#endif +# define STORED_USB_SETUPS 50 +# define EEPROM_USER_OFFSET (uint8_t*)EECONFIG_SIZE + +static uint16_t usb_setups[STORED_USB_SETUPS]; +# endif -#ifdef OS_DETECTION_ENABLE struct setups_data_t { uint8_t count; uint8_t cnt_02; @@ -45,43 +50,63 @@ struct setups_data_t setups_data = { .cnt_ff = 0, }; -os_variant_t detected_os = OS_UNSURE; +# ifndef OS_DETECTION_DEBOUNCE +# define OS_DETECTION_DEBOUNCE 200 +# endif -// Some collected sequences of wLength can be found in tests. -void make_guess(void) { - if (setups_data.count < 3) { - return; - } - if (setups_data.cnt_ff >= 2 && setups_data.cnt_04 >= 1) { - detected_os = OS_WINDOWS; - return; - } - if (setups_data.count == setups_data.cnt_ff) { - // Linux has 3 packets with 0xFF. - detected_os = OS_LINUX; - return; - } - if (setups_data.count == 5 && setups_data.last_wlength == 0xFF && setups_data.cnt_ff == 1 && setups_data.cnt_02 == 2) { - detected_os = OS_MACOS; - return; - } - if (setups_data.count == 4 && setups_data.cnt_ff == 0 && setups_data.cnt_02 == 2) { - // iOS and iPadOS don't have the last 0xFF packet. - detected_os = OS_IOS; - return; - } - if (setups_data.cnt_ff == 0 && setups_data.cnt_02 == 3 && setups_data.cnt_04 == 1) { - // This is actually PS5. - detected_os = OS_LINUX; - return; +// 2s should always be more than enough (otherwise, you may have other issues) +# if OS_DETECTION_DEBOUNCE > 2000 +# undef OS_DETECTION_DEBOUNCE +# define OS_DETECTION_DEBOUNCE 2000 +# endif + +typedef uint16_t debouncing_t; + +static volatile os_variant_t detected_os = OS_UNSURE; +static os_variant_t reported_os = OS_UNSURE; + +// we need to be able to report OS_UNSURE if that is the stable result of the guesses +static bool first_report = true; + +// to react on USB state changes +static volatile enum usb_device_state current_usb_device_state = USB_DEVICE_STATE_INIT; +static enum usb_device_state reported_usb_device_state = USB_DEVICE_STATE_INIT; + +// the OS detection might be unstable for a while, "debounce" it +static volatile bool debouncing = false; +static volatile fast_timer_t last_time; + +void os_detection_task(void) { + if (current_usb_device_state == USB_DEVICE_STATE_CONFIGURED) { + // debouncing goes for both the detected OS as well as the USB state + if (debouncing && timer_elapsed_fast(last_time) >= OS_DETECTION_DEBOUNCE) { + debouncing = false; + reported_usb_device_state = current_usb_device_state; + if (detected_os != reported_os || first_report) { + first_report = false; + reported_os = detected_os; + process_detected_host_os_kb(detected_os); + } + } } - if (setups_data.cnt_ff >= 1 && setups_data.cnt_02 == 0 && setups_data.cnt_04 == 0) { - // This is actually Quest 2 or Nintendo Switch. - detected_os = OS_LINUX; - return; +# ifdef OS_DETECTION_KEYBOARD_RESET + // resetting the keyboard on the USB device state change callback results in instability, so delegate that to this task + // only take action if it's been stable at least once, to avoid issues with some KVMs + else if (current_usb_device_state == USB_DEVICE_STATE_INIT && reported_usb_device_state != USB_DEVICE_STATE_INIT) { + soft_reset_keyboard(); } +# endif } +__attribute__((weak)) bool process_detected_host_os_kb(os_variant_t detected_os) { + return process_detected_host_os_user(detected_os); +} + +__attribute__((weak)) bool process_detected_host_os_user(os_variant_t detected_os) { + return true; +} + +// Some collected sequences of wLength can be found in tests. void process_wlength(const uint16_t w_length) { # ifdef OS_DETECTION_DEBUG_ENABLE usb_setups[setups_data.count] = w_length; @@ -95,7 +120,37 @@ void process_wlength(const uint16_t w_length) { } else if (w_length == 0xFF) { setups_data.cnt_ff++; } - make_guess(); + + // now try to make a guess + os_variant_t guessed = OS_UNSURE; + if (setups_data.count >= 3) { + if (setups_data.cnt_ff >= 2 && setups_data.cnt_04 >= 1) { + guessed = OS_WINDOWS; + } else if (setups_data.count == setups_data.cnt_ff) { + // Linux has 3 packets with 0xFF. + guessed = OS_LINUX; + } else if (setups_data.count == 5 && setups_data.last_wlength == 0xFF && setups_data.cnt_ff == 1 && setups_data.cnt_02 == 2) { + guessed = OS_MACOS; + } else if (setups_data.count == 4 && setups_data.cnt_ff == 0 && setups_data.cnt_02 == 2) { + // iOS and iPadOS don't have the last 0xFF packet. + guessed = OS_IOS; + } else if (setups_data.cnt_ff == 0 && setups_data.cnt_02 == 3 && setups_data.cnt_04 == 1) { + // This is actually PS5. + guessed = OS_LINUX; + } else if (setups_data.cnt_ff >= 1 && setups_data.cnt_02 == 0 && setups_data.cnt_04 == 0) { + // This is actually Quest 2 or Nintendo Switch. + guessed = OS_LINUX; + } + } + + // only replace the guessed value if not unsure + if (guessed != OS_UNSURE) { + detected_os = guessed; + } + + // whatever the result, debounce + last_time = timer_read_fast(); + debouncing = true; } os_variant_t detected_host_os(void) { @@ -104,25 +159,38 @@ os_variant_t detected_host_os(void) { void erase_wlength_data(void) { memset(&setups_data, 0, sizeof(setups_data)); - detected_os = OS_UNSURE; + detected_os = OS_UNSURE; + reported_os = OS_UNSURE; + current_usb_device_state = USB_DEVICE_STATE_INIT; + reported_usb_device_state = USB_DEVICE_STATE_INIT; + debouncing = false; + first_report = true; +} + +void os_detection_notify_usb_device_state_change(enum usb_device_state usb_device_state) { + // treat this like any other source of instability + current_usb_device_state = usb_device_state; + last_time = timer_read_fast(); + debouncing = true; } # if defined(SPLIT_KEYBOARD) && defined(SPLIT_DETECTED_OS_ENABLE) void slave_update_detected_host_os(os_variant_t os) { detected_os = os; + last_time = timer_read_fast(); + debouncing = true; } -# endif // defined(SPLIT_KEYBOARD) && defined(SPLIT_DETECTED_OS_ENABLE) -#endif // OS_DETECTION_ENABLE +# endif -#ifdef OS_DETECTION_DEBUG_ENABLE +# ifdef OS_DETECTION_DEBUG_ENABLE void print_stored_setups(void) { -# ifdef CONSOLE_ENABLE +# ifdef CONSOLE_ENABLE uint8_t cnt = eeprom_read_byte(EEPROM_USER_OFFSET); for (uint16_t i = 0; i < cnt; ++i) { uint16_t* addr = (uint16_t*)EEPROM_USER_OFFSET + i * sizeof(uint16_t) + sizeof(uint8_t); xprintf("i: %d, wLength: 0x%02X\n", i, eeprom_read_word(addr)); } -# endif +# endif } void store_setups_in_eeprom(void) { @@ -133,4 +201,6 @@ void store_setups_in_eeprom(void) { } } -#endif // OS_DETECTION_DEBUG_ENABLE +# endif // OS_DETECTION_DEBUG_ENABLE + +#endif diff --git a/quantum/os_detection.h b/quantum/os_detection.h index 3496ea0ed2..470f30943a 100644 --- a/quantum/os_detection.h +++ b/quantum/os_detection.h @@ -16,9 +16,12 @@ #pragma once -#include <stdint.h> - #ifdef OS_DETECTION_ENABLE + +# include <stdint.h> +# include <stdbool.h> +# include "usb_device_state.h" + typedef enum { OS_UNSURE, OS_LINUX, @@ -30,13 +33,20 @@ typedef enum { void process_wlength(const uint16_t w_length); os_variant_t detected_host_os(void); void erase_wlength_data(void); +void os_detection_notify_usb_device_state_change(enum usb_device_state usb_device_state); + +void os_detection_task(void); + +bool process_detected_host_os_kb(os_variant_t os); +bool process_detected_host_os_user(os_variant_t os); # if defined(SPLIT_KEYBOARD) && defined(SPLIT_DETECTED_OS_ENABLE) void slave_update_detected_host_os(os_variant_t os); -# endif // defined(SPLIT_KEYBOARD) && defined(SPLIT_DETECTED_OS_ENABLE) -#endif +# endif -#ifdef OS_DETECTION_DEBUG_ENABLE +# ifdef OS_DETECTION_DEBUG_ENABLE void print_stored_setups(void); void store_setups_in_eeprom(void); -#endif +# endif + +#endif // OS_DETECTION_ENABLE diff --git a/quantum/os_detection/tests/os_detection.cpp b/quantum/os_detection/tests/os_detection.cpp index 102349852e..11e93fdea8 100644 --- a/quantum/os_detection/tests/os_detection.cpp +++ b/quantum/os_detection/tests/os_detection.cpp @@ -18,12 +18,20 @@ extern "C" { #include "os_detection.h" +#include "timer.h" + +void advance_time(uint32_t ms); } +static uint32_t reported_count; +static os_variant_t reported_os; + class OsDetectionTest : public ::testing::Test { protected: void SetUp() override { erase_wlength_data(); + reported_count = 0; + reported_os = OS_UNSURE; } }; @@ -34,6 +42,24 @@ os_variant_t check_sequence(const std::vector<uint16_t> &w_lengths) { return detected_host_os(); } +bool process_detected_host_os_kb(os_variant_t os) { + reported_count = reported_count + 1; + reported_os = os; +} + +void assert_not_reported(void) { + // check that it does not report the result, nor any intermediate results + EXPECT_EQ(reported_count, 0); + EXPECT_EQ(reported_os, OS_UNSURE); +} + +void assert_reported(os_variant_t os) { + // check that it reports exclusively the result, not any intermediate results + EXPECT_EQ(reported_count, 1); + EXPECT_EQ(reported_os, os); + EXPECT_EQ(reported_os, detected_host_os()); +} + /* Some collected data. ChibiOS: @@ -77,88 +103,291 @@ Quest 2: [FF, FF, FF, FE, ...] */ TEST_F(OsDetectionTest, TestLinux) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0xFF}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestChibiosMacos) { EXPECT_EQ(check_sequence({0x2, 0x24, 0x2, 0x28, 0xFF}), OS_MACOS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestLufaMacos) { EXPECT_EQ(check_sequence({0x2, 0x10, 0x2, 0xE, 0xFF}), OS_MACOS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestVusbMacos) { EXPECT_EQ(check_sequence({0x2, 0xE, 0x2, 0xE, 0xFF}), OS_MACOS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestChibiosIos) { EXPECT_EQ(check_sequence({0x2, 0x24, 0x2, 0x28}), OS_IOS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestLufaIos) { EXPECT_EQ(check_sequence({0x2, 0x10, 0x2, 0xE}), OS_IOS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestVusbIos) { EXPECT_EQ(check_sequence({0x2, 0xE, 0x2, 0xE}), OS_IOS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestChibiosWindows10) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0x4, 0x24, 0x4, 0x24, 0x4, 0xFF, 0x24, 0xFF, 0x4, 0xFF, 0x24, 0x4, 0x24, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestChibiosWindows10_2) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0x4, 0x24, 0x4, 0x24, 0x4, 0x24, 0x4, 0x24, 0x4, 0x24}), OS_WINDOWS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestLufaWindows10) { EXPECT_EQ(check_sequence({0x12, 0xFF, 0xFF, 0x4, 0x10, 0xFF, 0xFF, 0xFF, 0x4, 0x10, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestLufaWindows10_2) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0x4, 0x10, 0xFF, 0x4, 0xFF, 0x10, 0xFF, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestLufaWindows10_3) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0x4, 0x10, 0x4, 0x10}), OS_WINDOWS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestVusbWindows10) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0x4, 0xE, 0xFF}), OS_WINDOWS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestVusbWindows10_2) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0x4, 0xE, 0x4}), OS_WINDOWS); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestChibiosPs5) { EXPECT_EQ(check_sequence({0x2, 0x4, 0x2, 0x28, 0x2, 0x24}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestLufaPs5) { EXPECT_EQ(check_sequence({0x2, 0x4, 0x2, 0xE, 0x2, 0x10}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestVusbPs5) { EXPECT_EQ(check_sequence({0x2, 0x4, 0x2, 0xE, 0x2}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestChibiosNintendoSwitch) { EXPECT_EQ(check_sequence({0x82, 0xFF, 0x40, 0x40, 0xFF, 0x40, 0x40, 0xFF, 0x40, 0x40, 0xFF, 0x40, 0x40, 0xFF, 0x40, 0x40}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestLufaNintendoSwitch) { EXPECT_EQ(check_sequence({0x82, 0xFF, 0x40, 0x40, 0xFF, 0x40, 0x40}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestVusbNintendoSwitch) { EXPECT_EQ(check_sequence({0x82, 0xFF, 0x40, 0x40}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestChibiosQuest2) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } TEST_F(OsDetectionTest, TestVusbQuest2) { EXPECT_EQ(check_sequence({0xFF, 0xFF, 0xFF, 0xFE}), OS_LINUX); + os_detection_task(); + assert_not_reported(); +} + +// Regression reported in https://github.com/qmk/qmk_firmware/pull/21777#issuecomment-1922815841 +TEST_F(OsDetectionTest, TestDetectMacM1AsIOS) { + EXPECT_EQ(check_sequence({0x02, 0x32, 0x02, 0x24, 0x101, 0xFF}), OS_IOS); + os_detection_task(); + assert_not_reported(); +} + +TEST_F(OsDetectionTest, TestDoNotReportIfUsbUnstable) { + EXPECT_EQ(check_sequence({0xFF, 0xFF, 0xFF, 0xFE}), OS_LINUX); + os_detection_task(); + assert_not_reported(); + + advance_time(OS_DETECTION_DEBOUNCE); + os_detection_task(); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_LINUX); +} + +TEST_F(OsDetectionTest, TestReportAfterDebounce) { + EXPECT_EQ(check_sequence({0xFF, 0xFF, 0xFF, 0xFE}), OS_LINUX); + os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); + os_detection_task(); + assert_not_reported(); + + advance_time(1); + os_detection_task(); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_LINUX); + + advance_time(OS_DETECTION_DEBOUNCE - 3); + os_detection_task(); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_LINUX); + + advance_time(1); + os_detection_task(); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_LINUX); + + // advancing the timer alone must not cause a report + advance_time(1); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_LINUX); + // the task will cause a report + os_detection_task(); + assert_reported(OS_LINUX); + EXPECT_EQ(detected_host_os(), OS_LINUX); + + // check that it remains the same after a long time + advance_time(OS_DETECTION_DEBOUNCE * 15); + assert_reported(OS_LINUX); + EXPECT_EQ(detected_host_os(), OS_LINUX); +} + +TEST_F(OsDetectionTest, TestReportAfterDebounceLongWait) { + EXPECT_EQ(check_sequence({0x12, 0xFF, 0xFF, 0x4, 0x10, 0xFF, 0xFF, 0xFF, 0x4, 0x10, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); + os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); + os_detection_task(); + assert_not_reported(); + + advance_time(1); + os_detection_task(); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_WINDOWS); + + // advancing the timer alone must not cause a report + advance_time(OS_DETECTION_DEBOUNCE * 15); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_WINDOWS); + // the task will cause a report + os_detection_task(); + assert_reported(OS_WINDOWS); + EXPECT_EQ(detected_host_os(), OS_WINDOWS); + + // check that it remains the same after a long time + advance_time(OS_DETECTION_DEBOUNCE * 10); + os_detection_task(); + assert_reported(OS_WINDOWS); + EXPECT_EQ(detected_host_os(), OS_WINDOWS); +} + +TEST_F(OsDetectionTest, TestReportUnsure) { + EXPECT_EQ(check_sequence({0x12, 0xFF}), OS_UNSURE); + os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); + os_detection_task(); + assert_not_reported(); + + advance_time(1); + os_detection_task(); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_UNSURE); + + // advancing the timer alone must not cause a report + advance_time(OS_DETECTION_DEBOUNCE - 1); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_UNSURE); + // the task will cause a report + os_detection_task(); + assert_reported(OS_UNSURE); + EXPECT_EQ(detected_host_os(), OS_UNSURE); + + // check that it remains the same after a long time + advance_time(OS_DETECTION_DEBOUNCE * 10); + os_detection_task(); + assert_reported(OS_UNSURE); + EXPECT_EQ(detected_host_os(), OS_UNSURE); +} + +TEST_F(OsDetectionTest, TestDoNotReportIntermediateResults) { + EXPECT_EQ(check_sequence({0x12, 0xFF}), OS_UNSURE); + os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); + os_detection_task(); + assert_not_reported(); + + advance_time(OS_DETECTION_DEBOUNCE - 1); + os_detection_task(); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_UNSURE); + + // at this stage, the final result has not been reached yet + EXPECT_EQ(check_sequence({0xFF}), OS_LINUX); + os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); + advance_time(OS_DETECTION_DEBOUNCE - 1); + os_detection_task(); + assert_not_reported(); + // the intermedite but yet unstable result is exposed through detected_host_os() + EXPECT_EQ(detected_host_os(), OS_LINUX); + + // the remainder is processed + EXPECT_EQ(check_sequence({0x4, 0x10, 0xFF, 0xFF, 0xFF, 0x4, 0x10, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); + os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); + advance_time(OS_DETECTION_DEBOUNCE - 1); + os_detection_task(); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_WINDOWS); + + // advancing the timer alone must not cause a report + advance_time(1); + assert_not_reported(); + EXPECT_EQ(detected_host_os(), OS_WINDOWS); + // the task will cause a report + os_detection_task(); + assert_reported(OS_WINDOWS); + EXPECT_EQ(detected_host_os(), OS_WINDOWS); + + // check that it remains the same after a long time + advance_time(OS_DETECTION_DEBOUNCE * 10); + os_detection_task(); + assert_reported(OS_WINDOWS); + EXPECT_EQ(detected_host_os(), OS_WINDOWS); +} + +TEST_F(OsDetectionTest, TestDoNotGoBackToUnsure) { + // 0x02 would cause it to go back to Unsure, so check that it does not + EXPECT_EQ(check_sequence({0xFF, 0xFF, 0xFF, 0xFE, 0x02}), OS_LINUX); + os_detection_task(); + assert_not_reported(); } diff --git a/quantum/os_detection/tests/rules.mk b/quantum/os_detection/tests/rules.mk index 9bfe373f46..1b69b71ba9 100644 --- a/quantum/os_detection/tests/rules.mk +++ b/quantum/os_detection/tests/rules.mk @@ -1,5 +1,7 @@ os_detection_DEFS := -DOS_DETECTION_ENABLE +os_detection_DEFS += -DOS_DETECTION_DEBOUNCE=50 os_detection_SRC := \ $(QUANTUM_PATH)/os_detection/tests/os_detection.cpp \ - $(QUANTUM_PATH)/os_detection.c + $(QUANTUM_PATH)/os_detection.c \ + $(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c diff --git a/quantum/painter/qp_draw.h b/quantum/painter/qp_draw.h index 3d073efe8c..7546c061a7 100644 --- a/quantum/painter/qp_draw.h +++ b/quantum/painter/qp_draw.h @@ -92,4 +92,9 @@ typedef struct qp_internal_byte_output_state_t { bool qp_internal_byte_appender(uint8_t byteval, void* cb_arg); +// Helper shared between image and font rendering, sends pixels to the display using: +// - qp_internal_decode_palette + qp_internal_pixel_appender (bpp <= 8) +// - qp_internal_send_bytes (bpp > 8) +bool qp_internal_appender(painter_device_t device, uint8_t bpp, uint32_t pixel_count, qp_internal_byte_input_callback input_callback, void* input_state); + qp_internal_byte_input_callback qp_internal_prepare_input_state(qp_internal_byte_input_state_t* input_state, painter_compression_t compression); diff --git a/quantum/painter/qp_draw_codec.c b/quantum/painter/qp_draw_codec.c index cee2e32e28..4ff41d0650 100644 --- a/quantum/painter/qp_draw_codec.c +++ b/quantum/painter/qp_draw_codec.c @@ -1,4 +1,5 @@ // Copyright 2021 Nick Brassel (@tzarc) +// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev> // SPDX-License-Identifier: GPL-2.0-or-later #include "qp_internal.h" @@ -164,6 +165,45 @@ bool qp_internal_byte_appender(uint8_t byteval, void* cb_arg) { return true; } +// Helper shared between image and font rendering -- uses either (qp_internal_decode_palette + qp_internal_pixel_appender) or (qp_internal_send_bytes) to send data data to the display based on the asset's native-ness +bool qp_internal_appender(painter_device_t device, uint8_t bpp, uint32_t pixel_count, qp_internal_byte_input_callback input_callback, void* input_state) { + painter_driver_t* driver = (painter_driver_t*)device; + + bool ret = false; + + // Non-native pixel format + if (bpp <= 8) { + // Set up the output state + qp_internal_pixel_output_state_t output_state = {.device = device, .pixel_write_pos = 0, .max_pixels = qp_internal_num_pixels_in_buffer(device)}; + + // Decode the pixel data and stream to the display + ret = qp_internal_decode_palette(device, pixel_count, bpp, input_callback, input_state, qp_internal_global_pixel_lookup_table, qp_internal_pixel_appender, &output_state); + // Any leftovers need transmission as well. + if (ret && output_state.pixel_write_pos > 0) { + ret &= driver->driver_vtable->pixdata(device, qp_internal_global_pixdata_buffer, output_state.pixel_write_pos); + } + } + + // Native pixel format + else if (bpp != driver->native_bits_per_pixel) { + qp_dprintf("Asset's bpp (%d) doesn't match the target display's native_bits_per_pixel (%d)\n", bpp, driver->native_bits_per_pixel); + return false; + } else { + // Set up the output state + qp_internal_byte_output_state_t output_state = {.device = device, .byte_write_pos = 0, .max_bytes = qp_internal_num_pixels_in_buffer(device) * driver->native_bits_per_pixel / 8}; + + // Stream the raw pixel data to the display + uint32_t byte_count = pixel_count * bpp / 8; + ret = qp_internal_send_bytes(device, byte_count, input_callback, input_state, qp_internal_byte_appender, &output_state); + // Any leftovers need transmission as well. + if (ret && output_state.byte_write_pos > 0) { + ret &= driver->driver_vtable->pixdata(device, qp_internal_global_pixdata_buffer, output_state.byte_write_pos * 8 / driver->native_bits_per_pixel); + } + } + + return ret; +} + qp_internal_byte_input_callback qp_internal_prepare_input_state(qp_internal_byte_input_state_t* input_state, painter_compression_t compression) { switch (compression) { case IMAGE_UNCOMPRESSED: diff --git a/quantum/painter/qp_draw_image.c b/quantum/painter/qp_draw_image.c index 87c59148c2..18fa38cb19 100644 --- a/quantum/painter/qp_draw_image.c +++ b/quantum/painter/qp_draw_image.c @@ -263,33 +263,8 @@ static bool qp_drawimage_recolor_impl(painter_device_t device, uint16_t x, uint1 return false; } - bool ret = false; - if (!frame_info->is_panel_native) { - // Set up the output state - qp_internal_pixel_output_state_t output_state = {.device = device, .pixel_write_pos = 0, .max_pixels = qp_internal_num_pixels_in_buffer(device)}; - - // Decode the pixel data and stream to the display - ret = qp_internal_decode_palette(device, pixel_count, frame_info->bpp, input_callback, &input_state, qp_internal_global_pixel_lookup_table, qp_internal_pixel_appender, &output_state); - // Any leftovers need transmission as well. - if (ret && output_state.pixel_write_pos > 0) { - ret &= driver->driver_vtable->pixdata(device, qp_internal_global_pixdata_buffer, output_state.pixel_write_pos); - } - } else if (frame_info->bpp != driver->native_bits_per_pixel) { - // Prevent stuff like drawing 24bpp images on 16bpp displays - qp_dprintf("Image's bpp doesn't match the target display's native_bits_per_pixel\n"); - return false; - } else { - // Set up the output state - qp_internal_byte_output_state_t output_state = {.device = device, .byte_write_pos = 0, .max_bytes = qp_internal_num_pixels_in_buffer(device) * driver->native_bits_per_pixel / 8}; - - // Stream the raw pixel data to the display - uint32_t byte_count = pixel_count * frame_info->bpp / 8; - ret = qp_internal_send_bytes(device, byte_count, input_callback, &input_state, qp_internal_byte_appender, &output_state); - // Any leftovers need transmission as well. - if (ret && output_state.byte_write_pos > 0) { - ret &= driver->driver_vtable->pixdata(device, qp_internal_global_pixdata_buffer, output_state.byte_write_pos * 8 / driver->native_bits_per_pixel); - } - } + // Decode and stream pixels + bool ret = qp_internal_appender(device, frame_info->bpp, pixel_count, input_callback, &input_state); qp_dprintf("qp_drawimage_recolor: %s\n", ret ? "ok" : "fail"); qp_comms_stop(device); diff --git a/quantum/painter/qp_draw_text.c b/quantum/painter/qp_draw_text.c index 1ac5cab646..664c89c6e5 100644 --- a/quantum/painter/qp_draw_text.c +++ b/quantum/painter/qp_draw_text.c @@ -364,16 +364,9 @@ static inline bool qp_font_code_point_handler_drawglyph(qff_font_handle_t *qff_f // Move the x-position for the next glyph state->xpos += width; - // Decode the pixel data for the glyph + // Decode the pixel data for the glyph, and stream it uint32_t pixel_count = ((uint32_t)width) * height; - bool ret = qp_internal_decode_palette(state->device, pixel_count, qff_font->bpp, state->input_callback, state->input_state, qp_internal_global_pixel_lookup_table, qp_internal_pixel_appender, state->output_state); - - // Any leftovers need transmission as well. - if (ret && state->output_state->pixel_write_pos > 0) { - ret &= driver->driver_vtable->pixdata(state->device, qp_internal_global_pixdata_buffer, state->output_state->pixel_write_pos); - } - - return ret; + return qp_internal_appender(state->device, qff_font->bpp, pixel_count, state->input_callback, state->input_state); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/quantum/pointing_device/pointing_device.c b/quantum/pointing_device/pointing_device.c index 17dc701a41..2fa49ade8e 100644 --- a/quantum/pointing_device/pointing_device.c +++ b/quantum/pointing_device/pointing_device.c @@ -251,14 +251,15 @@ __attribute__((weak)) bool pointing_device_task(void) { # else if (readPin(POINTING_DEVICE_MOTION_PIN)) # endif + { #endif #if defined(SPLIT_POINTING_ENABLE) # if defined(POINTING_DEVICE_COMBINED) static uint8_t old_buttons = 0; - local_mouse_report.buttons = old_buttons; - local_mouse_report = pointing_device_driver.get_report(local_mouse_report); - old_buttons = local_mouse_report.buttons; + local_mouse_report.buttons = old_buttons; + local_mouse_report = pointing_device_driver.get_report(local_mouse_report); + old_buttons = local_mouse_report.buttons; # elif defined(POINTING_DEVICE_LEFT) || defined(POINTING_DEVICE_RIGHT) local_mouse_report = POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_report(local_mouse_report) : shared_mouse_report; # else @@ -268,6 +269,10 @@ __attribute__((weak)) bool pointing_device_task(void) { local_mouse_report = pointing_device_driver.get_report(local_mouse_report); #endif // defined(SPLIT_POINTING_ENABLE) +#ifdef POINTING_DEVICE_MOTION_PIN + } +#endif + // allow kb to intercept and modify report #if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED) if (is_keyboard_left()) { diff --git a/quantum/pointing_device/pointing_device_auto_mouse.c b/quantum/pointing_device/pointing_device_auto_mouse.c index 3135b9e531..1b11fffedb 100644 --- a/quantum/pointing_device/pointing_device_auto_mouse.c +++ b/quantum/pointing_device/pointing_device_auto_mouse.c @@ -17,6 +17,7 @@ #ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE +# include <stdlib.h> # include <string.h> # include "pointing_device_auto_mouse.h" # include "debug.h" @@ -217,7 +218,11 @@ void auto_mouse_layer_off(void) { * @return bool of pointing_device activation */ __attribute__((weak)) bool auto_mouse_activation(report_mouse_t mouse_report) { - return mouse_report.x != 0 || mouse_report.y != 0 || mouse_report.h != 0 || mouse_report.v != 0 || mouse_report.buttons; + auto_mouse_context.total_mouse_movement.x += mouse_report.x; + auto_mouse_context.total_mouse_movement.y += mouse_report.y; + auto_mouse_context.total_mouse_movement.h += mouse_report.h; + auto_mouse_context.total_mouse_movement.v += mouse_report.v; + return abs(auto_mouse_context.total_mouse_movement.x) > AUTO_MOUSE_THRESHOLD || abs(auto_mouse_context.total_mouse_movement.y) > AUTO_MOUSE_THRESHOLD || abs(auto_mouse_context.total_mouse_movement.h) > AUTO_MOUSE_THRESHOLD || abs(auto_mouse_context.total_mouse_movement.v) > AUTO_MOUSE_THRESHOLD || mouse_report.buttons; } /** @@ -235,14 +240,16 @@ void pointing_device_task_auto_mouse(report_mouse_t mouse_report) { // update activation and reset debounce auto_mouse_context.status.is_activated = auto_mouse_activation(mouse_report); if (is_auto_mouse_active()) { - auto_mouse_context.timer.active = timer_read(); - auto_mouse_context.timer.delay = 0; + auto_mouse_context.total_mouse_movement = (total_mouse_movement_t){.x = 0, .y = 0, .h = 0, .v = 0}; + auto_mouse_context.timer.active = timer_read(); + auto_mouse_context.timer.delay = 0; if (!layer_state_is((AUTO_MOUSE_TARGET_LAYER))) { layer_on((AUTO_MOUSE_TARGET_LAYER)); } } else if (layer_state_is((AUTO_MOUSE_TARGET_LAYER)) && timer_elapsed(auto_mouse_context.timer.active) > auto_mouse_context.config.timeout) { layer_off((AUTO_MOUSE_TARGET_LAYER)); - auto_mouse_context.timer.active = 0; + auto_mouse_context.timer.active = 0; + auto_mouse_context.total_mouse_movement = (total_mouse_movement_t){.x = 0, .y = 0, .h = 0, .v = 0}; } } diff --git a/quantum/pointing_device/pointing_device_auto_mouse.h b/quantum/pointing_device/pointing_device_auto_mouse.h index 1343855e00..904f18b68e 100644 --- a/quantum/pointing_device/pointing_device_auto_mouse.h +++ b/quantum/pointing_device/pointing_device_auto_mouse.h @@ -42,9 +42,18 @@ #ifndef AUTO_MOUSE_DEBOUNCE # define AUTO_MOUSE_DEBOUNCE 25 #endif +#ifndef AUTO_MOUSE_THRESHOLD +# define AUTO_MOUSE_THRESHOLD 10 +#endif /* data structure */ typedef struct { + mouse_xy_report_t x; + mouse_xy_report_t y; + int8_t v; + int8_t h; +} total_mouse_movement_t; +typedef struct { struct { bool is_enabled; uint8_t layer; @@ -60,6 +69,7 @@ typedef struct { bool is_toggled; int8_t mouse_key_tracker; } status; + total_mouse_movement_t total_mouse_movement; } auto_mouse_context_t; /* ----------Set up and control------------------------------------------------------------------------------ */ diff --git a/quantum/process_keycode/process_caps_word.c b/quantum/process_keycode/process_caps_word.c index 1088c8f76c..b8fb868c6d 100644 --- a/quantum/process_keycode/process_caps_word.c +++ b/quantum/process_keycode/process_caps_word.c @@ -14,6 +14,7 @@ #include "process_caps_word.h" #include "process_auto_shift.h" +#include "process_space_cadet.h" #include "caps_word.h" #include "keycodes.h" #include "quantum_keycodes.h" @@ -110,6 +111,9 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) { # endif // COMMAND_ENABLE ) { caps_word_on(); +# ifdef SPACE_CADET_ENABLE + reset_space_cadet(); +# endif // SPACE_CADET_ENABLE } # endif // defined(COMMAND_ENABLE) && !defined(IS_COMMAND) #endif // BOTH_SHIFTS_TURNS_ON_CAPS_WORD diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 377fcb69e2..5ecd897d16 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -38,7 +38,7 @@ void process_midi_all_notes_off(void) { #endif // MIDI_BASIC #ifdef MIDI_ADVANCED -static uint8_t tone_status[2][MIDI_TONE_COUNT]; +static uint8_t tone_status[MIDI_TONE_COUNT]; static uint8_t midi_modulation; static int8_t midi_modulation_step; @@ -57,8 +57,7 @@ void midi_init(void) { midi_config.modulation_interval = 8; for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++) { - tone_status[0][i] = MIDI_INVALID_NOTE; - tone_status[1][i] = 0; + tone_status[i] = MIDI_INVALID_NOTE; } midi_modulation = 0; @@ -77,21 +76,19 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) { uint8_t tone = keycode - MIDI_TONE_MIN; uint8_t velocity = midi_config.velocity; if (record->event.pressed) { - uint8_t note = midi_compute_note(keycode); - midi_send_noteon(&midi_device, channel, note, velocity); - dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); - tone_status[1][tone] += 1; - if (tone_status[0][tone] == MIDI_INVALID_NOTE) { - tone_status[0][tone] = note; + if (tone_status[tone] == MIDI_INVALID_NOTE) { + uint8_t note = midi_compute_note(keycode); + midi_send_noteon(&midi_device, channel, note, velocity); + dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); + tone_status[tone] = note; } } else { - uint8_t note = tone_status[0][tone]; - tone_status[1][tone] -= 1; - if (tone_status[1][tone] == 0) { + uint8_t note = tone_status[tone]; + if (note != MIDI_INVALID_NOTE) { midi_send_noteoff(&midi_device, channel, note, velocity); dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity); - tone_status[0][tone] = MIDI_INVALID_NOTE; } + tone_status[tone] = MIDI_INVALID_NOTE; } return false; } diff --git a/quantum/process_keycode/process_space_cadet.c b/quantum/process_keycode/process_space_cadet.c index f948ad6238..3e280d57d9 100644 --- a/quantum/process_keycode/process_space_cadet.c +++ b/quantum/process_keycode/process_space_cadet.c @@ -157,10 +157,14 @@ bool process_space_cadet(uint16_t keycode, keyrecord_t *record) { } default: { if (record->event.pressed) { - sc_last = 0; + reset_space_cadet(); } break; } } return true; } + +void reset_space_cadet() { + sc_last = 0; +} diff --git a/quantum/process_keycode/process_space_cadet.h b/quantum/process_keycode/process_space_cadet.h index 6d10051532..9d254e26fd 100644 --- a/quantum/process_keycode/process_space_cadet.h +++ b/quantum/process_keycode/process_space_cadet.h @@ -21,3 +21,4 @@ void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdMod, uint8_t tapMod, uint8_t keycode); bool process_space_cadet(uint16_t keycode, keyrecord_t *record); +void reset_space_cadet(void); diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c index bd4361580b..c491d6f1d8 100644 --- a/quantum/process_keycode/process_steno.c +++ b/quantum/process_keycode/process_steno.c @@ -128,9 +128,6 @@ static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, ST #ifdef STENO_ENABLE_ALL void steno_init(void) { - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } mode = eeprom_read_byte(EECONFIG_STENOMODE); } diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c index b8a8d32f35..ce3b8fc81f 100644 --- a/quantum/process_keycode/process_tap_dance.c +++ b/quantum/process_keycode/process_tap_dance.c @@ -133,7 +133,7 @@ bool preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) { if (!active_td || keycode == active_td) return false; - action = &tap_dance_actions[TD_INDEX(active_td)]; + action = &tap_dance_actions[QK_TAP_DANCE_GET_INDEX(active_td)]; action->state.interrupted = true; action->state.interrupting_keycode = keycode; process_tap_dance_action_on_dance_finished(action); @@ -154,7 +154,7 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: - action = &tap_dance_actions[TD_INDEX(keycode)]; + action = &tap_dance_actions[QK_TAP_DANCE_GET_INDEX(keycode)]; action->state.pressed = record->event.pressed; if (record->event.pressed) { @@ -182,7 +182,7 @@ void tap_dance_task(void) { if (!active_td || timer_elapsed(last_tap_time) <= GET_TAPPING_TERM(active_td, &(keyrecord_t){})) return; - action = &tap_dance_actions[TD_INDEX(active_td)]; + action = &tap_dance_actions[QK_TAP_DANCE_GET_INDEX(active_td)]; if (!action->state.interrupted) { process_tap_dance_action_on_dance_finished(action); } diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h index 2b114dabd3..c0137c14a3 100644 --- a/quantum/process_keycode/process_tap_dance.h +++ b/quantum/process_keycode/process_tap_dance.h @@ -19,6 +19,7 @@ #include <stdint.h> #include <stdbool.h> #include "action.h" +#include "quantum_keycodes.h" typedef struct { uint16_t interrupting_keycode; @@ -74,8 +75,7 @@ typedef struct { #define ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(user_fn_on_each_tap, user_fn_on_each_release, user_fn_on_dance_finished, user_fn_on_dance_reset) \ { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, user_fn_on_each_release}, .user_data = NULL, } -#define TD(n) (QK_TAP_DANCE | TD_INDEX(n)) -#define TD_INDEX(code) ((code)&0xFF) +#define TD_INDEX(code) QK_TAP_DANCE_GET_INDEX(code) #define TAP_DANCE_KEYCODE(state) TD(((tap_dance_action_t *)state) - tap_dance_actions) extern tap_dance_action_t tap_dance_actions[]; diff --git a/quantum/quantum.h b/quantum/quantum.h index 996e93a12f..5446ab1ad7 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -42,7 +42,6 @@ #include "action_layer.h" #include "eeconfig.h" #include "bootloader.h" -#include "bootmagic.h" #include "timer.h" #include "sync_timer.h" #include "gpio.h" @@ -59,6 +58,10 @@ #include <stdio.h> #include <string.h> +#ifdef BOOTMAGIC_ENABLE +# include "bootmagic.h" +#endif + #ifdef DEFERRED_EXEC_ENABLE # include "deferred_exec.h" #endif @@ -233,6 +236,10 @@ extern layer_state_t layer_state; # include "process_repeat_key.h" #endif +#ifdef OS_DETECTION_ENABLE +# include "os_detection.h" +#endif + void set_single_persistent_default_layer(uint8_t default_layer); #define IS_LAYER_ON(layer) layer_state_is(layer) diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index d3249bd455..882e1d07ae 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -190,6 +190,10 @@ #define SH_T(kc) (QK_SWAP_HANDS | ((kc)&0xFF)) #define QK_SWAP_HANDS_GET_TAP_KEYCODE(kc) ((kc)&0xFF) +// Tap dance +#define TD(i) (QK_TAP_DANCE | ((i)&0xFF)) +#define QK_TAP_DANCE_GET_INDEX(kc) ((kc)&0xFF) + // MIDI aliases #define MIDI_TONE_MIN QK_MIDI_NOTE_C_0 #define MIDI_TONE_MAX QK_MIDI_NOTE_B_5 diff --git a/quantum/rgb_matrix/animations/solid_reactive_anim.h b/quantum/rgb_matrix/animations/solid_reactive_anim.h index edf6041350..e18ffb5f2b 100644 --- a/quantum/rgb_matrix/animations/solid_reactive_anim.h +++ b/quantum/rgb_matrix/animations/solid_reactive_anim.h @@ -7,7 +7,7 @@ static HSV SOLID_REACTIVE_math(HSV hsv, uint16_t offset) { # ifdef RGB_MATRIX_SOLID_REACTIVE_GRADIENT_MODE hsv.h = scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed, 8) >> 4); # endif - hsv.h += qsub8(130, offset); + hsv.h += scale8(255 - offset, 64); return hsv; } diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c index d93d189827..655aca1867 100644 --- a/quantum/rgb_matrix/rgb_matrix.c +++ b/quantum/rgb_matrix/rgb_matrix.c @@ -76,9 +76,6 @@ static uint8_t rgb_last_enable = UINT8_MAX; static uint8_t rgb_last_effect = UINT8_MAX; static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; static rgb_task_states rgb_task_state = SYNCING; -#if RGB_MATRIX_TIMEOUT > 0 -static uint32_t rgb_anykey_timer; -#endif // RGB_MATRIX_TIMEOUT > 0 // double buffers static uint32_t rgb_timer_buffer; @@ -103,7 +100,7 @@ void eeconfig_update_rgb_matrix_default(void) { rgb_matrix_config.mode = RGB_MATRIX_DEFAULT_MODE; rgb_matrix_config.hsv = (HSV){RGB_MATRIX_DEFAULT_HUE, RGB_MATRIX_DEFAULT_SAT, RGB_MATRIX_DEFAULT_VAL}; rgb_matrix_config.speed = RGB_MATRIX_DEFAULT_SPD; - rgb_matrix_config.flags = LED_FLAG_ALL; + rgb_matrix_config.flags = RGB_MATRIX_DEFAULT_FLAGS; eeconfig_flush_rgb_matrix(true); } @@ -163,9 +160,6 @@ void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) { #ifndef RGB_MATRIX_SPLIT if (!is_keyboard_master()) return; #endif -#if RGB_MATRIX_TIMEOUT > 0 - rgb_anykey_timer = 0; -#endif // RGB_MATRIX_TIMEOUT > 0 #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED uint8_t led[LED_HITS_TO_REMEMBER]; @@ -246,18 +240,11 @@ static bool rgb_matrix_none(effect_params_t *params) { } static void rgb_task_timers(void) { -#if defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_MATRIX_TIMEOUT > 0 +#if defined(RGB_MATRIX_KEYREACTIVE_ENABLED) uint32_t deltaTime = sync_timer_elapsed32(rgb_timer_buffer); -#endif // defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_MATRIX_TIMEOUT > 0 +#endif // defined(RGB_MATRIX_KEYREACTIVE_ENABLED) rgb_timer_buffer = sync_timer_read32(); - // Update double buffer timers -#if RGB_MATRIX_TIMEOUT > 0 - if (rgb_anykey_timer + deltaTime <= UINT32_MAX) { - rgb_anykey_timer += deltaTime; - } -#endif // RGB_MATRIX_TIMEOUT > 0 - // Update double buffer last hit timers #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED uint8_t count = last_hit_buffer.count; @@ -370,7 +357,7 @@ void rgb_matrix_task(void) { // while suspended and just do a software shutdown. This is a cheap hack for now. bool suspend_backlight = suspend_state || #if RGB_MATRIX_TIMEOUT > 0 - (rgb_anykey_timer > (uint32_t)RGB_MATRIX_TIMEOUT) || + (last_input_activity_elapsed() > (uint32_t)RGB_MATRIX_TIMEOUT) || #endif // RGB_MATRIX_TIMEOUT > 0 false; @@ -473,12 +460,6 @@ void rgb_matrix_init(void) { } #endif // RGB_MATRIX_KEYREACTIVE_ENABLED - if (!eeconfig_is_enabled()) { - dprintf("rgb_matrix_init_drivers eeconfig is not enabled.\n"); - eeconfig_init(); - eeconfig_update_rgb_matrix_default(); - } - eeconfig_init_rgb_matrix(); if (!rgb_matrix_config.mode) { dprintf("rgb_matrix_init_drivers rgb_matrix_config.mode = 0. Write default values to EEPROM.\n"); @@ -488,7 +469,7 @@ void rgb_matrix_init(void) { } void rgb_matrix_set_suspend_state(bool state) { -#ifdef RGB_DISABLE_WHEN_USB_SUSPENDED +#ifdef RGB_MATRIX_SLEEP if (state && !suspend_state) { // only run if turning off, and only once rgb_task_render(0); // turn off all LEDs when suspending rgb_task_flush(0); // and actually flash led state to LEDs diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h index 9a3ffb8ea3..f8a6845e02 100644 --- a/quantum/rgb_matrix/rgb_matrix.h +++ b/quantum/rgb_matrix/rgb_matrix.h @@ -21,31 +21,10 @@ #include <stdint.h> #include <stdbool.h> #include "rgb_matrix_types.h" +#include "rgb_matrix_drivers.h" #include "color.h" #include "keyboard.h" -#if defined(RGB_MATRIX_IS31FL3218) -# include "is31fl3218.h" -#elif defined(RGB_MATRIX_IS31FL3731) -# include "is31fl3731.h" -#elif defined(RGB_MATRIX_IS31FL3733) -# include "is31fl3733.h" -#elif defined(RGB_MATRIX_IS31FL3736) -# include "is31fl3736.h" -#elif defined(RGB_MATRIX_IS31FL3737) -# include "is31fl3737.h" -#elif defined(RGB_MATRIX_IS31FL3741) -# include "is31fl3741.h" -#elif defined(IS31FLCOMMON) -# include "is31flcommon.h" -#elif defined(RGB_MATRIX_SNLED27351) -# include "snled27351.h" -#elif defined(RGB_MATRIX_AW20216S) -# include "aw20216s.h" -#elif defined(RGB_MATRIX_WS2812) -# include "ws2812.h" -#endif - #ifndef RGB_MATRIX_TIMEOUT # define RGB_MATRIX_TIMEOUT 0 #endif @@ -99,6 +78,10 @@ # define RGB_MATRIX_DEFAULT_SPD UINT8_MAX / 2 #endif +#ifndef RGB_MATRIX_DEFAULT_FLAGS +# define RGB_MATRIX_DEFAULT_FLAGS LED_FLAG_ALL +#endif + #ifndef RGB_MATRIX_LED_FLUSH_LIMIT # define RGB_MATRIX_LED_FLUSH_LIMIT 16 #endif @@ -272,17 +255,6 @@ void rgb_matrix_set_flags_noeeprom(led_flags_t flags); # define rgblight_decrease_speed_noeeprom rgb_matrix_decrease_speed_noeeprom #endif -typedef struct { - /* Perform any initialisation required for the other driver functions to work. */ - void (*init)(void); - /* Set the colour of a single LED in the buffer. */ - void (*set_color)(int index, uint8_t r, uint8_t g, uint8_t b); - /* Set the colour of all LEDS on the keyboard in the buffer. */ - void (*set_color_all)(uint8_t r, uint8_t g, uint8_t b); - /* Flush any buffered changes to the hardware. */ - void (*flush)(void); -} rgb_matrix_driver_t; - static inline bool rgb_matrix_check_finished_leds(uint8_t led_idx) { #if defined(RGB_MATRIX_SPLIT) if (is_keyboard_left()) { @@ -295,8 +267,6 @@ static inline bool rgb_matrix_check_finished_leds(uint8_t led_idx) { #endif } -extern const rgb_matrix_driver_t rgb_matrix_driver; - extern rgb_config_t rgb_matrix_config; extern uint32_t g_rgb_timer; diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c index 0f979cb233..95d1e884f0 100644 --- a/quantum/rgb_matrix/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix/rgb_matrix_drivers.c @@ -14,7 +14,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "rgb_matrix.h" +#include "rgb_matrix_drivers.h" + +#include <stdbool.h> +#include "keyboard.h" +#include "color.h" #include "util.h" /* Each driver needs to define the struct @@ -32,6 +36,14 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color_all = is31fl3218_set_color_all, }; +#elif defined(RGB_MATRIX_IS31FL3729) +const rgb_matrix_driver_t rgb_matrix_driver = { + .init = is31fl3729_init_drivers, + .flush = is31fl3729_flush, + .set_color = is31fl3729_set_color, + .set_color_all = is31fl3729_set_color_all, +}; + #elif defined(RGB_MATRIX_IS31FL3731) const rgb_matrix_driver_t rgb_matrix_driver = { .init = is31fl3731_init_drivers, @@ -72,12 +84,36 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color_all = is31fl3741_set_color_all, }; -#elif defined(IS31FLCOMMON) +#elif defined(RGB_MATRIX_IS31FL3742A) +const rgb_matrix_driver_t rgb_matrix_driver = { + .init = is31fl3742a_init_drivers, + .flush = is31fl3742a_flush, + .set_color = is31fl3742a_set_color, + .set_color_all = is31fl3742a_set_color_all, +}; + +#elif defined(RGB_MATRIX_IS31FL3743A) +const rgb_matrix_driver_t rgb_matrix_driver = { + .init = is31fl3743a_init_drivers, + .flush = is31fl3743a_flush, + .set_color = is31fl3743a_set_color, + .set_color_all = is31fl3743a_set_color_all, +}; + +#elif defined(RGB_MATRIX_IS31FL3745) +const rgb_matrix_driver_t rgb_matrix_driver = { + .init = is31fl3745_init_drivers, + .flush = is31fl3745_flush, + .set_color = is31fl3745_set_color, + .set_color_all = is31fl3745_set_color_all, +}; + +#elif defined(RGB_MATRIX_IS31FL3746A) const rgb_matrix_driver_t rgb_matrix_driver = { - .init = IS31FL_RGB_init_drivers, - .flush = IS31FL_common_flush, - .set_color = IS31FL_RGB_set_color, - .set_color_all = IS31FL_RGB_set_color_all, + .init = is31fl3746a_init_drivers, + .flush = is31fl3746a_flush, + .set_color = is31fl3746a_set_color, + .set_color_all = is31fl3746a_set_color_all, }; #elif defined(RGB_MATRIX_SNLED27351) @@ -103,7 +139,7 @@ const rgb_matrix_driver_t rgb_matrix_driver = { # endif // LED color buffer -rgb_led_t rgb_matrix_ws2812_array[RGB_MATRIX_LED_COUNT]; +rgb_led_t rgb_matrix_ws2812_array[WS2812_LED_COUNT]; bool ws2812_dirty = false; static void init(void) { @@ -112,7 +148,7 @@ static void init(void) { static void flush(void) { if (ws2812_dirty) { - ws2812_setleds(rgb_matrix_ws2812_array, RGB_MATRIX_LED_COUNT); + ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_COUNT); ws2812_dirty = false; } } diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.h b/quantum/rgb_matrix/rgb_matrix_drivers.h new file mode 100644 index 0000000000..a24cb03a18 --- /dev/null +++ b/quantum/rgb_matrix/rgb_matrix_drivers.h @@ -0,0 +1,49 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <stdint.h> + +#if defined(RGB_MATRIX_AW20216S) +# include "aw20216s.h" +#elif defined(RGB_MATRIX_IS31FL3218) +# include "is31fl3218.h" +#elif defined(RGB_MATRIX_IS31FL3729) +# include "is31fl3729.h" +#elif defined(RGB_MATRIX_IS31FL3731) +# include "is31fl3731.h" +#elif defined(RGB_MATRIX_IS31FL3733) +# include "is31fl3733.h" +#elif defined(RGB_MATRIX_IS31FL3736) +# include "is31fl3736.h" +#elif defined(RGB_MATRIX_IS31FL3737) +# include "is31fl3737.h" +#elif defined(RGB_MATRIX_IS31FL3741) +# include "is31fl3741.h" +#elif defined(RGB_MATRIX_IS31FL3742A) +# include "is31fl3742a.h" +#elif defined(RGB_MATRIX_IS31FL3743A) +# include "is31fl3743a.h" +#elif defined(RGB_MATRIX_IS31FL3745) +# include "is31fl3745.h" +#elif defined(RGB_MATRIX_IS31FL3746A) +# include "is31fl3746a.h" +#elif defined(RGB_MATRIX_SNLED27351) +# include "snled27351.h" +#elif defined(RGB_MATRIX_WS2812) +# include "ws2812.h" +#endif + +typedef struct { + /* Perform any initialisation required for the other driver functions to work. */ + void (*init)(void); + /* Set the colour of a single LED in the buffer. */ + void (*set_color)(int index, uint8_t r, uint8_t g, uint8_t b); + /* Set the colour of all LEDS on the keyboard in the buffer. */ + void (*set_color_all)(uint8_t r, uint8_t g, uint8_t b); + /* Flush any buffered changes to the hardware. */ + void (*flush)(void); +} rgb_matrix_driver_t; + +extern const rgb_matrix_driver_t rgb_matrix_driver; diff --git a/quantum/rgblight/rgblight.c b/quantum/rgblight/rgblight.c index 8ac886d441..530cb04688 100644 --- a/quantum/rgblight/rgblight.c +++ b/quantum/rgblight/rgblight.c @@ -116,7 +116,7 @@ animation_status_t animation_status = {}; #endif #ifndef LED_ARRAY -rgb_led_t led[RGBLED_NUM]; +rgb_led_t led[RGBLIGHT_LED_COUNT]; # define LED_ARRAY led #endif @@ -126,7 +126,7 @@ rgblight_segment_t const *const *rgblight_layers = NULL; static bool deferred_set_layer_state = false; #endif -rgblight_ranges_t rgblight_ranges = {0, RGBLED_NUM, 0, RGBLED_NUM, RGBLED_NUM}; +rgblight_ranges_t rgblight_ranges = {0, RGBLIGHT_LED_COUNT, 0, RGBLIGHT_LED_COUNT, RGBLIGHT_LED_COUNT}; void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) { rgblight_ranges.clipping_start_pos = start_pos; @@ -134,8 +134,8 @@ void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) { } void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) { - if (start_pos >= RGBLED_NUM) return; - if (start_pos + num_leds > RGBLED_NUM) return; + if (start_pos >= RGBLIGHT_LED_COUNT) return; + if (start_pos + num_leds > RGBLIGHT_LED_COUNT) return; rgblight_ranges.effect_start_pos = start_pos; rgblight_ranges.effect_end_pos = start_pos + num_leds; rgblight_ranges.effect_num_leds = num_leds; @@ -229,13 +229,7 @@ void rgblight_init(void) { return; } - dprintf("rgblight_init called.\n"); dprintf("rgblight_init start!\n"); - if (!eeconfig_is_enabled()) { - dprintf("rgblight_init eeconfig is not enabled.\n"); - eeconfig_init(); - eeconfig_update_rgblight_default(); - } rgblight_config.raw = eeconfig_read_rgblight(); RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; if (!rgblight_config.mode) { @@ -664,7 +658,7 @@ void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) { } void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) { - if (!rgblight_config.enable || index >= RGBLED_NUM) { + if (!rgblight_config.enable || index >= RGBLIGHT_LED_COUNT) { return; } @@ -700,7 +694,7 @@ static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_ #endif void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end) { - if (!rgblight_config.enable || start < 0 || start >= end || end > RGBLED_NUM) { + if (!rgblight_config.enable || start < 0 || start >= end || end > RGBLIGHT_LED_COUNT) { return; } @@ -727,19 +721,19 @@ void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, #ifndef RGBLIGHT_SPLIT void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b) { - rgblight_setrgb_range(r, g, b, 0, (uint8_t)RGBLED_NUM / 2); + rgblight_setrgb_range(r, g, b, 0, (uint8_t)RGBLIGHT_LED_COUNT / 2); } void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b) { - rgblight_setrgb_range(r, g, b, (uint8_t)RGBLED_NUM / 2, (uint8_t)RGBLED_NUM); + rgblight_setrgb_range(r, g, b, (uint8_t)RGBLIGHT_LED_COUNT / 2, (uint8_t)RGBLIGHT_LED_COUNT); } void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) { - rgblight_sethsv_range(hue, sat, val, 0, (uint8_t)RGBLED_NUM / 2); + rgblight_sethsv_range(hue, sat, val, 0, (uint8_t)RGBLIGHT_LED_COUNT / 2); } void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) { - rgblight_sethsv_range(hue, sat, val, (uint8_t)RGBLED_NUM / 2, (uint8_t)RGBLED_NUM); + rgblight_sethsv_range(hue, sat, val, (uint8_t)RGBLIGHT_LED_COUNT / 2, (uint8_t)RGBLIGHT_LED_COUNT); } #endif // ifndef RGBLIGHT_SPLIT @@ -789,7 +783,7 @@ static void rgblight_layers_write(void) { break; // No more segments } // Write segment.count LEDs - rgb_led_t *const limit = &led[MIN(segment.index + segment.count, RGBLED_NUM)]; + rgb_led_t *const limit = &led[MIN(segment.index + segment.count, RGBLIGHT_LED_COUNT)]; for (rgb_led_t *led_ptr = &led[segment.index]; led_ptr < limit; led_ptr++) { # ifdef RGBLIGHT_LAYERS_RETAIN_VAL sethsv(segment.hue, segment.sat, current_val, led_ptr); @@ -900,12 +894,6 @@ void rgblight_wakeup(void) { #endif -__attribute__((weak)) void rgblight_call_driver(rgb_led_t *start_led, uint8_t num_leds) { - ws2812_setleds(start_led, num_leds); -} - -#ifndef RGBLIGHT_CUSTOM - void rgblight_set(void) { rgb_led_t *start_led; uint8_t num_leds = rgblight_ranges.clipping_num_leds; @@ -915,42 +903,41 @@ void rgblight_set(void) { led[i].r = 0; led[i].g = 0; led[i].b = 0; -# ifdef RGBW +#ifdef RGBW led[i].w = 0; -# endif +#endif } } -# ifdef RGBLIGHT_LAYERS +#ifdef RGBLIGHT_LAYERS if (rgblight_layers != NULL -# if !defined(RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF) +# if !defined(RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF) && rgblight_config.enable -# elif defined(RGBLIGHT_SLEEP) +# elif defined(RGBLIGHT_SLEEP) && !is_suspended -# endif +# endif ) { rgblight_layers_write(); } -# endif +#endif -# ifdef RGBLIGHT_LED_MAP - rgb_led_t led0[RGBLED_NUM]; - for (uint8_t i = 0; i < RGBLED_NUM; i++) { +#ifdef RGBLIGHT_LED_MAP + rgb_led_t led0[RGBLIGHT_LED_COUNT]; + for (uint8_t i = 0; i < RGBLIGHT_LED_COUNT; i++) { led0[i] = led[pgm_read_byte(&led_map[i])]; } start_led = led0 + rgblight_ranges.clipping_start_pos; -# else +#else start_led = led + rgblight_ranges.clipping_start_pos; -# endif +#endif -# ifdef RGBW +#ifdef RGBW for (uint8_t i = 0; i < num_leds; i++) { convert_rgb_to_rgbw(&start_led[i]); } -# endif - rgblight_call_driver(start_led, num_leds); -} #endif + rgblight_driver.setleds(start_led, num_leds); +} #ifdef RGBLIGHT_SPLIT /* for split keyboard master side */ @@ -1279,8 +1266,8 @@ void rgblight_effect_snake(animation_status_t *anim) { # endif for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) { k = pos + j * increment; - if (k > RGBLED_NUM) { - k = k % (RGBLED_NUM); + if (k > RGBLIGHT_LED_COUNT) { + k = k % (RGBLIGHT_LED_COUNT); } if (k < 0) { k = k + rgblight_ranges.effect_num_leds; @@ -1465,7 +1452,7 @@ typedef struct PACKED { uint8_t max_life; } TwinkleState; -static TwinkleState led_twinkle_state[RGBLED_NUM]; +static TwinkleState led_twinkle_state[RGBLIGHT_LED_COUNT]; void rgblight_effect_twinkle(animation_status_t *anim) { const bool random_color = anim->delta / 3; diff --git a/quantum/rgblight/rgblight.h b/quantum/rgblight/rgblight.h index a222ab6b9f..9e2b073776 100644 --- a/quantum/rgblight/rgblight.h +++ b/quantum/rgblight/rgblight.h @@ -16,6 +16,12 @@ #pragma once +// DEPRECATED DEFINES - DO NOT USE +#if defined(RGBLED_NUM) +# define RGBLIGHT_LED_COUNT RGBLED_NUM +#endif +// ======== + /***** rgblight_mode(mode)/rgblight_mode_noeeprom(mode) **** old mode number (before 0.6.117) to new mode name table @@ -160,6 +166,7 @@ enum RGBLIGHT_EFFECT_MODE { #include <stdint.h> #include <stdbool.h> +#include "rgblight_drivers.h" #include "progmem.h" #include "eeconfig.h" #include "ws2812.h" @@ -233,7 +240,7 @@ void rgblight_unblink_all_but_layer(uint8_t layer); #endif -extern rgb_led_t led[RGBLED_NUM]; +extern rgb_led_t led[RGBLIGHT_LED_COUNT]; extern const uint8_t RGBLED_BREATHING_INTERVALS[4] PROGMEM; extern const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[3] PROGMEM; diff --git a/quantum/rgblight/rgblight_drivers.c b/quantum/rgblight/rgblight_drivers.c new file mode 100644 index 0000000000..45b60e1a5f --- /dev/null +++ b/quantum/rgblight/rgblight_drivers.c @@ -0,0 +1,20 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rgblight_drivers.h" + +#if defined(RGBLIGHT_WS2812) +# include "ws2812.h" + +const rgblight_driver_t rgblight_driver = { + .setleds = ws2812_setleds, +}; + +#elif defined(RGBLIGHT_APA102) +# include "apa102.h" + +const rgblight_driver_t rgblight_driver = { + .setleds = apa102_setleds, +}; + +#endif diff --git a/quantum/rgblight/rgblight_drivers.h b/quantum/rgblight/rgblight_drivers.h new file mode 100644 index 0000000000..f7125a6f3d --- /dev/null +++ b/quantum/rgblight/rgblight_drivers.h @@ -0,0 +1,13 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <stdint.h> +#include "color.h" + +typedef struct { + void (*setleds)(rgb_led_t *ledarray, uint16_t number_of_leds); +} rgblight_driver_t; + +extern const rgblight_driver_t rgblight_driver; diff --git a/quantum/send_string/send_string.c b/quantum/send_string/send_string.c index 820fc25163..8b59c19219 100644 --- a/quantum/send_string/send_string.c +++ b/quantum/send_string/send_string.c @@ -147,7 +147,7 @@ __attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = { #define PGM_LOADBIT(mem, pos) ((pgm_read_byte(&((mem)[(pos) / 8])) >> ((pos) % 8)) & 0x01) void send_string(const char *string) { - send_string_with_delay(string, 0); + send_string_with_delay(string, TAP_CODE_DELAY); } void send_string_with_delay(const char *string, uint8_t interval) { @@ -156,6 +156,7 @@ void send_string_with_delay(const char *string, uint8_t interval) { if (!ascii_code) break; if (ascii_code == SS_QMK_PREFIX) { ascii_code = *(++string); + if (ascii_code == SS_TAP_CODE) { // tap uint8_t keycode = *(++string); @@ -172,28 +173,30 @@ void send_string_with_delay(const char *string, uint8_t interval) { // delay int ms = 0; uint8_t keycode = *(++string); + while (isdigit(keycode)) { ms *= 10; ms += keycode - '0'; keycode = *(++string); } - while (ms--) - wait_ms(1); + + wait_ms(ms); } + + wait_ms(interval); } else { - send_char(ascii_code); + send_char_with_delay(ascii_code, interval); } + ++string; - // interval - { - uint8_t ms = interval; - while (ms--) - wait_ms(1); - } } } void send_char(char ascii_code) { + send_char_with_delay(ascii_code, TAP_CODE_DELAY); +} + +void send_char_with_delay(char ascii_code, uint8_t interval) { #if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL) if (ascii_code == '\a') { // BEL PLAY_SONG(bell_song); @@ -208,19 +211,30 @@ void send_char(char ascii_code) { if (is_shifted) { register_code(KC_LEFT_SHIFT); + wait_ms(interval); } + if (is_altgred) { register_code(KC_RIGHT_ALT); + wait_ms(interval); } - tap_code(keycode); + + tap_code_delay(keycode, interval); + wait_ms(interval); + if (is_altgred) { unregister_code(KC_RIGHT_ALT); + wait_ms(interval); } + if (is_shifted) { unregister_code(KC_LEFT_SHIFT); + wait_ms(interval); } + if (is_dead) { tap_code(KC_SPACE); + wait_ms(interval); } } diff --git a/quantum/send_string/send_string.h b/quantum/send_string/send_string.h index dbaed43ebc..f727ec507d 100644 --- a/quantum/send_string/send_string.h +++ b/quantum/send_string/send_string.h @@ -49,7 +49,7 @@ extern const uint8_t ascii_to_keycode_lut[128]; /** * \brief Type out a string of ASCII characters. * - * This function simply calls `send_string_with_delay(string, 0)`. + * This function simply calls `send_string_with_delay(string, TAP_CODE_DELAY)`. * * Most keycodes from the basic keycode range are also supported by way of a special sequence - see `send_string_keycodes.h`. * @@ -61,18 +61,28 @@ void send_string(const char *string); * \brief Type out a string of ASCII characters, with a delay between each character. * * \param string The string to type out. - * \param interval The amount of time, in milliseconds, to wait before typing the next character. + * \param interval The amount of time, in milliseconds, to wait before typing the next character. Note this can be set to 0 to ensure no delay, regardless of what TAP_CODE_DELAY is set to. */ void send_string_with_delay(const char *string, uint8_t interval); /** * \brief Type out an ASCII character. * + * This function simply calls `send_char_with_delay(string, TAP_CODE_DELAY)`. + * * \param ascii_code The character to type. */ void send_char(char ascii_code); /** + * \brief Type out an ASCII character, with a delay between any modifiers. + * + * \param ascii_code The character to type. + * \param interval The amount of time, in milliseconds, to wait in between key presses. Note this can be set to 0 to ensure no delay, regardless of what TAP_CODE_DELAY is set to. + */ +void send_char_with_delay(char ascii_code, uint8_t interval); + +/** * \brief Type out an eight digit (unsigned 32-bit) hexadecimal value. * * The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`. diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 874339361d..2f592bd4cf 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -147,10 +147,10 @@ __attribute__((weak)) bool is_keyboard_left_impl(void) { return readPin(SPLIT_HAND_PIN); # endif #elif defined(SPLIT_HAND_MATRIX_GRID) -# ifdef SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT - return peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID); -# else +# ifdef SPLIT_HAND_MATRIX_GRID_LOW_IS_LEFT return !peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID); +# else + return peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID); # endif #elif defined(EE_HANDS) if (!eeconfig_is_enabled()) { diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index aade3c98d7..83edc34859 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -56,7 +56,7 @@ i2c_status_t transport_trigger_callback(int8_t id) { // Kick off the "callback executor", now that data has been written to the slave split_shmem->transaction_id = id; split_transaction_desc_t *trans = &split_transaction_table[I2C_EXECUTE_CALLBACK]; - return i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, SLAVE_I2C_TIMEOUT); + return i2c_write_register(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, SLAVE_I2C_TIMEOUT); } bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) { @@ -65,7 +65,7 @@ bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, if (initiator2target_length > 0) { size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length; memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len); - if ((status = i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { + if ((status = i2c_write_register(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { return false; } } @@ -77,7 +77,7 @@ bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, if (target2initiator_length > 0) { size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length; - if ((status = i2c_readReg(SLAVE_I2C_ADDRESS, trans->target2initiator_offset, split_trans_target2initiator_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { + if ((status = i2c_read_register(SLAVE_I2C_ADDRESS, trans->target2initiator_offset, split_trans_target2initiator_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { return false; } memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len); |