#include "oled.h" /* KEYBOARD PET START */ /* settings */ # define MIN_WALK_SPEED 10 # define MIN_RUN_SPEED 40 /* advanced settings */ # define ANIM_FRAME_DURATION 200 // how long each frame lasts in ms # define ANIM_SIZE 96 // number of bytes in array. If you change sprites, minimize for adequate firmware size. max is 1024 /* timers */ uint32_t anim_timer = 0; /* current frame */ uint8_t current_frame = 0; /* bool isSneaking = false; bool isJumping = false; bool showedJump = true; */ /* logic */ static void render_luna(int LUNA_X, int LUNA_Y) { /* Sit */ static const char PROGMEM sit[2][ANIM_SIZE] = {/* 'sit1', 32x22px */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1c, 0x02, 0x05, 0x02, 0x24, 0x04, 0x04, 0x02, 0xa9, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x08, 0x68, 0x10, 0x08, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x82, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0c, 0x10, 0x10, 0x20, 0x20, 0x20, 0x28, 0x3e, 0x1c, 0x20, 0x20, 0x3e, 0x0f, 0x11, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* 'sit2', 32x22px */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1c, 0x02, 0x05, 0x02, 0x24, 0x04, 0x04, 0x02, 0xa9, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x90, 0x08, 0x18, 0x60, 0x10, 0x08, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x82, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0c, 0x10, 0x10, 0x20, 0x20, 0x20, 0x28, 0x3e, 0x1c, 0x20, 0x20, 0x3e, 0x0f, 0x11, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; /* Walk */ static const char PROGMEM walk[2][ANIM_SIZE] = {/* 'walk1', 32x22px */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x90, 0x90, 0x90, 0xa0, 0xc0, 0x80, 0x80, 0x80, 0x70, 0x08, 0x14, 0x08, 0x90, 0x10, 0x10, 0x08, 0xa4, 0x78, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x18, 0xea, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x20, 0x20, 0x3c, 0x0f, 0x11, 0x1f, 0x03, 0x06, 0x18, 0x20, 0x20, 0x3c, 0x0c, 0x12, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* 'walk2', 32x22px */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x20, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x28, 0x10, 0x20, 0x20, 0x20, 0x10, 0x48, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x20, 0xf8, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x30, 0xd5, 0x20, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x30, 0x0c, 0x02, 0x05, 0x09, 0x12, 0x1e, 0x02, 0x1c, 0x14, 0x08, 0x10, 0x20, 0x2c, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; /* Run */ static const char PROGMEM run[2][ANIM_SIZE] = {/* 'run1', 32x22px */ { 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x08, 0x08, 0xc8, 0xb0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x3c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xc4, 0xa4, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc8, 0x58, 0x28, 0x2a, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x09, 0x04, 0x04, 0x04, 0x04, 0x02, 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* 'run2', 32x22px */ { 0x00, 0x00, 0x00, 0xe0, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x78, 0x28, 0x08, 0x10, 0x20, 0x30, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0xb0, 0x50, 0x55, 0x20, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x1e, 0x20, 0x20, 0x18, 0x0c, 0x14, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; /* Bark */ static const char PROGMEM bark[2][ANIM_SIZE] = {/* 'bark1', 32x22px */ { 0x00, 0xc0, 0x20, 0x10, 0xd0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x3c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc8, 0x48, 0x28, 0x2a, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x02, 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* 'bark2', 32x22px */ { 0x00, 0xe0, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x40, 0x2c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x48, 0x28, 0x2a, 0x10, 0x0f, 0x20, 0x4a, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x02, 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; /* Sneak */ static const char PROGMEM sneak[2][ANIM_SIZE] = {/* 'sneak1', 32x22px */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x40, 0x80, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x21, 0xf0, 0x04, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04, 0x04, 0x04, 0x03, 0x01, 0x00, 0x00, 0x09, 0x01, 0x80, 0x80, 0xab, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x20, 0x20, 0x3c, 0x0f, 0x11, 0x1f, 0x02, 0x06, 0x18, 0x20, 0x20, 0x38, 0x08, 0x10, 0x18, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, }, /* 'sneak2', 32x22px */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xa0, 0x20, 0x40, 0x80, 0xc0, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x41, 0xf0, 0x04, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x40, 0x55, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x30, 0x0c, 0x02, 0x05, 0x09, 0x12, 0x1e, 0x04, 0x18, 0x10, 0x08, 0x10, 0x20, 0x28, 0x34, 0x06, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, }}; /* animation */ void animate_luna(void) { /* jump */ if (isLunaJumping() || !isLunaShowedJump()) { /* clear */ oled_set_cursor(LUNA_X, LUNA_Y + 2); oled_write(" ", false); oled_set_cursor(LUNA_X, LUNA_Y - 1); setLunaShowedJump(true); } else { /* clear */ oled_set_cursor(LUNA_X, LUNA_Y - 1); oled_write(" ", false); oled_set_cursor(LUNA_X, LUNA_Y); } /* switch frame */ current_frame = (current_frame + 1) % 2; /* current status */ if (host_keyboard_led_state().caps_lock || is_caps_word_on()) { oled_write_raw_P(bark[current_frame], ANIM_SIZE); } else if (isLunaSneaking()) { oled_write_raw_P(sneak[current_frame], ANIM_SIZE); } else if (get_current_wpm() <= MIN_WALK_SPEED) { oled_write_raw_P(sit[current_frame], ANIM_SIZE); } else if (get_current_wpm() <= MIN_RUN_SPEED) { oled_write_raw_P(walk[current_frame], ANIM_SIZE); } else { oled_write_raw_P(run[current_frame], ANIM_SIZE); } } # if OLED_TIMEOUT > 0 /* the animation prevents the normal timeout from occuring */ if (last_input_activity_elapsed() > OLED_TIMEOUT && last_led_activity_elapsed() > OLED_TIMEOUT) { oled_off(); return; } else { oled_on(); } # endif /* animation timer */ if (timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) { anim_timer = timer_read32(); animate_luna(); } } /* KEYBOARD PET END */ void render_crkbd_logo(void) { oled_write_P(crkbd_logo, false); } void render_rollow_logo(void) { oled_write_raw_P(rollow_logo, sizeof(rollow_logo)); } void render_qmk_logo(void) { oled_write_raw_P(qmk_logo, sizeof(qmk_logo)); } void render_default_layer_state(void) { switch (get_highest_layer(default_layer_state)) { case _QWERTY: oled_write_P(PSTR(OLED_RENDER_LAYOUT_QWERTY), false); break; case _COLEMAK_DH: oled_write_P(PSTR(OLED_RENDER_LAYOUT_COLEMAK_DH), false); break; case _GAME: oled_write_ln_P(PSTR(OLED_RENDER_LAYOUT_GAME), false); break; } } void render_layer_state(void) { switch (get_highest_layer(layer_state)) { case _NAVIGATION: oled_write_ln_P(PSTR(OLED_RENDER_LAYER_NAVIGATION), false); break; case _NUMBER: oled_write_ln_P(PSTR(OLED_RENDER_LAYER_NUMBER), false); break; case _SYMBOL: oled_write_ln_P(PSTR(OLED_RENDER_LAYER_SYMBOL), false); break; case _CONFIG: oled_write_ln_P(PSTR(OLED_RENDER_LAYER_CONFIG), false); break; default: oled_write_ln_P(PSTR(OLED_RENDER_LAYER_BASE), false); break; } } void render_keylock_status(void) { oled_write_ln_P(PSTR(OLED_RENDER_KEYLOCK_NAME), false); oled_write_P(PSTR(" "), false); if( host_keyboard_led_state().num_lock ) { oled_write_P(num_on, false ); }else { oled_write_P(num_off, false ); } if( host_keyboard_led_state().caps_lock || is_caps_word_on() ) { oled_write_P(caps_on, false ); }else { oled_write_P(caps_off, false ); } if( host_keyboard_led_state().scroll_lock ) { oled_write_ln_P(scroll_on, false ); }else { oled_write_ln_P(scroll_off, false ); } } void render_mod_status(void) { uint8_t current_mod = get_mods(); uint8_t current_osm = get_oneshot_mods(); oled_write_ln_P(PSTR(OLED_RENDER_MODS_NAME), false); oled_write_P(PSTR(" "), false); if( (current_mod | current_osm) & MOD_MASK_SHIFT ) { oled_write_P(shift_on, false ); }else { oled_write_P(shift_off, false ); } if( (current_mod | current_osm) & MOD_MASK_CTRL ) { oled_write_P(ctrl_on, false ); }else { oled_write_P(ctrl_off, false ); } oled_write_P(PSTR(" "), false); if( (current_mod | current_osm) & MOD_MASK_ALT ) { oled_write_P(alt_on, false ); }else { oled_write_P(alt_off, false ); } if( (current_mod | current_osm) & MOD_MASK_GUI ) { oled_write_P(gui_on, false ); }else { oled_write_P(gui_off, false ); } } void render_feature_status(void) { oled_write_ln_P(PSTR(OLED_RENDER_FEATURE_NAME), false); oled_write_P(PSTR(" "), false); #if defined(RGB_MATRIX_ENABLE) if (rgb_matrix_is_enabled()) { oled_write_P(rgb_on, false); } else { oled_write_P(rgb_off, false); } #else oled_write_P(rgb_off, false); #endif if(drag_scroll_is_enabled()) { oled_write_P(dragscr_on, false); } else { oled_write_P(dragscr_off, false); } oled_write_P(PSTR(" "), false); #if defined(AUDIO_ENABLE) if (is_audio_on()) { oled_write_P(audio_on, false); } else { oled_write_P(audio_off, false); } #else oled_write_P(audio_off, false); #endif //AUDIO_ENABLE #if defined(HAPTIC_ENABLE) if (haptic_get_enable()) { oled_write_P(haptic_on, false); } else { oled_write_P(haptic_off, false); } #else oled_write_P(haptic_off, false); #endif //AUDIO_ENABLE } void render_oled_main(void) { render_default_layer_state(); render_layer_state(); oled_write_ln_P(PSTR(" "), false); render_keylock_status(); oled_write_ln_P(PSTR(" "), false); render_mod_status(); oled_write_ln_P(PSTR(" "), false); render_feature_status(); } bool oled_task_user(void) { if (is_keyboard_master()) { render_oled_main(); // Renders the current keyboard state (layer, lock, caps, scroll, etc) } else { #if defined(KEYBOARD_barbellboards_rollow) render_rollow_logo(); #elif defined(KEYBOARD_crkbd) render_crkbd_logo(); #else //render_qmk_logo(); /* KEYBOARD PET RENDER START */ render_luna(0, 13); /* KEYBOARD PET RENDER END */ #endif } return false; } oled_rotation_t oled_init_user(oled_rotation_t rotation) { #if !defined(KEYBOARD_klor_2040) if (is_keyboard_master()) { return OLED_ROTATION_270; } #endif return OLED_ROTATION_270; }