summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
authorNick Brassel <nick@tzarc.org>2023-11-28 16:39:48 +1100
committerNick Brassel <nick@tzarc.org>2023-11-28 16:40:47 +1100
commit0115951de12bd4c798a43a380651c34552552e85 (patch)
tree62999011ae782d93aa6dc9c889615db2a840cafc /quantum
parent0379d1f59e58cefa18cdb72ba1b77507d1108ae6 (diff)
parent4d99e0a23cff02f4c6e55e093b5de08a9be0df7c (diff)
`develop` -> `master`, 2023q4 edition
Diffstat (limited to 'quantum')
-rw-r--r--quantum/action.c6
-rw-r--r--quantum/action_tapping.c78
-rw-r--r--quantum/action_util.c57
-rw-r--r--quantum/action_util.h9
-rw-r--r--quantum/backlight/backlight.c21
-rw-r--r--quantum/color.c2
-rw-r--r--quantum/color.h52
-rw-r--r--quantum/command.c5
-rw-r--r--quantum/debounce/none.c10
-rw-r--r--quantum/debounce/sym_defer_g.c15
-rw-r--r--quantum/debounce/sym_eager_pr.c4
-rw-r--r--quantum/debounce/tests/asym_eager_defer_pk_tests.cpp29
-rw-r--r--quantum/debounce/tests/debounce_test_common.cpp25
-rw-r--r--quantum/debounce/tests/debounce_test_common.h5
-rw-r--r--quantum/debounce/tests/none_tests.cpp256
-rw-r--r--quantum/debounce/tests/rules.mk5
-rw-r--r--quantum/debounce/tests/sym_defer_g_tests.cpp18
-rw-r--r--quantum/debounce/tests/sym_defer_pk_tests.cpp18
-rw-r--r--quantum/debounce/tests/sym_defer_pr_tests.cpp18
-rw-r--r--quantum/debounce/tests/sym_eager_pk_tests.cpp18
-rw-r--r--quantum/debounce/tests/sym_eager_pr_tests.cpp18
-rw-r--r--quantum/debounce/tests/testlist.mk1
-rw-r--r--quantum/eeconfig.c6
-rw-r--r--quantum/eeconfig.h3
-rw-r--r--quantum/haptic.c12
-rw-r--r--quantum/keyboard.c23
-rw-r--r--quantum/keycodes.h22
-rw-r--r--quantum/keymap_common.c10
-rw-r--r--quantum/keymap_extras/keymap_russian_typewriter.h93
-rw-r--r--quantum/keymap_extras/keymap_steno.h119
-rw-r--r--quantum/led_matrix/led_matrix.c77
-rw-r--r--quantum/led_matrix/led_matrix.h103
-rw-r--r--quantum/led_matrix/led_matrix_drivers.c249
-rw-r--r--quantum/led_matrix/led_matrix_types.h15
-rw-r--r--quantum/mousekey.c15
-rw-r--r--quantum/painter/lvgl/qp_lvgl.c11
-rw-r--r--quantum/painter/lvgl/qp_lvgl.h4
-rw-r--r--quantum/painter/qff.c8
-rw-r--r--quantum/painter/qff.h2
-rw-r--r--quantum/painter/qgf.c39
-rw-r--r--quantum/painter/qgf.h6
-rw-r--r--quantum/painter/qp.c123
-rw-r--r--quantum/painter/qp.h41
-rw-r--r--quantum/painter/qp_draw_ellipse.c12
-rw-r--r--quantum/painter/qp_draw_image.c9
-rw-r--r--quantum/painter/qp_draw_text.c3
-rw-r--r--quantum/painter/qp_internal.c1
-rw-r--r--quantum/painter/qp_internal_formats.h4
-rw-r--r--quantum/painter/rules.mk86
-rw-r--r--quantum/pointing_device/pointing_device.h3
-rw-r--r--quantum/pointing_device/pointing_device_drivers.c113
-rw-r--r--quantum/process_keycode/process_auto_shift.c29
-rw-r--r--quantum/process_keycode/process_auto_shift.h1
-rw-r--r--quantum/process_keycode/process_clicky.c2
-rw-r--r--quantum/process_keycode/process_steno.c1
-rw-r--r--quantum/process_keycode/process_steno.h1
-rw-r--r--quantum/quantum.c35
-rw-r--r--quantum/quantum.h10
-rw-r--r--quantum/rgb_matrix/animations/flower_blooming_anim.h53
-rw-r--r--quantum/rgb_matrix/animations/rgb_matrix_effects.inc5
-rw-r--r--quantum/rgb_matrix/animations/riverflow_anim.h22
-rw-r--r--quantum/rgb_matrix/animations/starlight_anim.h30
-rw-r--r--quantum/rgb_matrix/animations/starlight_dual_hue_anim.h31
-rw-r--r--quantum/rgb_matrix/animations/starlight_dual_sat_anim.h31
-rw-r--r--quantum/rgb_matrix/rgb_matrix.c87
-rw-r--r--quantum/rgb_matrix/rgb_matrix.h120
-rw-r--r--quantum/rgb_matrix/rgb_matrix_drivers.c412
-rw-r--r--quantum/rgb_matrix/rgb_matrix_types.h15
-rw-r--r--quantum/rgblight/rgblight.c137
-rw-r--r--quantum/rgblight/rgblight.h27
-rw-r--r--quantum/split_common/split_util.c73
-rw-r--r--quantum/steno_keycodes.h119
-rw-r--r--quantum/util.h8
-rw-r--r--quantum/velocikey.c40
-rw-r--r--quantum/velocikey.h10
-rw-r--r--quantum/via.c10
76 files changed, 1894 insertions, 1297 deletions
diff --git a/quantum/action.c b/quantum/action.c
index 6368f7398c..29822c39e9 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -374,7 +374,7 @@ void process_action(keyrecord_t *record, action_t action) {
if (is_oneshot_layer_active() && event.pressed &&
(action.kind.id == ACT_USAGE || !(IS_MODIFIER_KEYCODE(action.key.code)
# ifndef NO_ACTION_TAPPING
- || (tap_count == 0 && (action.kind.id == ACT_LMODS_TAP || action.kind.id == ACT_RMODS_TAP))
+ || ((action.kind.id == ACT_LMODS_TAP || action.kind.id == ACT_RMODS_TAP) && (action.layer_tap.code <= MODS_TAP_TOGGLE || tap_count == 0))
# endif
))
# ifdef SWAP_HANDS_ENABLE
@@ -497,7 +497,7 @@ void process_action(keyrecord_t *record, action_t action) {
default:
if (event.pressed) {
if (tap_count > 0) {
-# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
+# ifdef HOLD_ON_OTHER_KEY_PRESS
if (
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
get_hold_on_other_key_press(get_event_keycode(record->event, false), record) &&
@@ -925,7 +925,7 @@ __attribute__((weak)) void register_code(uint8_t code) {
// Force a new key press if the key is already pressed
// without this, keys with the same keycode, but different
// modifiers will be reported incorrectly, see issue #1708
- if (is_key_pressed(keyboard_report, code)) {
+ if (is_key_pressed(code)) {
del_key(code);
send_keyboard_report();
}
diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
index f94e5e6f69..8f238490f2 100644
--- a/quantum/action_tapping.c
+++ b/quantum/action_tapping.c
@@ -116,25 +116,26 @@ void action_tapping_process(keyrecord_t record) {
* readable. The conditional definition of tapping_keycode and all the
* conditional uses of it are hidden inside macros named TAP_...
*/
-# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
-# define TAP_DEFINE_KEYCODE const uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
-# else
-# define TAP_DEFINE_KEYCODE
-# endif
+# define TAP_DEFINE_KEYCODE const uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
# ifdef RETRO_TAPPING_PER_KEY
-# define TAP_GET_RETRO_TAPPING get_retro_tapping(tapping_keycode, &tapping_key)
+# define TAP_GET_RETRO_TAPPING(keyp) get_auto_shifted_key(tapping_keycode, keyp) && get_retro_tapping(tapping_keycode, &tapping_key)
# else
-# define TAP_GET_RETRO_TAPPING true
+# define TAP_GET_RETRO_TAPPING(keyp) get_auto_shifted_key(tapping_keycode, keyp)
# endif
-# define MAYBE_RETRO_SHIFTING(ev) (TAP_GET_RETRO_TAPPING && (RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16((ev).time, tapping_key.event.time) < (RETRO_SHIFT + 0))
+/* Used to extend TAPPING_TERM:
+ * indefinitely if RETRO_SHIFT does not have a value
+ * to RETRO_SHIFT if RETRO_SHIFT is set
+ * for possibly retro shifted keys.
+ */
+# define MAYBE_RETRO_SHIFTING(ev, keyp) (get_auto_shifted_key(tapping_keycode, keyp) && TAP_GET_RETRO_TAPPING(keyp) && ((RETRO_SHIFT + 0) == 0 || TIMER_DIFF_16((ev).time, tapping_key.event.time) < (RETRO_SHIFT + 0)))
# define TAP_IS_LT IS_QK_LAYER_TAP(tapping_keycode)
# define TAP_IS_MT IS_QK_MOD_TAP(tapping_keycode)
# define TAP_IS_RETRO IS_RETRO(tapping_keycode)
# else
-# define TAP_GET_RETRO_TAPPING false
-# define MAYBE_RETRO_SHIFTING(ev) false
+# define TAP_GET_RETRO_TAPPING(keyp) false
+# define MAYBE_RETRO_SHIFTING(ev, kp) false
# define TAP_IS_LT false
# define TAP_IS_MT false
# define TAP_IS_RETRO false
@@ -187,20 +188,19 @@ bool process_tapping(keyrecord_t *keyp) {
return true;
}
+# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
TAP_DEFINE_KEYCODE;
+# endif
// process "pressed" tapping key state
if (tapping_key.event.pressed) {
- if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event)) {
+ if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) {
if (IS_NOEVENT(event)) {
// early return for tick events
return true;
}
if (tapping_key.tap.count == 0) {
if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
-# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
- retroshift_swap_times();
-# endif
// first tap!
ac_dprintf("Tapping: First tap(0->1).\n");
tapping_key.tap.count = 1;
@@ -218,28 +218,12 @@ bool process_tapping(keyrecord_t *keyp) {
*/
// clang-format off
else if (
+ !event.pressed && waiting_buffer_typed(event) &&
(
- !event.pressed && waiting_buffer_typed(event) &&
- TAP_GET_PERMISSIVE_HOLD
- )
- // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
- // unnecessarily and fixes them for Layer Taps.
- || (TAP_GET_RETRO_TAPPING &&
- (
- // Rolled over the two keys.
- (tapping_key.tap.interrupted == true && (
- (TAP_IS_LT && TAP_GET_HOLD_ON_OTHER_KEY_PRESS) ||
- (TAP_IS_MT && TAP_GET_HOLD_ON_OTHER_KEY_PRESS)
- )
- )
- // Makes Retro Shift ignore the default behavior of
- // MTs and LTs on nested taps below TAPPING_TERM or RETRO_SHIFT
- || (
- TAP_IS_RETRO
- && (event.key.col != tapping_key.event.key.col || event.key.row != tapping_key.event.key.row)
- && !event.pressed && waiting_buffer_typed(event)
- )
- )
+ TAP_GET_PERMISSIVE_HOLD ||
+ // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
+ // unnecessarily and fixes them for Layer Taps.
+ TAP_GET_RETRO_TAPPING(keyp)
)
) {
// clang-format on
@@ -284,10 +268,16 @@ bool process_tapping(keyrecord_t *keyp) {
process_record(keyp);
return true;
} else {
- // set interrupted flag when other key preesed during tapping
+ // set interrupted flag when other key pressed during tapping
if (event.pressed) {
tapping_key.tap.interrupted = true;
- if (TAP_GET_HOLD_ON_OTHER_KEY_PRESS) {
+ if (TAP_GET_HOLD_ON_OTHER_KEY_PRESS
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ // Auto Shift cannot evaluate this early
+ // Retro Shift uses the hold action for all nested taps even without HOLD_ON_OTHER_KEY_PRESS, so this is fine to skip
+ && !(MAYBE_RETRO_SHIFTING(event, keyp) && get_auto_shifted_key(get_record_keycode(keyp, false), keyp))
+# endif
+ ) {
ac_dprintf("Tapping: End. No tap. Interfered by pressed key\n");
process_record(&tapping_key);
tapping_key = (keyrecord_t){0};
@@ -332,6 +322,9 @@ bool process_tapping(keyrecord_t *keyp) {
return true;
} else {
ac_dprintf("Tapping: key event while last tap(>0).\n");
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ retroshift_swap_times();
+# endif
process_record(keyp);
return true;
}
@@ -388,7 +381,7 @@ bool process_tapping(keyrecord_t *keyp) {
}
// process "released" tapping key state
else {
- if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event)) {
+ if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) {
if (IS_NOEVENT(event)) {
// early return for tick events
return true;
@@ -506,9 +499,16 @@ void waiting_buffer_scan_tap(void) {
return;
}
+# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
+ TAP_DEFINE_KEYCODE;
+# endif
for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
keyrecord_t *candidate = &waiting_buffer[i];
- if (IS_EVENT(candidate->event) && KEYEQ(candidate->event.key, tapping_key.event.key) && !candidate->event.pressed && WITHIN_TAPPING_TERM(candidate->event)) {
+ // clang-format off
+ if (IS_EVENT(candidate->event) && KEYEQ(candidate->event.key, tapping_key.event.key) && !candidate->event.pressed && (
+ WITHIN_TAPPING_TERM(waiting_buffer[i].event) || MAYBE_RETRO_SHIFTING(waiting_buffer[i].event, &tapping_key)
+ )) {
+ // clang-format on
tapping_key.tap.count = 1;
candidate->tap.count = 1;
process_record(&tapping_key);
diff --git a/quantum/action_util.c b/quantum/action_util.c
index 909dea0595..52171b5050 100644
--- a/quantum/action_util.c
+++ b/quantum/action_util.c
@@ -35,6 +35,9 @@ static uint8_t suppressed_mods = 0;
// TODO: pointer variable is not needed
// report_keyboard_t keyboard_report = {};
report_keyboard_t *keyboard_report = &(report_keyboard_t){};
+#ifdef NKRO_ENABLE
+report_nkro_t *nkro_report = &(report_nkro_t){};
+#endif
extern inline void add_key(uint8_t key);
extern inline void del_key(uint8_t key);
@@ -252,13 +255,8 @@ bool is_oneshot_enabled(void) {
#endif
-/** \brief Send keyboard report
- *
- * FIXME: needs doc
- */
-void send_keyboard_report(void) {
- keyboard_report->mods = real_mods;
- keyboard_report->mods |= weak_mods;
+static uint8_t get_mods_for_report(void) {
+ uint8_t mods = real_mods | weak_mods;
#ifndef NO_ACTION_ONESHOT
if (oneshot_mods) {
@@ -268,20 +266,25 @@ void send_keyboard_report(void) {
clear_oneshot_mods();
}
# endif
- keyboard_report->mods |= oneshot_mods;
- if (has_anykey(keyboard_report)) {
+ mods |= oneshot_mods;
+ if (has_anykey()) {
clear_oneshot_mods();
}
}
-
#endif
#ifdef KEY_OVERRIDE_ENABLE
// These need to be last to be able to properly control key overrides
- keyboard_report->mods &= ~suppressed_mods;
- keyboard_report->mods |= weak_override_mods;
+ mods &= ~suppressed_mods;
+ mods |= weak_override_mods;
#endif
+ return mods;
+}
+
+void send_6kro_report(void) {
+ keyboard_report->mods = get_mods_for_report();
+
#ifdef PROTOCOL_VUSB
host_keyboard_send(keyboard_report);
#else
@@ -295,6 +298,36 @@ void send_keyboard_report(void) {
#endif
}
+#ifdef NKRO_ENABLE
+void send_nkro_report(void) {
+ nkro_report->mods = get_mods_for_report();
+
+ static report_nkro_t last_report;
+
+ /* Only send the report if there are changes to propagate to the host. */
+ if (memcmp(nkro_report, &last_report, sizeof(report_nkro_t)) != 0) {
+ memcpy(&last_report, nkro_report, sizeof(report_nkro_t));
+ host_nkro_send(nkro_report);
+ }
+}
+#endif
+
+/** \brief Send keyboard report
+ *
+ * FIXME: needs doc
+ */
+void send_keyboard_report(void) {
+#ifdef NKRO_ENABLE
+ if (keyboard_protocol && keymap_config.nkro) {
+ send_nkro_report();
+ } else {
+ send_6kro_report();
+ }
+#else
+ send_6kro_report();
+#endif
+}
+
/** \brief Get mods
*
* FIXME: needs doc
diff --git a/quantum/action_util.h b/quantum/action_util.h
index 831caf3c0a..d2ecb145be 100644
--- a/quantum/action_util.h
+++ b/quantum/action_util.h
@@ -26,20 +26,23 @@ extern "C" {
#endif
extern report_keyboard_t *keyboard_report;
+#ifdef NKRO_ENABLE
+extern report_nkro_t *nkro_report;
+#endif
void send_keyboard_report(void);
/* key */
inline void add_key(uint8_t key) {
- add_key_to_report(keyboard_report, key);
+ add_key_to_report(key);
}
inline void del_key(uint8_t key) {
- del_key_from_report(keyboard_report, key);
+ del_key_from_report(key);
}
inline void clear_keys(void) {
- clear_keys_from_report(keyboard_report);
+ clear_keys_from_report();
}
/* modifier */
diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c
index 9d9f944f5d..e89b34696c 100644
--- a/quantum/backlight/backlight.c
+++ b/quantum/backlight/backlight.c
@@ -22,10 +22,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
backlight_config_t backlight_config;
+#ifndef BACKLIGHT_DEFAULT_ON
+# define BACKLIGHT_DEFAULT_ON true
+#endif
+
#ifndef BACKLIGHT_DEFAULT_LEVEL
# define BACKLIGHT_DEFAULT_LEVEL BACKLIGHT_LEVELS
#endif
+#ifndef BACKLIGHT_DEFAULT_BREATHING
+# define BACKLIGHT_DEFAULT_BREATHING false
+#else
+# undef BACKLIGHT_DEFAULT_BREATHING
+# define BACKLIGHT_DEFAULT_BREATHING true
+#endif
+
#ifdef BACKLIGHT_BREATHING
// TODO: migrate to backlight_config_t
static uint8_t breathing_period = BREATHING_PERIOD;
@@ -172,13 +183,9 @@ void eeconfig_update_backlight_current(void) {
}
void eeconfig_update_backlight_default(void) {
- backlight_config.enable = 1;
-#ifdef BACKLIGHT_DEFAULT_BREATHING
- backlight_config.breathing = 1;
-#else
- backlight_config.breathing = 0;
-#endif
- backlight_config.level = BACKLIGHT_DEFAULT_LEVEL;
+ backlight_config.enable = BACKLIGHT_DEFAULT_ON;
+ backlight_config.breathing = BACKLIGHT_DEFAULT_BREATHING;
+ backlight_config.level = BACKLIGHT_DEFAULT_LEVEL;
eeconfig_update_backlight(backlight_config.raw);
}
diff --git a/quantum/color.c b/quantum/color.c
index 767155c9db..395383f428 100644
--- a/quantum/color.c
+++ b/quantum/color.c
@@ -110,7 +110,7 @@ RGB hsv_to_rgb_nocie(HSV hsv) {
}
#ifdef RGBW
-void convert_rgb_to_rgbw(LED_TYPE *led) {
+void convert_rgb_to_rgbw(rgb_led_t *led) {
// Determine lowest value in all three colors, put that into
// the white channel and then shift all colors by that amount
led->w = MIN(led->r, MIN(led->g, led->b));
diff --git a/quantum/color.h b/quantum/color.h
index 135ad623b5..00a3bfb3f8 100644
--- a/quantum/color.h
+++ b/quantum/color.h
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "util.h"
// clang-format off
@@ -73,22 +74,6 @@
// clang-format on
-#if defined(__GNUC__)
-# define PACKED __attribute__((__packed__))
-#else
-# define PACKED
-#endif
-
-#if defined(_MSC_VER)
-# pragma pack(push, 1)
-#endif
-
-#ifdef RGBW
-# define LED_TYPE cRGBW
-#else
-# define LED_TYPE RGB
-#endif
-
#define WS2812_BYTE_ORDER_RGB 0
#define WS2812_BYTE_ORDER_GRB 1
#define WS2812_BYTE_ORDER_BGR 2
@@ -97,26 +82,7 @@
# define WS2812_BYTE_ORDER WS2812_BYTE_ORDER_GRB
#endif
-typedef struct PACKED {
-#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
- uint8_t g;
- uint8_t r;
- uint8_t b;
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
- uint8_t r;
- uint8_t g;
- uint8_t b;
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
- uint8_t b;
- uint8_t g;
- uint8_t r;
-#endif
-} cRGB;
-
-typedef cRGB RGB;
-
-// WS2812 specific layout
-typedef struct PACKED {
+typedef struct PACKED rgb_led_t {
#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
uint8_t g;
uint8_t r;
@@ -130,21 +96,21 @@ typedef struct PACKED {
uint8_t g;
uint8_t r;
#endif
+#ifdef RGBW
uint8_t w;
-} cRGBW;
+#endif
+} rgb_led_t;
-typedef struct PACKED {
+typedef rgb_led_t RGB;
+
+typedef struct PACKED HSV {
uint8_t h;
uint8_t s;
uint8_t v;
} HSV;
-#if defined(_MSC_VER)
-# pragma pack(pop)
-#endif
-
RGB hsv_to_rgb(HSV hsv);
RGB hsv_to_rgb_nocie(HSV hsv);
#ifdef RGBW
-void convert_rgb_to_rgbw(LED_TYPE *led);
+void convert_rgb_to_rgbw(rgb_led_t *led);
#endif
diff --git a/quantum/command.c b/quantum/command.c
index aa64b75064..c188638eb4 100644
--- a/quantum/command.c
+++ b/quantum/command.c
@@ -222,21 +222,16 @@ static void print_status(void) {
"\n\t- Status -\n"
"host_keyboard_leds(): %02X\n"
-#ifndef PROTOCOL_VUSB
"keyboard_protocol: %02X\n"
"keyboard_idle: %02X\n"
-#endif
#ifdef NKRO_ENABLE
"keymap_config.nkro: %02X\n"
#endif
"timer_read32(): %08lX\n"
, host_keyboard_leds()
-#ifndef PROTOCOL_VUSB
- /* these aren't set on the V-USB protocol, so we just ignore them for now */
, keyboard_protocol
, keyboard_idle
-#endif
#ifdef NKRO_ENABLE
, keymap_config.nkro
#endif
diff --git a/quantum/debounce/none.c b/quantum/debounce/none.c
index 1b8b1dc13a..0a8ccfc4ee 100644
--- a/quantum/debounce/none.c
+++ b/quantum/debounce/none.c
@@ -20,9 +20,15 @@
void debounce_init(uint8_t num_rows) {}
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
- bool cooked_changed = memcmp(raw, cooked, sizeof(matrix_row_t) * num_rows) != 0;
+ bool cooked_changed = false;
- memcpy(cooked, raw, sizeof(matrix_row_t) * num_rows);
+ if (changed) {
+ size_t matrix_size = num_rows * sizeof(matrix_row_t);
+ if (memcmp(cooked, raw, matrix_size) != 0) {
+ memcpy(cooked, raw, matrix_size);
+ cooked_changed = true;
+ }
+ }
return cooked_changed;
}
diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c
index 25e18890af..d96758fab3 100644
--- a/quantum/debounce/sym_defer_g.c
+++ b/quantum/debounce/sym_defer_g.c
@@ -24,6 +24,12 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
# define DEBOUNCE 5
#endif
+// Maximum debounce: 255ms
+#if DEBOUNCE > UINT8_MAX
+# undef DEBOUNCE
+# define DEBOUNCE UINT8_MAX
+#endif
+
#if DEBOUNCE > 0
static bool debouncing = false;
static fast_timer_t debouncing_time;
@@ -36,11 +42,10 @@ bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
if (changed) {
debouncing = true;
debouncing_time = timer_read_fast();
- }
-
- if (debouncing && timer_elapsed_fast(debouncing_time) >= DEBOUNCE) {
- if (memcmp(cooked, raw, sizeof(matrix_row_t) * num_rows) != 0) {
- memcpy(cooked, raw, sizeof(matrix_row_t) * num_rows);
+ } else if (debouncing && timer_elapsed_fast(debouncing_time) >= DEBOUNCE) {
+ size_t matrix_size = num_rows * sizeof(matrix_row_t);
+ if (memcmp(cooked, raw, matrix_size) != 0) {
+ memcpy(cooked, raw, matrix_size);
cooked_changed = true;
}
debouncing = false;
diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c
index ccc5d20fa2..6cd9308aff 100644
--- a/quantum/debounce/sym_eager_pr.c
+++ b/quantum/debounce/sym_eager_pr.c
@@ -128,8 +128,8 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
if (existing_row != raw_row) {
if (*debounce_pointer == DEBOUNCE_ELAPSED) {
*debounce_pointer = DEBOUNCE;
- cooked[row] = raw_row;
- cooked_changed |= cooked[row] ^ raw[row];
+ cooked_changed |= cooked[row] ^ raw_row;
+ cooked[row] = raw_row;
counters_need_update = true;
}
}
diff --git a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
index 44b4fe1956..6737f499ab 100644
--- a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
+++ b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
@@ -392,3 +392,32 @@ TEST_F(DebounceTest, OneKeyDelayedScan8) {
time_jumps_ = true;
runEvents();
}
+
+TEST_F(DebounceTest, AsyncTickOneKeyShort1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ /* Release key after 1ms delay */
+ {1, {{0, 1, UP}}, {}},
+
+ /*
+ * Until the eager timer on DOWN is observed to finish, the defer timer
+ * on UP can't start. There's no workaround for this because it's not
+ * possible to debounce an event that isn't being tracked.
+ *
+ * sym_defer_pk has the same problem but the test has to track that the
+ * key changed state so the DOWN timer is always allowed to finish
+ * before starting the UP timer.
+ */
+ {5, {}, {}},
+
+ {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
+ /* Press key again after 1ms delay */
+ {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ });
+ /*
+ * Debounce implementations should never read the timer more than once per invocation
+ */
+ async_time_jumps_ = DEBOUNCE;
+ runEvents();
+}
diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp
index b11378b286..fd4b6f01a6 100644
--- a/quantum/debounce/tests/debounce_test_common.cpp
+++ b/quantum/debounce/tests/debounce_test_common.cpp
@@ -26,8 +26,12 @@ extern "C" {
#include "debounce.h"
#include "timer.h"
-void set_time(uint32_t t);
-void advance_time(uint32_t ms);
+void simulate_async_tick(uint32_t t);
+void reset_access_counter(void);
+uint32_t current_access_counter(void);
+uint32_t timer_read_internal(void);
+void set_time(uint32_t t);
+void advance_time(uint32_t ms);
}
void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) {
@@ -58,6 +62,7 @@ void DebounceTest::runEventsInternal() {
/* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */
debounce_init(MATRIX_ROWS);
set_time(time_offset_);
+ simulate_async_tick(async_time_jumps_);
std::fill(std::begin(input_matrix_), std::end(input_matrix_), 0);
std::fill(std::begin(output_matrix_), std::end(output_matrix_), 0);
@@ -70,9 +75,9 @@ void DebounceTest::runEventsInternal() {
advance_time(1);
} else {
/* Fast forward to the time for this event, calling debounce() with no changes */
- ASSERT_LT((time_offset_ + event.time_) - timer_read_fast(), 60000) << "Test tries to advance more than 1 minute of time";
+ ASSERT_LT((time_offset_ + event.time_) - timer_read_internal(), 60000) << "Test tries to advance more than 1 minute of time";
- while (timer_read_fast() != time_offset_ + event.time_) {
+ while (timer_read_internal() != time_offset_ + event.time_) {
runDebounce(false);
checkCookedMatrix(false, "debounce() modified cooked matrix");
advance_time(1);
@@ -124,14 +129,20 @@ void DebounceTest::runDebounce(bool changed) {
std::copy(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_));
std::copy(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_));
+ reset_access_counter();
+
bool cooked_changed = debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) {
FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime() << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
}
- if (std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_)) && cooked_changed) {
- FAIL() << "Fatal error: debounce() did detect a wrong cooked matrix change at " << strTime() << "\noutput_matrix: cooked_changed=" << cooked_changed << "\n" << strMatrix(output_matrix_) << "\ncooked_matrix:\n" << strMatrix(cooked_matrix_);
+ if (std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_)) == cooked_changed) {
+ FAIL() << "Fatal error: debounce() reported a wrong cooked matrix change result at " << strTime() << "\noutput_matrix: cooked_changed=" << cooked_changed << "\n" << strMatrix(output_matrix_) << "\ncooked_matrix:\n" << strMatrix(cooked_matrix_);
+ }
+
+ if (current_access_counter() > 1) {
+ FAIL() << "Fatal error: debounce() read the timer multiple times, which is not allowed, at " << strTime() << "\ntimer: access_count=" << current_access_counter() << "\noutput_matrix: cooked_changed=" << cooked_changed << "\n" << strMatrix(output_matrix_) << "\ncooked_matrix:\n" << strMatrix(cooked_matrix_);
}
}
@@ -144,7 +155,7 @@ void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_mess
std::string DebounceTest::strTime() {
std::stringstream text;
- text << "time " << (timer_read_fast() - time_offset_) << " (extra_iterations=" << extra_iterations_ << ", auto_advance_time=" << auto_advance_time_ << ")";
+ text << "time " << (timer_read_internal() - time_offset_) << " (extra_iterations=" << extra_iterations_ << ", auto_advance_time=" << auto_advance_time_ << ")";
return text.str();
}
diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h
index 7319abfbf3..ebbe340c05 100644
--- a/quantum/debounce/tests/debounce_test_common.h
+++ b/quantum/debounce/tests/debounce_test_common.h
@@ -54,8 +54,9 @@ class DebounceTest : public ::testing::Test {
void addEvents(std::initializer_list<DebounceTestEvent> events);
void runEvents();
- fast_timer_t time_offset_ = 7777;
- bool time_jumps_ = false;
+ fast_timer_t time_offset_ = 7777;
+ bool time_jumps_ = false;
+ fast_timer_t async_time_jumps_ = 0;
private:
static bool directionValue(Direction direction);
diff --git a/quantum/debounce/tests/none_tests.cpp b/quantum/debounce/tests/none_tests.cpp
new file mode 100644
index 0000000000..69fdd02101
--- /dev/null
+++ b/quantum/debounce/tests/none_tests.cpp
@@ -0,0 +1,256 @@
+/* Copyright 2021 Simon Arlott
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gtest/gtest.h"
+
+#include "debounce_test_common.h"
+
+TEST_F(DebounceTest, OneKeyShort1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ {5, {}, {}},
+ /* 0ms delay (fast scan rate) */
+ {5, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ {10, {}, {}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyShort2) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ {5, {}, {}},
+ /* 1ms delay */
+ {6, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ {11, {}, {}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyShort3) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ {5, {}, {}},
+ /* 2ms delay */
+ {7, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ {12, {}, {}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyTooQuick1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ /* Release key exactly on the debounce time */
+ {5, {{0, 1, UP}}, {{0, 1, UP}}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyTooQuick2) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ {5, {}, {}},
+ {6, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ /* Press key exactly on the debounce time */
+ {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyBouncing1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {1, {{0, 1, UP}}, {{0, 1, UP}}},
+ {2, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {3, {{0, 1, UP}}, {{0, 1, UP}}},
+ {4, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {5, {{0, 1, UP}}, {{0, 1, UP}}},
+ {6, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {11, {{0, 1, UP}}, {{0, 1, UP}}}, /* 5ms after DOWN at time 7 */
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyBouncing2) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {5, {}, {}},
+ {6, {{0, 1, UP}}, {{0, 1, UP}}},
+ {7, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {8, {{0, 1, UP}}, {{0, 1, UP}}},
+ {9, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {10, {{0, 1, UP}}, {{0, 1, UP}}},
+ {15, {}, {}}, /* 5ms after UP at time 10 */
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyLong) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ {5, {}, {}},
+
+ {25, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ {30, {}, {}},
+
+ {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ {55, {}, {}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, TwoKeysShort) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {1, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
+
+ {6, {}, {}},
+
+ {7, {{0, 1, UP}}, {{0, 1, UP}}},
+ {8, {{0, 2, UP}}, {{0, 2, UP}}},
+
+ {13, {}, {}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, TwoKeysSimultaneous1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
+
+ {5, {}, {}},
+ {6, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}},
+
+ {11, {}, {}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, TwoKeysSimultaneous2) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {1, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
+
+ {5, {}, {}},
+ {6, {}, {}},
+ {7, {{0, 1, UP}}, {{0, 1, UP}}},
+ {8, {{0, 2, UP}}, {{0, 2, UP}}},
+
+ {13, {}, {}},
+ });
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyDelayedScan1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ /* Processing is very late */
+ {300, {}, {}},
+ /* Immediately release key */
+ {300, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ {305, {}, {}},
+ });
+ time_jumps_ = true;
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyDelayedScan2) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ /* Processing is very late */
+ {300, {}, {}},
+ /* Release key after 1ms */
+ {301, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ {306, {}, {}},
+ });
+ time_jumps_ = true;
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyDelayedScan3) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ /* Release key before debounce expires */
+ {300, {{0, 1, UP}}, {{0, 1, UP}}},
+ });
+ time_jumps_ = true;
+ runEvents();
+}
+
+TEST_F(DebounceTest, OneKeyDelayedScan4) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ /* Processing is a bit late */
+ {50, {}, {}},
+ /* Release key after 1ms */
+ {51, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ {56, {}, {}},
+ });
+ time_jumps_ = true;
+ runEvents();
+}
+
+TEST_F(DebounceTest, AsyncTickOneKeyShort1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+
+ {5, {}, {}},
+ /* 0ms delay (fast scan rate) */
+ {5, {{0, 1, UP}}, {{0, 1, UP}}},
+
+ {10, {}, {}},
+ });
+ /*
+ * Debounce implementations should never read the timer more than once per invocation
+ */
+ async_time_jumps_ = DEBOUNCE;
+ runEvents();
+}
diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk
index 8318b1c668..bbc362d4c7 100644
--- a/quantum/debounce/tests/rules.mk
+++ b/quantum/debounce/tests/rules.mk
@@ -18,6 +18,11 @@ DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5
DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \
$(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c
+debounce_none_DEFS := $(DEBOUNCE_COMMON_DEFS)
+debounce_none_SRC := $(DEBOUNCE_COMMON_SRC) \
+ $(QUANTUM_PATH)/debounce/none.c \
+ $(QUANTUM_PATH)/debounce/tests/none_tests.cpp
+
debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS)
debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \
$(QUANTUM_PATH)/debounce/sym_defer_g.c \
diff --git a/quantum/debounce/tests/sym_defer_g_tests.cpp b/quantum/debounce/tests/sym_defer_g_tests.cpp
index 73d3d45e30..33e8b17852 100644
--- a/quantum/debounce/tests/sym_defer_g_tests.cpp
+++ b/quantum/debounce/tests/sym_defer_g_tests.cpp
@@ -236,3 +236,21 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
time_jumps_ = true;
runEvents();
}
+
+TEST_F(DebounceTest, AsyncTickOneKeyShort1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {}},
+
+ {5, {}, {{0, 1, DOWN}}},
+ /* 0ms delay (fast scan rate) */
+ {5, {{0, 1, UP}}, {}},
+
+ {10, {}, {{0, 1, UP}}},
+ });
+ /*
+ * Debounce implementations should never read the timer more than once per invocation
+ */
+ async_time_jumps_ = DEBOUNCE;
+ runEvents();
+}
diff --git a/quantum/debounce/tests/sym_defer_pk_tests.cpp b/quantum/debounce/tests/sym_defer_pk_tests.cpp
index 7542c2dad4..864b7afcc4 100644
--- a/quantum/debounce/tests/sym_defer_pk_tests.cpp
+++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp
@@ -238,3 +238,21 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
time_jumps_ = true;
runEvents();
}
+
+TEST_F(DebounceTest, AsyncTickOneKeyShort1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {}},
+
+ {5, {}, {{0, 1, DOWN}}},
+ /* 0ms delay (fast scan rate) */
+ {5, {{0, 1, UP}}, {}},
+
+ {10, {}, {{0, 1, UP}}},
+ });
+ /*
+ * Debounce implementations should never read the timer more than once per invocation
+ */
+ async_time_jumps_ = DEBOUNCE;
+ runEvents();
+}
diff --git a/quantum/debounce/tests/sym_defer_pr_tests.cpp b/quantum/debounce/tests/sym_defer_pr_tests.cpp
index 417e1f4ca2..3ed360b966 100644
--- a/quantum/debounce/tests/sym_defer_pr_tests.cpp
+++ b/quantum/debounce/tests/sym_defer_pr_tests.cpp
@@ -236,3 +236,21 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
time_jumps_ = true;
runEvents();
}
+
+TEST_F(DebounceTest, AsyncTickOneKeyShort1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {}},
+
+ {5, {}, {{0, 1, DOWN}}},
+ /* 0ms delay (fast scan rate) */
+ {5, {{0, 1, UP}}, {}},
+
+ {10, {}, {{0, 1, UP}}},
+ });
+ /*
+ * Debounce implementations should never read the timer more than once per invocation
+ */
+ async_time_jumps_ = DEBOUNCE;
+ runEvents();
+}
diff --git a/quantum/debounce/tests/sym_eager_pk_tests.cpp b/quantum/debounce/tests/sym_eager_pk_tests.cpp
index d9a02fe33c..39d5b10d8e 100644
--- a/quantum/debounce/tests/sym_eager_pk_tests.cpp
+++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp
@@ -251,3 +251,21 @@ TEST_F(DebounceTest, OneKeyDelayedScan6) {
time_jumps_ = true;
runEvents();
}
+
+TEST_F(DebounceTest, AsyncTickOneKeyShort1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {1, {{0, 1, UP}}, {}},
+
+ {5, {}, {{0, 1, UP}}},
+ /* Press key again after 1ms delay (debounce has not yet finished) */
+ {6, {{0, 1, DOWN}}, {}},
+ {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
+ });
+ /*
+ * Debounce implementations should never read the timer more than once per invocation
+ */
+ async_time_jumps_ = DEBOUNCE;
+ runEvents();
+}
diff --git a/quantum/debounce/tests/sym_eager_pr_tests.cpp b/quantum/debounce/tests/sym_eager_pr_tests.cpp
index e91dd9cb87..9a94807a49 100644
--- a/quantum/debounce/tests/sym_eager_pr_tests.cpp
+++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp
@@ -297,3 +297,21 @@ TEST_F(DebounceTest, OneKeyDelayedScan6) {
time_jumps_ = true;
runEvents();
}
+
+TEST_F(DebounceTest, AsyncTickOneKeyShort1) {
+ addEvents({
+ /* Time, Inputs, Outputs */
+ {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
+ {1, {{0, 1, UP}}, {}},
+
+ {5, {}, {{0, 1, UP}}},
+ /* Press key again after 1ms delay (debounce has not yet finished) */
+ {6, {{0, 1, DOWN}}, {}},
+ {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
+ });
+ /*
+ * Debounce implementations should never read the timer more than once per invocation
+ */
+ async_time_jumps_ = DEBOUNCE;
+ runEvents();
+}
diff --git a/quantum/debounce/tests/testlist.mk b/quantum/debounce/tests/testlist.mk
index f7bd520698..dd53633343 100644
--- a/quantum/debounce/tests/testlist.mk
+++ b/quantum/debounce/tests/testlist.mk
@@ -1,4 +1,5 @@
TEST_LIST += \
+ debounce_none \
debounce_sym_defer_g \
debounce_sym_defer_pk \
debounce_sym_defer_pr \
diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c
index 84de025f0e..d9eea13758 100644
--- a/quantum/eeconfig.c
+++ b/quantum/eeconfig.c
@@ -49,15 +49,15 @@ void eeconfig_init_quantum(void) {
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
eeprom_update_byte(EECONFIG_DEBUG, 0);
- eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
- default_layer_state = 0;
+ default_layer_state = (layer_state_t)1 << 0;
+ eeprom_update_byte(EECONFIG_DEFAULT_LAYER, default_layer_state);
// 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_dword(EECONFIG_RGBLIGHT, 0);
eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, 0);
- eeprom_update_byte(EECONFIG_VELOCIKEY, 0);
+ eeprom_update_byte(EECONFIG_UNUSED, 0);
eeprom_update_byte(EECONFIG_UNICODEMODE, 0);
eeprom_update_byte(EECONFIG_STENOMODE, 0);
uint64_t dummy = 0;
diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h
index 85e80226b6..d7cce166bd 100644
--- a/quantum/eeconfig.h
+++ b/quantum/eeconfig.h
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
+#include "eeprom.h"
#ifndef EECONFIG_MAGIC_NUMBER
# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEE6 // When changing, decrement this value to avoid future re-init issues
@@ -39,7 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define EECONFIG_HANDEDNESS (uint8_t *)14
#define EECONFIG_KEYBOARD (uint32_t *)15
#define EECONFIG_USER (uint32_t *)19
-#define EECONFIG_VELOCIKEY (uint8_t *)23
+#define EECONFIG_UNUSED (uint8_t *)23
// Mutually exclusive
#define EECONFIG_LED_MATRIX (uint32_t *)24
#define EECONFIG_RGB_MATRIX (uint64_t *)24
diff --git a/quantum/haptic.c b/quantum/haptic.c
index 5a700dca38..a1fea29625 100644
--- a/quantum/haptic.c
+++ b/quantum/haptic.c
@@ -20,6 +20,7 @@
#include "debug.h"
#include "usb_device_state.h"
#include "gpio.h"
+#include "keyboard.h"
#ifdef HAPTIC_DRV2605L
# include "drv2605l.h"
@@ -58,6 +59,11 @@ static void set_haptic_config_enable(bool enabled) {
}
void haptic_init(void) {
+// only initialize on secondary boards if the user desires
+#if defined(SPLIT_KEYBOARD) && !defined(SPLIT_HAPTIC_ENABLE)
+ if (!is_keyboard_master()) return;
+#endif
+
if (!eeconfig_is_enabled()) {
eeconfig_init();
}
@@ -99,8 +105,12 @@ void haptic_init(void) {
void haptic_task(void) {
#ifdef HAPTIC_SOLENOID
+// Only run task on seconary boards if the user desires
+# if defined(SPLIT_KEYBOARD) && !defined(SPLIT_HAPTIC_ENABLE)
+ if (!is_keyboard_master()) return;
+# endif
solenoid_check();
-#endif
+#endif // HAPTIC_SOLENOID
}
void eeconfig_debug_haptic(void) {
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
index c2ca15d52d..86a1a9fea3 100644
--- a/quantum/keyboard.c
+++ b/quantum/keyboard.c
@@ -99,9 +99,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef ST7565_ENABLE
# include "st7565.h"
#endif
-#ifdef VELOCIKEY_ENABLE
-# include "velocikey.h"
-#endif
#ifdef VIA_ENABLE
# include "via.h"
#endif
@@ -395,9 +392,6 @@ void quantum_init(void) {
#if defined(UNICODE_COMMON_ENABLE)
unicode_input_mode_init();
#endif
-#ifdef HAPTIC_ENABLE
- haptic_init();
-#endif
}
/** \brief keyboard_init
@@ -462,6 +456,9 @@ void keyboard_init(void) {
#ifdef BLUETOOTH_ENABLE
bluetooth_init();
#endif
+#ifdef HAPTIC_ENABLE
+ haptic_init();
+#endif
#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)
debug_enable = true;
@@ -617,10 +614,6 @@ void quantum_task(void) {
decay_wpm();
#endif
-#ifdef HAPTIC_ENABLE
- haptic_task();
-#endif
-
#ifdef DIP_SWITCH_ENABLE
dip_switch_read(false);
#endif
@@ -712,12 +705,6 @@ void keyboard_task(void) {
midi_task();
#endif
-#ifdef VELOCIKEY_ENABLE
- if (velocikey_enabled()) {
- velocikey_decelerate();
- }
-#endif
-
#ifdef JOYSTICK_ENABLE
joystick_task();
#endif
@@ -726,5 +713,9 @@ void keyboard_task(void) {
bluetooth_task();
#endif
+#ifdef HAPTIC_ENABLE
+ haptic_task();
+#endif
+
led_task();
}
diff --git a/quantum/keycodes.h b/quantum/keycodes.h
index bbf10da36d..39fd2e2726 100644
--- a/quantum/keycodes.h
+++ b/quantum/keycodes.h
@@ -1420,3 +1420,25 @@ enum qk_keycode_defines {
#define IS_QUANTUM_KEYCODE(code) ((code) >= QK_BOOTLOADER && (code) <= QK_ALT_REPEAT_KEY)
#define IS_KB_KEYCODE(code) ((code) >= QK_KB_0 && (code) <= QK_KB_31)
#define IS_USER_KEYCODE(code) ((code) >= QK_USER_0 && (code) <= QK_USER_31)
+
+// Switch statement Helpers
+#define INTERNAL_KEYCODE_RANGE KC_NO ... KC_TRANSPARENT
+#define BASIC_KEYCODE_RANGE KC_A ... KC_EXSEL
+#define SYSTEM_KEYCODE_RANGE KC_SYSTEM_POWER ... KC_SYSTEM_WAKE
+#define CONSUMER_KEYCODE_RANGE KC_AUDIO_MUTE ... KC_LAUNCHPAD
+#define MOUSE_KEYCODE_RANGE KC_MS_UP ... KC_MS_ACCEL2
+#define MODIFIER_KEYCODE_RANGE KC_LEFT_CTRL ... KC_RIGHT_GUI
+#define SWAP_HANDS_KEYCODE_RANGE QK_SWAP_HANDS_TOGGLE ... QK_SWAP_HANDS_ONE_SHOT
+#define MAGIC_KEYCODE_RANGE QK_MAGIC_SWAP_CONTROL_CAPS_LOCK ... QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK
+#define MIDI_KEYCODE_RANGE QK_MIDI_ON ... QK_MIDI_PITCH_BEND_UP
+#define SEQUENCER_KEYCODE_RANGE QK_SEQUENCER_ON ... QK_SEQUENCER_STEPS_CLEAR
+#define JOYSTICK_KEYCODE_RANGE QK_JOYSTICK_BUTTON_0 ... QK_JOYSTICK_BUTTON_31
+#define PROGRAMMABLE_BUTTON_KEYCODE_RANGE QK_PROGRAMMABLE_BUTTON_1 ... QK_PROGRAMMABLE_BUTTON_32
+#define AUDIO_KEYCODE_RANGE QK_AUDIO_ON ... QK_AUDIO_VOICE_PREVIOUS
+#define STENO_KEYCODE_RANGE QK_STENO_BOLT ... QK_STENO_COMB_MAX
+#define MACRO_KEYCODE_RANGE QK_MACRO_0 ... QK_MACRO_31
+#define BACKLIGHT_KEYCODE_RANGE QK_BACKLIGHT_ON ... QK_BACKLIGHT_TOGGLE_BREATHING
+#define RGB_KEYCODE_RANGE RGB_TOG ... RGB_MODE_TWINKLE
+#define QUANTUM_KEYCODE_RANGE QK_BOOTLOADER ... QK_ALT_REPEAT_KEY
+#define KB_KEYCODE_RANGE QK_KB_0 ... QK_KB_31
+#define USER_KEYCODE_RANGE QK_USER_0 ... QK_USER_31
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index 9a67fad278..91e47a72ee 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -59,19 +59,19 @@ action_t action_for_keycode(uint16_t keycode) {
(void)mod;
switch (keycode) {
- case KC_A ... KC_EXSEL:
- case KC_LEFT_CTRL ... KC_RIGHT_GUI:
+ case BASIC_KEYCODE_RANGE:
+ case MODIFIER_KEYCODE_RANGE:
action.code = ACTION_KEY(keycode);
break;
#ifdef EXTRAKEY_ENABLE
- case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
+ case SYSTEM_KEYCODE_RANGE:
action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
break;
- case KC_AUDIO_MUTE ... KC_LAUNCHPAD:
+ case CONSUMER_KEYCODE_RANGE:
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
break;
#endif
- case KC_MS_UP ... KC_MS_ACCEL2:
+ case MOUSE_KEYCODE_RANGE:
action.code = ACTION_MOUSEKEY(keycode);
break;
case KC_TRANSPARENT:
diff --git a/quantum/keymap_extras/keymap_russian_typewriter.h b/quantum/keymap_extras/keymap_russian_typewriter.h
new file mode 100644
index 0000000000..59f341e38b
--- /dev/null
+++ b/quantum/keymap_extras/keymap_russian_typewriter.h
@@ -0,0 +1,93 @@
+// Copyright 2023 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 RU_PIPE KC_GRV // |
+#define RU_NUM KC_1 // №
+#define RU_MINS KC_2 // -
+#define RU_SLSH KC_3 // /
+#define RU_DQUO KC_4 // "
+#define RU_COLN KC_5 // :
+#define RU_COMM KC_6 // ,
+#define RU_DOT KC_7 // .
+#define RU_UNDS KC_8 // _
+#define RU_QUES KC_9 // ?
+#define RU_PERC KC_0 // %
+#define RU_EXLM KC_MINS // !
+#define RU_SCLN KC_EQL // ;
+#define RU_SHTI KC_Q // Й
+#define RU_TSE KC_W // Ц
+#define RU_U KC_E // У
+#define RU_KA KC_R // К
+#define RU_IE KC_T // Е
+#define RU_EN KC_Y // Н
+#define RU_GHE KC_U // Г
+#define RU_SHA KC_I // Ш
+#define RU_SHCH KC_O // Щ
+#define RU_ZE KC_P // З
+#define RU_HA KC_LBRC // Х
+#define RU_HARD KC_RBRC // Ъ
+#define RU_RPRN KC_BSLS // )
+#define RU_EF KC_A // Ф
+#define RU_YERU KC_S // Ы
+#define RU_VE KC_D // В
+#define RU_A KC_F // А
+#define RU_PE KC_G // П
+#define RU_ER KC_H // Р
+#define RU_O KC_J // О
+#define RU_EL KC_K // Л
+#define RU_DE KC_L // Д
+#define RU_ZHE KC_SCLN // Ж
+#define RU_E KC_QUOT // Э
+#define RU_YA KC_Z // Я
+#define RU_CHE KC_X // Ч
+#define RU_ES KC_C // С
+#define RU_EM KC_V // М
+#define RU_I KC_B // И
+#define RU_TE KC_N // Т
+#define RU_SOFT KC_M // Ь
+#define RU_BE KC_COMM // Б
+#define RU_YU KC_DOT // Ю
+#define RU_YO KC_SLSH // Ё
+#define RU_PLUS S(RU_PIPE) // +
+#define RU_1 S(RU_NUM) // 1
+#define RU_2 S(RU_MINS) // 2
+#define RU_3 S(RU_SLSH) // 3
+#define RU_4 S(RU_DQUO) // 4
+#define RU_5 S(RU_COLN) // 5
+#define RU_6 S(RU_COMM) // 6
+#define RU_7 S(RU_DOT) // 7
+#define RU_8 S(RU_UNDS) // 8
+#define RU_9 S(RU_QUES) // 9
+#define RU_0 S(RU_PERC) // 0
+#define RU_EQL S(RU_EXLM) // =
+#define RU_BSLS S(RU_SCLN) // (backslash)
+#define RU_LPRN S(RU_RPRN) // (
+#define RU_RUBL ALGR(RU_UNDS) // ₽
+
diff --git a/quantum/keymap_extras/keymap_steno.h b/quantum/keymap_extras/keymap_steno.h
index 852b2f7121..d2635446c6 100644
--- a/quantum/keymap_extras/keymap_steno.h
+++ b/quantum/keymap_extras/keymap_steno.h
@@ -1,119 +1,6 @@
-/* Copyright 2017 Joseph Wasson
- *
- * 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/>.
- */
+// Copyright 2023 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
-#include "keycodes.h"
-
-// List of keycodes for the steno keyboard. To prevent
-// errors, this must be <= 42 total entries in order to
-// support the GeminiPR protocol.
-enum steno_keycodes {
- STN__MIN = QK_STENO,
- STN_FN = STN__MIN,
- STN_NUM,
- STN_N1 = STN_NUM,
- STN_N2,
- STN_N3,
- STN_N4,
- STN_N5,
- STN_N6,
- STN_SL,
- STN_S1 = STN_SL,
- STN_S2,
- STN_TL,
- STN_KL,
- STN_PL,
- STN_WL,
- STN_HL,
- STN_RL,
- STN_A,
- STN_O,
- STN_STR,
- STN_ST1 = STN_STR,
- STN_ST2,
- STN_RES1,
- STN_RE1 = STN_RES1,
- STN_RES2,
- STN_RE2 = STN_RES2,
- STN_PWR,
- STN_ST3,
- STN_ST4,
- STN_E,
- STN_U,
- STN_FR,
- STN_RR,
- STN_PR,
- STN_BR,
- STN_LR,
- STN_GR,
- STN_TR,
- STN_SR,
- STN_DR,
- STN_N7,
- STN_N8,
- STN_N9,
- STN_NA,
- STN_NB,
- STN_NC,
- STN_ZR,
- STN__MAX = STN_ZR, // must be less than QK_STENO_BOLT
-};
-
-#ifdef STENO_COMBINEDMAP
-enum steno_combined_keycodes {
- STN_S3 = QK_STENO_COMB,
- STN_TKL,
- STN_PWL,
- STN_HRL,
- STN_FRR,
- STN_PBR,
- STN_LGR,
- STN_TSR,
- STN_DZR,
- STN_AO,
- STN_EU,
- STN_COMB_MAX = STN_EU,
-};
-#endif
-
-#ifdef STENO_ENABLE_BOLT
-// TxBolt Codes
-# define TXB_NUL 0
-# define TXB_S_L 0b00000001
-# define TXB_T_L 0b00000010
-# define TXB_K_L 0b00000100
-# define TXB_P_L 0b00001000
-# define TXB_W_L 0b00010000
-# define TXB_H_L 0b00100000
-# define TXB_R_L 0b01000001
-# define TXB_A_L 0b01000010
-# define TXB_O_L 0b01000100
-# define TXB_STR 0b01001000
-# define TXB_E_R 0b01010000
-# define TXB_U_R 0b01100000
-# define TXB_F_R 0b10000001
-# define TXB_R_R 0b10000010
-# define TXB_P_R 0b10000100
-# define TXB_B_R 0b10001000
-# define TXB_L_R 0b10010000
-# define TXB_G_R 0b10100000
-# define TXB_T_R 0b11000001
-# define TXB_S_R 0b11000010
-# define TXB_D_R 0b11000100
-# define TXB_Z_R 0b11001000
-# define TXB_NUM 0b11010000
-#endif // STENO_ENABLE_BOLT
+#pragma message("keymap_steno.h include is no longer required")
diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c
index 2ec0ec4b19..4d67a295df 100644
--- a/quantum/led_matrix/led_matrix.c
+++ b/quantum/led_matrix/led_matrix.c
@@ -58,35 +58,6 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
// -----End led effect includes macros-------
// ------------------------------------------
-#ifndef LED_MATRIX_TIMEOUT
-# define LED_MATRIX_TIMEOUT 0
-#endif
-
-#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
-# undef LED_MATRIX_MAXIMUM_BRIGHTNESS
-# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
-#endif
-
-#if !defined(LED_MATRIX_VAL_STEP)
-# define LED_MATRIX_VAL_STEP 8
-#endif
-
-#if !defined(LED_MATRIX_SPD_STEP)
-# define LED_MATRIX_SPD_STEP 16
-#endif
-
-#if !defined(LED_MATRIX_DEFAULT_MODE)
-# define LED_MATRIX_DEFAULT_MODE LED_MATRIX_SOLID
-#endif
-
-#if !defined(LED_MATRIX_DEFAULT_VAL)
-# define LED_MATRIX_DEFAULT_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS
-#endif
-
-#if !defined(LED_MATRIX_DEFAULT_SPD)
-# define LED_MATRIX_DEFAULT_SPD UINT8_MAX / 2
-#endif
-
// globals
led_eeconfig_t led_matrix_eeconfig; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr
uint32_t g_led_timer;
@@ -126,7 +97,7 @@ void eeconfig_update_led_matrix(void) {
void eeconfig_update_led_matrix_default(void) {
dprintf("eeconfig_update_led_matrix_default\n");
- led_matrix_eeconfig.enable = 1;
+ led_matrix_eeconfig.enable = LED_MATRIX_DEFAULT_ON;
led_matrix_eeconfig.mode = LED_MATRIX_DEFAULT_MODE;
led_matrix_eeconfig.val = LED_MATRIX_DEFAULT_VAL;
led_matrix_eeconfig.speed = LED_MATRIX_DEFAULT_SPD;
@@ -371,9 +342,8 @@ void led_matrix_task(void) {
case RENDERING:
led_task_render(effect);
if (effect) {
- // Only run the basic indicators in the last render iteration (default there are 5 iterations)
- if (led_effect_params.iter == LED_MATRIX_LED_PROCESS_MAX_ITERATIONS) {
- led_matrix_indicators();
+ if (led_task_state == FLUSHING) {
+ led_matrix_indicators(); // ensure we only draw basic indicators once rendering is finished
}
led_matrix_indicators_advanced(&led_effect_params);
}
@@ -405,14 +375,7 @@ void led_matrix_indicators_advanced(effect_params_t *params) {
* and not sure which would be better. Otherwise, this should be called from
* led_task_render, right before the iter++ line.
*/
-#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < LED_MATRIX_LED_COUNT
- uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * (params->iter - 1);
- uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT;
- if (max > LED_MATRIX_LED_COUNT) max = LED_MATRIX_LED_COUNT;
-#else
- uint8_t min = 0;
- uint8_t max = LED_MATRIX_LED_COUNT;
-#endif
+ LED_MATRIX_USE_LIMITS_ITER(min, max, params->iter - 1);
led_matrix_indicators_advanced_kb(min, max);
}
@@ -424,6 +387,36 @@ __attribute__((weak)) bool led_matrix_indicators_advanced_user(uint8_t led_min,
return true;
}
+struct led_matrix_limits_t led_matrix_get_limits(uint8_t iter) {
+ struct led_matrix_limits_t limits = {0};
+#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < LED_MATRIX_LED_COUNT
+# if defined(LED_MATRIX_SPLIT)
+ limits.led_min_index = LED_MATRIX_LED_PROCESS_LIMIT * (iter);
+ limits.led_max_index = limits.led_min_index + LED_MATRIX_LED_PROCESS_LIMIT;
+ if (limits.led_max_index > LED_MATRIX_LED_COUNT) limits.led_max_index = LED_MATRIX_LED_COUNT;
+ uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT;
+ if (is_keyboard_left() && (limits.led_max_index > k_led_matrix_split[0])) limits.led_max_index = k_led_matrix_split[0];
+ if (!(is_keyboard_left()) && (limits.led_min_index < k_led_matrix_split[0])) limits.led_min_index = k_led_matrix_split[0];
+# else
+ limits.led_min_index = LED_MATRIX_LED_PROCESS_LIMIT * (iter);
+ limits.led_max_index = limits.led_min_index + LED_MATRIX_LED_PROCESS_LIMIT;
+ if (limits.led_max_index > LED_MATRIX_LED_COUNT) limits.led_max_index = LED_MATRIX_LED_COUNT;
+# endif
+#else
+# if defined(LED_MATRIX_SPLIT)
+ limits.led_min_index = 0;
+ limits.led_max_index = LED_MATRIX_LED_COUNT;
+ const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT;
+ if (is_keyboard_left() && (limits.led_max_index > k_led_matrix_split[0])) limits.led_max_index = k_led_matrix_split[0];
+ if (!(is_keyboard_left()) && (limits.led_min_index < k_led_matrix_split[0])) limits.led_min_index = k_led_matrix_split[0];
+# else
+ limits.led_min_index = 0;
+ limits.led_max_index = LED_MATRIX_LED_COUNT;
+# endif
+#endif
+ return limits;
+}
+
void led_matrix_init(void) {
led_matrix_driver.init();
@@ -630,7 +623,7 @@ void led_matrix_decrease_speed(void) {
void led_matrix_set_flags_eeprom_helper(led_flags_t flags, bool write_to_eeprom) {
led_matrix_eeconfig.flags = flags;
eeconfig_flag_led_matrix(write_to_eeprom);
- dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.flags);
+ dprintf("led matrix set flags [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.flags);
}
led_flags_t led_matrix_get_flags(void) {
diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h
index c2533ca49c..c903a230f4 100644
--- a/quantum/led_matrix/led_matrix.h
+++ b/quantum/led_matrix/led_matrix.h
@@ -25,16 +25,60 @@
#include "led_matrix_types.h"
#include "keyboard.h"
-#ifdef IS31FL3731
+#if defined(LED_MATRIX_IS31FL3218)
+# include "is31fl3218-simple.h"
+#elif defined(LED_MATRIX_IS31FL3731)
# include "is31fl3731-simple.h"
-#elif defined(IS31FLCOMMON)
-# include "is31flcommon.h"
#endif
-#ifdef IS31FL3733
+#ifdef LED_MATRIX_IS31FL3733
# include "is31fl3733-simple.h"
#endif
-#ifdef CKLED2001
-# include "ckled2001-simple.h"
+#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
+
+#ifndef LED_MATRIX_MAXIMUM_BRIGHTNESS
+# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
+#endif
+
+#ifndef LED_MATRIX_VAL_STEP
+# define LED_MATRIX_VAL_STEP 8
+#endif
+
+#ifndef LED_MATRIX_SPD_STEP
+# define LED_MATRIX_SPD_STEP 16
+#endif
+
+#ifndef LED_MATRIX_DEFAULT_ON
+# define LED_MATRIX_DEFAULT_ON true
+#endif
+
+#ifndef LED_MATRIX_DEFAULT_MODE
+# define LED_MATRIX_DEFAULT_MODE LED_MATRIX_SOLID
+#endif
+
+#ifndef LED_MATRIX_DEFAULT_VAL
+# define LED_MATRIX_DEFAULT_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS
+#endif
+
+#ifndef LED_MATRIX_DEFAULT_SPD
+# define LED_MATRIX_DEFAULT_SPD UINT8_MAX / 2
#endif
#ifndef LED_MATRIX_LED_FLUSH_LIMIT
@@ -44,37 +88,22 @@
#ifndef LED_MATRIX_LED_PROCESS_LIMIT
# define LED_MATRIX_LED_PROCESS_LIMIT ((LED_MATRIX_LED_COUNT + 4) / 5)
#endif
-#define LED_MATRIX_LED_PROCESS_MAX_ITERATIONS ((LED_MATRIX_LED_COUNT + LED_MATRIX_LED_PROCESS_LIMIT - 1) / LED_MATRIX_LED_PROCESS_LIMIT)
-
-#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < LED_MATRIX_LED_COUNT
-# if defined(LED_MATRIX_SPLIT)
-# define LED_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
- uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
- if (max > LED_MATRIX_LED_COUNT) max = LED_MATRIX_LED_COUNT; \
- uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; \
- if (is_keyboard_left() && (max > k_led_matrix_split[0])) max = k_led_matrix_split[0]; \
- if (!(is_keyboard_left()) && (min < k_led_matrix_split[0])) min = k_led_matrix_split[0];
-# else
-# define LED_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
- uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
- if (max > LED_MATRIX_LED_COUNT) max = LED_MATRIX_LED_COUNT;
-# endif
-#else
-# if defined(LED_MATRIX_SPLIT)
-# define LED_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = 0; \
- uint8_t max = LED_MATRIX_LED_COUNT; \
- const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; \
- if (is_keyboard_left() && (max > k_led_matrix_split[0])) max = k_led_matrix_split[0]; \
- if (!(is_keyboard_left()) && (min < k_led_matrix_split[0])) min = k_led_matrix_split[0];
-# else
-# define LED_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = 0; \
- uint8_t max = LED_MATRIX_LED_COUNT;
-# endif
-#endif
+
+struct led_matrix_limits_t {
+ uint8_t led_min_index;
+ uint8_t led_max_index;
+};
+
+struct led_matrix_limits_t led_matrix_get_limits(uint8_t iter);
+
+#define LED_MATRIX_USE_LIMITS_ITER(min, max, iter) \
+ struct led_matrix_limits_t limits = led_matrix_get_limits(iter); \
+ uint8_t min = limits.led_min_index; \
+ uint8_t max = limits.led_max_index; \
+ (void)min; \
+ (void)max;
+
+#define LED_MATRIX_USE_LIMITS(min, max) LED_MATRIX_USE_LIMITS_ITER(min, max, params->iter)
#define LED_MATRIX_TEST_LED_FLAGS() \
if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) continue
diff --git a/quantum/led_matrix/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c
index 13c8935d11..117bed9851 100644
--- a/quantum/led_matrix/led_matrix_drivers.c
+++ b/quantum/led_matrix/led_matrix_drivers.c
@@ -25,223 +25,68 @@
* in their own files.
*/
-#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FLCOMMON) || defined(CKLED2001)
-# include "i2c_master.h"
-
-static void init(void) {
- i2c_init();
-
-# if defined(IS31FL3731)
- is31fl3731_init(LED_DRIVER_ADDR_1);
-# if defined(LED_DRIVER_ADDR_2)
- is31fl3731_init(LED_DRIVER_ADDR_2);
-# if defined(LED_DRIVER_ADDR_3)
- is31fl3731_init(LED_DRIVER_ADDR_3);
-# if defined(LED_DRIVER_ADDR_4)
- is31fl3731_init(LED_DRIVER_ADDR_4);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3733)
-# if !defined(LED_DRIVER_SYNC_1)
-# define LED_DRIVER_SYNC_1 0
-# endif
- is31fl3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1);
-# if defined(LED_DRIVER_ADDR_2)
-# if !defined(LED_DRIVER_SYNC_2)
-# define LED_DRIVER_SYNC_2 0
-# endif
- is31fl3733_init(LED_DRIVER_ADDR_2, LED_DRIVER_SYNC_2);
-# if defined(LED_DRIVER_ADDR_3)
-# if !defined(LED_DRIVER_SYNC_3)
-# define LED_DRIVER_SYNC_3 0
-# endif
- is31fl3733_init(LED_DRIVER_ADDR_3, LED_DRIVER_SYNC_3);
-# if defined(LED_DRIVER_ADDR_4)
-# if !defined(LED_DRIVER_SYNC_4)
-# define LED_DRIVER_SYNC_4 0
-# endif
- is31fl3733_init(LED_DRIVER_ADDR_4, LED_DRIVER_SYNC_4);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FLCOMMON)
- IS31FL_common_init(DRIVER_ADDR_1, ISSI_SSR_1);
-# if defined(LED_DRIVER_ADDR_2)
- IS31FL_common_init(DRIVER_ADDR_2, ISSI_SSR_2);
-# if defined(LED_DRIVER_ADDR_3)
- IS31FL_common_init(DRIVER_ADDR_3, ISSI_SSR_3);
-# if defined(LED_DRIVER_ADDR_4)
- IS31FL_common_init(DRIVER_ADDR_4, ISSI_SSR_4);
-# endif
-# endif
-# endif
-# elif defined(CKLED2001)
-# if defined(LED_DRIVER_SHUTDOWN_PIN)
- setPinOutput(LED_DRIVER_SHUTDOWN_PIN);
- writePinHigh(LED_DRIVER_SHUTDOWN_PIN);
-# endif
-
- ckled2001_init(DRIVER_ADDR_1);
-# if defined(DRIVER_ADDR_2)
- ckled2001_init(DRIVER_ADDR_2);
-# if defined(DRIVER_ADDR_3)
- ckled2001_init(DRIVER_ADDR_3);
-# if defined(DRIVER_ADDR_4)
- ckled2001_init(DRIVER_ADDR_4);
-# endif
-# endif
-# endif
-# endif
-
- for (int index = 0; index < LED_MATRIX_LED_COUNT; index++) {
-# if defined(IS31FL3731)
- is31fl3731_set_led_control_register(index, true);
-# elif defined(IS31FL3733)
- is31fl3733_set_led_control_register(index, true);
-# elif defined(IS31FLCOMMON)
- IS31FL_simple_set_scaling_buffer(index, true);
-# elif defined(CKLED2001)
- ckled2001_set_led_control_register(index, true);
-# endif
- }
-
-// This actually updates the LED drivers
-# if defined(IS31FL3731)
- is31fl3731_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
-# if defined(LED_DRIVER_ADDR_2)
- is31fl3731_update_led_control_registers(LED_DRIVER_ADDR_2, 1);
-# if defined(LED_DRIVER_ADDR_3)
- is31fl3731_update_led_control_registers(LED_DRIVER_ADDR_3, 2);
-# if defined(LED_DRIVER_ADDR_4)
- is31fl3731_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3733)
- is31fl3733_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
-# if defined(LED_DRIVER_ADDR_2)
- is31fl3733_update_led_control_registers(LED_DRIVER_ADDR_2, 1);
-# if defined(LED_DRIVER_ADDR_3)
- is31fl3733_update_led_control_registers(LED_DRIVER_ADDR_3, 2);
-# if defined(LED_DRIVER_ADDR_4)
- is31fl3733_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FLCOMMON)
-# ifdef ISSI_MANUAL_SCALING
- IS31FL_set_manual_scaling_buffer();
-# endif
- IS31FL_common_update_scaling_register(DRIVER_ADDR_1, 0);
-# if defined(LED_DRIVER_ADDR_2)
- IS31FL_common_update_scaling_register(DRIVER_ADDR_2, 1);
-# if defined(LED_DRIVER_ADDR_3)
- IS31FL_common_update_scaling_register(DRIVER_ADDR_3, 2);
-# if defined(LED_DRIVER_ADDR_4)
- IS31FL_common_update_scaling_register(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-# elif defined(CKLED2001)
- ckled2001_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- ckled2001_update_led_control_registers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- ckled2001_update_led_control_registers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- ckled2001_update_led_control_registers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-# endif
-}
-
-# if defined(IS31FL3731)
-static void flush(void) {
- is31fl3731_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
-# if defined(LED_DRIVER_ADDR_2)
- is31fl3731_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
-# if defined(LED_DRIVER_ADDR_3)
- is31fl3731_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
-# if defined(LED_DRIVER_ADDR_4)
- is31fl3731_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
+#if defined(LED_MATRIX_IS31FL3218)
+const led_matrix_driver_t led_matrix_driver = {
+ .init = is31fl3218_init,
+ .flush = is31fl3218_update_pwm_buffers,
+ .set_value = is31fl3218_set_value,
+ .set_value_all = is31fl3218_set_value_all,
+};
+#elif defined(LED_MATRIX_IS31FL3731)
const led_matrix_driver_t led_matrix_driver = {
- .init = init,
- .flush = flush,
+ .init = is31fl3731_init_drivers,
+ .flush = is31fl3731_flush,
.set_value = is31fl3731_set_value,
.set_value_all = is31fl3731_set_value_all,
};
-# elif defined(IS31FL3733)
-static void flush(void) {
- is31fl3733_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
-# if defined(LED_DRIVER_ADDR_2)
- is31fl3733_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
-# if defined(LED_DRIVER_ADDR_3)
- is31fl3733_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
-# if defined(LED_DRIVER_ADDR_4)
- is31fl3733_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
-
+#elif defined(LED_MATRIX_IS31FL3733)
const led_matrix_driver_t led_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_value = is31fl3733_set_value,
+ .init = is31fl3733_init_drivers,
+ .flush = is31fl3733_flush,
+ .set_value = is31fl3733_set_value,
.set_value_all = is31fl3733_set_value_all,
};
-# elif defined(IS31FLCOMMON)
-static void flush(void) {
- IS31FL_common_update_pwm_register(DRIVER_ADDR_1, 0);
-# if defined(LED_DRIVER_ADDR_2)
- IS31FL_common_update_pwm_register(DRIVER_ADDR_2, 1);
-# if defined(LED_DRIVER_ADDR_3)
- IS31FL_common_update_pwm_register(DRIVER_ADDR_3, 2);
-# if defined(LED_DRIVER_ADDR_4)
- IS31FL_common_update_pwm_register(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
+#elif defined(LED_MATRIX_IS31FL3736)
+const led_matrix_driver_t led_matrix_driver = {
+ .init = is31fl3736_init_drivers,
+ .flush = is31fl3736_flush,
+ .set_value = is31fl3736_set_value,
+ .set_value_all = is31fl3736_set_value_all,
+};
+#elif defined(LED_MATRIX_IS31FL3737)
const led_matrix_driver_t led_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_value = IS31FL_simple_set_brightness,
+ .init = is31fl3737_init_drivers,
+ .flush = is31fl3737_flush,
+ .set_value = is31fl3737_set_value,
+ .set_value_all = is31fl3737_set_value_all,
+};
+
+#elif defined(LED_MATRIX_IS31FL3741)
+const led_matrix_driver_t led_matrix_driver = {
+ .init = is31fl3741_init_drivers,
+ .flush = is31fl3741_flush,
+ .set_value = is31fl3741_set_value,
+ .set_value_all = is31fl3741_set_value_all,
+};
+
+#elif defined(IS31FLCOMMON)
+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,
};
-# elif defined(CKLED2001)
-static void flush(void) {
- ckled2001_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- ckled2001_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- ckled2001_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- ckled2001_update_pwm_buffers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
+#elif defined(LED_MATRIX_SNLED27351)
const led_matrix_driver_t led_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_value = ckled2001_set_value,
- .set_value_all = ckled2001_set_value_all,
+ .init = snled27351_init_drivers,
+ .flush = snled27351_flush,
+ .set_value = snled27351_set_value,
+ .set_value_all = snled27351_set_value_all,
};
-# endif
+
#endif
diff --git a/quantum/led_matrix/led_matrix_types.h b/quantum/led_matrix/led_matrix_types.h
index 6709a558bb..5a516ceb10 100644
--- a/quantum/led_matrix/led_matrix_types.h
+++ b/quantum/led_matrix/led_matrix_types.h
@@ -18,16 +18,7 @@
#include <stdint.h>
#include <stdbool.h>
-
-#if defined(__GNUC__)
-# define PACKED __attribute__((__packed__))
-#else
-# define PACKED
-#endif
-
-#if defined(_MSC_VER)
-# pragma pack(push, 1)
-#endif
+#include "util.h"
#if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES)
# define LED_MATRIX_KEYREACTIVE_ENABLED
@@ -92,7 +83,3 @@ typedef union {
} led_eeconfig_t;
_Static_assert(sizeof(led_eeconfig_t) == sizeof(uint32_t), "LED Matrix EECONFIG out of spec.");
-
-#if defined(_MSC_VER)
-# pragma pack(pop)
-#endif
diff --git a/quantum/mousekey.c b/quantum/mousekey.c
index c982a2f40b..3910811752 100644
--- a/quantum/mousekey.c
+++ b/quantum/mousekey.c
@@ -389,7 +389,20 @@ void mousekey_on(uint8_t code) {
if (mouse_timer == 0) {
mouse_timer = timer_read();
}
-# endif /* #ifdef MK_KINETIC_SPEED */
+# endif
+
+# ifndef MOUSEKEY_INERTIA
+ // If mouse report is not zero, the current mousekey press is overlapping
+ // with another. Restart acceleration for smoother directional transition.
+ if (mouse_report.x || mouse_report.y || mouse_report.h || mouse_report.v) {
+# ifdef MK_KINETIC_SPEED
+ mouse_timer = timer_read() - (MOUSEKEY_INTERVAL << 2);
+# else
+ mousekey_repeat = MOUSEKEY_MOVE_DELTA;
+ mousekey_wheel_repeat = MOUSEKEY_WHEEL_DELTA;
+# endif
+ }
+# endif // ifndef MOUSEKEY_INERTIA
# ifdef MOUSEKEY_INERTIA
diff --git a/quantum/painter/lvgl/qp_lvgl.c b/quantum/painter/lvgl/qp_lvgl.c
index 280aeaf91f..877b2652c6 100644
--- a/quantum/painter/lvgl/qp_lvgl.c
+++ b/quantum/painter/lvgl/qp_lvgl.c
@@ -81,8 +81,8 @@ bool qp_lvgl_attach(painter_device_t device) {
lvgl_state_t *lv_task_handler_state = &lvgl_states[1];
lv_task_handler_state->fnc_id = 1;
- lv_task_handler_state->delay_ms = 5;
- lv_task_handler_state->defer_token = defer_exec_advanced(lvgl_executors, 2, 5, tick_task_callback, lv_task_handler_state);
+ lv_task_handler_state->delay_ms = QP_LVGL_TASK_PERIOD;
+ lv_task_handler_state->defer_token = defer_exec_advanced(lvgl_executors, 2, QP_LVGL_TASK_PERIOD, tick_task_callback, lv_task_handler_state);
if (lv_task_handler_state->defer_token == INVALID_DEFERRED_TOKEN) {
qp_dprintf("qp_lvgl_attach: fail (could not set up qp_lvgl executor)\n");
@@ -96,13 +96,14 @@ bool qp_lvgl_attach(painter_device_t device) {
// Set up lvgl display buffer
static lv_disp_draw_buf_t draw_buf;
// Allocate a buffer for 1/10 screen size
- const size_t count_required = driver->panel_width * driver->panel_height / 10;
- color_buffer = color_buffer ? realloc(color_buffer, sizeof(lv_color_t) * count_required) : malloc(sizeof(lv_color_t) * count_required);
- if (!color_buffer) {
+ const size_t count_required = driver->panel_width * driver->panel_height / 10;
+ void * new_color_buffer = realloc(color_buffer, sizeof(lv_color_t) * count_required);
+ if (!new_color_buffer) {
qp_dprintf("qp_lvgl_attach: fail (could not set up memory buffer)\n");
qp_lvgl_detach();
return false;
}
+ color_buffer = new_color_buffer;
memset(color_buffer, 0, sizeof(lv_color_t) * count_required);
// Initialize the display buffer.
lv_disp_draw_buf_init(&draw_buf, color_buffer, NULL, count_required);
diff --git a/quantum/painter/lvgl/qp_lvgl.h b/quantum/painter/lvgl/qp_lvgl.h
index d9ad5e8df1..87ba3ac0a5 100644
--- a/quantum/painter/lvgl/qp_lvgl.h
+++ b/quantum/painter/lvgl/qp_lvgl.h
@@ -7,6 +7,10 @@
#include "qp.h"
#include "lvgl.h"
+#ifndef QP_LVGL_TASK_PERIOD
+# define QP_LVGL_TASK_PERIOD 5
+#endif
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter - LVGL External API
diff --git a/quantum/painter/qff.c b/quantum/painter/qff.c
index cd6af788f9..8590f5b400 100644
--- a/quantum/painter/qff.c
+++ b/quantum/painter/qff.c
@@ -10,7 +10,7 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// QFF API
-bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *has_ascii_table, uint16_t *num_unicode_glyphs, uint8_t *bpp, bool *has_palette, painter_compression_t *compression_scheme, uint32_t *total_bytes) {
+bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *has_ascii_table, uint16_t *num_unicode_glyphs, uint8_t *bpp, bool *has_palette, bool *is_panel_native, painter_compression_t *compression_scheme, uint32_t *total_bytes) {
// Seek to the start
qp_stream_setpos(stream, 0);
@@ -49,7 +49,7 @@ bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *h
*num_unicode_glyphs = font_descriptor.num_unicode_glyphs;
}
if (bpp || has_palette) {
- if (!qgf_parse_format(font_descriptor.format, bpp, has_palette)) {
+ if (!qgf_parse_format(font_descriptor.format, bpp, has_palette, is_panel_native)) {
return false;
}
}
@@ -102,7 +102,7 @@ bool qff_validate_stream(qp_stream_t *stream) {
bool has_ascii_table;
uint16_t num_unicode_glyphs;
- if (!qff_read_font_descriptor(stream, NULL, &has_ascii_table, &num_unicode_glyphs, NULL, NULL, NULL, NULL)) {
+ if (!qff_read_font_descriptor(stream, NULL, &has_ascii_table, &num_unicode_glyphs, NULL, NULL, NULL, NULL, NULL)) {
return false;
}
@@ -127,7 +127,7 @@ uint32_t qff_get_total_size(qp_stream_t *stream) {
// Read the font descriptor, grabbing the size
uint32_t total_size;
- if (!qff_read_font_descriptor(stream, NULL, NULL, NULL, NULL, NULL, NULL, &total_size)) {
+ if (!qff_read_font_descriptor(stream, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &total_size)) {
return false;
}
diff --git a/quantum/painter/qff.h b/quantum/painter/qff.h
index d1d629582f..c3b831da17 100644
--- a/quantum/painter/qff.h
+++ b/quantum/painter/qff.h
@@ -85,4 +85,4 @@ typedef struct QP_PACKED qff_unicode_glyph_table_v1_t {
bool qff_validate_stream(qp_stream_t *stream);
uint32_t qff_get_total_size(qp_stream_t *stream);
-bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *has_ascii_table, uint16_t *num_unicode_glyphs, uint8_t *bpp, bool *has_palette, painter_compression_t *compression_scheme, uint32_t *total_bytes);
+bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *has_ascii_table, uint16_t *num_unicode_glyphs, uint8_t *bpp, bool *has_palette, bool *is_panel_native, painter_compression_t *compression_scheme, uint32_t *total_bytes);
diff --git a/quantum/painter/qgf.c b/quantum/painter/qgf.c
index 6a4af07001..bc2df94933 100644
--- a/quantum/painter/qgf.c
+++ b/quantum/painter/qgf.c
@@ -24,22 +24,23 @@ bool qgf_validate_block_header(qgf_block_header_v1_t *desc, uint8_t expected_typ
return true;
}
-bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette) {
+bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette, bool *is_panel_native) {
// clang-format off
- static const struct QP_PACKED {
+ static const struct QP_PACKED {
uint8_t bpp;
bool has_palette;
+ bool is_panel_native;
} formats[] = {
- [GRAYSCALE_1BPP] = {.bpp = 1, .has_palette = false},
- [GRAYSCALE_2BPP] = {.bpp = 2, .has_palette = false},
- [GRAYSCALE_4BPP] = {.bpp = 4, .has_palette = false},
- [GRAYSCALE_8BPP] = {.bpp = 8, .has_palette = false},
- [PALETTE_1BPP] = {.bpp = 1, .has_palette = true},
- [PALETTE_2BPP] = {.bpp = 2, .has_palette = true},
- [PALETTE_4BPP] = {.bpp = 4, .has_palette = true},
- [PALETTE_8BPP] = {.bpp = 8, .has_palette = true},
- [RGB565_16BPP] = {.bpp = 16, .has_palette = false},
- [RGB888_24BPP] = {.bpp = 24, .has_palette = false},
+ [GRAYSCALE_1BPP] = {.bpp = 1, .has_palette = false, .is_panel_native = false},
+ [GRAYSCALE_2BPP] = {.bpp = 2, .has_palette = false, .is_panel_native = false},
+ [GRAYSCALE_4BPP] = {.bpp = 4, .has_palette = false, .is_panel_native = false},
+ [GRAYSCALE_8BPP] = {.bpp = 8, .has_palette = false, .is_panel_native = false},
+ [PALETTE_1BPP] = {.bpp = 1, .has_palette = true, .is_panel_native = false},
+ [PALETTE_2BPP] = {.bpp = 2, .has_palette = true, .is_panel_native = false},
+ [PALETTE_4BPP] = {.bpp = 4, .has_palette = true, .is_panel_native = false},
+ [PALETTE_8BPP] = {.bpp = 8, .has_palette = true, .is_panel_native = false},
+ [RGB565_16BPP] = {.bpp = 16, .has_palette = false, .is_panel_native = true},
+ [RGB888_24BPP] = {.bpp = 24, .has_palette = false, .is_panel_native = true},
};
// clang-format on
@@ -56,13 +57,16 @@ bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette)
if (has_palette) {
*has_palette = formats[format].has_palette;
}
+ if (is_panel_native) {
+ *is_panel_native = formats[format].is_panel_native;
+ }
return true;
}
-bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay) {
+bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_panel_native, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay) {
// Decode the format
- qgf_parse_format(frame_descriptor->format, bpp, has_palette);
+ qgf_parse_format(frame_descriptor->format, bpp, has_palette, is_panel_native);
// Copy out the required info
if (is_delta) {
@@ -173,7 +177,7 @@ void qgf_seek_to_frame_descriptor(qp_stream_t *stream, uint16_t frame_number) {
qp_stream_setpos(stream, offset);
}
-bool qgf_validate_frame_descriptor(qp_stream_t *stream, uint16_t frame_number, uint8_t *bpp, bool *has_palette, bool *is_delta) {
+bool qgf_validate_frame_descriptor(qp_stream_t *stream, uint16_t frame_number, uint8_t *bpp, bool *has_palette, bool *is_panel_native, bool *is_delta) {
// Seek to the correct location
qgf_seek_to_frame_descriptor(stream, frame_number);
@@ -189,7 +193,7 @@ bool qgf_validate_frame_descriptor(qp_stream_t *stream, uint16_t frame_number, u
return false;
}
- return qgf_parse_frame_descriptor(&frame_descriptor, bpp, has_palette, is_delta, NULL, NULL);
+ return qgf_parse_frame_descriptor(&frame_descriptor, bpp, has_palette, is_panel_native, is_delta, NULL, NULL);
}
bool qgf_validate_palette_descriptor(qp_stream_t *stream, uint16_t frame_number, uint8_t bpp) {
@@ -253,8 +257,9 @@ bool qgf_validate_stream(qp_stream_t *stream) {
// Validate the frame descriptor block
uint8_t bpp;
bool has_palette;
+ bool is_panel_native;
bool has_delta;
- if (!qgf_validate_frame_descriptor(stream, i, &bpp, &has_palette, &has_delta)) {
+ if (!qgf_validate_frame_descriptor(stream, i, &bpp, &has_palette, &is_panel_native, &has_delta)) {
return false;
}
diff --git a/quantum/painter/qgf.h b/quantum/painter/qgf.h
index 54585edd04..33a37709e6 100644
--- a/quantum/painter/qgf.h
+++ b/quantum/painter/qgf.h
@@ -65,7 +65,7 @@ _Static_assert(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t),
typedef struct QP_PACKED qgf_frame_v1_t {
qgf_block_header_v1_t header; // = { .type_id = 0x02, .neg_type_id = (~0x02), .length = 6 }
- qp_image_format_t format : 8; // Frame format, see qp.h.
+ qp_image_format_t format : 8; // Frame format, see qp_internal_formats.h.
uint8_t flags; // Frame flags, see below.
painter_compression_t compression_scheme : 8; // Compression scheme, see qp.h.
uint8_t transparency_index; // palette index used for transparent pixels (not yet implemented)
@@ -131,6 +131,6 @@ uint32_t qgf_get_total_size(qp_stream_t *stream);
bool qgf_validate_stream(qp_stream_t *stream);
bool qgf_validate_block_header(qgf_block_header_v1_t *desc, uint8_t expected_typeid, int32_t expected_length);
bool qgf_read_graphics_descriptor(qp_stream_t *stream, uint16_t *image_width, uint16_t *image_height, uint16_t *frame_count, uint32_t *total_bytes);
-bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette);
+bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette, bool *is_panel_native);
void qgf_seek_to_frame_descriptor(qp_stream_t *stream, uint16_t frame_number);
-bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay);
+bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_panel_native, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay);
diff --git a/quantum/painter/qp.c b/quantum/painter/qp.c
index f27bb7892a..3759866509 100644
--- a/quantum/painter/qp.c
+++ b/quantum/painter/qp.c
@@ -12,11 +12,11 @@
// Internal driver validation
static bool validate_driver_vtable(painter_driver_t *driver) {
- return (driver->driver_vtable && driver->driver_vtable->init && driver->driver_vtable->power && driver->driver_vtable->clear && driver->driver_vtable->viewport && driver->driver_vtable->pixdata && driver->driver_vtable->palette_convert && driver->driver_vtable->append_pixels && driver->driver_vtable->append_pixdata) ? true : false;
+ return (driver && driver->driver_vtable && driver->driver_vtable->init && driver->driver_vtable->power && driver->driver_vtable->clear && driver->driver_vtable->viewport && driver->driver_vtable->pixdata && driver->driver_vtable->palette_convert && driver->driver_vtable->append_pixels && driver->driver_vtable->append_pixdata) ? true : false;
}
static bool validate_comms_vtable(painter_driver_t *driver) {
- return (driver->comms_vtable && driver->comms_vtable->comms_init && driver->comms_vtable->comms_start && driver->comms_vtable->comms_stop && driver->comms_vtable->comms_send) ? true : false;
+ return (driver && driver->comms_vtable && driver->comms_vtable->comms_init && driver->comms_vtable->comms_start && driver->comms_vtable->comms_stop && driver->comms_vtable->comms_send) ? true : false;
}
static bool validate_driver_integrity(painter_driver_t *driver) {
@@ -131,49 +131,126 @@ bool qp_flush(painter_device_t device) {
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Quantum Painter External API: qp_get_geometry
+// Quantum Painter External API: qp_get_*
-void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height, painter_rotation_t *rotation, uint16_t *offset_x, uint16_t *offset_y) {
- qp_dprintf("qp_get_geometry: entry\n");
+uint16_t qp_get_width(painter_device_t device) {
+ qp_dprintf("qp_get_width: entry\n");
painter_driver_t *driver = (painter_driver_t *)device;
- if (!driver) {
- qp_dprintf("qp_get_geometry: fail (pointer to NULL)\n");
- return;
+ if (!driver || !driver->validate_ok) {
+ qp_dprintf("qp_get_width: fail (invalid driver)\n");
+ return 0;
+ }
+
+ uint16_t width;
+ switch (driver->rotation) {
+ default:
+ case QP_ROTATION_0:
+ case QP_ROTATION_180:
+ width = driver->panel_width;
+ break;
+ case QP_ROTATION_90:
+ case QP_ROTATION_270:
+ width = driver->panel_height;
+ break;
}
+ qp_dprintf("qp_get_width: ok\n");
+ return width;
+}
+
+uint16_t qp_get_height(painter_device_t device) {
+ qp_dprintf("qp_get_height: entry\n");
+ painter_driver_t *driver = (painter_driver_t *)device;
+
+ if (!driver || !driver->validate_ok) {
+ qp_dprintf("qp_get_height: fail (invalid driver)\n");
+ return 0;
+ }
+
+ uint16_t height;
switch (driver->rotation) {
default:
case QP_ROTATION_0:
case QP_ROTATION_180:
- if (width) {
- *width = driver->panel_width;
- }
- if (height) {
- *height = driver->panel_height;
- }
+ height = driver->panel_height;
break;
case QP_ROTATION_90:
case QP_ROTATION_270:
- if (width) {
- *width = driver->panel_height;
- }
- if (height) {
- *height = driver->panel_width;
- }
+ height = driver->panel_width;
break;
}
+ qp_dprintf("qp_get_height: ok\n");
+ return height;
+}
+
+painter_rotation_t qp_get_rotation(painter_device_t device) {
+ qp_dprintf("qp_get_rotation: entry\n");
+ painter_driver_t *driver = (painter_driver_t *)device;
+
+ if (!driver || !driver->validate_ok) {
+ qp_dprintf("qp_get_rotation: fail (invalid driver)\n");
+ return QP_ROTATION_0;
+ }
+
+ qp_dprintf("qp_get_rotation: ok\n");
+ return driver->rotation;
+}
+
+uint16_t qp_get_offset_x(painter_device_t device) {
+ qp_dprintf("qp_get_offset_x: entry\n");
+ painter_driver_t *driver = (painter_driver_t *)device;
+
+ if (!driver || !driver->validate_ok) {
+ qp_dprintf("qp_get_offset_x: fail (invalid driver)\n");
+ return 0;
+ }
+
+ qp_dprintf("qp_get_offset_x: ok\n");
+ return driver->offset_x;
+}
+
+uint16_t qp_get_offset_y(painter_device_t device) {
+ qp_dprintf("qp_get_offset_y: entry\n");
+ painter_driver_t *driver = (painter_driver_t *)device;
+
+ if (!driver || !driver->validate_ok) {
+ qp_dprintf("qp_get_offset_y: fail (invalid driver)\n");
+ return 0;
+ }
+
+ qp_dprintf("qp_get_offset_y: ok\n");
+ return driver->offset_y;
+}
+
+void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height, painter_rotation_t *rotation, uint16_t *offset_x, uint16_t *offset_y) {
+ qp_dprintf("qp_geometry: entry\n");
+ painter_driver_t *driver = (painter_driver_t *)device;
+
+ if (!driver || !driver->validate_ok) {
+ qp_dprintf("qp_geometry: fail (invalid driver)\n");
+ return;
+ }
+
+ if (width) {
+ *width = qp_get_width(device);
+ }
+
+ if (height) {
+ *height = qp_get_height(device);
+ }
+
if (rotation) {
- *rotation = driver->rotation;
+ *rotation = qp_get_rotation(device);
}
if (offset_x) {
- *offset_x = driver->offset_x;
+ *offset_x = qp_get_offset_x(device);
}
if (offset_y) {
- *offset_y = driver->offset_y;
+ *offset_y = qp_get_offset_y(device);
}
qp_dprintf("qp_get_geometry: ok\n");
diff --git a/quantum/painter/qp.h b/quantum/painter/qp.h
index 7222d3b413..873a9d9f32 100644
--- a/quantum/painter/qp.h
+++ b/quantum/painter/qp.h
@@ -176,6 +176,41 @@ bool qp_clear(painter_device_t device);
bool qp_flush(painter_device_t device);
/**
+ * Retrieves the width of the display.
+ *
+ * @param device[in] the handle of the device to control
+ */
+uint16_t qp_get_width(painter_device_t device);
+
+/**
+ * Retrieves the height of the display.
+ *
+ * @param device[in] the handle of the device to control
+ */
+uint16_t qp_get_height(painter_device_t device);
+
+/**
+ * Retrieves the rotation of the display.
+ *
+ * @param device[in] the handle of the device to control
+ */
+painter_rotation_t qp_get_rotation(painter_device_t device);
+
+/**
+ * Retrieves the x-offset of the display.
+ *
+ * @param device[in] the handle of the device to control
+ */
+uint16_t qp_get_offset_x(painter_device_t device);
+
+/**
+ * Retrieves the y-offset of the display.
+ *
+ * @param device[in] the handle of the device to control
+ */
+uint16_t qp_get_offset_y(painter_device_t device);
+
+/**
* Retrieves the size, rotation, and offsets for the display.
*
* @note Any arguments of NULL will be ignored.
@@ -504,6 +539,12 @@ int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, pai
# define SSD1351_NUM_DEVICES 0
#endif // QUANTUM_PAINTER_SSD1351_ENABLE
+#ifdef QUANTUM_PAINTER_SH1106_ENABLE
+# include "qp_sh1106.h"
+#else // QUANTUM_PAINTER_SH1106_ENABLE
+# define SH1106_NUM_DEVICES 0
+#endif // QUANTUM_PAINTER_SH1106_ENABLE
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter Extras
diff --git a/quantum/painter/qp_draw_ellipse.c b/quantum/painter/qp_draw_ellipse.c
index e912a3e91f..9e77bca8b0 100644
--- a/quantum/painter/qp_draw_ellipse.c
+++ b/quantum/painter/qp_draw_ellipse.c
@@ -67,10 +67,10 @@ bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex,
return false;
}
- int16_t aa = ((int16_t)sizex) * ((int16_t)sizex);
- int16_t bb = ((int16_t)sizey) * ((int16_t)sizey);
- int16_t fa = 4 * ((int16_t)aa);
- int16_t fb = 4 * ((int16_t)bb);
+ int32_t aa = ((int32_t)sizex) * ((int32_t)sizex);
+ int32_t bb = ((int32_t)sizey) * ((int32_t)sizey);
+ int32_t fa = 4 * aa;
+ int32_t fb = 4 * bb;
int16_t dx = 0;
int16_t dy = ((int16_t)sizey);
@@ -83,7 +83,7 @@ bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex,
}
bool ret = true;
- for (int16_t delta = (2 * bb) + (aa * (1 - (2 * sizey))); bb * dx <= aa * dy; dx++) {
+ for (int32_t delta = (2 * bb) + (aa * (1 - (2 * sizey))); bb * dx <= aa * dy; dx++) {
if (!qp_ellipse_helper_impl(device, x, y, dx, dy, filled)) {
ret = false;
break;
@@ -98,7 +98,7 @@ bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex,
dx = sizex;
dy = 0;
- for (int16_t delta = (2 * aa) + (bb * (1 - (2 * sizex))); aa * dy <= bb * dx; dy++) {
+ for (int32_t delta = (2 * aa) + (bb * (1 - (2 * sizex))); aa * dy <= bb * dx; dy++) {
if (!qp_ellipse_helper_impl(device, x, y, dx, dy, filled)) {
ret = false;
break;
diff --git a/quantum/painter/qp_draw_image.c b/quantum/painter/qp_draw_image.c
index fb17a05a1b..87c59148c2 100644
--- a/quantum/painter/qp_draw_image.c
+++ b/quantum/painter/qp_draw_image.c
@@ -115,6 +115,7 @@ typedef struct qgf_frame_info_t {
painter_compression_t compression_scheme;
uint8_t bpp;
bool has_palette;
+ bool is_panel_native;
bool is_delta;
uint16_t left;
uint16_t top;
@@ -143,7 +144,7 @@ static bool qp_drawimage_prepare_frame_for_stream_read(painter_device_t device,
}
// Parse out the frame info
- if (!qgf_parse_frame_descriptor(&frame_descriptor, &info->bpp, &info->has_palette, &info->is_delta, &info->compression_scheme, &info->delay)) {
+ if (!qgf_parse_frame_descriptor(&frame_descriptor, &info->bpp, &info->has_palette, &info->is_panel_native, &info->is_delta, &info->compression_scheme, &info->delay)) {
return false;
}
@@ -236,8 +237,8 @@ static bool qp_drawimage_recolor_impl(painter_device_t device, uint16_t x, uint1
if (frame_info->is_delta) {
l = x + frame_info->left;
t = y + frame_info->top;
- r = x + frame_info->right - 1;
- b = y + frame_info->bottom - 1;
+ r = x + frame_info->right;
+ b = y + frame_info->bottom;
} else {
l = x;
t = y;
@@ -263,7 +264,7 @@ static bool qp_drawimage_recolor_impl(painter_device_t device, uint16_t x, uint1
}
bool ret = false;
- if (frame_info->bpp <= 8) {
+ 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)};
diff --git a/quantum/painter/qp_draw_text.c b/quantum/painter/qp_draw_text.c
index ff6fc01d11..1ac5cab646 100644
--- a/quantum/painter/qp_draw_text.c
+++ b/quantum/painter/qp_draw_text.c
@@ -19,6 +19,7 @@ typedef struct qff_font_handle_t {
uint16_t num_unicode_glyphs;
uint8_t bpp;
bool has_palette;
+ bool is_panel_native;
painter_compression_t compression_scheme;
union {
qp_stream_t stream;
@@ -97,7 +98,7 @@ static painter_font_handle_t qp_load_font_internal(bool (*stream_factory)(qff_fo
#endif // QUANTUM_PAINTER_LOAD_FONTS_TO_RAM
// Read the info (parsing already successful above, no need to check return value)
- qff_read_font_descriptor(&font->stream, &font->base.line_height, &font->has_ascii_table, &font->num_unicode_glyphs, &font->bpp, &font->has_palette, &font->compression_scheme, NULL);
+ qff_read_font_descriptor(&font->stream, &font->base.line_height, &font->has_ascii_table, &font->num_unicode_glyphs, &font->bpp, &font->has_palette, &font->is_panel_native, &font->compression_scheme, NULL);
if (!qp_internal_bpp_capable(font->bpp)) {
qp_dprintf("qp_load_font: fail (image bpp too high (%d), check QUANTUM_PAINTER_SUPPORTS_256_PALETTE or QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS)\n", (int)font->bpp);
diff --git a/quantum/painter/qp_internal.c b/quantum/painter/qp_internal.c
index 87a30c3f9b..0e81467e26 100644
--- a/quantum/painter/qp_internal.c
+++ b/quantum/painter/qp_internal.c
@@ -16,6 +16,7 @@ enum {
+ (ST7735_NUM_DEVICES) // ST7735
+ (GC9A01_NUM_DEVICES) // GC9A01
+ (SSD1351_NUM_DEVICES) // SSD1351
+ + (SH1106_NUM_DEVICES) // SH1106
};
static painter_device_t qp_devices[QP_NUM_DEVICES] = {NULL};
diff --git a/quantum/painter/qp_internal_formats.h b/quantum/painter/qp_internal_formats.h
index 194f82b31a..1beb604b9e 100644
--- a/quantum/painter/qp_internal_formats.h
+++ b/quantum/painter/qp_internal_formats.h
@@ -44,8 +44,8 @@ typedef enum qp_image_format_t {
PALETTE_2BPP = 0x05,
PALETTE_4BPP = 0x06,
PALETTE_8BPP = 0x07,
- RGB565_16BPP = 0x08,
- RGB888_24BPP = 0x09,
+ RGB565_16BPP = 0x08, // Natively streamed to the panel, no interpolation or palette handling
+ RGB888_24BPP = 0x09, // Natively streamed to the panel, no interpolation or palette handling
} qp_image_format_t;
typedef enum painter_compression_t { IMAGE_UNCOMPRESSED, IMAGE_COMPRESSED_RLE } painter_compression_t;
diff --git a/quantum/painter/rules.mk b/quantum/painter/rules.mk
index 7752936cbd..ca81cffb03 100644
--- a/quantum/painter/rules.mk
+++ b/quantum/painter/rules.mk
@@ -6,14 +6,16 @@ QUANTUM_PAINTER_LVGL_INTEGRATION ?= no
# The list of permissible drivers that can be listed in QUANTUM_PAINTER_DRIVERS
VALID_QUANTUM_PAINTER_DRIVERS := \
- rgb565_surface \
- ili9163_spi \
- ili9341_spi \
- ili9488_spi \
- st7735_spi \
- st7789_spi \
- gc9a01_spi \
- ssd1351_spi
+ surface \
+ ili9163_spi \
+ ili9341_spi \
+ ili9488_spi \
+ st7735_spi \
+ st7789_spi \
+ gc9a01_spi \
+ ssd1351_spi \
+ sh1106_i2c \
+ sh1106_spi
#-------------------------------------------------------------------------------
@@ -42,7 +44,9 @@ ifeq ($(strip $(QUANTUM_PAINTER_ANIMATIONS_ENABLE)), yes)
endif
# Comms flags
+QUANTUM_PAINTER_NEEDS_COMMS_DUMMY ?= no
QUANTUM_PAINTER_NEEDS_COMMS_SPI ?= no
+QUANTUM_PAINTER_NEEDS_COMMS_I2C ?= no
# Handler for each driver
define handle_quantum_painter_driver
@@ -51,12 +55,8 @@ define handle_quantum_painter_driver
ifeq ($$(filter $$(strip $$(CURRENT_PAINTER_DRIVER)),$$(VALID_QUANTUM_PAINTER_DRIVERS)),)
$$(error "$$(CURRENT_PAINTER_DRIVER)" is not a valid Quantum Painter driver)
- else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),rgb565_surface)
- OPT_DEFS += -DQUANTUM_PAINTER_RGB565_SURFACE_ENABLE
- COMMON_VPATH += \
- $(DRIVER_PATH)/painter/generic
- SRC += \
- $(DRIVER_PATH)/painter/generic/qp_rgb565_surface.c \
+ else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),surface)
+ QUANTUM_PAINTER_NEEDS_SURFACE := yes
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ili9163_spi)
QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
@@ -135,16 +135,60 @@ define handle_quantum_painter_driver
$(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
$(DRIVER_PATH)/painter/ssd1351/qp_ssd1351.c
+ else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),sh1106_spi)
+ QUANTUM_PAINTER_NEEDS_SURFACE := yes
+ QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
+ QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
+ OPT_DEFS += -DQUANTUM_PAINTER_SH1106_ENABLE -DQUANTUM_PAINTER_SH1106_SPI_ENABLE
+ COMMON_VPATH += \
+ $(DRIVER_PATH)/painter/oled_panel \
+ $(DRIVER_PATH)/painter/sh1106
+ SRC += \
+ $(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \
+ $(DRIVER_PATH)/painter/sh1106/qp_sh1106.c
+
+ else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),sh1106_i2c)
+ QUANTUM_PAINTER_NEEDS_SURFACE := yes
+ QUANTUM_PAINTER_NEEDS_COMMS_I2C := yes
+ OPT_DEFS += -DQUANTUM_PAINTER_SH1106_ENABLE -DQUANTUM_PAINTER_SH1106_I2C_ENABLE
+ COMMON_VPATH += \
+ $(DRIVER_PATH)/painter/oled_panel \
+ $(DRIVER_PATH)/painter/sh1106
+ SRC += \
+ $(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \
+ $(DRIVER_PATH)/painter/sh1106/qp_sh1106.c
+
endif
endef
# Iterate through the listed drivers for the build, including what's necessary
$(foreach qp_driver,$(QUANTUM_PAINTER_DRIVERS),$(eval $(call handle_quantum_painter_driver,$(qp_driver))))
+# If a surface is needed, set up the required files
+ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_SURFACE)), yes)
+ QUANTUM_PAINTER_NEEDS_COMMS_DUMMY := yes
+ OPT_DEFS += -DQUANTUM_PAINTER_SURFACE_ENABLE
+ COMMON_VPATH += \
+ $(DRIVER_PATH)/painter/generic
+ SRC += \
+ $(DRIVER_PATH)/painter/generic/qp_surface_common.c \
+ $(DRIVER_PATH)/painter/generic/qp_surface_mono1bpp.c \
+ $(DRIVER_PATH)/painter/generic/qp_surface_rgb565.c
+endif
+
+# If dummy comms is needed, set up the required files
+ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_COMMS_DUMMY)), yes)
+ OPT_DEFS += -DQUANTUM_PAINTER_DUMMY_COMMS_ENABLE
+ VPATH += $(DRIVER_PATH)/painter/comms
+ SRC += \
+ $(QUANTUM_DIR)/painter/qp_comms.c \
+ $(DRIVER_PATH)/painter/comms/qp_comms_dummy.c
+endif
+
# If SPI comms is needed, set up the required files
ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_COMMS_SPI)), yes)
OPT_DEFS += -DQUANTUM_PAINTER_SPI_ENABLE
- QUANTUM_LIB_SRC += spi_master.c
+ SPI_DRIVER_REQUIRED = yes
VPATH += $(DRIVER_PATH)/painter/comms
SRC += \
$(QUANTUM_DIR)/painter/qp_comms.c \
@@ -155,7 +199,17 @@ ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_COMMS_SPI)), yes)
endif
endif
+# If I2C comms is needed, set up the required files
+ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_COMMS_I2C)), yes)
+ OPT_DEFS += -DQUANTUM_PAINTER_I2C_ENABLE
+ I2C_DRIVER_REQUIRED = yes
+ VPATH += $(DRIVER_PATH)/painter/comms
+ SRC += \
+ $(QUANTUM_DIR)/painter/qp_comms.c \
+ $(DRIVER_PATH)/painter/comms/qp_comms_i2c.c
+endif
+
# Check if LVGL needs to be enabled
ifeq ($(strip $(QUANTUM_PAINTER_LVGL_INTEGRATION)), yes)
- include $(QUANTUM_DIR)/painter/lvgl/rules.mk
+ include $(QUANTUM_DIR)/painter/lvgl/rules.mk
endif
diff --git a/quantum/pointing_device/pointing_device.h b/quantum/pointing_device/pointing_device.h
index afd653eaee..1cd4b0b5e6 100644
--- a/quantum/pointing_device/pointing_device.h
+++ b/quantum/pointing_device/pointing_device.h
@@ -39,6 +39,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "analog.h"
# include "drivers/sensors/analog_joystick.h"
# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
+#elif defined(POINTING_DEVICE_DRIVER_azoteq_iqs5xx)
+# include "i2c_master.h"
+# include "drivers/sensors/azoteq_iqs5xx.h"
#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
# include "drivers/sensors/cirque_pinnacle.h"
# include "drivers/sensors/cirque_pinnacle_gestures.h"
diff --git a/quantum/pointing_device/pointing_device_drivers.c b/quantum/pointing_device/pointing_device_drivers.c
index 9a4315f76f..bf131c6eda 100644
--- a/quantum/pointing_device/pointing_device_drivers.c
+++ b/quantum/pointing_device/pointing_device_drivers.c
@@ -115,6 +115,119 @@ const pointing_device_driver_t pointing_device_driver = {
};
// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_azoteq_iqs5xx)
+
+static i2c_status_t azoteq_iqs5xx_init_status = 1;
+
+void azoteq_iqs5xx_init(void) {
+ i2c_init();
+ azoteq_iqs5xx_wake();
+ azoteq_iqs5xx_reset_suspend(true, false, true);
+ wait_ms(100);
+ azoteq_iqs5xx_wake();
+ if (azoteq_iqs5xx_get_product() != AZOTEQ_IQS5XX_UNKNOWN) {
+ azoteq_iqs5xx_setup_resolution();
+ azoteq_iqs5xx_init_status = azoteq_iqs5xx_set_report_rate(AZOTEQ_IQS5XX_REPORT_RATE, AZOTEQ_IQS5XX_ACTIVE, false);
+ azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_event_mode(false, false);
+ azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_reati(true, false);
+# if defined(AZOTEQ_IQS5XX_ROTATION_90)
+ azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_xy_config(false, true, true, true, false);
+# elif defined(AZOTEQ_IQS5XX_ROTATION_180)
+ azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_xy_config(true, true, false, true, false);
+# elif defined(AZOTEQ_IQS5XX_ROTATION_270)
+ azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_xy_config(true, false, true, true, false);
+# else
+ azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_xy_config(false, false, false, true, false);
+# endif
+ azoteq_iqs5xx_init_status |= azoteq_iqs5xx_set_gesture_config(true);
+ wait_ms(AZOTEQ_IQS5XX_REPORT_RATE + 1);
+ }
+};
+
+report_mouse_t azoteq_iqs5xx_get_report(report_mouse_t mouse_report) {
+ report_mouse_t temp_report = {0};
+ static uint8_t previous_button_state = 0;
+ static uint8_t read_error_count = 0;
+
+ if (azoteq_iqs5xx_init_status == I2C_STATUS_SUCCESS) {
+ azoteq_iqs5xx_base_data_t base_data = {0};
+# if !defined(POINTING_DEVICE_MOTION_PIN)
+ azoteq_iqs5xx_wake();
+# endif
+ i2c_status_t status = azoteq_iqs5xx_get_base_data(&base_data);
+ bool ignore_movement = false;
+
+ if (status == I2C_STATUS_SUCCESS) {
+ // pd_dprintf("IQS5XX - previous cycle time: %d \n", base_data.previous_cycle_time);
+ read_error_count = 0;
+ if (base_data.gesture_events_0.single_tap || base_data.gesture_events_0.press_and_hold) {
+ pd_dprintf("IQS5XX - Single tap/hold.\n");
+ temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON1);
+ } else if (base_data.gesture_events_1.two_finger_tap) {
+ pd_dprintf("IQS5XX - Two finger tap.\n");
+ temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON2);
+ } else if (base_data.gesture_events_0.swipe_x_neg) {
+ pd_dprintf("IQS5XX - X-.\n");
+ temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON4);
+ ignore_movement = true;
+ } else if (base_data.gesture_events_0.swipe_x_pos) {
+ pd_dprintf("IQS5XX - X+.\n");
+ temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON5);
+ ignore_movement = true;
+ } else if (base_data.gesture_events_0.swipe_y_neg) {
+ pd_dprintf("IQS5XX - Y-.\n");
+ temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON6);
+ ignore_movement = true;
+ } else if (base_data.gesture_events_0.swipe_y_pos) {
+ pd_dprintf("IQS5XX - Y+.\n");
+ temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON3);
+ ignore_movement = true;
+ } else if (base_data.gesture_events_1.zoom) {
+ if (AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.x.h, base_data.x.l) < 0) {
+ pd_dprintf("IQS5XX - Zoom out.\n");
+ temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON7);
+ } else if (AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.x.h, base_data.x.l) > 0) {
+ pd_dprintf("IQS5XX - Zoom in.\n");
+ temp_report.buttons = pointing_device_handle_buttons(temp_report.buttons, true, POINTING_DEVICE_BUTTON8);
+ }
+ } else if (base_data.gesture_events_1.scroll) {
+ pd_dprintf("IQS5XX - Scroll.\n");
+ temp_report.h = CONSTRAIN_HID(AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.x.h, base_data.x.l));
+ temp_report.v = CONSTRAIN_HID(AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.y.h, base_data.y.l));
+ }
+ if (base_data.number_of_fingers == 1 && !ignore_movement) {
+ temp_report.x = CONSTRAIN_HID_XY(AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.x.h, base_data.x.l));
+ temp_report.y = CONSTRAIN_HID_XY(AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(base_data.y.h, base_data.y.l));
+ }
+
+ previous_button_state = temp_report.buttons;
+
+ } else {
+ if (read_error_count > 10) {
+ read_error_count = 0;
+ previous_button_state = 0;
+ } else {
+ read_error_count++;
+ }
+ temp_report.buttons = previous_button_state;
+ pd_dprintf("IQS5XX - get report failed: %d \n", status);
+ }
+ } else {
+ pd_dprintf("IQS5XX - Init failed: %d \n", azoteq_iqs5xx_init_status);
+ }
+
+ return temp_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = azoteq_iqs5xx_init,
+ .get_report = azoteq_iqs5xx_get_report,
+ .set_cpi = azoteq_iqs5xx_set_cpi,
+ .get_cpi = azoteq_iqs5xx_get_cpi
+};
+// clang-format on
+
#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
# ifdef POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE
static bool cursor_glide_enable = true;
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index 9b78214e43..28a21c4b67 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -66,7 +66,7 @@ __attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyreco
return false;
}
-/** \brief Called on physical press, returns whether is Auto Shift key */
+/** \brief Called on physical press, returns whether key is an Auto Shift key */
__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
#ifndef NO_AUTO_SHIFT_ALPHA
@@ -178,9 +178,8 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)
}
// Store record to be sent to user functions if there's no release record then.
- autoshift_lastrecord = *record;
- autoshift_lastrecord.event.pressed = false;
- autoshift_lastrecord.event.time = 0;
+ autoshift_lastrecord = *record;
+ autoshift_lastrecord.event.time = 0;
// clang-format off
#if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)
if (keycode == autoshift_lastkey &&
@@ -409,8 +408,12 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
// If Retro Shift is disabled, possible custom actions shouldn't happen.
// clang-format off
#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
-# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
- const bool is_hold_on_interrupt = get_hold_on_other_key_press(keycode, record);
+# ifdef HOLD_ON_OTHER_KEY_PRESS
+ const bool is_hold_on_interrupt = (IS_QK_MOD_TAP(keycode)
+# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
+ && get_hold_on_other_key_press(keycode, record)
+# endif
+ );
# else
const bool is_hold_on_interrupt = false;
# endif
@@ -450,8 +453,12 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
#endif
) {
// Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set.
-#ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
- if (autoshift_flags.in_progress && get_hold_on_other_key_press(keycode, record)) {
+#ifdef HOLD_ON_OTHER_KEY_PRESS
+ if (autoshift_flags.in_progress
+# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
+ && get_hold_on_other_key_press(keycode, record)
+# endif
+ ) {
autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
}
#endif
@@ -488,10 +495,8 @@ void retroshift_poll_time(keyevent_t *event) {
}
// Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it.
void retroshift_swap_times(void) {
- if (last_retroshift_time != 0 && autoshift_flags.in_progress) {
- uint16_t temp = retroshift_time;
- retroshift_time = last_retroshift_time;
- last_retroshift_time = temp;
+ if (autoshift_flags.in_progress) {
+ autoshift_time = last_retroshift_time;
}
}
#endif
diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
index 885a47b533..1353548aa6 100644
--- a/quantum/process_keycode/process_auto_shift.h
+++ b/quantum/process_keycode/process_auto_shift.h
@@ -56,4 +56,5 @@ uint16_t (get_autoshift_timeout)(uint16_t keycode, keyrecord_t *record);
void set_autoshift_timeout(uint16_t timeout);
void autoshift_matrix_scan(void);
bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
+bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
// clang-format on
diff --git a/quantum/process_keycode/process_clicky.c b/quantum/process_keycode/process_clicky.c
index 0ee58282e6..82000db9b3 100644
--- a/quantum/process_keycode/process_clicky.c
+++ b/quantum/process_keycode/process_clicky.c
@@ -28,7 +28,7 @@ float clicky_freq = AUDIO_CLICKY_FREQ_DEFAULT;
float clicky_rand = AUDIO_CLICKY_FREQ_RANDOMNESS;
// the first "note" is an intentional delay; the 2nd and 3rd notes are the "clicky"
-float clicky_song[][2] = {{AUDIO_CLICKY_FREQ_MIN, AUDIO_CLICKY_DELAY_DURATION}, {AUDIO_CLICKY_FREQ_DEFAULT, 3}, {AUDIO_CLICKY_FREQ_DEFAULT, 1}}; // 3 and 1 --> durations
+float clicky_song[][2] = {{0.0f, AUDIO_CLICKY_DELAY_DURATION}, {AUDIO_CLICKY_FREQ_DEFAULT, 3}, {AUDIO_CLICKY_FREQ_DEFAULT, 1}}; // 3 and 1 --> durations
extern audio_config_t audio_config;
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index af26d4ca86..bd4361580b 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -16,7 +16,6 @@
#include "process_steno.h"
#include "quantum_keycodes.h"
#include "eeconfig.h"
-#include "keymap_steno.h"
#include <string.h>
#ifdef VIRTSER_ENABLE
# include "virtser.h"
diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h
index 0dd2103218..5529980b71 100644
--- a/quantum/process_keycode/process_steno.h
+++ b/quantum/process_keycode/process_steno.h
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "action.h"
+#include "steno_keycodes.h"
#define BOLT_STROKE_SIZE 4
#define GEMINI_STROKE_SIZE 6
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 3323a5adb6..6639dc2291 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -40,7 +40,7 @@
# include "process_leader.h"
#endif
-#ifdef MAGIC_KEYCODE_ENABLE
+#ifdef MAGIC_ENABLE
# include "process_magic.h"
#endif
@@ -68,10 +68,6 @@
# include "process_unicode_common.h"
#endif
-#ifdef VELOCIKEY_ENABLE
-# include "velocikey.h"
-#endif
-
#ifdef AUDIO_ENABLE
# ifndef GOODBYE_SONG
# define GOODBYE_SONG SONG(GOODBYE_SOUND)
@@ -176,7 +172,7 @@ __attribute__((weak)) void post_process_record_kb(uint16_t keycode, keyrecord_t
__attribute__((weak)) void post_process_record_user(uint16_t keycode, keyrecord_t *record) {}
-void shutdown_quantum(void) {
+void shutdown_quantum(bool jump_to_bootloader) {
clear_keyboard();
#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
process_midi_all_notes_off();
@@ -187,12 +183,12 @@ void shutdown_quantum(void) {
# endif
uint16_t timer_start = timer_read();
PLAY_SONG(goodbye_song);
- shutdown_user();
+ shutdown_kb(jump_to_bootloader);
while (timer_elapsed(timer_start) < 250)
wait_ms(1);
stop_all_notes();
#else
- shutdown_user();
+ shutdown_kb(jump_to_bootloader);
wait_ms(250);
#endif
#ifdef HAPTIC_ENABLE
@@ -201,12 +197,12 @@ void shutdown_quantum(void) {
}
void reset_keyboard(void) {
- shutdown_quantum();
+ shutdown_quantum(true);
bootloader_jump();
}
void soft_reset_keyboard(void) {
- shutdown_quantum();
+ shutdown_quantum(false);
mcu_reset();
}
@@ -288,9 +284,9 @@ bool process_record_quantum(keyrecord_t *record) {
}
#endif
-#ifdef VELOCIKEY_ENABLE
- if (velocikey_enabled() && record->event.pressed) {
- velocikey_accelerate();
+#ifdef RGBLIGHT_ENABLE
+ if (record->event.pressed) {
+ preprocess_rgblight();
}
#endif
@@ -370,7 +366,7 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef SPACE_CADET_ENABLE
process_space_cadet(keycode, record) &&
#endif
-#ifdef MAGIC_KEYCODE_ENABLE
+#ifdef MAGIC_ENABLE
process_magic(keycode, record) &&
#endif
#ifdef GRAVE_ESC_ENABLE
@@ -495,9 +491,16 @@ void set_single_persistent_default_layer(uint8_t default_layer) {
// Override these functions in your keymap file to play different tunes on
// different events such as startup and bootloader jump
-__attribute__((weak)) void startup_user(void) {}
+__attribute__((weak)) bool shutdown_user(bool jump_to_bootloader) {
+ return true;
+}
-__attribute__((weak)) void shutdown_user(void) {}
+__attribute__((weak)) bool shutdown_kb(bool jump_to_bootloader) {
+ if (!shutdown_user(jump_to_bootloader)) {
+ return false;
+ }
+ return true;
+}
void suspend_power_down_quantum(void) {
suspend_power_down_kb();
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 4d183e755f..996e93a12f 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -56,6 +56,8 @@
#include "suspend.h"
#include <stddef.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
#ifdef DEFERRED_EXEC_ENABLE
# include "deferred_exec.h"
@@ -209,6 +211,10 @@ extern layer_state_t layer_state;
# include "pointing_device.h"
#endif
+#ifdef MOUSEKEY_ENABLE
+# include "mousekey.h"
+#endif
+
#ifdef CAPS_WORD_ENABLE
# include "caps_word.h"
# include "process_caps_word.h"
@@ -249,8 +255,8 @@ void post_process_record_user(uint16_t keycode, keyrecord_t *record);
void reset_keyboard(void);
void soft_reset_keyboard(void);
-void startup_user(void);
-void shutdown_user(void);
+bool shutdown_kb(bool jump_to_bootloader);
+bool shutdown_user(bool jump_to_bootloader);
void register_code16(uint16_t code);
void unregister_code16(uint16_t code);
diff --git a/quantum/rgb_matrix/animations/flower_blooming_anim.h b/quantum/rgb_matrix/animations/flower_blooming_anim.h
new file mode 100644
index 0000000000..7629fde858
--- /dev/null
+++ b/quantum/rgb_matrix/animations/flower_blooming_anim.h
@@ -0,0 +1,53 @@
+/* Copyright 2023 HorrorTroll <https://github.com/HorrorTroll>
+ *
+ * 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/>.
+ */
+
+#ifdef ENABLE_RGB_MATRIX_FLOWER_BLOOMING
+RGB_MATRIX_EFFECT(FLOWER_BLOOMING)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+typedef HSV (*flower_blooming_f)(HSV hsv, uint8_t i, uint8_t time);
+
+bool effect_runner_bloom(effect_params_t* params, flower_blooming_f effect_func) {
+ RGB_MATRIX_USE_LIMITS(led_min, led_max);
+
+ uint8_t time = scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed / 10, 1));
+ for (uint8_t i = led_min; i < led_max; i++) {
+ RGB_MATRIX_TEST_LED_FLAGS();
+ if (g_led_config.point[i].y > k_rgb_matrix_center.y) {
+ RGB bgr = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time));
+ rgb_matrix_set_color(i, bgr.b, bgr.g, bgr.r);
+ } else {
+ RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time));
+ rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
+ }
+ }
+ return rgb_matrix_check_finished_leds(led_max);
+}
+
+static HSV FLOWER_BLOOMING_math(HSV hsv, uint8_t i, uint8_t time) {
+ if (g_led_config.point[i].y > k_rgb_matrix_center.y)
+ hsv.h = g_led_config.point[i].x * 3 - g_led_config.point[i].y * 3 + time;
+ else
+ hsv.h = g_led_config.point[i].x * 3 - g_led_config.point[i].y * 3 - time;
+ return hsv;
+}
+
+bool FLOWER_BLOOMING(effect_params_t* params) {
+ return effect_runner_bloom(params, &FLOWER_BLOOMING_math);
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_FLOWER_BLOOMING
diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
index ac7bac428d..a02238a2d1 100644
--- a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
+++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
@@ -21,6 +21,7 @@
#include "dual_beacon_anim.h"
#include "rainbow_beacon_anim.h"
#include "rainbow_pinwheels_anim.h"
+#include "flower_blooming_anim.h"
#include "raindrops_anim.h"
#include "jellybean_raindrops_anim.h"
#include "hue_breathing_anim.h"
@@ -38,3 +39,7 @@
#include "solid_reactive_nexus.h"
#include "splash_anim.h"
#include "solid_splash_anim.h"
+#include "starlight_anim.h"
+#include "starlight_dual_sat_anim.h"
+#include "starlight_dual_hue_anim.h"
+#include "riverflow_anim.h" \ No newline at end of file
diff --git a/quantum/rgb_matrix/animations/riverflow_anim.h b/quantum/rgb_matrix/animations/riverflow_anim.h
new file mode 100644
index 0000000000..79a38e7f6e
--- /dev/null
+++ b/quantum/rgb_matrix/animations/riverflow_anim.h
@@ -0,0 +1,22 @@
+#ifdef ENABLE_RGB_MATRIX_RIVERFLOW
+RGB_MATRIX_EFFECT(RIVERFLOW)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+// inspired by @PleasureTek's Massdrop Alt LED animation
+
+bool RIVERFLOW(effect_params_t* params) {
+ RGB_MATRIX_USE_LIMITS(led_min, led_max);
+ for (uint8_t i = led_min; i < led_max; i++) {
+ HSV hsv = rgb_matrix_config.hsv;
+ uint16_t time = scale16by8(g_rgb_timer + (i * 315), rgb_matrix_config.speed / 8);
+ hsv.v = scale8(abs8(sin8(time) - 128) * 2, hsv.v);
+ RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
+ RGB_MATRIX_TEST_LED_FLAGS();
+ rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
+ }
+
+ return rgb_matrix_check_finished_leds(led_max);
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_RIVERFLOW
diff --git a/quantum/rgb_matrix/animations/starlight_anim.h b/quantum/rgb_matrix/animations/starlight_anim.h
new file mode 100644
index 0000000000..33f0b61a91
--- /dev/null
+++ b/quantum/rgb_matrix/animations/starlight_anim.h
@@ -0,0 +1,30 @@
+#ifdef ENABLE_RGB_MATRIX_STARLIGHT
+RGB_MATRIX_EFFECT(STARLIGHT)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+void set_starlight_color(int i, effect_params_t* params) {
+ uint16_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 8);
+ HSV hsv = rgb_matrix_config.hsv;
+ hsv.v = scale8(abs8(sin8(time) - 128) * 2, hsv.v);
+ RGB rgb = hsv_to_rgb(hsv);
+ rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
+}
+
+bool STARLIGHT(effect_params_t* params) {
+ if (!params->init) {
+ if (scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed, 5)) % 5 == 0) {
+ int rand_led = rand() % RGB_MATRIX_LED_COUNT;
+ set_starlight_color(rand_led, params);
+ }
+ return false;
+ }
+
+ RGB_MATRIX_USE_LIMITS(led_min, led_max);
+ for (int i = led_min; i < led_max; i++) {
+ set_starlight_color(i, params);
+ }
+ return rgb_matrix_check_finished_leds(led_max);
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_STARLIGHT \ No newline at end of file
diff --git a/quantum/rgb_matrix/animations/starlight_dual_hue_anim.h b/quantum/rgb_matrix/animations/starlight_dual_hue_anim.h
new file mode 100644
index 0000000000..df6461b8b7
--- /dev/null
+++ b/quantum/rgb_matrix/animations/starlight_dual_hue_anim.h
@@ -0,0 +1,31 @@
+#ifdef ENABLE_RGB_MATRIX_STARLIGHT_DUAL_HUE
+RGB_MATRIX_EFFECT(STARLIGHT_DUAL_HUE)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+void set_starlight_dual_hue_color(int i, effect_params_t* params) {
+ uint16_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 8);
+ HSV hsv = rgb_matrix_config.hsv;
+ hsv.v = scale8(abs8(sin8(time) - 128) * 2, hsv.v);
+ hsv.h = hsv.h + (rand() % (30 + 1 - -30) + -30);
+ RGB rgb = hsv_to_rgb(hsv);
+ rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
+}
+
+bool STARLIGHT_DUAL_HUE(effect_params_t* params) {
+ if (!params->init) {
+ if (scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed, 5)) % 5 == 0) {
+ int rand_led = rand() % RGB_MATRIX_LED_COUNT;
+ set_starlight_dual_hue_color(rand_led, params);
+ }
+ return false;
+ }
+
+ RGB_MATRIX_USE_LIMITS(led_min, led_max);
+ for (int i = led_min; i < led_max; i++) {
+ set_starlight_dual_hue_color(i, params);
+ }
+ return rgb_matrix_check_finished_leds(led_max);
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_STARLIGHT_DUAL_HUE \ No newline at end of file
diff --git a/quantum/rgb_matrix/animations/starlight_dual_sat_anim.h b/quantum/rgb_matrix/animations/starlight_dual_sat_anim.h
new file mode 100644
index 0000000000..f6ecd48aa1
--- /dev/null
+++ b/quantum/rgb_matrix/animations/starlight_dual_sat_anim.h
@@ -0,0 +1,31 @@
+#ifdef ENABLE_RGB_MATRIX_STARLIGHT_DUAL_SAT
+RGB_MATRIX_EFFECT(STARLIGHT_DUAL_SAT)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+void set_starlight_dual_sat_color(int i, effect_params_t* params) {
+ uint16_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 8);
+ HSV hsv = rgb_matrix_config.hsv;
+ hsv.v = scale8(abs8(sin8(time) - 128) * 2, hsv.v);
+ hsv.s = hsv.s + (rand() % (30 + 1 - -30) + -30);
+ RGB rgb = hsv_to_rgb(hsv);
+ rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
+}
+
+bool STARLIGHT_DUAL_SAT(effect_params_t* params) {
+ if (!params->init) {
+ if (scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed, 5)) % 5 == 0) {
+ int rand_led = rand() % RGB_MATRIX_LED_COUNT;
+ set_starlight_dual_sat_color(rand_led, params);
+ }
+ return false;
+ }
+
+ RGB_MATRIX_USE_LIMITS(led_min, led_max);
+ for (int i = led_min; i < led_max; i++) {
+ set_starlight_dual_sat_color(i, params);
+ }
+ return rgb_matrix_check_finished_leds(led_max);
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_STARLIGHT_DUAL_SAT \ No newline at end of file
diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index 96be615162..d93d189827 100644
--- a/quantum/rgb_matrix/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -60,56 +60,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) {
// -----End rgb effect includes macros-------
// ------------------------------------------
-#ifndef RGB_MATRIX_TIMEOUT
-# define RGB_MATRIX_TIMEOUT 0
-#endif
-
-#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
-# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
-# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
-#endif
-
-#if !defined(RGB_MATRIX_HUE_STEP)
-# define RGB_MATRIX_HUE_STEP 8
-#endif
-
-#if !defined(RGB_MATRIX_SAT_STEP)
-# define RGB_MATRIX_SAT_STEP 16
-#endif
-
-#if !defined(RGB_MATRIX_VAL_STEP)
-# define RGB_MATRIX_VAL_STEP 16
-#endif
-
-#if !defined(RGB_MATRIX_SPD_STEP)
-# define RGB_MATRIX_SPD_STEP 16
-#endif
-
-#if !defined(RGB_MATRIX_DEFAULT_MODE)
-# ifdef ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
-# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_CYCLE_LEFT_RIGHT
-# else
-// fallback to solid colors if RGB_MATRIX_CYCLE_LEFT_RIGHT is disabled in userspace
-# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_SOLID_COLOR
-# endif
-#endif
-
-#if !defined(RGB_MATRIX_DEFAULT_HUE)
-# define RGB_MATRIX_DEFAULT_HUE 0
-#endif
-
-#if !defined(RGB_MATRIX_DEFAULT_SAT)
-# define RGB_MATRIX_DEFAULT_SAT UINT8_MAX
-#endif
-
-#if !defined(RGB_MATRIX_DEFAULT_VAL)
-# define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS
-#endif
-
-#if !defined(RGB_MATRIX_DEFAULT_SPD)
-# define RGB_MATRIX_DEFAULT_SPD UINT8_MAX / 2
-#endif
-
// globals
rgb_config_t rgb_matrix_config; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr
uint32_t g_rgb_timer;
@@ -149,7 +99,7 @@ void eeconfig_update_rgb_matrix(void) {
void eeconfig_update_rgb_matrix_default(void) {
dprintf("eeconfig_update_rgb_matrix_default\n");
- rgb_matrix_config.enable = 1;
+ rgb_matrix_config.enable = RGB_MATRIX_DEFAULT_ON;
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;
@@ -433,8 +383,7 @@ void rgb_matrix_task(void) {
case RENDERING:
rgb_task_render(effect);
if (effect) {
- // Only run the basic indicators in the last render iteration (default there are 5 iterations)
- if (rgb_effect_params.iter == RGB_MATRIX_LED_PROCESS_MAX_ITERATIONS) {
+ if (rgb_task_state == FLUSHING) { // ensure we only draw basic indicators once rendering is finished
rgb_matrix_indicators();
}
rgb_matrix_indicators_advanced(&rgb_effect_params);
@@ -461,6 +410,36 @@ __attribute__((weak)) bool rgb_matrix_indicators_user(void) {
return true;
}
+struct rgb_matrix_limits_t rgb_matrix_get_limits(uint8_t iter) {
+ struct rgb_matrix_limits_t limits = {0};
+#if defined(RGB_MATRIX_LED_PROCESS_LIMIT) && RGB_MATRIX_LED_PROCESS_LIMIT > 0 && RGB_MATRIX_LED_PROCESS_LIMIT < RGB_MATRIX_LED_COUNT
+# if defined(RGB_MATRIX_SPLIT)
+ limits.led_min_index = RGB_MATRIX_LED_PROCESS_LIMIT * (iter);
+ limits.led_max_index = limits.led_min_index + RGB_MATRIX_LED_PROCESS_LIMIT;
+ if (limits.led_max_index > RGB_MATRIX_LED_COUNT) limits.led_max_index = RGB_MATRIX_LED_COUNT;
+ uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
+ if (is_keyboard_left() && (limits.led_max_index > k_rgb_matrix_split[0])) limits.led_max_index = k_rgb_matrix_split[0];
+ if (!(is_keyboard_left()) && (limits.led_min_index < k_rgb_matrix_split[0])) limits.led_min_index = k_rgb_matrix_split[0];
+# else
+ limits.led_min_index = RGB_MATRIX_LED_PROCESS_LIMIT * (iter);
+ limits.led_max_index = limits.led_min_index + RGB_MATRIX_LED_PROCESS_LIMIT;
+ if (limits.led_max_index > RGB_MATRIX_LED_COUNT) limits.led_max_index = RGB_MATRIX_LED_COUNT;
+# endif
+#else
+# if defined(RGB_MATRIX_SPLIT)
+ limits.led_min_index = 0;
+ limits.led_max_index = RGB_MATRIX_LED_COUNT;
+ const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
+ if (is_keyboard_left() && (limits.led_max_index > k_rgb_matrix_split[0])) limits.led_max_index = k_rgb_matrix_split[0];
+ if (!(is_keyboard_left()) && (limits.led_min_index < k_rgb_matrix_split[0])) limits.led_min_index = k_rgb_matrix_split[0];
+# else
+ limits.led_min_index = 0;
+ limits.led_max_index = RGB_MATRIX_LED_COUNT;
+# endif
+#endif
+ return limits;
+}
+
void rgb_matrix_indicators_advanced(effect_params_t *params) {
/* special handling is needed for "params->iter", since it's already been incremented.
* Could move the invocations to rgb_task_render, but then it's missing a few checks
@@ -736,7 +715,7 @@ void rgb_matrix_decrease_speed(void) {
void rgb_matrix_set_flags_eeprom_helper(led_flags_t flags, bool write_to_eeprom) {
rgb_matrix_config.flags = flags;
eeconfig_flag_rgb_matrix(write_to_eeprom);
- dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.flags);
+ dprintf("rgb matrix set flags [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.flags);
}
led_flags_t rgb_matrix_get_flags(void) {
diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h
index 38040fb0cc..9a3ffb8ea3 100644
--- a/quantum/rgb_matrix/rgb_matrix.h
+++ b/quantum/rgb_matrix/rgb_matrix.h
@@ -24,26 +24,81 @@
#include "color.h"
#include "keyboard.h"
-#ifdef IS31FL3731
+#if defined(RGB_MATRIX_IS31FL3218)
+# include "is31fl3218.h"
+#elif defined(RGB_MATRIX_IS31FL3731)
# include "is31fl3731.h"
-#elif defined(IS31FL3733)
+#elif defined(RGB_MATRIX_IS31FL3733)
# include "is31fl3733.h"
-#elif defined(IS31FL3736)
+#elif defined(RGB_MATRIX_IS31FL3736)
# include "is31fl3736.h"
-#elif defined(IS31FL3737)
+#elif defined(RGB_MATRIX_IS31FL3737)
# include "is31fl3737.h"
-#elif defined(IS31FL3741)
+#elif defined(RGB_MATRIX_IS31FL3741)
# include "is31fl3741.h"
#elif defined(IS31FLCOMMON)
# include "is31flcommon.h"
-#elif defined(CKLED2001)
-# include "ckled2001.h"
-#elif defined(AW20216)
-# include "aw20216.h"
-#elif defined(WS2812)
+#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
+
+#ifndef RGB_MATRIX_MAXIMUM_BRIGHTNESS
+# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
+#endif
+
+#ifndef RGB_MATRIX_HUE_STEP
+# define RGB_MATRIX_HUE_STEP 8
+#endif
+
+#ifndef RGB_MATRIX_SAT_STEP
+# define RGB_MATRIX_SAT_STEP 16
+#endif
+
+#ifndef RGB_MATRIX_VAL_STEP
+# define RGB_MATRIX_VAL_STEP 16
+#endif
+
+#ifndef RGB_MATRIX_SPD_STEP
+# define RGB_MATRIX_SPD_STEP 16
+#endif
+
+#ifndef RGB_MATRIX_DEFAULT_ON
+# define RGB_MATRIX_DEFAULT_ON true
+#endif
+
+#ifndef RGB_MATRIX_DEFAULT_MODE
+# ifdef ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_CYCLE_LEFT_RIGHT
+# else
+// fallback to solid colors if RGB_MATRIX_CYCLE_LEFT_RIGHT is disabled in userspace
+# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_SOLID_COLOR
+# endif
+#endif
+
+#ifndef RGB_MATRIX_DEFAULT_HUE
+# define RGB_MATRIX_DEFAULT_HUE 0
+#endif
+
+#ifndef RGB_MATRIX_DEFAULT_SAT
+# define RGB_MATRIX_DEFAULT_SAT UINT8_MAX
+#endif
+
+#ifndef RGB_MATRIX_DEFAULT_VAL
+# define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS
+#endif
+
+#ifndef RGB_MATRIX_DEFAULT_SPD
+# define RGB_MATRIX_DEFAULT_SPD UINT8_MAX / 2
+#endif
+
#ifndef RGB_MATRIX_LED_FLUSH_LIMIT
# define RGB_MATRIX_LED_FLUSH_LIMIT 16
#endif
@@ -51,37 +106,20 @@
#ifndef RGB_MATRIX_LED_PROCESS_LIMIT
# define RGB_MATRIX_LED_PROCESS_LIMIT ((RGB_MATRIX_LED_COUNT + 4) / 5)
#endif
-#define RGB_MATRIX_LED_PROCESS_MAX_ITERATIONS ((RGB_MATRIX_LED_COUNT + RGB_MATRIX_LED_PROCESS_LIMIT - 1) / RGB_MATRIX_LED_PROCESS_LIMIT)
-
-#if defined(RGB_MATRIX_LED_PROCESS_LIMIT) && RGB_MATRIX_LED_PROCESS_LIMIT > 0 && RGB_MATRIX_LED_PROCESS_LIMIT < RGB_MATRIX_LED_COUNT
-# if defined(RGB_MATRIX_SPLIT)
-# define RGB_MATRIX_USE_LIMITS_ITER(min, max, iter) \
- uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * (iter); \
- uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \
- if (max > RGB_MATRIX_LED_COUNT) max = RGB_MATRIX_LED_COUNT; \
- uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; \
- if (is_keyboard_left() && (max > k_rgb_matrix_split[0])) max = k_rgb_matrix_split[0]; \
- if (!(is_keyboard_left()) && (min < k_rgb_matrix_split[0])) min = k_rgb_matrix_split[0];
-# else
-# define RGB_MATRIX_USE_LIMITS_ITER(min, max, iter) \
- uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * (iter); \
- uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \
- if (max > RGB_MATRIX_LED_COUNT) max = RGB_MATRIX_LED_COUNT;
-# endif
-#else
-# if defined(RGB_MATRIX_SPLIT)
-# define RGB_MATRIX_USE_LIMITS_ITER(min, max, iter) \
- uint8_t min = 0; \
- uint8_t max = RGB_MATRIX_LED_COUNT; \
- const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; \
- if (is_keyboard_left() && (max > k_rgb_matrix_split[0])) max = k_rgb_matrix_split[0]; \
- if (!(is_keyboard_left()) && (min < k_rgb_matrix_split[0])) min = k_rgb_matrix_split[0];
-# else
-# define RGB_MATRIX_USE_LIMITS_ITER(min, max, iter) \
- uint8_t min = 0; \
- uint8_t max = RGB_MATRIX_LED_COUNT;
-# endif
-#endif
+
+struct rgb_matrix_limits_t {
+ uint8_t led_min_index;
+ uint8_t led_max_index;
+};
+
+struct rgb_matrix_limits_t rgb_matrix_get_limits(uint8_t iter);
+
+#define RGB_MATRIX_USE_LIMITS_ITER(min, max, iter) \
+ struct rgb_matrix_limits_t limits = rgb_matrix_get_limits(iter); \
+ uint8_t min = limits.led_min_index; \
+ uint8_t max = limits.led_max_index; \
+ (void)min; \
+ (void)max;
#define RGB_MATRIX_USE_LIMITS(min, max) RGB_MATRIX_USE_LIMITS_ITER(min, max, params->iter)
diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c
index 695ecc78a4..0f979cb233 100644
--- a/quantum/rgb_matrix/rgb_matrix_drivers.c
+++ b/quantum/rgb_matrix/rgb_matrix_drivers.c
@@ -24,410 +24,87 @@
* be here if shared between boards.
*/
-#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3736) || defined(IS31FL3737) || defined(IS31FL3741) || defined(IS31FLCOMMON) || defined(CKLED2001)
-# include "i2c_master.h"
-
-// TODO: Remove this at some later date
-# if defined(DRIVER_ADDR_1) && defined(DRIVER_ADDR_2)
-# if DRIVER_ADDR_1 == DRIVER_ADDR_2
-# error "Setting DRIVER_ADDR_2 == DRIVER_ADDR_1 is obsolete. If you are only using one ISSI driver, set DRIVER_COUNT to 1 and remove DRIVER_ADDR_2"
-# endif
-# endif
-
-static void init(void) {
- i2c_init();
-
-# if defined(IS31FL3731)
- is31fl3731_init(DRIVER_ADDR_1);
-# if defined(DRIVER_ADDR_2)
- is31fl3731_init(DRIVER_ADDR_2);
-# if defined(DRIVER_ADDR_3)
- is31fl3731_init(DRIVER_ADDR_3);
-# if defined(DRIVER_ADDR_4)
- is31fl3731_init(DRIVER_ADDR_4);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3733)
-# if !defined(DRIVER_SYNC_1)
-# define DRIVER_SYNC_1 0
-# endif
- is31fl3733_init(DRIVER_ADDR_1, DRIVER_SYNC_1);
-# if defined(DRIVER_ADDR_2)
-# if !defined(DRIVER_SYNC_2)
-# define DRIVER_SYNC_2 0
-# endif
- is31fl3733_init(DRIVER_ADDR_2, DRIVER_SYNC_2);
-# if defined(DRIVER_ADDR_3)
-# if !defined(DRIVER_SYNC_3)
-# define DRIVER_SYNC_3 0
-# endif
- is31fl3733_init(DRIVER_ADDR_3, DRIVER_SYNC_3);
-# if defined(DRIVER_ADDR_4)
-# if !defined(DRIVER_SYNC_4)
-# define DRIVER_SYNC_4 0
-# endif
- is31fl3733_init(DRIVER_ADDR_4, DRIVER_SYNC_4);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3736)
- is31fl3736_init(DRIVER_ADDR_1);
-# if defined(DRIVER_ADDR_2)
- is31fl3736_init(DRIVER_ADDR_2);
-# if defined(DRIVER_ADDR_3)
- is31fl3736_init(DRIVER_ADDR_3);
-# if defined(DRIVER_ADDR_4)
- is31fl3736_init(DRIVER_ADDR_4);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3737)
- is31fl3737_init(DRIVER_ADDR_1);
-# if defined(DRIVER_ADDR_2)
- is31fl3737_init(DRIVER_ADDR_2);
-# if defined(DRIVER_ADDR_3)
- is31fl3737_init(DRIVER_ADDR_3);
-# if defined(DRIVER_ADDR_4)
- is31fl3737_init(DRIVER_ADDR_4);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3741)
- is31fl3741_init(DRIVER_ADDR_1);
-# if defined(DRIVER_ADDR_2)
- is31fl3741_init(DRIVER_ADDR_2);
-# if defined(DRIVER_ADDR_3)
- is31fl3741_init(DRIVER_ADDR_3);
-# if defined(DRIVER_ADDR_4)
- is31fl3741_init(DRIVER_ADDR_4);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FLCOMMON)
- IS31FL_common_init(DRIVER_ADDR_1, ISSI_SSR_1);
-# if defined(DRIVER_ADDR_2)
- IS31FL_common_init(DRIVER_ADDR_2, ISSI_SSR_2);
-# if defined(DRIVER_ADDR_3)
- IS31FL_common_init(DRIVER_ADDR_3, ISSI_SSR_3);
-# if defined(DRIVER_ADDR_4)
- IS31FL_common_init(DRIVER_ADDR_4, ISSI_SSR_4);
-# endif
-# endif
-# endif
-
-# elif defined(CKLED2001)
- ckled2001_init(DRIVER_ADDR_1);
-# if defined(DRIVER_ADDR_2)
- ckled2001_init(DRIVER_ADDR_2);
-# if defined(DRIVER_ADDR_3)
- ckled2001_init(DRIVER_ADDR_3);
-# if defined(DRIVER_ADDR_4)
- ckled2001_init(DRIVER_ADDR_4);
-# endif
-# endif
-# endif
-# endif
-
- for (int index = 0; index < RGB_MATRIX_LED_COUNT; index++) {
- bool enabled = true;
-
- // This only caches it for later
-# if defined(IS31FL3731)
- is31fl3731_set_led_control_register(index, enabled, enabled, enabled);
-# elif defined(IS31FL3733)
- is31fl3733_set_led_control_register(index, enabled, enabled, enabled);
-# elif defined(IS31FL3736)
- is31fl3736_set_led_control_register(index, enabled, enabled, enabled);
-# elif defined(IS31FL3737)
- is31fl3737_set_led_control_register(index, enabled, enabled, enabled);
-# elif defined(IS31FL3741)
- is31fl3741_set_led_control_register(index, enabled, enabled, enabled);
-# elif defined(IS31FLCOMMON)
- IS31FL_RGB_set_scaling_buffer(index, enabled, enabled, enabled);
-# elif defined(CKLED2001)
- ckled2001_set_led_control_register(index, enabled, enabled, enabled);
-# endif
- }
-
- // This actually updates the LED drivers
-# if defined(IS31FL3731)
- is31fl3731_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3731_update_led_control_registers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3731_update_led_control_registers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3731_update_led_control_registers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3733)
- is31fl3733_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3733_update_led_control_registers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3733_update_led_control_registers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3733_update_led_control_registers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3736)
- is31fl3736_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3736_update_led_control_registers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3736_update_led_control_registers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3736_update_led_control_registers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3737)
- is31fl3737_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3737_update_led_control_registers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3737_update_led_control_registers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3737_update_led_control_registers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FL3741)
- is31fl3741_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3741_update_led_control_registers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3741_update_led_control_registers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3741_update_led_control_registers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-
-# elif defined(IS31FLCOMMON)
-# ifdef ISSI_MANUAL_SCALING
- IS31FL_set_manual_scaling_buffer();
-# endif
- IS31FL_common_update_scaling_register(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- IS31FL_common_update_scaling_register(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- IS31FL_common_update_scaling_register(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- IS31FL_common_update_scaling_register(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-
-# elif defined(CKLED2001)
- ckled2001_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- ckled2001_update_led_control_registers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- ckled2001_update_led_control_registers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- ckled2001_update_led_control_registers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-# endif
-}
-
-# if defined(IS31FL3731)
-static void flush(void) {
- is31fl3731_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3731_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3731_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3731_update_pwm_buffers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
+#if defined(RGB_MATRIX_IS31FL3218)
+const rgb_matrix_driver_t rgb_matrix_driver = {
+ .init = is31fl3218_init,
+ .flush = is31fl3218_update_pwm_buffers,
+ .set_color = is31fl3218_set_color,
+ .set_color_all = is31fl3218_set_color_all,
+};
+#elif defined(RGB_MATRIX_IS31FL3731)
const rgb_matrix_driver_t rgb_matrix_driver = {
- .init = init,
- .flush = flush,
+ .init = is31fl3731_init_drivers,
+ .flush = is31fl3731_flush,
.set_color = is31fl3731_set_color,
.set_color_all = is31fl3731_set_color_all,
};
-# elif defined(IS31FL3733)
-static void flush(void) {
- is31fl3733_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3733_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3733_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3733_update_pwm_buffers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
-
+#elif defined(RGB_MATRIX_IS31FL3733)
const rgb_matrix_driver_t rgb_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_color = is31fl3733_set_color,
+ .init = is31fl3733_init_drivers,
+ .flush = is31fl3733_flush,
+ .set_color = is31fl3733_set_color,
.set_color_all = is31fl3733_set_color_all,
};
-# elif defined(IS31FL3736)
-static void flush(void) {
- is31fl3736_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3736_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3736_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3736_update_pwm_buffers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
-
+#elif defined(RGB_MATRIX_IS31FL3736)
const rgb_matrix_driver_t rgb_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_color = is31fl3736_set_color,
+ .init = is31fl3736_init_drivers,
+ .flush = is31fl3736_flush,
+ .set_color = is31fl3736_set_color,
.set_color_all = is31fl3736_set_color_all,
};
-# elif defined(IS31FL3737)
-static void flush(void) {
- is31fl3737_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3737_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3737_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3737_update_pwm_buffers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
-
+#elif defined(RGB_MATRIX_IS31FL3737)
const rgb_matrix_driver_t rgb_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_color = is31fl3737_set_color,
+ .init = is31fl3737_init_drivers,
+ .flush = is31fl3737_flush,
+ .set_color = is31fl3737_set_color,
.set_color_all = is31fl3737_set_color_all,
};
-# elif defined(IS31FL3741)
-static void flush(void) {
- is31fl3741_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- is31fl3741_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- is31fl3741_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- is31fl3741_update_pwm_buffers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
-
+#elif defined(RGB_MATRIX_IS31FL3741)
const rgb_matrix_driver_t rgb_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_color = is31fl3741_set_color,
+ .init = is31fl3741_init_drivers,
+ .flush = is31fl3741_flush,
+ .set_color = is31fl3741_set_color,
.set_color_all = is31fl3741_set_color_all,
};
-# elif defined(IS31FLCOMMON)
-static void flush(void) {
- IS31FL_common_update_pwm_register(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- IS31FL_common_update_pwm_register(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- IS31FL_common_update_pwm_register(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- IS31FL_common_update_pwm_register(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
-
+#elif defined(IS31FLCOMMON)
const rgb_matrix_driver_t rgb_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_color = IS31FL_RGB_set_color,
+ .init = IS31FL_RGB_init_drivers,
+ .flush = IS31FL_common_flush,
+ .set_color = IS31FL_RGB_set_color,
.set_color_all = IS31FL_RGB_set_color_all,
};
-# elif defined(CKLED2001)
-static void flush(void) {
- ckled2001_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2)
- ckled2001_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# if defined(DRIVER_ADDR_3)
- ckled2001_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# if defined(DRIVER_ADDR_4)
- ckled2001_update_pwm_buffers(DRIVER_ADDR_4, 3);
-# endif
-# endif
-# endif
-}
-
+#elif defined(RGB_MATRIX_SNLED27351)
const rgb_matrix_driver_t rgb_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_color = ckled2001_set_color,
- .set_color_all = ckled2001_set_color_all,
+ .init = snled27351_init_drivers,
+ .flush = snled27351_flush,
+ .set_color = snled27351_set_color,
+ .set_color_all = snled27351_set_color_all,
};
-# endif
-
-#elif defined(AW20216)
-# include "spi_master.h"
-
-static void init(void) {
- spi_init();
-
- aw20216_init(DRIVER_1_CS, DRIVER_1_EN);
-# if defined(DRIVER_2_CS)
- aw20216_init(DRIVER_2_CS, DRIVER_2_EN);
-# endif
-}
-
-static void flush(void) {
- aw20216_update_pwm_buffers(DRIVER_1_CS, 0);
-# if defined(DRIVER_2_CS)
- aw20216_update_pwm_buffers(DRIVER_2_CS, 1);
-# endif
-}
+#elif defined(RGB_MATRIX_AW20216S)
const rgb_matrix_driver_t rgb_matrix_driver = {
- .init = init,
- .flush = flush,
- .set_color = aw20216_set_color,
- .set_color_all = aw20216_set_color_all,
+ .init = aw20216s_init_drivers,
+ .flush = aw20216s_flush,
+ .set_color = aw20216s_set_color,
+ .set_color_all = aw20216s_set_color_all,
};
-#elif defined(WS2812)
-# if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_CUSTOM_DRIVER)
+#elif defined(RGB_MATRIX_WS2812)
+# if defined(RGBLIGHT_WS2812)
# pragma message "Cannot use RGBLIGHT and RGB Matrix using WS2812 at the same time."
# pragma message "You need to use a custom driver, or re-implement the WS2812 driver to use a different configuration."
# endif
// LED color buffer
-LED_TYPE rgb_matrix_ws2812_array[RGB_MATRIX_LED_COUNT];
-bool ws2812_dirty = false;
+rgb_led_t rgb_matrix_ws2812_array[RGB_MATRIX_LED_COUNT];
+bool ws2812_dirty = false;
static void init(void) {
ws2812_dirty = false;
@@ -480,4 +157,5 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = setled,
.set_color_all = setled_all,
};
+
#endif
diff --git a/quantum/rgb_matrix/rgb_matrix_types.h b/quantum/rgb_matrix/rgb_matrix_types.h
index 53ff7321b8..0a3fd7cc0d 100644
--- a/quantum/rgb_matrix/rgb_matrix_types.h
+++ b/quantum/rgb_matrix/rgb_matrix_types.h
@@ -19,16 +19,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "color.h"
-
-#if defined(__GNUC__)
-# define PACKED __attribute__((__packed__))
-#else
-# define PACKED
-#endif
-
-#if defined(_MSC_VER)
-# pragma pack(push, 1)
-#endif
+#include "util.h"
#if defined(RGB_MATRIX_KEYPRESSES) || defined(RGB_MATRIX_KEYRELEASES)
# define RGB_MATRIX_KEYREACTIVE_ENABLED
@@ -94,7 +85,3 @@ typedef union {
} rgb_config_t;
_Static_assert(sizeof(rgb_config_t) == sizeof(uint64_t), "RGB Matrix EECONFIG out of spec.");
-
-#if defined(_MSC_VER)
-# pragma pack(pop)
-#endif
diff --git a/quantum/rgblight/rgblight.c b/quantum/rgblight/rgblight.c
index 158112f31d..8ac886d441 100644
--- a/quantum/rgblight/rgblight.c
+++ b/quantum/rgblight/rgblight.c
@@ -27,9 +27,6 @@
#ifdef EEPROM_ENABLE
# include "eeprom.h"
#endif
-#ifdef VELOCIKEY_ENABLE
-# include "velocikey.h"
-#endif
#ifdef RGBLIGHT_SPLIT
/* for split keyboard */
@@ -89,6 +86,10 @@ static uint8_t mode_base_table[] = {
# define RGBLIGHT_DEFAULT_SPD 0
#endif
+#if !defined(RGBLIGHT_DEFAULT_ON)
+# define RGBLIGHT_DEFAULT_ON true
+#endif
+
static inline int is_static_effect(uint8_t mode) {
return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL;
}
@@ -115,7 +116,7 @@ animation_status_t animation_status = {};
#endif
#ifndef LED_ARRAY
-LED_TYPE led[RGBLED_NUM];
+rgb_led_t led[RGBLED_NUM];
# define LED_ARRAY led
#endif
@@ -144,17 +145,17 @@ __attribute__((weak)) RGB rgblight_hsv_to_rgb(HSV hsv) {
return hsv_to_rgb(hsv);
}
-void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
+void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, rgb_led_t *led1) {
HSV hsv = {hue, sat, val};
RGB rgb = rgblight_hsv_to_rgb(hsv);
setrgb(rgb.r, rgb.g, rgb.b, led1);
}
-void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
+void sethsv(uint8_t hue, uint8_t sat, uint8_t val, rgb_led_t *led1) {
sethsv_raw(hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val, led1);
}
-void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
+void setrgb(uint8_t r, uint8_t g, uint8_t b, rgb_led_t *led1) {
led1->r = r;
led1->g = g;
led1->b = b;
@@ -198,12 +199,13 @@ void eeconfig_update_rgblight_current(void) {
}
void eeconfig_update_rgblight_default(void) {
- rgblight_config.enable = 1;
- rgblight_config.mode = RGBLIGHT_DEFAULT_MODE;
- rgblight_config.hue = RGBLIGHT_DEFAULT_HUE;
- rgblight_config.sat = RGBLIGHT_DEFAULT_SAT;
- rgblight_config.val = RGBLIGHT_DEFAULT_VAL;
- rgblight_config.speed = RGBLIGHT_DEFAULT_SPD;
+ rgblight_config.enable = RGBLIGHT_DEFAULT_ON;
+ rgblight_config.velocikey = 0;
+ rgblight_config.mode = RGBLIGHT_DEFAULT_MODE;
+ rgblight_config.hue = RGBLIGHT_DEFAULT_HUE;
+ rgblight_config.sat = RGBLIGHT_DEFAULT_SAT;
+ rgblight_config.val = RGBLIGHT_DEFAULT_VAL;
+ rgblight_config.speed = RGBLIGHT_DEFAULT_SPD;
RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
eeconfig_update_rgblight(rgblight_config.raw);
}
@@ -211,6 +213,7 @@ void eeconfig_update_rgblight_default(void) {
void eeconfig_debug_rgblight(void) {
dprintf("rgblight_config EEPROM:\n");
dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
+ dprintf("rgblight_config.velocikey = %d\n", rgblight_config.velocikey);
dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
@@ -516,7 +519,7 @@ void rgblight_decrease_speed_noeeprom(void) {
void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) {
if (rgblight_config.enable) {
- LED_TYPE tmp_led;
+ rgb_led_t tmp_led;
sethsv(hue, sat, val, &tmp_led);
rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
}
@@ -532,7 +535,7 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w
rgblight_status.base_mode = mode_base_table[rgblight_config.mode];
if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) {
// same static color
- LED_TYPE tmp_led;
+ rgb_led_t tmp_led;
#ifdef RGBLIGHT_LAYERS_RETAIN_VAL
// needed for rgblight_layers_write() to get the new val, since it reads rgblight_config.val
rgblight_config.val = val;
@@ -576,7 +579,7 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w
_hue = hue - _hue;
}
dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range);
- sethsv(_hue, sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
+ sethsv(_hue, sat, val, (rgb_led_t *)&led[i + rgblight_ranges.effect_start_pos]);
}
# ifdef RGBLIGHT_LAYERS_RETAIN_VAL
// needed for rgblight_layers_write() to get the new val, since it reads rgblight_config.val
@@ -679,7 +682,7 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
return;
}
- LED_TYPE tmp_led;
+ rgb_led_t tmp_led;
sethsv(hue, sat, val, &tmp_led);
rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
}
@@ -689,9 +692,9 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
return
# ifdef VELOCIKEY_ENABLE
- velocikey_enabled() ? velocikey_match_speed(velocikey_min, velocikey_max) :
+ rgblight_velocikey_enabled() ? rgblight_velocikey_match_speed(velocikey_min, velocikey_max) :
# endif
- pgm_read_byte(default_interval_address);
+ pgm_read_byte(default_interval_address);
}
#endif
@@ -717,7 +720,7 @@ void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start,
return;
}
- LED_TYPE tmp_led;
+ rgb_led_t tmp_led;
sethsv(hue, sat, val, &tmp_led);
rgblight_setrgb_range(tmp_led.r, tmp_led.g, tmp_led.b, start, end);
}
@@ -786,8 +789,8 @@ static void rgblight_layers_write(void) {
break; // No more segments
}
// Write segment.count LEDs
- LED_TYPE *const limit = &led[MIN(segment.index + segment.count, RGBLED_NUM)];
- for (LED_TYPE *led_ptr = &led[segment.index]; led_ptr < limit; led_ptr++) {
+ rgb_led_t *const limit = &led[MIN(segment.index + segment.count, RGBLED_NUM)];
+ 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);
# else
@@ -897,15 +900,15 @@ void rgblight_wakeup(void) {
#endif
-__attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) {
+__attribute__((weak)) void rgblight_call_driver(rgb_led_t *start_led, uint8_t num_leds) {
ws2812_setleds(start_led, num_leds);
}
-#ifndef RGBLIGHT_CUSTOM_DRIVER
+#ifndef RGBLIGHT_CUSTOM
void rgblight_set(void) {
- LED_TYPE *start_led;
- uint8_t num_leds = rgblight_ranges.clipping_num_leds;
+ rgb_led_t *start_led;
+ uint8_t num_leds = rgblight_ranges.clipping_num_leds;
if (!rgblight_config.enable) {
for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
@@ -931,7 +934,7 @@ void rgblight_set(void) {
# endif
# ifdef RGBLIGHT_LED_MAP
- LED_TYPE led0[RGBLED_NUM];
+ rgb_led_t led0[RGBLED_NUM];
for (uint8_t i = 0; i < RGBLED_NUM; i++) {
led0[i] = led[pgm_read_byte(&led_map[i])];
}
@@ -1049,7 +1052,7 @@ static void rgblight_effect_dummy(animation_status_t *anim) {
**/
}
-void rgblight_task(void) {
+void rgblight_timer_task(void) {
if (rgblight_status.timer_enabled) {
effect_func_t effect_func = rgblight_effect_dummy;
uint16_t interval_time = 2000; // dummy interval
@@ -1230,7 +1233,7 @@ void rgblight_effect_rainbow_swirl(animation_status_t *anim) {
for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / rgblight_ranges.effect_num_leds * i + anim->current_hue);
- sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
+ sethsv(hue, rgblight_config.sat, rgblight_config.val, (rgb_led_t *)&led[i + rgblight_ranges.effect_start_pos]);
}
rgblight_set();
@@ -1267,10 +1270,10 @@ void rgblight_effect_snake(animation_status_t *anim) {
# endif
for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
- LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
- ledp->r = 0;
- ledp->g = 0;
- ledp->b = 0;
+ rgb_led_t *ledp = led + i + rgblight_ranges.effect_start_pos;
+ ledp->r = 0;
+ ledp->g = 0;
+ ledp->b = 0;
# ifdef RGBW
ledp->w = 0;
# endif
@@ -1340,7 +1343,7 @@ void rgblight_effect_knight(animation_status_t *anim) {
cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % rgblight_ranges.effect_num_leds + rgblight_ranges.effect_start_pos;
if (i >= low_bound && i <= high_bound) {
- sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
+ sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (rgb_led_t *)&led[cur]);
} else {
led[cur].r = 0;
led[cur].g = 0;
@@ -1392,7 +1395,7 @@ void rgblight_effect_christmas(animation_status_t *anim) {
for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
uint8_t local_hue = (i / RGBLIGHT_EFFECT_CHRISTMAS_STEP) % 2 ? hue : hue_green - hue;
- sethsv(local_hue, rgblight_config.sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
+ sethsv(local_hue, rgblight_config.sat, val, (rgb_led_t *)&led[i + rgblight_ranges.effect_start_pos]);
}
rgblight_set();
@@ -1415,7 +1418,7 @@ void rgblight_effect_rgbtest(animation_status_t *anim) {
uint8_t b;
if (maxval == 0) {
- LED_TYPE tmp_led;
+ rgb_led_t tmp_led;
sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led);
maxval = tmp_led.r;
}
@@ -1439,7 +1442,7 @@ void rgblight_effect_rgbtest(animation_status_t *anim) {
#ifdef RGBLIGHT_EFFECT_ALTERNATING
void rgblight_effect_alternating(animation_status_t *anim) {
for (int i = 0; i < rgblight_ranges.effect_num_leds; i++) {
- LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
+ rgb_led_t *ledp = led + i + rgblight_ranges.effect_start_pos;
if (i < rgblight_ranges.effect_num_leds / 2 && anim->pos) {
sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
} else if (i >= rgblight_ranges.effect_num_leds / 2 && !anim->pos) {
@@ -1512,10 +1515,68 @@ void rgblight_effect_twinkle(animation_status_t *anim) {
// This LED is off, and was NOT selected to start brightening
}
- LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
+ rgb_led_t *ledp = led + i + rgblight_ranges.effect_start_pos;
sethsv(c->h, c->s, c->v, ledp);
}
rgblight_set();
}
#endif
+
+void preprocess_rgblight(void) {
+#ifdef VELOCIKEY_ENABLE
+ if (rgblight_velocikey_enabled()) {
+ rgblight_velocikey_accelerate();
+ }
+#endif
+}
+
+void rgblight_task(void) {
+#ifdef RGBLIGHT_USE_TIMER
+ rgblight_timer_task();
+#endif
+
+#ifdef VELOCIKEY_ENABLE
+ if (rgblight_velocikey_enabled()) {
+ rgblight_velocikey_decelerate();
+ }
+#endif
+}
+
+#ifdef VELOCIKEY_ENABLE
+# define TYPING_SPEED_MAX_VALUE 200
+
+static uint8_t typing_speed = 0;
+
+bool rgblight_velocikey_enabled(void) {
+ return rgblight_config.velocikey;
+}
+
+void rgblight_velocikey_toggle(void) {
+ dprintf("rgblight velocikey toggle [EEPROM]: rgblight_config.velocikey = %u\n", !rgblight_config.velocikey);
+ rgblight_config.velocikey = !rgblight_config.velocikey;
+ eeconfig_update_rgblight_current();
+}
+
+void rgblight_velocikey_accelerate(void) {
+ if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += (TYPING_SPEED_MAX_VALUE / 100);
+}
+
+void rgblight_velocikey_decelerate(void) {
+ static uint16_t decay_timer = 0;
+
+ if (timer_elapsed(decay_timer) > 500 || decay_timer == 0) {
+ if (typing_speed > 0) typing_speed -= 1;
+ // Decay a little faster at half of max speed
+ if (typing_speed > TYPING_SPEED_MAX_VALUE / 2) typing_speed -= 1;
+ // Decay even faster at 3/4 of max speed
+ if (typing_speed > TYPING_SPEED_MAX_VALUE / 4 * 3) typing_speed -= 2;
+ decay_timer = timer_read();
+ }
+}
+
+uint8_t rgblight_velocikey_match_speed(uint8_t minValue, uint8_t maxValue) {
+ return MAX(minValue, maxValue - (maxValue - minValue) * ((float)typing_speed / TYPING_SPEED_MAX_VALUE));
+}
+
+#endif \ No newline at end of file
diff --git a/quantum/rgblight/rgblight.h b/quantum/rgblight/rgblight.h
index 001058f962..a222ab6b9f 100644
--- a/quantum/rgblight/rgblight.h
+++ b/quantum/rgblight/rgblight.h
@@ -233,7 +233,7 @@ void rgblight_unblink_all_but_layer(uint8_t layer);
#endif
-extern LED_TYPE led[RGBLED_NUM];
+extern rgb_led_t led[RGBLED_NUM];
extern const uint8_t RGBLED_BREATHING_INTERVALS[4] PROGMEM;
extern const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[3] PROGMEM;
@@ -248,7 +248,8 @@ typedef union {
uint64_t raw;
struct {
bool enable : 1;
- uint8_t mode : 7;
+ bool velocikey : 1;
+ uint8_t mode : 6;
uint8_t hue : 8;
uint8_t sat : 8;
uint8_t val : 8;
@@ -283,9 +284,9 @@ typedef struct _rgblight_ranges_t {
extern rgblight_ranges_t rgblight_ranges;
/* === Utility Functions ===*/
-void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1);
-void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1); // without RGBLIGHT_LIMIT_VAL check
-void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1);
+void sethsv(uint8_t hue, uint8_t sat, uint8_t val, rgb_led_t *led1);
+void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, rgb_led_t *led1); // without RGBLIGHT_LIMIT_VAL check
+void setrgb(uint8_t r, uint8_t g, uint8_t b, rgb_led_t *led1);
/* === Low level Functions === */
void rgblight_set(void);
@@ -385,14 +386,15 @@ void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom);
#define EZ_RGB(val) rgblight_show_solid_color((val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF)
void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b);
-#ifdef RGBLIGHT_USE_TIMER
+void preprocess_rgblight(void);
void rgblight_task(void);
+
+#ifdef RGBLIGHT_USE_TIMER
void rgblight_timer_init(void);
void rgblight_timer_enable(void);
void rgblight_timer_disable(void);
void rgblight_timer_toggle(void);
#else
-# define rgblight_task()
# define rgblight_timer_init()
# define rgblight_timer_enable()
# define rgblight_timer_disable()
@@ -446,3 +448,14 @@ void rgblight_effect_alternating(animation_status_t *anim);
void rgblight_effect_twinkle(animation_status_t *anim);
#endif
+
+#ifdef VELOCIKEY_ENABLE
+bool rgblight_velocikey_enabled(void);
+void rgblight_velocikey_toggle(void);
+void rgblight_velocikey_accelerate(void);
+void rgblight_velocikey_decelerate(void);
+uint8_t rgblight_velocikey_match_speed(uint8_t minValue, uint8_t maxValue);
+
+# define velocikey_enabled rgblight_velocikey_enabled
+# define velocikey_toggle rgblight_velocikey_toggle
+#endif
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 5d044c4ea0..874339361d 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -56,6 +56,11 @@ static uint8_t connection_errors = 0;
volatile bool isLeftHand = true;
+static struct {
+ bool master;
+ bool left;
+} split_config;
+
#if defined(SPLIT_USB_DETECT)
_Static_assert((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL.");
static bool usbIsActive(void) {
@@ -131,8 +136,10 @@ static uint8_t peek_matrix_intersection(pin_t out_pin, pin_t in_pin) {
}
#endif
-__attribute__((weak)) bool is_keyboard_left(void) {
+__attribute__((weak)) bool is_keyboard_left_impl(void) {
#if defined(SPLIT_HAND_PIN)
+ setPinInput(SPLIT_HAND_PIN);
+ wait_us(100);
// Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
# ifdef SPLIT_HAND_PIN_LOW_IS_LEFT
return !readPin(SPLIT_HAND_PIN);
@@ -146,36 +153,6 @@ __attribute__((weak)) bool is_keyboard_left(void) {
return !peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID);
# endif
#elif defined(EE_HANDS)
- return eeconfig_read_handedness();
-#elif defined(MASTER_RIGHT)
- return !is_keyboard_master();
-#endif
-
- return is_keyboard_master();
-}
-
-__attribute__((weak)) bool is_keyboard_master(void) {
- static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN;
-
- // only check once, as this is called often
- if (usbstate == UNKNOWN) {
- usbstate = usbIsActive() ? MASTER : SLAVE;
-
- // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
- if (usbstate == SLAVE) {
- usb_disconnect();
- }
- }
-
- return (usbstate == MASTER);
-}
-
-// this code runs before the keyboard is fully initialized
-void split_pre_init(void) {
-#if defined(SPLIT_HAND_PIN)
- setPinInput(SPLIT_HAND_PIN);
- wait_us(100);
-#elif defined(EE_HANDS)
if (!eeconfig_is_enabled()) {
eeconfig_init();
}
@@ -193,12 +170,42 @@ void split_pre_init(void) {
eeconfig_update_handedness(should_be_left);
}
# endif // defined(INIT_EE_HANDS_LEFT) || defined(INIT_EE_HANDS_RIGHT)
+ return eeconfig_read_handedness();
+#elif defined(MASTER_RIGHT)
+ return !is_keyboard_master();
+#else
+ return is_keyboard_master();
#endif
- isLeftHand = is_keyboard_left();
+}
+
+__attribute__((weak)) bool is_keyboard_master_impl(void) {
+ bool is_master = usbIsActive();
+
+ // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
+ if (!is_master) {
+ usb_disconnect();
+ }
+ return is_master;
+}
+
+__attribute__((weak)) bool is_keyboard_left(void) {
+ return split_config.left;
+}
+
+__attribute__((weak)) bool is_keyboard_master(void) {
+ return split_config.master;
+}
+
+// this code runs before the keyboard is fully initialized
+void split_pre_init(void) {
+ split_config.master = is_keyboard_master_impl();
+ split_config.left = is_keyboard_left_impl();
+
+ isLeftHand = is_keyboard_left(); // TODO: Remove isLeftHand
#if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)
uint8_t num_rgb_leds_split[2] = RGBLED_SPLIT;
- if (isLeftHand) {
+ if (is_keyboard_left()) {
rgblight_set_clipping_range(0, num_rgb_leds_split[0]);
} else {
rgblight_set_clipping_range(num_rgb_leds_split[0], num_rgb_leds_split[1]);
diff --git a/quantum/steno_keycodes.h b/quantum/steno_keycodes.h
new file mode 100644
index 0000000000..852b2f7121
--- /dev/null
+++ b/quantum/steno_keycodes.h
@@ -0,0 +1,119 @@
+/* Copyright 2017 Joseph Wasson
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "keycodes.h"
+
+// List of keycodes for the steno keyboard. To prevent
+// errors, this must be <= 42 total entries in order to
+// support the GeminiPR protocol.
+enum steno_keycodes {
+ STN__MIN = QK_STENO,
+ STN_FN = STN__MIN,
+ STN_NUM,
+ STN_N1 = STN_NUM,
+ STN_N2,
+ STN_N3,
+ STN_N4,
+ STN_N5,
+ STN_N6,
+ STN_SL,
+ STN_S1 = STN_SL,
+ STN_S2,
+ STN_TL,
+ STN_KL,
+ STN_PL,
+ STN_WL,
+ STN_HL,
+ STN_RL,
+ STN_A,
+ STN_O,
+ STN_STR,
+ STN_ST1 = STN_STR,
+ STN_ST2,
+ STN_RES1,
+ STN_RE1 = STN_RES1,
+ STN_RES2,
+ STN_RE2 = STN_RES2,
+ STN_PWR,
+ STN_ST3,
+ STN_ST4,
+ STN_E,
+ STN_U,
+ STN_FR,
+ STN_RR,
+ STN_PR,
+ STN_BR,
+ STN_LR,
+ STN_GR,
+ STN_TR,
+ STN_SR,
+ STN_DR,
+ STN_N7,
+ STN_N8,
+ STN_N9,
+ STN_NA,
+ STN_NB,
+ STN_NC,
+ STN_ZR,
+ STN__MAX = STN_ZR, // must be less than QK_STENO_BOLT
+};
+
+#ifdef STENO_COMBINEDMAP
+enum steno_combined_keycodes {
+ STN_S3 = QK_STENO_COMB,
+ STN_TKL,
+ STN_PWL,
+ STN_HRL,
+ STN_FRR,
+ STN_PBR,
+ STN_LGR,
+ STN_TSR,
+ STN_DZR,
+ STN_AO,
+ STN_EU,
+ STN_COMB_MAX = STN_EU,
+};
+#endif
+
+#ifdef STENO_ENABLE_BOLT
+// TxBolt Codes
+# define TXB_NUL 0
+# define TXB_S_L 0b00000001
+# define TXB_T_L 0b00000010
+# define TXB_K_L 0b00000100
+# define TXB_P_L 0b00001000
+# define TXB_W_L 0b00010000
+# define TXB_H_L 0b00100000
+# define TXB_R_L 0b01000001
+# define TXB_A_L 0b01000010
+# define TXB_O_L 0b01000100
+# define TXB_STR 0b01001000
+# define TXB_E_R 0b01010000
+# define TXB_U_R 0b01100000
+# define TXB_F_R 0b10000001
+# define TXB_R_R 0b10000010
+# define TXB_P_R 0b10000100
+# define TXB_B_R 0b10001000
+# define TXB_L_R 0b10010000
+# define TXB_G_R 0b10100000
+# define TXB_T_R 0b11000001
+# define TXB_S_R 0b11000010
+# define TXB_D_R 0b11000100
+# define TXB_Z_R 0b11001000
+# define TXB_NUM 0b11010000
+#endif // STENO_ENABLE_BOLT
diff --git a/quantum/util.h b/quantum/util.h
index 9c034cc404..94d9f22317 100644
--- a/quantum/util.h
+++ b/quantum/util.h
@@ -46,3 +46,11 @@
*/
# define ARRAY_SIZE(array) (__builtin_choose_expr(IS_ARRAY((array)), sizeof((array)) / sizeof((array)[0]), (void)0))
#endif
+
+#if !defined(PACKED)
+# define PACKED __attribute__((__packed__))
+#endif
+
+#if __has_include("_util.h")
+# include "_util.h" /* Include the platform's _util.h */
+#endif
diff --git a/quantum/velocikey.c b/quantum/velocikey.c
deleted file mode 100644
index 03e91911f6..0000000000
--- a/quantum/velocikey.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "velocikey.h"
-#include "timer.h"
-#include "eeconfig.h"
-#include "eeprom.h"
-#include "util.h"
-
-#define TYPING_SPEED_MAX_VALUE 200
-uint8_t typing_speed = 0;
-
-bool velocikey_enabled(void) {
- return eeprom_read_byte(EECONFIG_VELOCIKEY) == 1;
-}
-
-void velocikey_toggle(void) {
- if (velocikey_enabled())
- eeprom_update_byte(EECONFIG_VELOCIKEY, 0);
- else
- eeprom_update_byte(EECONFIG_VELOCIKEY, 1);
-}
-
-void velocikey_accelerate(void) {
- if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += (TYPING_SPEED_MAX_VALUE / 100);
-}
-
-void velocikey_decelerate(void) {
- static uint16_t decay_timer = 0;
-
- if (timer_elapsed(decay_timer) > 500 || decay_timer == 0) {
- if (typing_speed > 0) typing_speed -= 1;
- // Decay a little faster at half of max speed
- if (typing_speed > TYPING_SPEED_MAX_VALUE / 2) typing_speed -= 1;
- // Decay even faster at 3/4 of max speed
- if (typing_speed > TYPING_SPEED_MAX_VALUE / 4 * 3) typing_speed -= 2;
- decay_timer = timer_read();
- }
-}
-
-uint8_t velocikey_match_speed(uint8_t minValue, uint8_t maxValue) {
- return MAX(minValue, maxValue - (maxValue - minValue) * ((float)typing_speed / TYPING_SPEED_MAX_VALUE));
-}
diff --git a/quantum/velocikey.h b/quantum/velocikey.h
deleted file mode 100644
index c375f82f71..0000000000
--- a/quantum/velocikey.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <stdbool.h>
-
-bool velocikey_enabled(void);
-void velocikey_toggle(void);
-void velocikey_accelerate(void);
-void velocikey_decelerate(void);
-uint8_t velocikey_match_speed(uint8_t minValue, uint8_t maxValue);
diff --git a/quantum/via.c b/quantum/via.c
index 2acd7aa90c..643d7aa3c3 100644
--- a/quantum/via.c
+++ b/quantum/via.c
@@ -634,11 +634,6 @@ void via_qmk_rgblight_save(void) {
#if defined(RGB_MATRIX_ENABLE)
-# if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
-# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
-# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
-# endif
-
void via_qmk_rgb_matrix_command(uint8_t *data, uint8_t length) {
// data = [ command_id, channel_id, value_id, value_data ]
uint8_t *command_id = &(data[0]);
@@ -727,11 +722,6 @@ void via_qmk_rgb_matrix_save(void) {
#if defined(LED_MATRIX_ENABLE)
-# if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
-# undef LED_MATRIX_MAXIMUM_BRIGHTNESS
-# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
-# endif
-
void via_qmk_led_matrix_command(uint8_t *data, uint8_t length) {
// data = [ command_id, channel_id, value_id, value_data ]
uint8_t *command_id = &(data[0]);