diff options
30 files changed, 1773 insertions, 292 deletions
| diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/config.h index d7618912f7..59cd098fdb 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/config.h +++ b/keyboards/handwired/tractyl_manuform/5x6_right/config.h @@ -50,7 +50,5 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define NO_ACTION_MACRO  #define NO_ACTION_FUNCTION -#define OLED_DISPLAY_128X64 -  #define POINTING_DEVICE_TASK_THROTTLE  #define POINTING_DEVICE_RIGHT diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h index 9daec0cd8f..d8d36e824c 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h +++ b/keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h @@ -35,7 +35,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define RGBLED_SPLIT \      { 10, 10 }  #define RGBLIGHT_LIMIT_VAL 80 -#define OLED_BRIGHTNESS    50  #define AUDIO_PIN       C6 diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h index 986ccae69b..6ae51ca6f0 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h +++ b/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h @@ -43,12 +43,13 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  //#define WS2812_PWM_COMPLEMENTARY_OUTPUT // Define for a complementary timer output (TIMx_CHyN); omit for a normal timer output (TIMx_CHy).  #define WS2812_DMA_STREAM   STM32_DMA1_STREAM7  // DMA Stream for TIMx_UP, see the respective reference manual for the appropriate values for your MCU.  #define WS2812_DMA_CHANNEL  3                   // DMA Channel for TIMx_UP, see the respective reference manual for the appropriate values for your MCU. +#define WS2812_PWM_TARGET_PERIOD 800000 +  #define RGBLED_NUM          52  #define RGBLIGHT_SPLIT  #define RGBLED_SPLIT \      { 26, 26 } -#define RGBLIGHT_LIMIT_VAL 150  #define DEBUG_LED_PIN      C13 @@ -68,6 +69,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define SERIAL_USART_RX_PAL_MODE 7    // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7  #define SERIAL_USART_TIMEOUT     100  // USART driver timeout. default 100 + +#define CRC8_USE_TABLE +#define CRC8_OPTIMIZE_SPEED +  /* i2c config for oleds */  #define I2C_DRIVER        I2CD1  #define I2C1_SCL_PIN      B8 @@ -75,9 +80,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define I2C1_SCL_PAL_MODE 4  #define I2C1_SDA_PAL_MODE 4  // #define I2C1_CLOCK_SPEED  400000 -/* For Legacy Compatibility: */ -#define I2C1_SCL 8 -#define I2C1_SDA 9  /* encoder config */  #define ENCODERS_PAD_A \ @@ -110,3 +112,4 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define PMW3360_CS_PIN                       B0  #define PMW3360_SPI_MODE                     3  #define PMW3360_SPI_DIVISOR                  64 +#define PMW3360_FIRMWARE_UPLOAD_FAST diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/f411/post_config.h b/keyboards/handwired/tractyl_manuform/5x6_right/f411/post_config.h new file mode 100644 index 0000000000..0e33129e1a --- /dev/null +++ b/keyboards/handwired/tractyl_manuform/5x6_right/f411/post_config.h @@ -0,0 +1,20 @@ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're  (@drashna) <[email protected]> +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#ifndef RGBLIGHT_LIMIT_VAL +#    if defined(OLED_ENABLE) +#        define RGBLIGHT_LIMIT_VAL 100 +#    else +#        define RGBLIGHT_LIMIT_VAL 150 +#    endif +#endif + +#ifndef OLED_BRIGHTNESS +#    ifdef RGBLIGHT_ENABLE +#        define OLED_BRIGHTNESS 80 +#    else +#        define OLED_BRIGHTNESS 150 +#    endif +#endif diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h index 85ddef103a..0b33138ec0 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h +++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h @@ -18,5 +18,9 @@  #define TRACKBALL_DPI_OPTIONS { 1200, 1800, 2600, 3400 } -#define DEBOUNCE 45 +#define DEBOUNCE 60  #define ENCODER_DEFAULT_POS 0x3 + +#ifdef OLED_DRIVER_SH1107 +#    undef OLED_DISPLAY_128X64 +#endif diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c index 958f694172..b5310b37dd 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c +++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c @@ -125,7 +125,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {          KEYLOCK, _________________ADJUST_L2_________________,                      _________________ADJUST_R2_________________, TG_MODS,          UC_MOD,  _________________ADJUST_L3_________________,                      _________________ADJUST_R3_________________, KC_MPLY,                     TG(_DIABLOII), AUTO_CTN,                                                          TG_GAME, TG_DBLO, -                                            _______, _______,                               KC_NUKE, +                                            _______, REBOOT,                                KC_NUKE,                                                       _______, _______,             _______,                                                       _______, _______,    KC_NUKE, _______      ), @@ -145,7 +145,7 @@ const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {      [_MEDIA]           = { { _______, _______ }, { _______, _______ } },      [_RAISE]           = { { _______, _______ }, { KC_PGDN, KC_PGUP } },      [_LOWER]           = { { RGB_MOD, RGB_RMOD}, { RGB_HUD, RGB_HUI } }, -    [_ADJUST]          = { { CK_DOWN, CK_UP   }, { _______, _______ } }, +    [_ADJUST]          = { { CK_DOWN, CK_UP   }, { _______, _F______ } },  };  // clang-format on  #else @@ -165,144 +165,5 @@ bool encoder_update_user(uint8_t index, bool clockwise) {  #endif  #ifdef OLED_ENABLE -// WPM-responsive animation stuff here -#    define SLEEP_FRAMES 2 -#    define SLEEP_SPEED  10  // below this wpm value your animation will idle - -#    define WAKE_FRAMES  2  // uncomment if >1 - -#    define KAKI_FRAMES  3 -#    define KAKI_SPEED   40  // above this wpm value typing animation to triggere - -#    define RTOGI_FRAMES 2 -//#define LTOGI_FRAMES 2 - -//#define ANIM_FRAME_DURATION 500 // how long each frame lasts in ms -// #define SLEEP_TIMER 60000 // should sleep after this period of 0 wpm, needs fixing -#    define ANIM_SIZE    512  // number of bytes in array, minimize for adequate firmware size, max is 1024 - -uint32_t anim_timer          = 0; -uint32_t anim_frame_duration = 500; -uint8_t  current_sleep_frame = 0; -uint8_t  current_wake_frame  = 0;  // uncomment if WAKE_FRAMES >1 -uint8_t  current_kaki_frame  = 0; -uint8_t  current_rtogi_frame = 0; -// uint8_t current_ltogi_frame = 0; - -void render_kitty(void) { -    // Images credit j-inc(/James Incandenza) and pixelbenny. Credit to obosob for initial animation approach. -    static const char PROGMEM sleep[SLEEP_FRAMES][ANIM_SIZE] = {{ -                                                                    // 'sleep1', 128x32px -                                                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xa8, 0x48, 0xa8, 0x18, 0x08, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x80, 0x44, 0x84, 0x06, 0x05, 0x04, 0x80, 0x40, 0x20, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x18, 0x04, 0x04, 0x02, 0x7a, 0x86, 0x01, 0x80, 0x80, 0x01, 0x03, 0x05, 0x07, 0x01, 0x00, 0x00, 0x80, 0x83, 0x45, 0xfa, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x33, 0x24, 0x28, 0x28, 0x29, 0x29, 0x29, 0x3a, 0x18, 0x1c, 0x39, 0x24, 0x24, 0x3a, 0x2d, 0x26, 0x31, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                }, -                                                                {// 'sleep2', 128x32px -                                                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x3a, 0x2a, 0x26, 0x22, 0x80, 0xc0, 0x80, 0x00, 0x24, 0x34, 0x2c, 0xe4, 0x60, 0x10, 0x70, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38, 0x04, 0x02, 0x02, 0x01, 0x79, 0x87, 0x01, 0x80, 0x81, 0x83, 0x05, 0x05, 0x03, 0x01, 0x00, 0x00, 0x80, 0x43, 0x05, 0xfa, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x33, 0x24, 0x28, 0x28, 0x28, 0x29, 0x29, 0x3a, 0x18, 0x1c, 0x39, 0x24, 0x24, 0x3a, 0x2d, 0x26, 0x31, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -    static const char PROGMEM wake[WAKE_FRAMES][ANIM_SIZE]   = {{ -                                                                  // 'mati2', 128x32px -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x30, 0x08, 0x10, 0x60, 0x80, 0x00, 0x80, 0x60, 0x10, 0x08, 0x30, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x40, 0x40, 0x5c, 0x00, 0x01, 0x41, 0x01, 0x00, 0x5c, 0x40, 0x40, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x80, 0xe1, 0x12, 0x0a, 0x06, 0x00, 0x80, 0x00, 0x06, 0x0a, 0x12, 0xe1, 0x80, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x11, 0x10, 0x10, 0x14, 0x14, 0x1f, 0x1c, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                              }, -                                                              {// 'mati3', 128x32px -                                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x30, 0x08, 0x10, 0x60, 0x80, 0x00, 0x80, 0x60, 0x10, 0x08, 0x30, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x90, 0x12, 0x0a, 0x02, 0xf4, 0x09, 0x0d, 0xf1, 0x04, 0x02, 0x0a, 0x12, 0x90, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x80, 0xe1, 0x12, 0x0a, 0x06, 0x01, 0x81, 0x00, 0x06, 0x0a, 0x12, 0xe1, 0x80, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x11, 0x10, 0x10, 0x14, 0x14, 0x1f, 0x1c, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -    static const char PROGMEM kaki[KAKI_FRAMES][ANIM_SIZE]   = {{ -                                                                  // 'jare2', 128x32px -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x40, 0x80, 0x80, 0x80, 0x00, 0xfc, 0x84, 0x08, 0x08, 0x10, 0x20, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1e, 0x60, 0x80, 0x00, 0x00, 0x91, 0xa1, 0x80, 0x00, 0x00, 0x22, 0x84, 0x40, 0x50, 0x48, 0xc1, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x41, 0x82, 0xe2, 0x12, 0x0a, 0x06, 0x00, 0x80, 0x88, 0x4f, 0x02, 0x22, 0xe2, 0x9f, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10, 0x14, 0x14, 0x1f, 0x1a, 0x0a, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                              }, -                                                              { -                                                                  // 'kaki1', 128x32px -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x06, 0x1a, 0x22, 0xc2, 0x04, 0x04, 0x04, 0x07, 0x00, 0xc0, 0x20, 0x10, 0x80, 0x80, 0x01, 0x01, 0x02, 0xfc, 0xfe, 0x02, 0x3c, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d, 0x55, 0x50, 0x94, 0xf0, 0x10, 0x09, 0x08, 0x00, 0x80, 0x00, 0x06, 0x09, 0x1b, 0xee, 0x00, 0x00, 0x00, 0x00, 0x81, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c, 0x14, 0x16, 0x15, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                              }, -                                                              {// 'kaki2', 128x32px -                                                               0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                               0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x01, 0x02, 0x04, 0x04, 0x03, 0x80, 0x40, 0x40, 0x20, 0x00, 0x01, 0x02, 0x8c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d, 0x55, 0x50, 0x94, 0xf0, 0x10, 0x0a, 0x0e, 0x1d, 0x95, 0x24, 0x24, 0x27, 0x13, 0xe1, 0x01, 0x01, 0x01, 0x01, 0x02, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -    static const char PROGMEM rtogi[KAKI_FRAMES][ANIM_SIZE]  = {{ -                                                                   // 'rtogi1', 128x32px -                                                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x0f, 0x90, 0x10, 0x20, 0xf0, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x48, 0x47, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x88, 0xc7, 0xc4, 0x62, 0x23, 0x11, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                   0x80, 0x40, 0x20, 0x10, 0x88, 0xcc, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                   0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, 0x05, 0x04, 0x04, 0x04, 0x07, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                               }, -                                                               {// 'rtogi2', 128x32px -                                                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1f, 0xa0, 0x20, 0x40, 0x80, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x48, 0x47, 0x88, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x28, 0x6b, 0x40, 0xa0, 0x99, 0x86, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                0x0f, 0x11, 0x22, 0x44, 0x48, 0x4c, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c, 0x04, 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -                                                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, 0x05, 0x04, 0x04, 0x04, 0x07, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; - -    // assumes 1 frame prep stage -    void        animation_phase(void) { -        if (tap_toggling) { -            anim_frame_duration = 300; -            current_rtogi_frame = (current_rtogi_frame + 1) % RTOGI_FRAMES; -            oled_write_raw_P(rtogi[abs((RTOGI_FRAMES - 1) - current_rtogi_frame)], ANIM_SIZE); -        } else { -            if (get_current_wpm() <= SLEEP_SPEED) { -                anim_frame_duration = 500; -                current_sleep_frame = (current_sleep_frame + 1) % SLEEP_FRAMES; -                oled_write_raw_P(sleep[abs((SLEEP_FRAMES - 1) - current_sleep_frame)], ANIM_SIZE); -            } -            // if(get_current_wpm() >IDLE_SPEED && get_current_wpm() <TAP_SPEED){ -            if (get_current_wpm() > SLEEP_SPEED) { -                anim_frame_duration = 800; -                current_wake_frame  = (current_wake_frame + 1) % WAKE_FRAMES; -                oled_write_raw_P(wake[abs((WAKE_FRAMES - 1) - current_wake_frame)], ANIM_SIZE); -                // oled_write_raw_P(wake[0], ANIM_SIZE);  // remove if IDLE_FRAMES >1 -            } -            if (get_current_wpm() >= KAKI_SPEED) { -                anim_frame_duration = 500; -                current_kaki_frame  = (current_kaki_frame + 1) % KAKI_FRAMES; -                oled_write_raw_P(kaki[abs((KAKI_FRAMES - 1) - current_kaki_frame)], ANIM_SIZE); -            } -        } -    } -    if (get_current_wpm() != 000) { -        // if(timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) { -        if (timer_elapsed32(anim_timer) > anim_frame_duration) { -            anim_timer = timer_read32(); -            animation_phase(); -        } -    } else { -        // if(timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) { -        if (timer_elapsed32(anim_timer) > anim_frame_duration) { -            anim_timer = timer_read32(); -            animation_phase(); -        } -    } -} - -void oled_driver_render_logo_left(void) { -    render_kitty(); - -    oled_set_cursor(6, 0); -    oled_write_P(PSTR("  Tractyl      "), false); -    oled_set_cursor(6, 1); -    oled_write_P(PSTR("     Manuform  "), false); -    oled_set_cursor(6, 2); -#    if defined(WPM_ENABLE) -    render_wpm(1); -#    endif -    oled_set_cursor(6, 3); -#    if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right) -    render_pointing_dpi_status(0); -#    endif -    oled_set_cursor(0, 4); -} +oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return OLED_ROTATION_180; }  #endif diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk index 0765bb2c6e..9ef58ab5ec 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk +++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk @@ -32,3 +32,5 @@ ifeq ($(strip $(KEYBOARD)), handwired/tractyl_manuform/5x6_right/teensy2pp)      CAPS_WORD_ENABLE             = yes  endif  # DEBOUNCE_TYPE = sym_eager_pk + +OLED_DRIVER = custom diff --git a/keyboards/handwired/tractyl_manuform/tractyl_manuform.h b/keyboards/handwired/tractyl_manuform/tractyl_manuform.h index 6aa40fc18b..c3acade6f1 100644 --- a/keyboards/handwired/tractyl_manuform/tractyl_manuform.h +++ b/keyboards/handwired/tractyl_manuform/tractyl_manuform.h @@ -43,6 +43,8 @@ typedef struct {      uint16_t device_cpi;  } kb_config_data_t; +extern kb_config_data_t                      kb_config; +  void trackball_set_cpi(uint16_t cpi);  void matrix_init_sub_kb(void);  void matrix_scan_sub_kb(void); diff --git a/keyboards/moonlander/keymaps/drashna/keymap.c b/keyboards/moonlander/keymaps/drashna/keymap.c index 82abdb0055..ba07834614 100644 --- a/keyboards/moonlander/keymaps/drashna/keymap.c +++ b/keyboards/moonlander/keymaps/drashna/keymap.c @@ -111,7 +111,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {          KEYLOCK, _________________ADJUST_L2_________________, _______,        _______, _________________ADJUST_R2_________________, RGB_IDL,          UC_MOD,  _________________ADJUST_L3_________________,                          _________________ADJUST_R3_________________, TG_MODS,          _______, _______, _______, _______, _______,          _______,        _______,          _______, _______, _______, _______, AUTO_CTN, -                                            _______, _______, _______,        _______, _______, _______ +                                            REBOOT,  _______, _______,        _______, _______, _______      ),  }; diff --git a/keyboards/splitkb/kyria/keymaps/drashna/keymap.c b/keyboards/splitkb/kyria/keymaps/drashna/keymap.c index 6c7ac34d51..1346616b20 100644 --- a/keyboards/splitkb/kyria/keymaps/drashna/keymap.c +++ b/keyboards/splitkb/kyria/keymaps/drashna/keymap.c @@ -93,7 +93,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {          KC_MAKE, _________________ADJUST_L1_________________,                                       _________________ADJUST_R1_________________, KC_RESET,          VRSN,    _________________ADJUST_L2_________________,                                       _________________ADJUST_R2_________________, EEP_RST,          UC_MOD,  _________________ADJUST_L3_________________, HPT_TOG, HPT_FBK,   MG_NKRO, UC_MOD,  _________________ADJUST_R3_________________, TG_MODS, -                                   _______, _______, KEYLOCK, KC_NUKE, _______,   _______, _______, _______, _______, _______ +                                   REBOOT,  _______, KEYLOCK, KC_NUKE, _______,   _______, _______, _______, _______, AUTO_CTN      ),  //     [_LAYERINDEX] = LAYOUT_wrapper(  //       _______, _______, _______, _______, _______, _______,                                       _______, _______, _______, _______, _______, _______, diff --git a/layouts/community/ergodox/drashna/keymap.c b/layouts/community/ergodox/drashna/keymap.c index 798680628f..0b81232af9 100644 --- a/layouts/community/ergodox/drashna/keymap.c +++ b/layouts/community/ergodox/drashna/keymap.c @@ -16,10 +16,6 @@  #include "drashna.h" -#ifdef UNICODEMAP_ENABLE -#    include "drashna_unicode.h" -#endif  // UNICODEMAP_ENABLE -#include "drivers/sensors/pimoroni_trackball.h"  enum more_custom_keycodes {      KC_SWAP_NUM = NEW_SAFE_RANGE,      PM_SCROLL, diff --git a/layouts/community/ergodox/drashna/rules.mk b/layouts/community/ergodox/drashna/rules.mk index 61b6263071..f5e9b500e0 100644 --- a/layouts/community/ergodox/drashna/rules.mk +++ b/layouts/community/ergodox/drashna/rules.mk @@ -2,7 +2,6 @@ BOOTMAGIC_ENABLE   = yes      # Enable Bootmagic Lite  TAP_DANCE_ENABLE   = no  COMMAND_ENABLE     = no  # Commands for debug and configuration  CONSOLE_ENABLE     = no -SPACE_CADET_ENABLE = no  ifeq ($(strip $(KEYBOARD)), ergodox_ez)      RGBLIGHT_ENABLE            = yes @@ -16,5 +15,3 @@ endif  UNICODE_ENABLE        = no  UNICDOEMAP_ENABLE     = no  CUSTOM_UNICODE_ENABLE = no - -DEBOUNCE_TYPE     = sym_eager_pr diff --git a/layouts/community/ortho_4x12/drashna/keymap.c b/layouts/community/ortho_4x12/drashna/keymap.c index ce241fd76d..522fc772b4 100644 --- a/layouts/community/ortho_4x12/drashna/keymap.c +++ b/layouts/community/ortho_4x12/drashna/keymap.c @@ -106,7 +106,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {      KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RST,      VRSN,    _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,      TH_LVL,  _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL, -    KEYLOCK, _______, _______, _______, _______, KC_NUKE, _______, _______, _______, _______, _______, TG_MODS +    KEYLOCK, _______, _______, REBOOT,  _______, KC_NUKE, _______, _______, AUTO_CTN,_______, _______, TG_MODS    )  }; diff --git a/layouts/community/split_3x6_3/drashna/keymap.c b/layouts/community/split_3x6_3/drashna/keymap.c index 476ca5fcef..4bd4618d0c 100644 --- a/layouts/community/split_3x6_3/drashna/keymap.c +++ b/layouts/community/split_3x6_3/drashna/keymap.c @@ -90,7 +90,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {      KC_MAKE, _________________ADJUST_L1_________________,                    _________________ADJUST_R1_________________, KC_RESET,      VRSN,    _________________ADJUST_L2_________________,                    _________________ADJUST_R2_________________, EEP_RST,      KEYLOCK, _________________ADJUST_L3_________________,                    _________________ADJUST_R3_________________, RGB_IDL, -                                     AUTO_CTN,KC_NUKE, _______,        _______, TG_MODS, HPT_FBK +                                     REBOOT, KC_NUKE, _______,        _______, TG_MODS, AUTO_CTN    )  };  // clang-format on diff --git a/users/drashna/callbacks.c b/users/drashna/callbacks.c index 48b076b6ba..ffc777692e 100644 --- a/users/drashna/callbacks.c +++ b/users/drashna/callbacks.c @@ -70,6 +70,15 @@ void                       shutdown_user(void) {  __attribute__((weak)) void suspend_power_down_keymap(void) {}  void suspend_power_down_user(void) { +    if (layer_state_is(_GAMEPAD)) { +        layer_off(_GAMEPAD); +    } +    if (layer_state_is(_DIABLO)) { +        layer_off(_DIABLO); +    } +    if (layer_state_is(_DIABLOII)) { +        layer_off(_DIABLOII); +    }  #ifdef OLED_ENABLE      oled_off();  #endif @@ -78,12 +87,6 @@ void suspend_power_down_user(void) {  __attribute__((weak)) void suspend_wakeup_init_keymap(void) {}  void                       suspend_wakeup_init_user(void) { -    if (layer_state_is(_GAMEPAD)) { -        layer_off(_GAMEPAD); -    } -    if (layer_state_is(_DIABLO)) { -        layer_off(_DIABLO); -    }      suspend_wakeup_init_keymap();  } diff --git a/users/drashna/config.h b/users/drashna/config.h index 46cd276dd4..a6b4beb741 100644 --- a/users/drashna/config.h +++ b/users/drashna/config.h @@ -29,7 +29,7 @@  #        define SELECT_SOFT_SERIAL_SPEED 1  #    endif  #    ifdef CUSTOM_SPLIT_TRANSPORT_SYNC -#        define SPLIT_TRANSACTION_IDS_USER RPC_ID_USER_STATE_SYNC, RPC_ID_USER_KEYMAP_SYNC, RPC_ID_USER_CONFIG_SYNC, RPC_ID_USER_WATCHDOG_SYNC +#        define SPLIT_TRANSACTION_IDS_USER RPC_ID_USER_STATE_SYNC, RPC_ID_USER_KEYMAP_SYNC, RPC_ID_USER_CONFIG_SYNC, RPC_ID_USER_WATCHDOG_SYNC, RPC_ID_USER_KEYLOG_STR  #    endif  #endif @@ -271,3 +271,21 @@  #    define C14 PAL_LINE(GPIOC, 14)  #    define C15 PAL_LINE(GPIOC, 15)  #endif + +#ifdef OLED_DRIVER_SH1107 +#    define OLED_DISPLAY_CUSTOM +#    define OLED_IC_SH1107 2 +#    define OLED_DISPLAY_128X128 +#    define OLED_DISPLAY_WIDTH 128 +#    define OLED_DISPLAY_HEIGHT 128 +#    define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) +#    define OLED_BLOCK_TYPE uint16_t +#    define OLED_SOURCE_MAP \ +        { 0, 8, 16, 24, 32, 40, 48, 56 } +#    define OLED_TARGET_MAP \ +        { 56, 48, 40, 32, 24, 16, 8, 0 } +#    define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) +#    define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) +#    define OLED_COM_PINS COM_PINS_ALT +#    define OLED_IC OLED_IC_SH1107 +#endif diff --git a/users/drashna/drashna.c b/users/drashna/drashna.c index 9128a89bc6..6e8d4ac9bd 100644 --- a/users/drashna/drashna.c +++ b/users/drashna/drashna.c @@ -2,25 +2,37 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "drashna.h" +#ifdef __AVR__ +#    include <avr/wdt.h> +#endif  userspace_config_t userspace_config; +/** + * @brief Handle registering a keycode, with optional modifer based on timed event + * + * @param code keycode to send to host + * @param mod_code modifier to send with code, if held for tapping term or longer + * @param pressed the press/release event (can use "record->event.pressed" for this) + * @return true exits function + * @return false exits function + */  bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed) {      static uint16_t this_timer; -    if (pressed) { -        this_timer = timer_read(); -    } else { -        if (timer_elapsed(this_timer) < TAPPING_TERM) { -            tap_code(code); -        } else { -            register_code(mod_code); -            tap_code(code); -            unregister_code(mod_code); -        } -    } +    mod_key_press(code, mod_code, pressed, this_timer);      return false;  } +/** + * @brief Handle registation of keycode, with optional modifier based on custom timer + * + * @param code keycode to send to host + * @param mod_code modifier keycode to send with code, if held for tapping term or longer + * @param pressed the press/release event + * @param this_timer custom timer to use + * @return true + * @return false + */  bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer) {      if (pressed) {          this_timer = timer_read(); @@ -36,6 +48,14 @@ bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this      return false;  } +/** + * @brief Performs exact match for modifier values + * + * @param value the modifer varible (get_mods/get_oneshot_mods/get_weak_mods) + * @param mask the modifier mask to check for + * @return true Has the exact modifiers specifed + * @return false Does not have the exact modifiers specified + */  bool hasAllBitsInMask(uint8_t value, uint8_t mask) {      value &= 0xF;      mask &= 0xF; @@ -43,10 +63,62 @@ bool hasAllBitsInMask(uint8_t value, uint8_t mask) {      return (value & mask) == mask;  } -void tap_code16_nomods(uint8_t kc) { +/** + * @brief Tap keycode, with no mods + * + * @param kc keycode to use + */ +void tap_code16_nomods(uint16_t kc) {      uint8_t temp_mod = get_mods();      clear_mods();      clear_oneshot_mods();      tap_code16(kc);      set_mods(temp_mod);  } + +/** + * @brief Run shutdown routine and soft reboot firmware. + * + */ + +#ifdef HAPTIC_ENABLE +#    include "haptic.h" +#endif + +#ifdef AUDIO_ENABLE +#    ifndef GOODBYE_SONG +#        define GOODBYE_SONG SONG(GOODBYE_SOUND) +#    endif +float reset_song[][2] = GOODBYE_SONG; +#endif + +void software_reset(void) { +    clear_keyboard(); +#if defined(MIDI_ENABLE) && defined(MIDI_BASIC) +    process_midi_all_notes_off(); +#endif +#ifdef AUDIO_ENABLE +#    ifndef NO_MUSIC_MODE +    music_all_notes_off(); +#    endif +    uint16_t timer_start = timer_read(); +    PLAY_SONG(reset_song); +    shutdown_user(); +    while (timer_elapsed(timer_start) < 250) wait_ms(1); +    stop_all_notes(); +#else +    shutdown_user(); +    wait_ms(250); +#endif +#ifdef HAPTIC_ENABLE +    haptic_shutdown(); +#endif + +#if defined(PROTOCOL_LUFA) +    wdt_enable(WDTO_250MS); +#elif defined(PROTOCOL_CHIBIOS) +#    if defined(MCU_STM32) || defined(MCU_KINETIS) +    NVIC_SystemReset(); +#    endif +#endif +} diff --git a/users/drashna/drashna.h b/users/drashna/drashna.h index 5a9da16273..0bf1de84cf 100644 --- a/users/drashna/drashna.h +++ b/users/drashna/drashna.h @@ -78,7 +78,8 @@ enum userspace_layers {  bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed);  bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer);  bool hasAllBitsInMask(uint8_t value, uint8_t mask); -void tap_code16_nomods(uint8_t kc); +void tap_code16_nomods(uint16_t kc); +void software_reset(void);  // clang-format off  typedef union { diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.c b/users/drashna/keyrecords/autocorrection/autocorrection.c index e561224374..c7e938a341 100644 --- a/users/drashna/keyrecords/autocorrection/autocorrection.c +++ b/users/drashna/keyrecords/autocorrection/autocorrection.c @@ -17,6 +17,14 @@  #        error Dictionary size excees maximum size permitted  #    endif +/** + * @brief Process handler for autocorrect feature + * + * @param keycode Keycode registered by matrix press, per keymap + * @param record keyrecord_t structure + * @return true Continue processing keycodes, and send to host + * @return false Stop processing keycodes, and don't send to host + */  bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {      static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {KC_SPC};      static uint8_t typo_buffer_size                       = 1; @@ -53,6 +61,14 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {              keycode &= 0xFF;              break;  #    endif +#    ifdef SWAP_HANDS_ENABLE +        case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: +            if (keycode >= 0x56F0 || record->event.pressed || !record->tap.count) { +                return true; +            } +            keycode &= 0xFF; +            break; +#    endif  #    ifndef NO_ACTION_ONESHOT          case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:              if ((keycode & 0xF) == MOD_LSFT) { @@ -70,7 +86,6 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {              }      } -      // Subtract buffer for Backspace key, reset for other non-alpha.      if (!(KC_A <= keycode && keycode <= KC_Z)) {          if (keycode == KC_BSPC) { @@ -83,7 +98,7 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {              // Set a word boundary if space, period, digit, etc. is pressed.              // Behave more conservatively for the enter key. Reset, so that enter              // can't be used on a word ending. -            if (keycode == KC_ENT) { +            if (keycode == KC_ENT || (keycode == KC_MINUS && (get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT)) {                  typo_buffer_size = 0;              }              keycode = KC_SPC; diff --git a/users/drashna/keyrecords/caps_word.c b/users/drashna/keyrecords/caps_word.c index cc9ca93b72..0c7cd6cfe5 100644 --- a/users/drashna/keyrecords/caps_word.c +++ b/users/drashna/keyrecords/caps_word.c @@ -10,6 +10,16 @@  bool caps_word_enabled = false;  bool caps_word_shifted = false; +/** + * @brief Handler for Caps Word feature. + * + * This checks the keycodes, and applies shift to the correct keys, if and when needid. + * + * @param keycode Keycode from matrix + * @param record keyrecord_t data structure + * @return true Continue processing keycode and sent to host + * @return false Stop processing keycode, and do not send to host + */  bool process_caps_word(uint16_t keycode, keyrecord_t* record) {      if (!caps_word_enabled) {          // Pressing both shift keys at the same time enables caps word. diff --git a/users/drashna/keyrecords/process_records.c b/users/drashna/keyrecords/process_records.c index f49ac6ef64..012a57f7e4 100644 --- a/users/drashna/keyrecords/process_records.c +++ b/users/drashna/keyrecords/process_records.c @@ -18,8 +18,24 @@ bool     host_driver_disabled = false;  // Defines actions tor my global custom keycodes. Defined in drashna.h file  // Then runs the _keymap's record handier if not processed here +/** + * @brief Keycode handler for keymaps + * + * This handles the keycodes at the keymap level, useful for keyboard specific customization + */  __attribute__((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { return true; }  __attribute__((weak)) bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { return true; } + +/** + * @brief Main user keycode handler + * + * This handles all of the keycodes for the user, including calling feature handlers. + * + * @param keycode Keycode from matrix + * @param record keyrecord_t data structure + * @return true Continue processing keycode and send to host + * @return false Stop process keycode and do not send to host + */  bool                       process_record_user(uint16_t keycode, keyrecord_t *record) {      // If console is enabled, it will print the matrix position and status of each key pressed  #ifdef KEYLOGGER_ENABLE @@ -215,12 +231,7 @@ bool                       process_record_user(uint16_t keycode, keyrecord_t *re              return false;          case REBOOT:              if (record->event.pressed) { -                shutdown_user(); -#ifdef __AVR__ -                wdt_enable(WDTO_250MS); -#else -                NVIC_SystemReset(); -#endif +                software_reset();              }              return false; diff --git a/users/drashna/keyrecords/tap_dances.c b/users/drashna/keyrecords/tap_dances.c index 63eb0c3348..a1a7439164 100644 --- a/users/drashna/keyrecords/tap_dances.c +++ b/users/drashna/keyrecords/tap_dances.c @@ -11,7 +11,12 @@ diablo_timer_t diablo_timer[NUM_OF_DIABLO_KEYS];  // Otherwise, you will need to hit a bunch of times, or hit the "clear" command  uint8_t diablo_times[] = {0, 1, 3, 5, 10, 30}; -// Cycle through the times for the macro, starting at 0, for disabled. +/** + * @brief Main function for handling diable related tap dances. + * + * @param state Main data struction contining information about events + * @param user_data Local data for the dance. Allows customization to be passed on to function + */  void diablo_tapdance_master(qk_tap_dance_state_t *state, void *user_data) {      diable_keys_t *diablo_keys = (diable_keys_t *)user_data;      // Sets the keycode based on the index @@ -43,7 +48,10 @@ qk_tap_dance_action_t tap_dance_actions[] = {      [TD_D3_4] = ACTION_TAP_DANCE_DIABLO(3, KC_4),  }; -// Checks each of the 4 timers/keys to see if enough time has elapsed +/** + * @brief Runs check to see if timer has elapsed for each dance, and sends keycodes, if it has. + * + */  void run_diablo_macro_check(void) {      for (uint8_t index = 0; index < NUM_OF_DIABLO_KEYS; index++) {          // if key_interval is 0, it's disabled, so only run if it's set.  If it's set, check the timer. diff --git a/users/drashna/keyrecords/unicode.c b/users/drashna/keyrecords/unicode.c index 4010b9c1c6..db2058e5d1 100644 --- a/users/drashna/keyrecords/unicode.c +++ b/users/drashna/keyrecords/unicode.c @@ -8,6 +8,11 @@  uint16_t typing_mode; +/** + * @brief Registers the unicode keystrokes based on desired unicode + * + * @param glyph Unicode character, supports up to 0x1FFFF (or higher) + */  void tap_unicode_glyph_nomods(uint32_t glyph) {      uint8_t temp_mod = get_mods();      clear_mods(); @@ -43,6 +48,15 @@ typedef uint32_t (*translator_function_t)(bool is_shifted, uint32_t keycode);          return ret;                                                             \      } +/** + * @brief Handler function for outputting unicode. + * + * @param keycode Keycode from matrix. + * @param record keyrecord_t data structure + * @param translator translator lut for different unicode modes + * @return true Continue processing matrix press, and send to host + * @return false Replace keycode, and do not send to host + */  bool process_record_glyph_replacement(uint16_t keycode, keyrecord_t *record, translator_function_t translator) {      uint8_t temp_mod   = get_mods();      uint8_t temp_osm   = get_oneshot_mods(); @@ -182,6 +196,15 @@ bool process_record_zalgo(uint16_t keycode, keyrecord_t *record) {      return true;  } +/** + * @brief Main handler for unicode input + * + * @param keycode Keycode from switch matrix + * @param record keyrecord_t data struture + * @return true Send keycode from matrix to host + * @return false Stop processing and do not send to host + */ +  bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {      switch (keycode) {          case UC_FLIP:  // (ノಠ痊ಠ)ノ彡┻━┻ @@ -265,6 +288,10 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {      return process_unicode_common(keycode, record);  } +/** + * @brief Initialize the default unicode mode on firmware startu + * + */  void matrix_init_unicode(void) {      unicode_input_mode_init();  } diff --git a/users/drashna/oled/oled_stuff.c b/users/drashna/oled/oled_stuff.c index de84766725..eeca010de0 100644 --- a/users/drashna/oled/oled_stuff.c +++ b/users/drashna/oled/oled_stuff.c @@ -22,17 +22,12 @@  extern bool host_driver_disabled; -#ifndef KEYLOGGER_LENGTH -// #    ifdef OLED_DISPLAY_128X64 -#    define KEYLOGGER_LENGTH ((uint8_t)(OLED_DISPLAY_HEIGHT / OLED_FONT_WIDTH)) -// #    else -// #        define KEYLOGGER_LENGTH (uint8_t *(OLED_DISPLAY_WIDTH / OLED_FONT_HEIGHT)) -// #    endif -#endif +uint32_t                  oled_timer                            = 0; +char                      keylog_str[OLED_KEYLOGGER_LENGTH]     = {0}; +static uint16_t           log_timer                             = 0; +static const char PROGMEM display_border[3]                     = {0x0, 0xFF, 0x0}; -uint32_t        oled_timer                       = 0; -static char     keylog_str[KEYLOGGER_LENGTH + 1] = {0}; -static uint16_t log_timer                        = 0; +deferred_token kittoken;  // clang-format off  static const char PROGMEM code_to_name[256] = { @@ -56,10 +51,16 @@ static const char PROGMEM code_to_name[256] = {  };  // clang-format on +/** + * @brief parses pressed keycodes and saves to buffer + * + * @param keycode Keycode pressed from switch matrix + * @param record keyrecord_t data structure + */  void add_keylog(uint16_t keycode, keyrecord_t *record) {      if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) || (keycode >= QK_MODS && keycode <= QK_MODS_MAX)) {          if (((keycode & 0xFF) == KC_BSPC) && mod_config(get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) { -            memset(keylog_str, ' ', sizeof(keylog_str) - 1); +            memset(keylog_str, ' ', OLED_KEYLOGGER_LENGTH);              return;          }          if (record->tap.count) { @@ -72,23 +73,29 @@ void add_keylog(uint16_t keycode, keyrecord_t *record) {          return;      } -    for (uint8_t i = 1; i < KEYLOGGER_LENGTH; i++) { -        keylog_str[i - 1] = keylog_str[i]; -    } +    memmove(keylog_str, keylog_str + 1, OLED_KEYLOGGER_LENGTH - 1);      if (keycode < (sizeof(code_to_name) / sizeof(char))) { -        keylog_str[(KEYLOGGER_LENGTH - 1)] = pgm_read_byte(&code_to_name[keycode]); +        keylog_str[(OLED_KEYLOGGER_LENGTH - 1)] = pgm_read_byte(&code_to_name[keycode]);      }      log_timer = timer_read();  } +/** + * @brief Keycode handler for oled display. + * + * This adds pressed keys to buffer, but also resets the oled timer + * + * @param keycode Keycode from matrix + * @param record keyrecord data struture + * @return true + * @return false + */  bool process_record_user_oled(uint16_t keycode, keyrecord_t *record) {      if (record->event.pressed) { -#ifdef OLED_ENABLE          oled_timer = timer_read32();          add_keylog(keycode, record); -#endif      }      return true;  } @@ -99,12 +106,29 @@ void update_log(void) {      }  } +/** + * @brief Renders keylogger buffer to oled + * + */  void render_keylogger_status(void) { +#ifdef OLED_DISPLAY_VERBOSE +    oled_set_cursor(1, 7); +#endif      oled_write_P(PSTR(OLED_RENDER_KEYLOGGER), false);      oled_write(keylog_str, false); +#ifdef OLED_DISPLAY_VERBOSE +    oled_advance_page(true); +#endif  } +/** + * @brief Renders default layer state (aka layout) to oled + * + */  void render_default_layer_state(void) { +#ifdef OLED_DISPLAY_VERBOSE +    oled_set_cursor(5, 2); +#endif      oled_write_P(PSTR(OLED_RENDER_LAYOUT_NAME), false);      switch (get_highest_layer(default_layer_state)) {          case _QWERTY: @@ -120,46 +144,150 @@ void render_default_layer_state(void) {              oled_write_P(PSTR(OLED_RENDER_LAYOUT_DVORAK), false);              break;      } -#ifdef OLED_DISPLAY_128X64 +#ifdef OLED_DISPLAY_VERBOSE      oled_advance_page(true);  #endif  } +/** + * @brief Renders the active layers to the OLED + * + */  void render_layer_state(void) { -    oled_write_P(PSTR(OLED_RENDER_LAYER_NAME), false); -#ifdef OLED_DISPLAY_128X64 -    oled_write_P(PSTR(" "), false); -#endif -    oled_write_P(PSTR(OLED_RENDER_LAYER_LOWER), layer_state_is(_LOWER)); -#ifdef OLED_DISPLAY_128X64 +#ifdef OLED_DISPLAY_VERBOSE +    static const char PROGMEM tri_layer_image[4][3][18] = { +        { +            { +                0x80, 0x80, 0x40, 0x40, 0x20, 0x20, +                0x10, 0x10, 0x08, 0x08, 0x10, 0x10, +                0x20, 0x20, 0x40, 0x40, 0x80, 0x80 +            }, +            { +                0x88, 0x88, 0x5D, 0x5D, 0x3E, 0x3E, +                0x7C, 0x7C, 0xF8, 0xF8, 0x7C, 0x7C, +                0x3E, 0x3E, 0x5D, 0x5D, 0x88, 0x88 +            }, +            { +                0x00, 0x00, 0x01, 0x01, 0x02, 0x02, +                0x04, 0x04, 0x08, 0x08, 0x04, 0x04, +                0x02, 0x02, 0x01, 0x01, 0x00, 0x00 +            } +        }, +        { +            { +                0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, +                0xF0, 0xF0, 0xF8, 0xF8, 0xF0, 0xF0, +                0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x80 +            }, +            { +                0x88, 0x88, 0x55, 0x55, 0x23, 0x23, +                0x47, 0x47, 0x8F, 0x8F, 0x47, 0x47, +                0x23, 0x23, 0x55, 0x55, 0x88, 0x88 +            }, +            { +                0x00, 0x00, 0x01, 0x01, 0x02, 0x02, +                0x04, 0x04, 0x08, 0x08, 0x04, 0x04, +                0x02, 0x02, 0x01, 0x01, 0x00, 0x00 +            } +        }, +        { +            { +                0x80, 0x80, 0x40, 0x40, 0x20, 0x20, +                0x10, 0x10, 0x08, 0x08, 0x10, 0x10, +                0x20, 0x20, 0x40, 0x40, 0x80, 0x80 +            }, +            { +                0x88, 0x88, 0xD5, 0xD5, 0xE2, 0xE2, +                0xC4, 0xC4, 0x88, 0x88, 0xC4, 0xC4, +                0xE2, 0xE2, 0xD5, 0xD5, 0x88, 0x88 +            }, +            { +                0x00, 0x00, 0x01, 0x01, 0x03, 0x03, +                0x07, 0x07, 0x0F, 0x0F, 0x07, 0x07, +                0x03, 0x03, 0x01, 0x01, 0x00, 0x00 +            } +        }, +        { +            { +                0x80, 0x80, 0x40, 0xC0, 0x60, 0xA0, +                0x50, 0xB0, 0x58, 0xA8, 0x50, 0xB0, +                0x60, 0xA0, 0x40, 0xC0, 0x80, 0x80 +            }, +            { +                0x88, 0x88, 0x5D, 0xD5, 0x6B, 0xB6, +                0x6D, 0xD6, 0xAD, 0xDA, 0x6D, 0xD6, +                0x6B, 0xB6, 0x5D, 0xD5, 0x88, 0x88 +            }, +            { +                0x00, 0x00, 0x01, 0x01, 0x03, 0x02, +                0x05, 0x06, 0x0D, 0x0A, 0x05, 0x06, +                0x03, 0x02, 0x01, 0x01, 0x00, 0x00 +            } +        } +    }; + +    uint8_t layer_is = 0; +    if (layer_state_is(_ADJUST)) { +        layer_is = 3; +    } else if (layer_state_is(_RAISE)) { +        layer_is = 1; +    } else if (layer_state_is(_LOWER)) { +        layer_is = 2; +    } + +    oled_set_cursor(1, 2); +    oled_write_raw_P(tri_layer_image[layer_is][0], sizeof(tri_layer_image[0][0])); +    oled_set_cursor(5, 3); +    oled_write_P(PSTR("Diablo2"), layer_state_is(_DIABLOII));      oled_write_P(PSTR(" "), false); -#endif -    oled_write_P(PSTR(OLED_RENDER_LAYER_RAISE), layer_state_is(_RAISE)); -#ifdef OLED_DISPLAY_128X64 +    oled_write_P(PSTR("Diablo3"), layer_state_is(_DIABLO));      oled_advance_page(true); -    oled_write_P(PSTR(" "), false); + +    oled_set_cursor(1, 3); +    oled_write_raw_P(tri_layer_image[layer_is][1], sizeof(tri_layer_image[0][0])); +    oled_set_cursor(5, 4);      oled_write_P(PSTR("GamePad"), layer_state_is(_GAMEPAD));      oled_write_P(PSTR(" "), false); -    oled_write_P(PSTR("Diablo"), layer_state_is(_DIABLO)); -    oled_write_P(PSTR(" "), false);      oled_write_P(PSTR("Mouse"), layer_state_is(_MOUSE)); +    oled_advance_page(true); + +    oled_set_cursor(1, 4); +    oled_write_raw_P(tri_layer_image[layer_is][2], sizeof(tri_layer_image[0][0])); + +#else +    oled_write_P(PSTR(OLED_RENDER_LAYER_NAME), false); +    oled_write_P(PSTR(OLED_RENDER_LAYER_LOWER), layer_state_is(_LOWER)); +    oled_write_P(PSTR(OLED_RENDER_LAYER_RAISE), layer_state_is(_RAISE)); +    oled_advance_page(true);  #endif  } +/** + * @brief Renders the current lock status to oled + * + * @param led_usb_state Current keyboard led state + */  void render_keylock_status(uint8_t led_usb_state) { +#if defined(OLED_DISPLAY_VERBOSE) +    oled_set_cursor(1, 6); +#endif      oled_write_P(PSTR(OLED_RENDER_LOCK_NAME), false); -#if !defined(OLED_DISPLAY_128X64) +#if !defined(OLED_DISPLAY_VERBOSE)      oled_write_P(PSTR(" "), false);  #endif      oled_write_P(PSTR(OLED_RENDER_LOCK_NUML), led_usb_state & (1 << USB_LED_NUM_LOCK));      oled_write_P(PSTR(" "), false);      oled_write_P(PSTR(OLED_RENDER_LOCK_CAPS), led_usb_state & (1 << USB_LED_CAPS_LOCK)); -#if defined(OLED_DISPLAY_128X64) +#if defined(OLED_DISPLAY_VERBOSE)      oled_write_P(PSTR(" "), false);      oled_write_P(PSTR(OLED_RENDER_LOCK_SCLK), led_usb_state & (1 << USB_LED_SCROLL_LOCK));  #endif  } +/** + * @brief Renders the matrix scan rate to the host system + * + */  void render_matrix_scan_rate(void) {  #ifdef DEBUG_MATRIX_SCAN_RATE      oled_write_P(PSTR("MS:"), false); @@ -167,10 +295,18 @@ void render_matrix_scan_rate(void) {  #endif  } +/** + * @brief Renders the modifier state + * + * @param modifiers Modifiers to check against (real, weak, onesheot, etc;) + */  void render_mod_status(uint8_t modifiers) {      static const char PROGMEM mod_status[5][3] = {{0xE8, 0xE9, 0}, {0xE4, 0xE5, 0}, {0xE6, 0xE7, 0}, {0xEA, 0xEB, 0}, {0xEC, 0xED, 0}}; +#if defined(OLED_DISPLAY_VERBOSE) +    oled_set_cursor(1, 5); +#endif      oled_write_P(PSTR(OLED_RENDER_MODS_NAME), false); -#if defined(OLED_DISPLAY_128X64) +#if defined(OLED_DISPLAY_VERBOSE)      oled_write_P(mod_status[0], (modifiers & MOD_BIT(KC_LSHIFT)));      oled_write_P(mod_status[!keymap_config.swap_lctl_lgui ? 3 : 4], (modifiers & MOD_BIT(KC_LGUI)));      oled_write_P(mod_status[2], (modifiers & MOD_BIT(KC_LALT))); @@ -200,26 +336,27 @@ void render_bootmagic_status(void) {      };      bool is_bootmagic_on; -#ifdef OLED_DISPLAY_128X64 +#ifdef OLED_DISPLAY_VERBOSE +    oled_set_cursor(7, 4);      is_bootmagic_on = !keymap_config.swap_lctl_lgui;  #else      is_bootmagic_on = keymap_config.swap_lctl_lgui;  #endif -    oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NAME), false); -#ifdef OLED_DISPLAY_128X64 +#ifdef OLED_DISPLAY_VERBOSE      if (keymap_config.swap_lctl_lgui)  #else +    oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NAME), false);      oled_write_P(PSTR(" "), false);  #endif      {          oled_write_P(logo[1][0], is_bootmagic_on); -#ifdef OLED_DISPLAY_128X64 +#ifdef OLED_DISPLAY_VERBOSE      } else {  #endif          oled_write_P(logo[0][0], !is_bootmagic_on);      } -#ifndef OLED_DISPLAY_128X64 +#ifndef OLED_DISPLAY_VERBOSE      oled_write_P(PSTR(" "), false);      oled_write_P(logo[1][1], is_bootmagic_on);      oled_write_P(logo[0][1], !is_bootmagic_on); @@ -232,10 +369,8 @@ void render_bootmagic_status(void) {  #else      oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui);  #endif -#ifdef OLED_DISPLAY_128X64 -    oled_advance_page(true); -    oled_write_P(PSTR("Magic"), false); -    oled_write_P(PSTR(" "), false); +#ifdef OLED_DISPLAY_VERBOSE +    oled_set_cursor(7, 5);      if (keymap_config.swap_lctl_lgui) {          oled_write_P(logo[1][1], is_bootmagic_on);      } else { @@ -248,9 +383,6 @@ void render_bootmagic_status(void) {      oled_write_P(PSTR(" "), false);      oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_SWAP), swap_hands);  #endif -#ifdef OLED_DISPLAY_128X64 -    oled_advance_page(true); -#endif  }  #if defined(POINTING_DEVICE_ENABLE) @@ -269,13 +401,16 @@ void render_user_status(void) {      is_clicky_on = is_clicky_on();  #    endif  #endif +#if defined(OLED_DISPLAY_VERBOSE) +    oled_set_cursor(1, 6); +#endif      oled_write_P(PSTR(OLED_RENDER_USER_NAME), false); -#if !defined(OLED_DISPLAY_128X64) +#if !defined(OLED_DISPLAY_VERBOSE)      oled_write_P(PSTR(" "), false);  #endif  #if defined(RGB_MATRIX_ENABLE)      oled_write_P(PSTR(OLED_RENDER_USER_ANIM), userspace_config.rgb_matrix_idle_anim); -#    if !defined(OLED_DISPLAY_128X64) +#    if !defined(OLED_DISPLAY_VERBOSE)      oled_write_P(PSTR(" "), false);  #    endif  #elif defined(POINTING_DEVICE_ENABLE) @@ -289,7 +424,7 @@ void render_user_status(void) {  #    ifdef AUDIO_CLICKY      static const char PROGMEM audio_clicky_status[2][3] = {{0xF4, 0xF5, 0}, {0xF6, 0xF7, 0}};      oled_write_P(audio_clicky_status[is_clicky_on && is_audio_on], false); -#        if !defined(OLED_DISPLAY_128X64) +#        if !defined(OLED_DISPLAY_VERBOSE)      oled_write_P(PSTR(" "), false);  #        endif  #    endif @@ -304,30 +439,20 @@ void render_user_status(void) {      oled_write_P(uc_mod_status[get_unicode_input_mode() == UC_MAC], false);  #endif      if (userspace_config.nuke_switch) { -#if !defined(OLED_DISPLAY_128X64) +#if !defined(OLED_DISPLAY_VERBOSE)          oled_write_P(PSTR(" "), false);  #endif          static const char PROGMEM nukem_good[2] = {0xFA, 0};          oled_write_P(nukem_good, false); -#if !defined(OLED_DISPLAY_128X64) +#if !defined(OLED_DISPLAY_VERBOSE)          oled_advance_page(true);  #endif      } -#if defined(OLED_DISPLAY_128X64) +#if defined(OLED_DISPLAY_VERBOSE)      oled_advance_page(true);  #endif  } -void oled_driver_render_logo(void) { -    // clang-format off -    static const char PROGMEM qmk_logo[] = { -        0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94, -        0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4, -        0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0}; -    // clang-format on -    oled_write_P(qmk_logo, false); -} -  void render_wpm(uint8_t padding) {  #ifdef WPM_ENABLE @@ -356,49 +481,389 @@ void                    render_pointing_dpi_status(uint8_t padding) {  #endif  __attribute__((weak)) void oled_driver_render_logo_right(void) { -#if defined(OLED_DISPLAY_128X64) -    oled_driver_render_logo(); +#if defined(OLED_DISPLAY_VERBOSE) +    oled_set_cursor(0, 2);      render_default_layer_state(); -    oled_set_cursor(0, 4);  #else      render_default_layer_state();  #endif  } -__attribute__((weak)) void oled_driver_render_logo_left(void) { -#if defined(OLED_DISPLAY_128X64) -    oled_driver_render_logo(); -#    ifdef DEBUG_MATRIX_SCAN_RATE +// WPM-responsive animation stuff here +#define OLED_SLEEP_FRAMES 2 +#define OLED_SLEEP_SPEED 10  // below this wpm value your animation will idle + +#define OLED_WAKE_FRAMES 2                // uncomment if >1 +#define OLED_WAKE_SPEED OLED_SLEEP_SPEED  // below this wpm value your animation will idle + +#define OLED_KAKI_FRAMES 3 +#define OLED_KAKI_SPEED 40  // above this wpm value typing animation to triggere + +#define OLED_RTOGI_FRAMES 2 +//#define OLED_LTOGI_FRAMES 2 + +//#define ANIM_FRAME_DURATION 500 // how long each frame lasts in ms +// #define SLEEP_TIMER 60000 // should sleep after this period of 0 wpm, needs fixing +#define OLED_ANIM_SIZE 32  // number of bytes in array, minimize for adequate firmware size, max is 1024 +#define OLED_ANIM_ROWS 4 +#define OLED_ANIM_MAX_FRAMES 3 +#if (OLED_SLEEP_FRAMES > OLED_ANIM_MAX_FRAMES) || (OLED_WAKE_FRAMES > OLED_ANIM_MAX_FRAMES) || (OLED_KAKI_FRAMES > OLED_ANIM_MAX_FRAMES) || (OLED_RTOGI_FRAMES > OLED_ANIM_MAX_FRAMES) +#    error frame size too large +#endif + +static uint8_t  animation_frame     = 0; +static uint8_t  animation_type      = 0; + +void render_kitty(void) { +    // Images credit j-inc(/James Incandenza) and pixelbenny. +    // Credit to obosob for initial animation approach. +    // heavily modified by drashna because he's a glutton for punishment + +    // clang-format off +    static const char PROGMEM animation[4][OLED_ANIM_MAX_FRAMES][OLED_ANIM_ROWS][OLED_ANIM_SIZE] = { +        // sleep frames +        { +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, +                    0xa8, 0x48, 0xa8, 0x18, 0x08, 0x00, 0x00, 0x00, +                    0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, +                    0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x80, +                    0x44, 0x84, 0x06, 0x05, 0x04, 0x80, 0x40, 0x20, +                    0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, +                    0x18, 0x04, 0x04, 0x02, 0x7a, 0x86, 0x01, 0x80, +                    0x80, 0x01, 0x03, 0x05, 0x07, 0x01, 0x00, 0x00, +                    0x80, 0x83, 0x45, 0xfa, 0x3c, 0xe0, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, +                    0x10, 0x10, 0x10, 0x10, 0x10, 0x33, 0x24, 0x28, +                    0x28, 0x29, 0x29, 0x29, 0x3a, 0x18, 0x1c, 0x39, +                    0x24, 0x24, 0x3a, 0x2d, 0x26, 0x31, 0x1f, 0x00 +                } +            }, +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x22, 0x22, 0x3a, 0x2a, 0x26, 0x22, 0x80, 0xc0, +                    0x80, 0x00, 0x24, 0x34, 0x2c, 0xe4, 0x60, 0x10, +                    0x70, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38, +                    0x04, 0x02, 0x02, 0x01, 0x79, 0x87, 0x01, 0x80, +                    0x81, 0x83, 0x05, 0x05, 0x03, 0x01, 0x00, 0x00, +                    0x80, 0x43, 0x05, 0xfa, 0x3c, 0xe0, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, +                    0x10, 0x10, 0x10, 0x10, 0x10, 0x33, 0x24, 0x28, +                    0x28, 0x28, 0x29, 0x29, 0x3a, 0x18, 0x1c, 0x39, +                    0x24, 0x24, 0x3a, 0x2d, 0x26, 0x31, 0x1f, 0x00 +                } +            } +        }, +        // wake frames +        { +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0xc0, 0x30, 0x08, 0x10, 0x60, 0x80, +                    0x00, 0x80, 0x60, 0x10, 0x08, 0x30, 0xc0, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x7f, 0x80, 0x40, 0x40, 0x5c, 0x00, 0x01, +                    0x41, 0x01, 0x00, 0x5c, 0x40, 0x40, 0x80, 0x7f, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +                    0x40, 0x40, 0x80, 0xe1, 0x12, 0x0a, 0x06, 0x00, +                    0x80, 0x00, 0x06, 0x0a, 0x12, 0xe1, 0x80, 0x40, +                    0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, +                    0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, +                    0x0f, 0x18, 0x10, 0x10, 0x1f, 0x11, 0x10, 0x10, +                    0x14, 0x14, 0x1f, 0x1c, 0x14, 0x14, 0x14, 0x08 +                } +            }, +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0xc0, 0x30, 0x08, 0x10, 0x60, 0x80, +                    0x00, 0x80, 0x60, 0x10, 0x08, 0x30, 0xc0, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x7f, 0x90, 0x12, 0x0a, 0x02, 0xf4, 0x09, +                    0x0d, 0xf1, 0x04, 0x02, 0x0a, 0x12, 0x90, 0x7f, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +                    0x40, 0x40, 0x80, 0xe1, 0x12, 0x0a, 0x06, 0x01, +                    0x81, 0x00, 0x06, 0x0a, 0x12, 0xe1, 0x80, 0x40, +                    0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, +                    0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, +                    0x0f, 0x18, 0x10, 0x10, 0x1f, 0x11, 0x10, 0x10, +                    0x14, 0x14, 0x1f, 0x1c, 0x14, 0x14, 0x14, 0x08 +                } +            } +        }, +        // kaki frames +        { +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x40, +                    0x80, 0x80, 0x80, 0x00, 0xfc, 0x84, 0x08, 0x08, +                    0x10, 0x20, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1e, 0x60, +                    0x80, 0x00, 0x00, 0x91, 0xa1, 0x80, 0x00, 0x00, +                    0x22, 0x84, 0x40, 0x50, 0x48, 0xc1, 0x3e, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +                    0x40, 0x41, 0x82, 0xe2, 0x12, 0x0a, 0x06, 0x00, +                    0x80, 0x88, 0x4f, 0x02, 0x22, 0xe2, 0x9f, 0x40, +                    0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, +                    0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, +                    0x0f, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10, +                    0x14, 0x14, 0x1f, 0x1a, 0x0a, 0x0a, 0x04, 0x00 +                } +            }, +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0xf0, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x06, 0x1a, 0x22, 0xc2, 0x04, 0x04, +                    0x04, 0x07, 0x00, 0xc0, 0x20, 0x10, 0x80, 0x80, +                    0x01, 0x01, 0x02, 0xfc, 0xfe, 0x02, 0x3c, 0x20, +                    0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d, +                    0x55, 0x50, 0x94, 0xf0, 0x10, 0x09, 0x08, 0x00, +                    0x80, 0x00, 0x06, 0x09, 0x1b, 0xee, 0x00, 0x00, +                    0x00, 0x00, 0x81, 0xfe, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, +                    0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, +                    0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c, +                    0x14, 0x16, 0x15, 0x14, 0x14, 0x14, 0x14, 0x08 +                } +            }, +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x80, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x20, 0x40, +                    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x01, +                    0x02, 0x04, 0x04, 0x03, 0x80, 0x40, 0x40, 0x20, +                    0x00, 0x01, 0x02, 0x8c, 0x70, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d, +                    0x55, 0x50, 0x94, 0xf0, 0x10, 0x0a, 0x0e, 0x1d, +                    0x95, 0x24, 0x24, 0x27, 0x13, 0xe1, 0x01, 0x01, +                    0x01, 0x01, 0x02, 0xfc, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, +                    0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, +                    0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c, +                    0x14, 0x14, 0x17, 0x14, 0x14, 0x14, 0x14, 0x08 +                } +            } +        }, +        // rtogi frames +        { +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02, +                    0x01, 0x0f, 0x90, 0x10, 0x20, 0xf0, 0xf8, 0xf8 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +                    0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, +                    0x48, 0x47, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x08, 0x88, 0xc7, 0xc4, 0x62, 0x23, 0x11, 0x3f +                }, +                { +                    0x80, 0x40, 0x20, 0x10, 0x88, 0xcc, 0x43, 0x80, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, +                    0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c, +                    0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                }, +                { +                    0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, +                    0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, +                    0x05, 0x04, 0x04, 0x04, 0x07, 0x07, 0x07, 0x03, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                } +            }, +            { +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02, +                    0x01, 0x1f, 0xa0, 0x20, 0x40, 0x80, 0x00, 0xf0 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +                    0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, +                    0x48, 0x47, 0x88, 0x00, 0x00, 0x00, 0x00, 0x24, +                    0x24, 0x28, 0x6b, 0x40, 0xa0, 0x99, 0x86, 0xff +                }, +                { +                    0x0f, 0x11, 0x22, 0x44, 0x48, 0x4c, 0x43, 0x80, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, +                    0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c, +                    0x04, 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x06, 0x01 +                }, +                { +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +                    0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, +                    0x05, 0x04, 0x04, 0x04, 0x07, 0x07, 0x07, 0x03, +                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +                } +            } +        } +    }; +    // clang-format on + +    for (uint8_t i = 0; i < 4; i++) { +        oled_set_cursor(1, i + 2); +        oled_write_raw_P(animation[animation_type][animation_frame][i], OLED_ANIM_SIZE); +    } +} + +uint32_t kitty_animation_phases(uint32_t triger_time, void *cb_arg) { +    uint32_t anim_frame_duration = 500; +    // can't change animation frame duration here, otherwise, it gets stuck. +    // weirdly, it seems to work fine if it's in keymap.c but not here. +    // Should move this block to the deferred execution? +#ifdef POINTING_DEVICE_ENABLE +    if (tap_toggling) { +        animation_frame = (animation_frame + 1) % OLED_RTOGI_FRAMES; +        animation_type = 3; +        anim_frame_duration = 300; +    } else +#endif +    { +        if (get_current_wpm() <= OLED_SLEEP_SPEED) { +            animation_frame     = (animation_frame + 1) % OLED_SLEEP_FRAMES; +            animation_type      = 0; +            anim_frame_duration = 500; +        } else if (get_current_wpm() > OLED_WAKE_SPEED) { +            animation_frame     = (animation_frame + 1) % OLED_WAKE_FRAMES; +            animation_type      = 1; +            anim_frame_duration = 800; +        } else if (get_current_wpm() >= OLED_KAKI_SPEED) { +            animation_frame     = (animation_frame + 1) % OLED_KAKI_FRAMES; +            animation_type      = 2; +            anim_frame_duration = 500; +        } +    } +    return anim_frame_duration; +} + +void oled_driver_render_logo_left(void) { +#if defined(OLED_DISPLAY_VERBOSE) +    oled_set_cursor(0, 2); +    render_kitty(); + +#    if defined(KEYBOARD_handwired_tractyl_manuform) +    oled_set_cursor(7, 0); +    oled_write_P(PSTR("Tractyl"), true); +#    elif defined(KEYBOARD_bastardkb_charybdis) +    oled_set_cursor(6, 0); +    oled_write_P(PSTR("Charybdis"), true); +#    else +    oled_set_cursor(8, 0); +    oled_write_P(PSTR("Left"), true); +#    endif +    oled_set_cursor(7, 2); +#    if defined(DEBUG_MATRIX_SCAN_RATE)      render_matrix_scan_rate();  #    elif defined(WPM_ENABLE) -    render_wpm(0); +    render_wpm(1);  #    endif -    oled_write_P(PSTR("  "), false); -#    if defined(KEYBOARD_handwired_tractyl_manuform) || defined(KEYBOARD_bastardkb_charybdis) +    oled_set_cursor(7, 3); +#    if defined(KEYBOARD_handwired_tractyl_manuform) +    render_pointing_dpi_status(0); +#    elif defined(KEYBOARD_bastardkb_charybdis)      render_pointing_dpi_status(1);  #    endif -    oled_set_cursor(0, 4); +    oled_set_cursor(0, 6);  #else      render_default_layer_state();  #endif  }  void render_status_secondary(void) { +#    if defined(KEYBOARD_handwired_tractyl_manuform) +    oled_set_cursor(7, 0); +    oled_write_P(PSTR("Manuform"), true); +#    elif defined(KEYBOARD_bastardkb_charybdis) +    oled_set_cursor(6, 0); +    oled_write_P(PSTR("Charybdis"), true); +#    else +    oled_set_cursor(8, 0); +    oled_write_P(PSTR("Right"), true); +#    endif      oled_driver_render_logo_right();      /* Show Keyboard Layout  */      render_layer_state();      render_mod_status(get_mods() | get_oneshot_mods()); -#if !defined(OLED_DISPLAY_128X64) && defined(WPM_ENABLE) && !defined(CONVERT_TO_PROTON_C) +#if !defined(OLED_DISPLAY_VERBOSE) && defined(WPM_ENABLE) && !defined(CONVERT_TO_PROTON_C)      render_wpm(2);  #endif -    // render_keylock_status(host_keyboard_leds()); +    render_keylock_status(host_keyboard_leds());  }  void render_status_main(void) {      oled_driver_render_logo_left();      /* Show Keyboard Layout  */ -    // render_keylock_status(host_keyboard_leds());      render_bootmagic_status();      render_user_status(); @@ -408,8 +873,14 @@ void render_status_main(void) {  __attribute__((weak)) oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return rotation; }  oled_rotation_t oled_init_user(oled_rotation_t rotation) { -    memset(keylog_str, ' ', sizeof(keylog_str) - 1); +    if (is_keyboard_master()) { +        memset(keylog_str, ' ', OLED_KEYLOGGER_LENGTH); +    } + +    kittoken = defer_exec(3000, kitty_animation_phases, NULL); +    oled_clear(); +    oled_render();      return oled_init_keymap(rotation);  } @@ -417,22 +888,61 @@ bool oled_task_user(void) {      update_log();      if (is_keyboard_master()) { +#ifndef OLED_DISPLAY_TEST          if (timer_elapsed32(oled_timer) > 30000) {              oled_off();              return false; -        } else { +        } else +#endif +        {              oled_on();          }      } +#if defined(OLED_DISPLAY_VERBOSE) +     static const char PROGMEM header_image[] = { +         0,192, 32, 16,  8,  4,  2,  1,  1,  1,  1,  1,  1,  1,  1,  3,  7, 15, 31, 63,127,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127, 63, 31, 15,  7,  3,  1,  1,  1,  1,  1,  1,  1,  1,  2,  4,  8, 16, 32,192,  0, +         0,255,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  3,  7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  7,  3,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,255,  0 +     }; +     static const char PROGMEM footer_image[] = { +         0,  3,  4,  8, 16, 32, 64,128,128,128,128,128,128,128,192,224,240,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,240,224,192,128,128,128,128,128,128,128, 64, 32, 16,  8,  4,  3,  0 +     }; +    oled_write_raw_P(header_image, sizeof(header_image)); +    oled_set_cursor(0, 1); +#endif + +#ifndef OLED_DISPLAY_TEST      if (is_keyboard_left()) { +#endif          render_status_main();  // Renders the current keyboard state (layer, lock, caps, scroll, etc) +#ifndef OLED_DISPLAY_TEST      } else {          render_status_secondary();      } -    if (is_keyboard_master()) { +#endif + +#if defined(OLED_DISPLAY_128X128) +    if (is_keyboard_left()) {          render_keylogger_status(); -    } else { -        render_keylock_status(host_keyboard_leds());      } +#endif + +#if defined(OLED_DISPLAY_VERBOSE) +    uint8_t num_of_rows; +#    if defined(OLED_DISPLAY_128X128) +    num_of_rows = 15; +#    else +    num_of_rows = 7; +#    endif +    for (uint8_t i= 1; i < num_of_rows; i++) { +        oled_set_cursor(0, i); +        oled_write_raw_P(display_border, sizeof(display_border)); +        oled_set_cursor(21, i); +        oled_write_raw_P(display_border, sizeof(display_border)); +    } + +    oled_set_cursor(0, num_of_rows); +    oled_write_raw_P(footer_image, sizeof(footer_image)); +#endif +      return false;  } diff --git a/users/drashna/oled/oled_stuff.h b/users/drashna/oled/oled_stuff.h index 8795684d6a..985153c2ff 100644 --- a/users/drashna/oled/oled_stuff.h +++ b/users/drashna/oled/oled_stuff.h @@ -18,6 +18,7 @@  #include "quantum.h"  #include "oled_driver.h" +extern deferred_token kittoken;  void            oled_driver_render_logo(void);  bool            process_record_user_oled(uint16_t keycode, keyrecord_t *record); @@ -37,12 +38,16 @@ void            render_pointing_dpi_status(uint8_t padding);  void            oled_driver_render_logo_left(void);  void            oled_driver_render_logo_right(void); -#ifdef OLED_DISPLAY_128X64 -#    define OLED_RENDER_KEYLOGGER         "Keylogger: " +#if defined(OLED_DISPLAY_128X128) || defined(OLED_DISPLAY_128X64) +#    define OLED_DISPLAY_VERBOSE +#    define OLED_RENDER_KEYLOGGER         "Keylogger: " +#    ifndef OLED_KEYLOGGER_LENGTH +#        define OLED_KEYLOGGER_LENGTH         9 +#    endif  #    define OLED_RENDER_LAYOUT_NAME       "Layout: "  #    define OLED_RENDER_LAYOUT_QWERTY     "Qwerty" -#    define OLED_RENDER_LAYOUT_COLEMAK_DH "Colemak-DH" +#    define OLED_RENDER_LAYOUT_COLEMAK_DH "ColemkDH"  #    define OLED_RENDER_LAYOUT_COLEMAK    "Colemak"  #    define OLED_RENDER_LAYOUT_DVORAK     "Dvorak"  #    define OLED_RENDER_LAYOUT_WORKMAN    "Workman" @@ -58,11 +63,11 @@ void            oled_driver_render_logo_right(void);  #    define OLED_RENDER_LAYER_MODS        "Mods"  #    define OLED_RENDER_LOCK_NAME         "Lock: " -#    define OLED_RENDER_LOCK_NUML         "NUML" +#    define OLED_RENDER_LOCK_NUML         "NUM"  #    define OLED_RENDER_LOCK_CAPS         "CAPS"  #    define OLED_RENDER_LOCK_SCLK         "SCLK" -#    define OLED_RENDER_MODS_NAME         "Mods:" +#    define OLED_RENDER_MODS_NAME         "Mods"  #    define OLED_RENDER_MODS_SFT          "Sft"  #    define OLED_RENDER_MODS_CTL          "Ctl"  #    define OLED_RENDER_MODS_ALT          "Alt" @@ -84,6 +89,9 @@ void            oled_driver_render_logo_right(void);  #    define OLED_RENDER_WPM_COUNTER       "WPM: "  #else  #    define OLED_RENDER_KEYLOGGER         "KLogr" +#    ifndef OLED_KEYLOGGER_LENGTH +#        define OLED_KEYLOGGER_LENGTH         5 +#    endif  #    define OLED_RENDER_LAYOUT_NAME       "Lyout"  #    define OLED_RENDER_LAYOUT_QWERTY     " QRTY" @@ -127,5 +135,7 @@ void            oled_driver_render_logo_right(void);  #    define OLED_RENDER_USER_NUKE         "Nuke"  #    define OLED_RENDER_WPM_COUNTER       "WPM: " -  #endif + + +extern char                      keylog_str[OLED_KEYLOGGER_LENGTH]; diff --git a/users/drashna/oled/sh110x.c b/users/drashna/oled/sh110x.c new file mode 100644 index 0000000000..c850a47538 --- /dev/null +++ b/users/drashna/oled/sh110x.c @@ -0,0 +1,860 @@ +/* +Copyright 2019 Ryan Caltabiano <https://github.com/XScorpion2> + +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 "i2c_master.h" +#include "oled_driver.h" +#include OLED_FONT_H +#include "timer.h" +#include "print.h" + +#include <string.h> + +#include "progmem.h" + +#include "keyboard.h" + +// Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf +// for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf + +// Fundamental Commands +#define CONTRAST 0x81 +#define DISPLAY_ALL_ON 0xA5 +#define DISPLAY_ALL_ON_RESUME 0xA4 +#define NORMAL_DISPLAY 0xA6 +#define INVERT_DISPLAY 0xA7 +#define DISPLAY_ON 0xAF +#define DISPLAY_OFF 0xAE +#define NOP 0xE3 + +// Scrolling Commands +#define ACTIVATE_SCROLL 0x2F +#define DEACTIVATE_SCROLL 0x2E +#define SCROLL_RIGHT 0x26 +#define SCROLL_LEFT 0x27 +#define SCROLL_RIGHT_UP 0x29 +#define SCROLL_LEFT_UP 0x2A + +// Addressing Setting Commands +#define MEMORY_MODE 0x20 +#define COLUMN_ADDR 0x21 +#define PAGE_ADDR 0x22 +#define PAM_SETCOLUMN_LSB 0x00 +#define PAM_SETCOLUMN_MSB 0x10 +#define PAM_PAGE_ADDR 0xB0  // 0xb0 -- 0xb7 + +// Hardware Configuration Commands +#define DISPLAY_START_LINE 0x40 +#define SEGMENT_REMAP 0xA0 +#define SEGMENT_REMAP_INV 0xA1 +#define MULTIPLEX_RATIO 0xA8 +#define COM_SCAN_INC 0xC0 +#define COM_SCAN_DEC 0xC8 +#define DISPLAY_OFFSET 0xD3 +#define COM_PINS 0xDA +#define COM_PINS_SEQ 0x02 +#define COM_PINS_ALT 0x12 +#define COM_PINS_SEQ_LR 0x22 +#define COM_PINS_ALT_LR 0x32 + +// Timing & Driving Commands +#define DISPLAY_CLOCK 0xD5 +#define PRE_CHARGE_PERIOD 0xD9 +#define VCOM_DETECT 0xDB + +// Advance Graphic Commands +#define FADE_BLINK 0x23 +#define ENABLE_FADE 0x20 +#define ENABLE_BLINK 0x30 + +// Charge Pump Commands +#define CHARGE_PUMP 0x8D + +// Commands specific to the SH1107 chip +#define SH1107_DISPLAY_START_LINE 0xDC +#define SH1107_MEMORY_MODE_PAGE 0x20 +#define SH1107_MEMORY_MODE_VERTICAL 0x21 + +// Misc defines +#ifndef OLED_BLOCK_COUNT +#    define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) +#endif +#ifndef OLED_BLOCK_SIZE +#    define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) +#endif + +#define OLED_ALL_BLOCKS_MASK (((((OLED_BLOCK_TYPE)1 << (OLED_BLOCK_COUNT - 1)) - 1) << 1) | 1) + +#define OLED_IC_HAS_HORIZONTAL_MODE (OLED_IC == OLED_IC_SSD1306) +#define OLED_IC_COM_PINS_ARE_COLUMNS (OLED_IC == OLED_IC_SH1107) + +#ifndef OLED_COM_PIN_COUNT +#    if OLED_IC == OLED_IC_SH1106 +#        define OLED_COM_PIN_COUNT 64 +#    elif OLED_IC == OLED_IC_SH1107 +#        define OLED_COM_PIN_COUNT 128 +#    else +#        error Invalid OLED_IC value +#    endif +#endif + +#ifndef OLED_COM_PIN_OFFSET +#    define OLED_COM_PIN_OFFSET 0 +#endif + +// i2c defines +#define I2C_CMD 0x00 +#define I2C_DATA 0x40 +#if defined(__AVR__) +#    define I2C_TRANSMIT_P(data) i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT) +#else  // defined(__AVR__) +#    define I2C_TRANSMIT_P(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT) +#endif  // defined(__AVR__) +#define I2C_TRANSMIT(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT) +#define I2C_WRITE_REG(mode, data, size) i2c_writeReg((OLED_DISPLAY_ADDRESS << 1), mode, data, size, OLED_I2C_TIMEOUT) + +#define HAS_FLAGS(bits, flags) ((bits & flags) == flags) + +// Display buffer's is the same as the OLED memory layout +// this is so we don't end up with rounding errors with +// parts of the display unusable or don't get cleared correctly +// and also allows for drawing & inverting +uint8_t         oled_buffer[OLED_MATRIX_SIZE]; +uint8_t *       oled_cursor; +OLED_BLOCK_TYPE oled_dirty          = 0; +bool            oled_initialized    = false; +bool            oled_active         = false; +bool            oled_scrolling      = false; +bool            oled_inverted       = false; +uint8_t         oled_brightness     = OLED_BRIGHTNESS; +oled_rotation_t oled_rotation       = 0; +uint8_t         oled_rotation_width = 0; +uint8_t         oled_scroll_speed   = 0;  // this holds the speed after being remapped to ssd1306 internal values +uint8_t         oled_scroll_start   = 0; +uint8_t         oled_scroll_end     = 7; +#if OLED_TIMEOUT > 0 +uint32_t oled_timeout; +#endif +#if OLED_SCROLL_TIMEOUT > 0 +uint32_t oled_scroll_timeout; +#endif +#if OLED_UPDATE_INTERVAL > 0 +uint16_t oled_update_timeout; +#endif + +// Internal variables to reduce math instructions + +#if defined(__AVR__) +// identical to i2c_transmit, but for PROGMEM since all initialization is in PROGMEM arrays currently +// probably should move this into i2c_master... +static i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout) { +    i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); + +    for (uint16_t i = 0; i < length && status >= 0; i++) { +        status = i2c_write(pgm_read_byte((const char *)data++), timeout); +        if (status) break; +    } + +    i2c_stop(); + +    return status; +} +#endif + +// Flips the rendering bits for a character at the current cursor position +static void InvertCharacter(uint8_t *cursor) { +    const uint8_t *end = cursor + OLED_FONT_WIDTH; +    while (cursor < end) { +        *cursor = ~(*cursor); +        cursor++; +    } +} + +bool oled_init(oled_rotation_t rotation) { +#if defined(USE_I2C) && defined(SPLIT_KEYBOARD) +    if (!is_keyboard_master()) { +        return true; +    } +#endif + +    oled_rotation = oled_init_user(oled_init_kb(rotation)); +    if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { +        oled_rotation_width = OLED_DISPLAY_WIDTH; +    } else { +        oled_rotation_width = OLED_DISPLAY_HEIGHT; +    } +    i2c_init(); + +    static const uint8_t PROGMEM display_setup1[] = { +        I2C_CMD, +        DISPLAY_OFF, +        DISPLAY_CLOCK, +        0x80, +        MULTIPLEX_RATIO, +#if OLED_IC_COM_PINS_ARE_COLUMNS +        OLED_DISPLAY_WIDTH - 1, +#else +        OLED_DISPLAY_HEIGHT - 1, +#endif +        DISPLAY_OFFSET, +        0x00, +        DISPLAY_START_LINE | 0x00, +        CHARGE_PUMP, +        0x14, +#if (OLED_IC != OLED_IC_SH1106) +        // MEMORY_MODE is unsupported on SH1106 (Page Addressing only) +        MEMORY_MODE, +        0x00,  // Horizontal addressing mode +#elif OLED_IC == OLED_IC_SH1107 +        // Page addressing mode +        SH1107_MEMORY_MODE_PAGE, +#endif +    }; +    if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) { +        print("oled_init cmd set 1 failed\n"); +        return false; +    } + +    if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_180)) { +        static const uint8_t PROGMEM display_normal[] = { +            I2C_CMD, SEGMENT_REMAP_INV, COM_SCAN_DEC, DISPLAY_OFFSET, OLED_COM_PIN_OFFSET, +        }; +        if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) { +            print("oled_init cmd normal rotation failed\n"); +            return false; +        } +    } else { +        static const uint8_t PROGMEM display_flipped[] = { +            I2C_CMD, SEGMENT_REMAP, COM_SCAN_INC, DISPLAY_OFFSET, (OLED_COM_PIN_COUNT - OLED_COM_PIN_OFFSET) % OLED_COM_PIN_COUNT, +        }; +        if (I2C_TRANSMIT_P(display_flipped) != I2C_STATUS_SUCCESS) { +            print("display_flipped failed\n"); +            return false; +        } +    } + +    static const uint8_t PROGMEM display_setup2[] = {I2C_CMD, COM_PINS, OLED_COM_PINS, CONTRAST, OLED_BRIGHTNESS, PRE_CHARGE_PERIOD, 0x22, VCOM_DETECT, 0x35, DISPLAY_ALL_ON_RESUME, NORMAL_DISPLAY, DEACTIVATE_SCROLL, DISPLAY_ON};    if (I2C_TRANSMIT_P(display_setup2) != I2C_STATUS_SUCCESS) { +        print("display_setup2 failed\n"); +        return false; +    } + +#if OLED_TIMEOUT > 0 +    oled_timeout = timer_read32() + OLED_TIMEOUT; +#endif +#if OLED_SCROLL_TIMEOUT > 0 +    oled_scroll_timeout = timer_read32() + OLED_SCROLL_TIMEOUT; +#endif + +    oled_clear(); +    oled_initialized = true; +    oled_active      = true; +    oled_scrolling   = false; +    return true; +} + +__attribute__((weak)) oled_rotation_t oled_init_kb(oled_rotation_t rotation) { return rotation; } +__attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) { return rotation; } + +void oled_clear(void) { +    memset(oled_buffer, 0, sizeof(oled_buffer)); +    oled_cursor = &oled_buffer[0]; +    oled_dirty  = OLED_ALL_BLOCKS_MASK; +} + +static void calc_bounds(uint8_t update_start, uint8_t *cmd_array) { +    // Calculate commands to set memory addressing bounds. +    uint8_t start_page   = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH; +    uint8_t start_column = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH; +#if !OLED_IC_HAS_HORIZONTAL_MODE +    // Commands for Page Addressing Mode. Sets starting page and column; has no end bound. +    // Column value must be split into high and low nybble and sent as two commands. +    cmd_array[0] = PAM_PAGE_ADDR | start_page; +    cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f); +    cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f); +    cmd_array[3] = NOP; +    cmd_array[4] = NOP; +    cmd_array[5] = NOP; +#else +    // Commands for use in Horizontal Addressing mode. +    cmd_array[1] = start_column + OLED_COLUMN_OFFSET; +    cmd_array[4] = start_page; +    cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) % OLED_DISPLAY_WIDTH + cmd_array[1]; +    cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) / OLED_DISPLAY_WIDTH - 1 + cmd_array[4]; +#endif +} + +static void calc_bounds_90(uint8_t update_start, uint8_t *cmd_array) { +    // Block numbering starts from the bottom left corner, going up and then to +    // the right.  The controller needs the page and column numbers for the top +    // left and bottom right corners of that block. + +    // Total number of pages across the screen height. +    const uint8_t height_in_pages = OLED_DISPLAY_HEIGHT / 8; + +    // Difference of starting page numbers for adjacent blocks; may be 0 if +    // blocks are large enough to occupy one or more whole 8px columns. +    const uint8_t page_inc_per_block = OLED_BLOCK_SIZE % OLED_DISPLAY_HEIGHT / 8; + +    // Top page number for a block which is at the bottom edge of the screen. +    const uint8_t bottom_block_top_page = (height_in_pages - page_inc_per_block) % height_in_pages; + +#if !OLED_IC_HAS_HORIZONTAL_MODE +    // Only the Page Addressing Mode is supported +    uint8_t start_page   = bottom_block_top_page - (OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_HEIGHT / 8); +    uint8_t start_column = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_HEIGHT * 8; +    cmd_array[0] = PAM_PAGE_ADDR | start_page; +    cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f); +    cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f); +#else +    cmd_array[1] = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_HEIGHT * 8 + OLED_COLUMN_OFFSET; +    cmd_array[4] = bottom_block_top_page - (OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_HEIGHT / 8); +    cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) / OLED_DISPLAY_HEIGHT * 8 - 1 + cmd_array[1]; +    cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) % OLED_DISPLAY_HEIGHT / 8 + cmd_array[4]; +#endif +} + +uint8_t crot(uint8_t a, int8_t n) { +    const uint8_t mask = 0x7; +    n &= mask; +    return a << n | a >> (-n & mask); +} + +static void rotate_90(const uint8_t *src, uint8_t *dest) { +    for (uint8_t i = 0, shift = 7; i < 8; ++i, --shift) { +        uint8_t selector = (1 << i); +        for (uint8_t j = 0; j < 8; ++j) { +            dest[i] |= crot(src[j] & selector, shift - (int8_t)j); +        } +    } +} + +void oled_render(void) { +    if (!oled_initialized) { +        return; +    } + +    // Do we have work to do? +    oled_dirty &= OLED_ALL_BLOCKS_MASK; +    if (!oled_dirty || oled_scrolling) { +        return; +    } + +    // Find first dirty block +    uint8_t update_start = 0; +    while (!(oled_dirty & ((OLED_BLOCK_TYPE)1 << update_start))) { +        ++update_start; +    } + +    // Set column & page position +#if OLED_IC_HAS_HORIZONTAL_MODE +    static uint8_t display_start[] = {I2C_CMD, COLUMN_ADDR, 0, OLED_DISPLAY_WIDTH - 1, PAGE_ADDR, 0, OLED_DISPLAY_HEIGHT / 8 - 1}; +#else +    static uint8_t display_start[] = {I2C_CMD, PAM_PAGE_ADDR, PAM_SETCOLUMN_LSB, PAM_SETCOLUMN_MSB}; +#endif +    if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { +        calc_bounds(update_start, &display_start[1]);  // Offset from I2C_CMD byte at the start +    } else { +        calc_bounds_90(update_start, &display_start[1]);  // Offset from I2C_CMD byte at the start +    } + +    // Send column & page position +    if (I2C_TRANSMIT(display_start) != I2C_STATUS_SUCCESS) { +        print("oled_render offset command failed\n"); +        return; +    } + +    if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { +        // Send render data chunk as is +        if (I2C_WRITE_REG(I2C_DATA, &oled_buffer[OLED_BLOCK_SIZE * update_start], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { +            print("oled_render data failed\n"); +            return; +        } +    } else { +        // Rotate the render chunks +        const static uint8_t source_map[] = OLED_SOURCE_MAP; +        const static uint8_t target_map[] = OLED_TARGET_MAP; + +        static uint8_t temp_buffer[OLED_BLOCK_SIZE]; +        memset(temp_buffer, 0, sizeof(temp_buffer)); +        for (uint8_t i = 0; i < sizeof(source_map); ++i) { +            rotate_90(&oled_buffer[OLED_BLOCK_SIZE * update_start + source_map[i]], &temp_buffer[target_map[i]]); +        } + +#if OLED_IC_HAS_HORIZONTAL_MODE +        // Send render data chunk after rotating +        if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[0], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { +            print("oled_render90 data failed\n"); +            return; +        } +#else +        // For SH1106 or SH1107 the data chunk must be split into separate pieces for each page +        const uint8_t columns_in_block = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) / OLED_DISPLAY_HEIGHT * 8; +        const uint8_t num_pages = OLED_BLOCK_SIZE / columns_in_block; +        for (uint8_t i = 0; i < num_pages; ++i) { +            // Send column & page position for all pages except the first one +            if (i > 0) { +                display_start[1]++; +                if (I2C_TRANSMIT(display_start) != I2C_STATUS_SUCCESS) { +                    print("oled_render offset command failed\n"); +                    return; +                } +            } +            // Send data for the page +            if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[columns_in_block * i], columns_in_block) != I2C_STATUS_SUCCESS) { +                print("oled_render90 data failed\n"); +                return; +            } +        } +#endif +    } + +    // Turn on display if it is off +    oled_on(); + +    // Clear dirty flag +    oled_dirty &= ~((OLED_BLOCK_TYPE)1 << update_start); +} + +void oled_set_cursor(uint8_t col, uint8_t line) { +    uint16_t index = line * oled_rotation_width + col * OLED_FONT_WIDTH; + +    // Out of bounds? +    if (index >= OLED_MATRIX_SIZE) { +        index = 0; +    } + +    oled_cursor = &oled_buffer[index]; +} + +void oled_advance_page(bool clearPageRemainder) { +    uint16_t index     = oled_cursor - &oled_buffer[0]; +    uint8_t  remaining = oled_rotation_width - (index % oled_rotation_width); + +    if (clearPageRemainder) { +        // Remaining Char count +        remaining = remaining / OLED_FONT_WIDTH; + +        // Write empty character until next line +        while (remaining--) oled_write_char(' ', false); +    } else { +        // Next page index out of bounds? +        if (index + remaining >= OLED_MATRIX_SIZE) { +            index     = 0; +            remaining = 0; +        } + +        oled_cursor = &oled_buffer[index + remaining]; +    } +} + +void oled_advance_char(void) { +    uint16_t nextIndex      = oled_cursor - &oled_buffer[0] + OLED_FONT_WIDTH; +    uint8_t  remainingSpace = oled_rotation_width - (nextIndex % oled_rotation_width); + +    // Do we have enough space on the current line for the next character +    if (remainingSpace < OLED_FONT_WIDTH) { +        nextIndex += remainingSpace; +    } + +    // Did we go out of bounds +    if (nextIndex >= OLED_MATRIX_SIZE) { +        nextIndex = 0; +    } + +    // Update cursor position +    oled_cursor = &oled_buffer[nextIndex]; +} + +// Main handler that writes character data to the display buffer +void oled_write_char(const char data, bool invert) { +    // Advance to the next line if newline +    if (data == '\n') { +        // Old source wrote ' ' until end of line... +        oled_advance_page(true); +        return; +    } + +    if (data == '\r') { +        oled_advance_page(false); +        return; +    } + +    // copy the current render buffer to check for dirty after +    static uint8_t oled_temp_buffer[OLED_FONT_WIDTH]; +    memcpy(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH); + +    _Static_assert(sizeof(font) >= ((OLED_FONT_END + 1 - OLED_FONT_START) * OLED_FONT_WIDTH), "OLED_FONT_END references outside array"); + +    // set the reder buffer data +    uint8_t cast_data = (uint8_t)data;  // font based on unsigned type for index +    if (cast_data < OLED_FONT_START || cast_data > OLED_FONT_END) { +        memset(oled_cursor, 0x00, OLED_FONT_WIDTH); +    } else { +        const uint8_t *glyph = &font[(cast_data - OLED_FONT_START) * OLED_FONT_WIDTH]; +        memcpy_P(oled_cursor, glyph, OLED_FONT_WIDTH); +    } + +    // Invert if needed +    if (invert) { +        InvertCharacter(oled_cursor); +    } + +    // Dirty check +    if (memcmp(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH)) { +        uint16_t index = oled_cursor - &oled_buffer[0]; +        oled_dirty |= ((OLED_BLOCK_TYPE)1 << (index / OLED_BLOCK_SIZE)); +        // Edgecase check if the written data spans the 2 chunks +        oled_dirty |= ((OLED_BLOCK_TYPE)1 << ((index + OLED_FONT_WIDTH - 1) / OLED_BLOCK_SIZE)); +    } + +    // Finally move to the next char +    oled_advance_char(); +} + +void oled_write(const char *data, bool invert) { +    const char *end = data + strlen(data); +    while (data < end) { +        oled_write_char(*data, invert); +        data++; +    } +} + +void oled_write_ln(const char *data, bool invert) { +    oled_write(data, invert); +    oled_advance_page(true); +} + +void oled_pan(bool left) { +    uint16_t i = 0; +    for (uint16_t y = 0; y < OLED_DISPLAY_HEIGHT / 8; y++) { +        if (left) { +            for (uint16_t x = 0; x < OLED_DISPLAY_WIDTH - 1; x++) { +                i              = y * OLED_DISPLAY_WIDTH + x; +                oled_buffer[i] = oled_buffer[i + 1]; +            } +        } else { +            for (uint16_t x = OLED_DISPLAY_WIDTH - 1; x > 0; x--) { +                i              = y * OLED_DISPLAY_WIDTH + x; +                oled_buffer[i] = oled_buffer[i - 1]; +            } +        } +    } +    oled_dirty = OLED_ALL_BLOCKS_MASK; +} + +oled_buffer_reader_t oled_read_raw(uint16_t start_index) { +    if (start_index > OLED_MATRIX_SIZE) start_index = OLED_MATRIX_SIZE; +    oled_buffer_reader_t ret_reader; +    ret_reader.current_element         = &oled_buffer[start_index]; +    ret_reader.remaining_element_count = OLED_MATRIX_SIZE - start_index; +    return ret_reader; +} + +void oled_write_raw_byte(const char data, uint16_t index) { +    if (index > OLED_MATRIX_SIZE) index = OLED_MATRIX_SIZE; +    if (oled_buffer[index] == data) return; +    oled_buffer[index] = data; +    oled_dirty |= ((OLED_BLOCK_TYPE)1 << (index / OLED_BLOCK_SIZE)); +} + +void oled_write_raw(const char *data, uint16_t size) { +    uint16_t cursor_start_index = oled_cursor - &oled_buffer[0]; +    if ((size + cursor_start_index) > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE - cursor_start_index; +    for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) { +        uint8_t c = *data++; +        if (oled_buffer[i] == c) continue; +        oled_buffer[i] = c; +        oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE)); +    } +} + +void oled_write_pixel(uint8_t x, uint8_t y, bool on) { +    if (x >= oled_rotation_width) { +        return; +    } +    uint16_t index = x + (y / 8) * oled_rotation_width; +    if (index >= OLED_MATRIX_SIZE) { +        return; +    } +    uint8_t data = oled_buffer[index]; +    if (on) { +        data |= (1 << (y % 8)); +    } else { +        data &= ~(1 << (y % 8)); +    } +    if (oled_buffer[index] != data) { +        oled_buffer[index] = data; +        oled_dirty |= ((OLED_BLOCK_TYPE)1 << (index / OLED_BLOCK_SIZE)); +    } +} + +#if defined(__AVR__) +void oled_write_P(const char *data, bool invert) { +    uint8_t c = pgm_read_byte(data); +    while (c != 0) { +        oled_write_char(c, invert); +        c = pgm_read_byte(++data); +    } +} + +void oled_write_ln_P(const char *data, bool invert) { +    oled_write_P(data, invert); +    oled_advance_page(true); +} + +void oled_write_raw_P(const char *data, uint16_t size) { +    uint16_t cursor_start_index = oled_cursor - &oled_buffer[0]; +    if ((size + cursor_start_index) > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE - cursor_start_index; +    for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) { +        uint8_t c = pgm_read_byte(data++); +        if (oled_buffer[i] == c) continue; +        oled_buffer[i] = c; +        oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE)); +    } +} +#endif  // defined(__AVR__) + +bool oled_on(void) { +    if (!oled_initialized) { +        return oled_active; +    } + +#if OLED_TIMEOUT > 0 +    oled_timeout = timer_read32() + OLED_TIMEOUT; +#endif + +    static const uint8_t PROGMEM display_on[] = +#ifdef OLED_FADE_OUT +        {I2C_CMD, FADE_BLINK, 0x00}; +#else +        {I2C_CMD, DISPLAY_ON}; +#endif + +    if (!oled_active) { +        if (I2C_TRANSMIT_P(display_on) != I2C_STATUS_SUCCESS) { +            print("oled_on cmd failed\n"); +            return oled_active; +        } +        oled_active = true; +    } +    return oled_active; +} + +bool oled_off(void) { +    if (!oled_initialized) { +        return !oled_active; +    } + +    static const uint8_t PROGMEM display_off[] = +#ifdef OLED_FADE_OUT +        {I2C_CMD, FADE_BLINK, ENABLE_FADE | OLED_FADE_OUT_INTERVAL}; +#else +        {I2C_CMD, DISPLAY_OFF}; +#endif + +    if (oled_active) { +        if (I2C_TRANSMIT_P(display_off) != I2C_STATUS_SUCCESS) { +            print("oled_off cmd failed\n"); +            return oled_active; +        } +        oled_active = false; +    } +    return !oled_active; +} + +bool is_oled_on(void) { return oled_active; } + +uint8_t oled_set_brightness(uint8_t level) { +    if (!oled_initialized) { +        return oled_brightness; +    } + +    uint8_t set_contrast[] = {I2C_CMD, CONTRAST, level}; +    if (oled_brightness != level) { +        if (I2C_TRANSMIT(set_contrast) != I2C_STATUS_SUCCESS) { +            print("set_brightness cmd failed\n"); +            return oled_brightness; +        } +        oled_brightness = level; +    } +    return oled_brightness; +} + +uint8_t oled_get_brightness(void) { return oled_brightness; } + +// Set the specific 8 lines rows of the screen to scroll. +// 0 is the default for start, and 7 for end, which is the entire +// height of the screen.  For 128x32 screens, rows 4-7 are not used. +void oled_scroll_set_area(uint8_t start_line, uint8_t end_line) { +    oled_scroll_start = start_line; +    oled_scroll_end   = end_line; +} + +void oled_scroll_set_speed(uint8_t speed) { +    // Sets the speed for scrolling... does not take effect +    // until scrolling is either started or restarted +    // the ssd1306 supports 8 speeds +    // FrameRate2   speed = 7 +    // FrameRate3   speed = 4 +    // FrameRate4   speed = 5 +    // FrameRate5   speed = 0 +    // FrameRate25  speed = 6 +    // FrameRate64  speed = 1 +    // FrameRate128 speed = 2 +    // FrameRate256 speed = 3 +    // for ease of use these are remaped here to be in order +    static const uint8_t scroll_remap[8] = {7, 4, 5, 0, 6, 1, 2, 3}; +    oled_scroll_speed                    = scroll_remap[speed]; +} + +bool oled_scroll_right(void) { +    if (!oled_initialized) { +        return oled_scrolling; +    } + +    // Dont enable scrolling if we need to update the display +    // This prevents scrolling of bad data from starting the scroll too early after init +    if (!oled_dirty && !oled_scrolling) { +        uint8_t display_scroll_right[] = {I2C_CMD, SCROLL_RIGHT, 0x00, oled_scroll_start, oled_scroll_speed, oled_scroll_end, 0x00, 0xFF, ACTIVATE_SCROLL}; +        if (I2C_TRANSMIT(display_scroll_right) != I2C_STATUS_SUCCESS) { +            print("oled_scroll_right cmd failed\n"); +            return oled_scrolling; +        } +        oled_scrolling = true; +    } +    return oled_scrolling; +} + +bool oled_scroll_left(void) { +    if (!oled_initialized) { +        return oled_scrolling; +    } + +    // Dont enable scrolling if we need to update the display +    // This prevents scrolling of bad data from starting the scroll too early after init +    if (!oled_dirty && !oled_scrolling) { +        uint8_t display_scroll_left[] = {I2C_CMD, SCROLL_LEFT, 0x00, oled_scroll_start, oled_scroll_speed, oled_scroll_end, 0x00, 0xFF, ACTIVATE_SCROLL}; +        if (I2C_TRANSMIT(display_scroll_left) != I2C_STATUS_SUCCESS) { +            print("oled_scroll_left cmd failed\n"); +            return oled_scrolling; +        } +        oled_scrolling = true; +    } +    return oled_scrolling; +} + +bool oled_scroll_off(void) { +    if (!oled_initialized) { +        return !oled_scrolling; +    } + +    if (oled_scrolling) { +        static const uint8_t PROGMEM display_scroll_off[] = {I2C_CMD, DEACTIVATE_SCROLL}; +        if (I2C_TRANSMIT_P(display_scroll_off) != I2C_STATUS_SUCCESS) { +            print("oled_scroll_off cmd failed\n"); +            return oled_scrolling; +        } +        oled_scrolling = false; +        oled_dirty     = OLED_ALL_BLOCKS_MASK; +    } +    return !oled_scrolling; +} + +bool is_oled_scrolling(void) { return oled_scrolling; } + +bool oled_invert(bool invert) { +    if (!oled_initialized) { +        return oled_inverted; +    } + +    if (invert && !oled_inverted) { +        static const uint8_t PROGMEM display_inverted[] = {I2C_CMD, INVERT_DISPLAY}; +        if (I2C_TRANSMIT_P(display_inverted) != I2C_STATUS_SUCCESS) { +            print("oled_invert cmd failed\n"); +            return oled_inverted; +        } +        oled_inverted = true; +    } else if (!invert && oled_inverted) { +        static const uint8_t PROGMEM display_normal[] = {I2C_CMD, NORMAL_DISPLAY}; +        if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) { +            print("oled_invert cmd failed\n"); +            return oled_inverted; +        } +        oled_inverted = false; +    } + +    return oled_inverted; +} + +uint8_t oled_max_chars(void) { +    if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { +        return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH; +    } +    return OLED_DISPLAY_HEIGHT / OLED_FONT_WIDTH; +} + +uint8_t oled_max_lines(void) { +    if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { +        return OLED_DISPLAY_HEIGHT / OLED_FONT_HEIGHT; +    } +    return OLED_DISPLAY_WIDTH / OLED_FONT_HEIGHT; +} + +void oled_task(void) { +    if (!oled_initialized) { +        return; +    } + +#if OLED_UPDATE_INTERVAL > 0 +    if (timer_elapsed(oled_update_timeout) >= OLED_UPDATE_INTERVAL) { +        oled_update_timeout = timer_read(); +        oled_set_cursor(0, 0); +        oled_task_kb(); +    } +#else +    oled_set_cursor(0, 0); +    oled_task_kb(); +#endif + +#if OLED_SCROLL_TIMEOUT > 0 +    if (oled_dirty && oled_scrolling) { +        oled_scroll_timeout = timer_read32() + OLED_SCROLL_TIMEOUT; +        oled_scroll_off(); +    } +#endif + +    // Smart render system, no need to check for dirty +    oled_render(); + +    // Display timeout check +#if OLED_TIMEOUT > 0 +    if (oled_active && timer_expired32(timer_read32(), oled_timeout)) { +        oled_off(); +    } +#endif + +#if OLED_SCROLL_TIMEOUT > 0 +    if (!oled_scrolling && timer_expired32(timer_read32(), oled_scroll_timeout)) { +#    ifdef OLED_SCROLL_TIMEOUT_RIGHT +        oled_scroll_right(); +#    else +        oled_scroll_left(); +#    endif +    } +#endif +} + +__attribute__((weak)) bool oled_task_kb(void) { return oled_task_user(); } +__attribute__((weak)) bool oled_task_user(void) { return true; } diff --git a/users/drashna/pointing/pointing.c b/users/drashna/pointing/pointing.c index 0bd14e4775..0116ce0900 100644 --- a/users/drashna/pointing/pointing.c +++ b/users/drashna/pointing/pointing.c @@ -105,7 +105,7 @@ bool process_record_pointing(uint16_t keycode, keyrecord_t* record) {                  mouse_timer = timer_read();                  break;              } -            if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) { +            if (layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) {                  layer_off(_MOUSE);              }              mouse_keycode_tracker = 0; diff --git a/users/drashna/rules.mk b/users/drashna/rules.mk index 445d1cf5ac..553cc2cbc7 100644 --- a/users/drashna/rules.mk +++ b/users/drashna/rules.mk @@ -78,10 +78,20 @@ endif  CUSTOM_OLED_DRIVER ?= yes  ifeq ($(strip $(OLED_ENABLE)), yes) +    ifeq ($(strip $(OLED_DRIVER)), custom) +        OPT_DEFS += -DOLED_ENABLE \ +            -DOLED_DRIVER_SH1107 +        SRC += $(USER_PATH)/oled/sh110x.c +        QUANTUM_LIB_SRC += i2c_master.c +    endif      ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes) -        SRC += $(USER_PATH)/oled/oled_stuff.c          OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE +        SRC += $(USER_PATH)/oled/oled_stuff.c      endif +    ifeq ($(strip $(OLED_DISPLAY_TEST)), yes) +        OPT_DEFS += -DOLED_DISPLAY_TEST +    endif +    DEFERRED_EXEC_ENABLE = yes  endif  CUSTOM_POINTING_DEVICE ?= yes @@ -97,6 +107,7 @@ ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes)          QUANTUM_LIB_SRC += $(USER_PATH)/split/transport_sync.c          OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC      endif +  endif  AUTOCORRECTION_ENABLE ?= no diff --git a/users/drashna/split/transport_sync.c b/users/drashna/split/transport_sync.c index 794664293c..2509e448cb 100644 --- a/users/drashna/split/transport_sync.c +++ b/users/drashna/split/transport_sync.c @@ -9,7 +9,7 @@  #endif  #ifdef CUSTOM_UNICODE_ENABLE -#include "process_unicode_common.h" +#    include "process_unicode_common.h"  extern unicode_config_t unicode_config;  #endif  #ifdef AUDIO_ENABLE @@ -24,8 +24,10 @@ extern bool tap_toggling;  extern bool swap_hands;  #endif -static bool watchdog_ping_done = false; -static uint32_t watchdog_timer = 0; +#if defined(SPLIT_WATCHDOG_TIMEOUT) +static bool     watchdog_ping_done = false; +static uint32_t watchdog_timer     = 0; +#endif  extern userspace_config_t userspace_config;  extern bool               host_driver_disabled; @@ -51,20 +53,35 @@ void user_config_sync(uint8_t initiator2target_buffer_size, const void* initiato      }  } +#if defined(SPLIT_WATCHDOG_TIMEOUT)  void watchdog_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { watchdog_ping_done = true; } +#endif +#ifdef OLED_ENABLE +#include "oled/oled_stuff.h" +void keylogger_string_sync(uint8_t initiator2target_buffer_size, const void* initiator2target_buffer, uint8_t target2initiator_buffer_size, void* target2initiator_buffer) { +    if (initiator2target_buffer_size == OLED_KEYLOGGER_LENGTH) { +        memcpy(&keylog_str, initiator2target_buffer, initiator2target_buffer_size); +    } +} +#endif  void keyboard_post_init_transport_sync(void) {      // Register keyboard state sync split transaction      transaction_register_rpc(RPC_ID_USER_STATE_SYNC, user_state_sync);      transaction_register_rpc(RPC_ID_USER_KEYMAP_SYNC, user_keymap_sync);      transaction_register_rpc(RPC_ID_USER_CONFIG_SYNC, user_config_sync); +#ifdef OLED_ENABLE +    transaction_register_rpc(RPC_ID_USER_KEYLOG_STR, keylogger_string_sync); +#endif -#ifdef __AVR__ +#if defined(SPLIT_WATCHDOG_TIMEOUT) +#    if defined(PROTOCOL_LUFA)      wdt_disable(); -#endif +#    endif      transaction_register_rpc(RPC_ID_USER_WATCHDOG_SYNC, watchdog_handler);      watchdog_timer = timer_read32(); +#endif  }  void user_transport_update(void) { @@ -107,9 +124,12 @@ void user_transport_update(void) {  void user_transport_sync(void) {      if (is_keyboard_master()) {          // Keep track of the last state, so that we can tell if we need to propagate to slave -        static uint16_t              last_keymap = 0; -        static uint32_t              last_config = 0, last_sync[3], last_user_state = 0; -        bool                         needs_sync = false; +        static uint16_t last_keymap = 0; +        static uint32_t last_config = 0, last_sync[4], last_user_state = 0; +        bool            needs_sync = false; +#ifdef OLED_ENABLE +        static char     keylog_temp[OLED_KEYLOGGER_LENGTH] = { 0 }; +#endif          // Check if the state values are different          if (memcmp(&transport_user_state, &last_user_state, sizeof(transport_user_state))) { @@ -164,9 +184,30 @@ void user_transport_sync(void) {              if (transaction_rpc_send(RPC_ID_USER_CONFIG_SYNC, sizeof(transport_userspace_config), &transport_userspace_config)) {                  last_sync[2] = timer_read32();              } +            needs_sync = false; +        } + +#ifdef OLED_ENABLE +        // Check if the state values are different +        if (memcmp(&keylog_str, &keylog_temp, OLED_KEYLOGGER_LENGTH)) { +            needs_sync = true; +            memcpy(&keylog_temp, &keylog_str, OLED_KEYLOGGER_LENGTH); +        } +        if (timer_elapsed32(last_sync[3]) > 250) { +            needs_sync = true; +        } + +        // Perform the sync if requested +        if (needs_sync) { +            if (transaction_rpc_send(RPC_ID_USER_KEYLOG_STR, OLED_KEYLOGGER_LENGTH, &keylog_str)) { +                last_sync[3] = timer_read32(); +            } +            needs_sync = false;          } +#endif      } +#if defined(SPLIT_WATCHDOG_TIMEOUT)      if (!watchdog_ping_done) {          if (is_keyboard_master()) {              if (timer_elapsed32(watchdog_timer) > 100) { @@ -180,16 +221,14 @@ void user_transport_sync(void) {              }          } else {              if (timer_elapsed32(watchdog_timer) > 3500) { -#ifdef __AVR__ -                wdt_enable(WDTO_250MS); -#else -                NVIC_SystemReset(); -#endif +                software_reset();                  while (1) {                  }              }          }      } +#endif +  }  void housekeeping_task_user(void) { diff --git a/users/drashna/split/transport_sync.h b/users/drashna/split/transport_sync.h index 6b6f0c388b..884586dfdd 100644 --- a/users/drashna/split/transport_sync.h +++ b/users/drashna/split/transport_sync.h @@ -4,6 +4,10 @@  #pragma once  #include "drashna.h" +#ifdef OLED_ENABLE +#    include "oled/oled_stuff.h" +extern char keylog_str[OLED_KEYLOGGER_LENGTH]; +#endif  typedef union {      uint32_t raw; | 
