diff options
Diffstat (limited to 'quantum')
70 files changed, 1640 insertions, 1288 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/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..86c6768729 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) @@ -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 diff --git a/quantum/quantum.h b/quantum/quantum.h index 4d183e755f..e41542e4af 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" 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..df34718838 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" 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..21e3487b28 100644 --- a/quantum/util.h +++ b/quantum/util.h @@ -46,3 +46,7 @@   */  #    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 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]); | 
