summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keyboards/9key/keymaps/bcat/keymap.c19
-rw-r--r--keyboards/9key/keymaps/bcat/readme.md6
-rw-r--r--keyboards/eco/keymaps/bcat/config.h2
-rw-r--r--keyboards/eco/keymaps/bcat/keymap.c19
-rw-r--r--keyboards/eco/keymaps/bcat/readme.md2
-rw-r--r--keyboards/keebio/bdn9/keymaps/bcat/keymap.c13
-rw-r--r--keyboards/keebio/quefrency/keymaps/bcat/keymap.c13
-rw-r--r--keyboards/keebio/quefrency/keymaps/bcat/readme.md2
-rw-r--r--keyboards/lily58/keymaps/bcat/config.h2
-rw-r--r--keyboards/lily58/keymaps/bcat/keymap.c33
-rw-r--r--keyboards/lily58/keymaps/bcat/readme.md2
-rw-r--r--keyboards/lily58/keymaps/bcat/rules.mk2
-rw-r--r--layouts/community/60_ansi_split_bs_rshift/bcat/keymap.c11
-rw-r--r--layouts/community/60_ansi_split_bs_rshift/bcat/readme.md2
-rw-r--r--layouts/community/60_tsangan_hhkb/bcat/keymap.c11
-rw-r--r--layouts/community/60_tsangan_hhkb/bcat/readme.md2
-rw-r--r--layouts/community/65_ansi_blocker_split_bs/bcat/keymap.c13
-rw-r--r--layouts/community/65_ansi_blocker_split_bs/bcat/readme.md2
-rw-r--r--layouts/community/split_3x6_3/bcat/config.h9
-rw-r--r--layouts/community/split_3x6_3/bcat/keymap.c33
-rw-r--r--layouts/community/split_3x6_3/bcat/readme.md2
-rw-r--r--layouts/community/split_3x6_3/bcat/rules.mk4
-rw-r--r--users/bcat/bcat.c10
-rw-r--r--users/bcat/bcat.h36
-rw-r--r--users/bcat/bcat_oled.c216
-rw-r--r--users/bcat/bcat_oled.h55
-rw-r--r--users/bcat/bcat_oled_pet.h73
-rw-r--r--users/bcat/bcat_oled_pet_isda.c134
-rw-r--r--users/bcat/bcat_oled_pet_luna.c168
-rw-r--r--users/bcat/bcat_rgblight.c22
-rwxr-xr-xusers/bcat/compile.sh51
-rw-r--r--users/bcat/config.h79
-rw-r--r--users/bcat/readme.md2
-rw-r--r--users/bcat/rules.mk43
34 files changed, 959 insertions, 134 deletions
diff --git a/keyboards/9key/keymaps/bcat/keymap.c b/keyboards/9key/keymaps/bcat/keymap.c
index 5c08a42a56..944a48c0d3 100644
--- a/keyboards/9key/keymaps/bcat/keymap.c
+++ b/keyboards/9key/keymaps/bcat/keymap.c
@@ -16,22 +16,21 @@
#include QMK_KEYBOARD_H
-enum layer {
- LAYER_DEFAULT,
- LAYER_FUNCTION,
-};
+#include "bcat.h"
-#define LY_FUNC MO(LAYER_FUNCTION)
-#define KY_LOCK LCA(KC_L) /* Cinnamon lock screen */
+#define KY_LOCK LGUI(KC_L) /* Chrome OS: Lock screen */
+#define KY_MICM LSG(KC_1) /* Meet Shortcuts: Mute mic */
+#define KY_MICU LSG(KC_2) /* Meet Shortcuts: Unmute mic */
+#define KY_RHAND LSG(KC_3) /* Meet Shortcuts: Raise/lower hand */
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
[LAYER_DEFAULT] = LAYOUT(
- KC_MPLY, KC_VOLU, KC_MSTP,
- KC_MPRV, KC_VOLD, KC_MNXT,
- KY_LOCK, KC_MUTE, LY_FUNC
+ KC_MPLY, KC_VOLU, KY_RHAND,
+ KY_LOCK, KC_VOLD, KY_MICU,
+ LY_FN1, KC_MUTE, KY_MICM
),
- [LAYER_FUNCTION] = LAYOUT(
+ [LAYER_FUNCTION_1] = LAYOUT(
EEP_RST, _______, RESET,
_______, _______, _______,
_______, _______, _______
diff --git a/keyboards/9key/keymaps/bcat/readme.md b/keyboards/9key/keymaps/bcat/readme.md
index 2dee51de8b..d38ae5463b 100644
--- a/keyboards/9key/keymaps/bcat/readme.md
+++ b/keyboards/9key/keymaps/bcat/readme.md
@@ -1,5 +1,5 @@
# bcat's 9-Key layout
-This is a super simple PCB-mount macropad with nine keys, used at work for
-media keys and quick access to screen lock on Linux (Cinnamon desktop
-environment).
+This is a super simple PCB-mount macropad with nine keys, used on my
+work-from-home Chromebox for media/volume control and to activate some global
+shortcuts for Google Meet.
diff --git a/keyboards/eco/keymaps/bcat/config.h b/keyboards/eco/keymaps/bcat/config.h
index dffdc7b40a..f2d51c324a 100644
--- a/keyboards/eco/keymaps/bcat/config.h
+++ b/keyboards/eco/keymaps/bcat/config.h
@@ -16,6 +16,8 @@
#pragma once
+#define BCAT_ORTHO_LAYERS
+
/* WS2812B RGB LED strip hand wired to Elite-C. */
#define RGB_DI_PIN B7
#define RGBLED_NUM 15
diff --git a/keyboards/eco/keymaps/bcat/keymap.c b/keyboards/eco/keymaps/bcat/keymap.c
index d46a7d416b..8c50a9ed55 100644
--- a/keyboards/eco/keymaps/bcat/keymap.c
+++ b/keyboards/eco/keymaps/bcat/keymap.c
@@ -18,21 +18,6 @@
#include "bcat.h"
-enum layer {
- LAYER_DEFAULT,
- LAYER_LOWER,
- LAYER_RAISE,
- LAYER_ADJUST,
-};
-
-#define LY_LWR MO(LAYER_LOWER)
-#define LY_RSE MO(LAYER_RAISE)
-
-#define KY_CSPC LCTL(KC_SPC)
-#define KY_ZMIN LCTL(KC_EQL)
-#define KY_ZMOUT LCTL(KC_MINS)
-#define KY_ZMRST LCTL(KC_0)
-
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
/* Default layer: http://www.keyboard-layout-editor.com/#/gists/2c11371c7a5f7cd08a0132631d3d3281 */
@@ -58,12 +43,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
/* Adjust layer: http://www.keyboard-layout-editor.com/#/gists/b18aafa0327d7e83eaf485546c067a21 */
[LAYER_ADJUST] = LAYOUT(
- _______, NK_TOGG, KC_MPLY, KC_VOLU, KC_MSTP, _______, _______, _______, EEP_RST, RESET, _______, _______, _______, _______,
+ _______, _______, KC_MPLY, KC_VOLU, KC_MSTP, _______, _______, _______, EEP_RST, RESET, _______, _______, _______, _______,
_______, _______, KC_MPRV, KC_VOLD, KC_MNXT, _______, _______, _______, RGB_RMOD, RGB_VAD, RGB_VAI, RGB_MOD, RGB_SPI, _______,
_______, _______, _______, KC_MUTE, _______, _______, _______, _______, RGB_HUI, RGB_SAD, RGB_SAI, RGB_HUD, RGB_SPD, _______,
_______, _______, _______, _______, _______, _______, _______, _______, RGB_TOG, _______, _______, _______, _______, _______
),
// clang-format on
};
-
-layer_state_t layer_state_set_keymap(layer_state_t state) { return update_tri_layer_state(state, LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST); }
diff --git a/keyboards/eco/keymaps/bcat/readme.md b/keyboards/eco/keymaps/bcat/readme.md
index 85e2615512..fd9e1bea73 100644
--- a/keyboards/eco/keymaps/bcat/readme.md
+++ b/keyboards/eco/keymaps/bcat/readme.md
@@ -39,6 +39,6 @@ nothing really useful to bind them to anyway.
## Adjust layer
-![Adjust layer layout](https://i.imgur.com/J2rOshm.png)
+![Adjust layer layout](https://i.imgur.com/63vm0ke.png)
([KLE](http://www.keyboard-layout-editor.com/#/gists/b18aafa0327d7e83eaf485546c067a21))
diff --git a/keyboards/keebio/bdn9/keymaps/bcat/keymap.c b/keyboards/keebio/bdn9/keymaps/bcat/keymap.c
index c64f702b20..2028deb4f1 100644
--- a/keyboards/keebio/bdn9/keymaps/bcat/keymap.c
+++ b/keyboards/keebio/bdn9/keymaps/bcat/keymap.c
@@ -16,21 +16,16 @@
#include QMK_KEYBOARD_H
-enum layer {
- LAYER_FIRST,
- LAYER_SECOND,
-};
-
-#define LY_SECND MO(LAYER_SECOND)
+#include "bcat.h"
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
- [LAYER_FIRST] = LAYOUT(
- KC_MUTE, LY_SECND, BL_BRTG,
+ [LAYER_DEFAULT] = LAYOUT(
+ KC_MUTE, LY_FN1, BL_BRTG,
KC_F4, KC_F5, KC_F6,
KC_F1, KC_F2, KC_F3
),
- [LAYER_SECOND] = LAYOUT(
+ [LAYER_FUNCTION_1] = LAYOUT(
EEP_RST, _______, RESET,
KC_F10, KC_F11, KC_F12,
KC_F7, KC_F8, KC_F9
diff --git a/keyboards/keebio/quefrency/keymaps/bcat/keymap.c b/keyboards/keebio/quefrency/keymaps/bcat/keymap.c
index d28a5083ac..3dd48623fa 100644
--- a/keyboards/keebio/quefrency/keymaps/bcat/keymap.c
+++ b/keyboards/keebio/quefrency/keymaps/bcat/keymap.c
@@ -16,12 +16,7 @@
#include QMK_KEYBOARD_H
-enum layer {
- LAYER_DEFAULT,
- LAYER_FUNCTION,
-};
-
-#define LY_FN MO(LAYER_FUNCTION)
+#include "bcat.h"
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
@@ -31,12 +26,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, KC_PGUP,
KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END,
- KC_LCTL, KC_LGUI, KC_LALT, LY_FN, KC_SPC, KC_SPC, XXXXXXX, KC_RALT, LY_FN, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
+ KC_LCTL, KC_LGUI, KC_LALT, LY_FN1, KC_SPC, KC_SPC, XXXXXXX, KC_RALT, LY_FN1, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
/* Function layer: http://www.keyboard-layout-editor.com/#/gists/59636898946da51f91fb290f8e078b4d */
- [LAYER_FUNCTION] = LAYOUT_65(
+ [LAYER_FUNCTION_1] = LAYOUT_65(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_DEL, RGB_HUI,
- KC_CAPS, NK_TOGG, KC_MPLY, KC_VOLU, KC_MSTP, _______, EEP_RST, RESET, KC_PSCR, KC_SLCK, KC_PAUS, _______, _______, _______, RGB_SAI,
+ KC_CAPS, _______, KC_MPLY, KC_VOLU, KC_MSTP, _______, EEP_RST, RESET, KC_PSCR, KC_SLCK, KC_PAUS, _______, _______, _______, RGB_SAI,
_______, _______, KC_MPRV, KC_VOLD, KC_MNXT, _______, _______, _______, _______, _______, _______, _______, RGB_TOG, RGB_SAD,
_______, KC_APP, _______, KC_MUTE, _______, _______, _______, _______, _______, _______, _______, _______, RGB_VAI, RGB_HUD,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_RMOD, RGB_VAD, RGB_MOD
diff --git a/keyboards/keebio/quefrency/keymaps/bcat/readme.md b/keyboards/keebio/quefrency/keymaps/bcat/readme.md
index 914aa84b6b..59a691654d 100644
--- a/keyboards/keebio/quefrency/keymaps/bcat/readme.md
+++ b/keyboards/keebio/quefrency/keymaps/bcat/readme.md
@@ -12,6 +12,6 @@ ESDF cluster), and RGB controls in the function layer (on the arrow/nav keys).
## Function layer
-![Function layer layout](https://i.imgur.com/Fzshl0F.png)
+![Function layer layout](https://i.imgur.com/7oCdN86.png)
([KLE](http://www.keyboard-layout-editor.com/#/gists/59636898946da51f91fb290f8e078b4d))
diff --git a/keyboards/lily58/keymaps/bcat/config.h b/keyboards/lily58/keymaps/bcat/config.h
index dbe724d56b..2ee0071bda 100644
--- a/keyboards/lily58/keymaps/bcat/config.h
+++ b/keyboards/lily58/keymaps/bcat/config.h
@@ -16,4 +16,6 @@
#pragma once
+#define BCAT_ORTHO_LAYERS
+
#define EE_HANDS
diff --git a/keyboards/lily58/keymaps/bcat/keymap.c b/keyboards/lily58/keymaps/bcat/keymap.c
index 69af2ca003..a0856d0fdd 100644
--- a/keyboards/lily58/keymaps/bcat/keymap.c
+++ b/keyboards/lily58/keymaps/bcat/keymap.c
@@ -18,20 +18,9 @@
#include "bcat.h"
-enum layer {
- LAYER_DEFAULT,
- LAYER_LOWER,
- LAYER_RAISE,
- LAYER_ADJUST,
-};
-
-#define LY_LWR MO(LAYER_LOWER)
-#define LY_RSE MO(LAYER_RAISE)
-
-#define KY_CSPC LCTL(KC_SPC)
-#define KY_ZMIN LCTL(KC_EQL)
-#define KY_ZMOUT LCTL(KC_MINS)
-#define KY_ZMRST LCTL(KC_0)
+#if defined(OLED_ENABLE)
+# include "bcat_oled.h"
+#endif
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
@@ -62,7 +51,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Adjust layer: http://www.keyboard-layout-editor.com/#/gists/8f6a3f08350a9bbe1d414b22bca4e6c7 */
[LAYER_ADJUST] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, NK_TOGG, KC_MPLY, KC_VOLU, KC_MSTP, _______, EEP_RST, RESET, _______, _______, _______, _______,
+ _______, _______, KC_MPLY, KC_VOLU, KC_MSTP, _______, EEP_RST, RESET, _______, _______, _______, _______,
_______, _______, KC_MPRV, KC_VOLD, KC_MNXT, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, KC_MUTE, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______
@@ -70,4 +59,16 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format on
};
-layer_state_t layer_state_set_keymap(layer_state_t state) { return update_tri_layer_state(state, LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST); }
+#if defined(OLED_ENABLE)
+oled_rotation_t oled_init_user(oled_rotation_t rotation) { return is_keyboard_master() ? OLED_ROTATION_270 : OLED_ROTATION_180; }
+
+void oled_task_keymap(const oled_keyboard_state_t *keyboard_state) {
+ render_oled_layers();
+ oled_advance_page(/*clearPageRemainder=*/false);
+ render_oled_indicators(keyboard_state->leds);
+ oled_advance_page(/*clearPageRemainder=*/false);
+ oled_advance_page(/*clearPageRemainder=*/false);
+ render_oled_wpm(keyboard_state->wpm);
+ render_oled_pet(/*col=*/0, /*line=*/12, keyboard_state);
+}
+#endif
diff --git a/keyboards/lily58/keymaps/bcat/readme.md b/keyboards/lily58/keymaps/bcat/readme.md
index de03526a8b..8b0e77e1b7 100644
--- a/keyboards/lily58/keymaps/bcat/readme.md
+++ b/keyboards/lily58/keymaps/bcat/readme.md
@@ -37,6 +37,6 @@ back/forward navigation keys.
## Adjust layer
-![Adjust layer layout](https://i.imgur.com/Q3PGsiK.png)
+![Adjust layer layout](https://i.imgur.com/XC2eR2M.png)
([KLE](http://www.keyboard-layout-editor.com/#/gists/8f6a3f08350a9bbe1d414b22bca4e6c7))
diff --git a/keyboards/lily58/keymaps/bcat/rules.mk b/keyboards/lily58/keymaps/bcat/rules.mk
index c87b447c1e..62d1007a54 100644
--- a/keyboards/lily58/keymaps/bcat/rules.mk
+++ b/keyboards/lily58/keymaps/bcat/rules.mk
@@ -1 +1,3 @@
+BCAT_OLED_PET = luna
+
BOOTLOADER = atmel-dfu # Elite-C
diff --git a/layouts/community/60_ansi_split_bs_rshift/bcat/keymap.c b/layouts/community/60_ansi_split_bs_rshift/bcat/keymap.c
index 6bfafc3325..b40148e995 100644
--- a/layouts/community/60_ansi_split_bs_rshift/bcat/keymap.c
+++ b/layouts/community/60_ansi_split_bs_rshift/bcat/keymap.c
@@ -16,14 +16,7 @@
#include QMK_KEYBOARD_H
-enum layer {
- LAYER_DEFAULT,
- LAYER_FUNCTION_1,
- LAYER_FUNCTION_2,
-};
-
-#define LY_FN1 MO(LAYER_FUNCTION_1)
-#define LY_FN2 MO(LAYER_FUNCTION_2)
+#include "bcat.h"
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
@@ -48,7 +41,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Function 2 layer: http://www.keyboard-layout-editor.com/#/gists/6e1068e4f91bbacccaf5ac0acbeec79c */
[LAYER_FUNCTION_2] = LAYOUT_60_ansi_split_bs_rshift(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_DEL,
- _______, NK_TOGG, KC_MPLY, KC_VOLU, KC_MSTP, BL_BRTG, EEP_RST, RESET, _______, _______, _______, RGB_VAI, _______, _______,
+ _______, _______, KC_MPLY, KC_VOLU, KC_MSTP, BL_BRTG, EEP_RST, RESET, _______, _______, _______, RGB_VAI, _______, _______,
_______, _______, KC_MPRV, KC_VOLD, KC_MNXT, BL_INC, _______, RGB_SPI, RGB_HUI, RGB_SAI, RGB_RMOD, RGB_MOD, RGB_TOG,
_______, _______, _______, KC_MUTE, _______, BL_DEC, _______, RGB_SPD, RGB_HUD, RGB_SAD, RGB_VAD, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______
diff --git a/layouts/community/60_ansi_split_bs_rshift/bcat/readme.md b/layouts/community/60_ansi_split_bs_rshift/bcat/readme.md
index 2d578aa3d3..f6bcda9197 100644
--- a/layouts/community/60_ansi_split_bs_rshift/bcat/readme.md
+++ b/layouts/community/60_ansi_split_bs_rshift/bcat/readme.md
@@ -19,6 +19,6 @@ layout](https://github.com/qmk/qmk_firmware/tree/master/layouts/community/60_tsa
## Function 2 layer
-![Function 2 layer layout](https://i.imgur.com/vJaCzVo.png)
+![Function 2 layer layout](https://i.imgur.com/DW03vvJ.png)
([KLE](http://www.keyboard-layout-editor.com/#/gists/6e1068e4f91bbacccaf5ac0acbeec79c))
diff --git a/layouts/community/60_tsangan_hhkb/bcat/keymap.c b/layouts/community/60_tsangan_hhkb/bcat/keymap.c
index 05e6462d90..9ec75f3c4d 100644
--- a/layouts/community/60_tsangan_hhkb/bcat/keymap.c
+++ b/layouts/community/60_tsangan_hhkb/bcat/keymap.c
@@ -16,14 +16,7 @@
#include QMK_KEYBOARD_H
-enum layer {
- LAYER_DEFAULT,
- LAYER_FUNCTION_1,
- LAYER_FUNCTION_2,
-};
-
-#define LY_FN1 MO(LAYER_FUNCTION_1)
-#define LY_FN2 MO(LAYER_FUNCTION_2)
+#include "bcat.h"
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
@@ -46,7 +39,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Function 2 layer: http://www.keyboard-layout-editor.com/#/gists/65ac939caec878401603bc36290852d4 */
[LAYER_FUNCTION_2] = LAYOUT_60_tsangan_hhkb(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_DEL,
- _______, NK_TOGG, KC_MPLY, KC_VOLU, KC_MSTP, BL_BRTG, EEP_RST, RESET, _______, _______, _______, RGB_VAI, _______, _______,
+ _______, _______, KC_MPLY, KC_VOLU, KC_MSTP, BL_BRTG, EEP_RST, RESET, _______, _______, _______, RGB_VAI, _______, _______,
_______, _______, KC_MPRV, KC_VOLD, KC_MNXT, BL_INC, _______, RGB_SPI, RGB_HUI, RGB_SAI, RGB_RMOD, RGB_MOD, RGB_TOG,
_______, _______, _______, KC_MUTE, _______, BL_DEC, _______, RGB_SPD, RGB_HUD, RGB_SAD, RGB_VAD, _______, _______,
_______, _______, _______, _______, _______, _______, _______
diff --git a/layouts/community/60_tsangan_hhkb/bcat/readme.md b/layouts/community/60_tsangan_hhkb/bcat/readme.md
index b7a3cde5d2..c8d0d72dd0 100644
--- a/layouts/community/60_tsangan_hhkb/bcat/readme.md
+++ b/layouts/community/60_tsangan_hhkb/bcat/readme.md
@@ -39,6 +39,6 @@ and/or blockers, so there aren't switches installed in those positions.
## Function 2 layer
-![Function 2 layer layout](https://i.imgur.com/vdNpFae.png)
+![Function 2 layer layout](https://i.imgur.com/4Jdw9eL.png)
([KLE](http://www.keyboard-layout-editor.com/#/gists/65ac939caec878401603bc36290852d4))
diff --git a/layouts/community/65_ansi_blocker_split_bs/bcat/keymap.c b/layouts/community/65_ansi_blocker_split_bs/bcat/keymap.c
index c91a1b0ead..c099d36e25 100644
--- a/layouts/community/65_ansi_blocker_split_bs/bcat/keymap.c
+++ b/layouts/community/65_ansi_blocker_split_bs/bcat/keymap.c
@@ -16,12 +16,7 @@
#include QMK_KEYBOARD_H
-enum layer {
- LAYER_DEFAULT,
- LAYER_FUNCTION,
-};
-
-#define LY_FN MO(LAYER_FUNCTION)
+#include "bcat.h"
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
@@ -31,13 +26,13 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, KC_PGUP,
KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END,
- KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, LY_FN, KC_LEFT, KC_DOWN, KC_RGHT
+ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, LY_FN1, KC_LEFT, KC_DOWN, KC_RGHT
),
/* Function layer: http://www.keyboard-layout-editor.com/#/gists/f29128427f674c43777f045e363d1b44 */
- [LAYER_FUNCTION] = LAYOUT_65_ansi_blocker_split_bs(
+ [LAYER_FUNCTION_1] = LAYOUT_65_ansi_blocker_split_bs(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_DEL, _______,
- KC_CAPS, NK_TOGG, KC_MPLY, KC_VOLU, KC_MSTP, _______, EEP_RST, RESET, KC_PSCR, KC_SLCK, KC_PAUS, _______, _______, _______, _______,
+ KC_CAPS, _______, KC_MPLY, KC_VOLU, KC_MSTP, _______, EEP_RST, RESET, KC_PSCR, KC_SLCK, KC_PAUS, _______, _______, _______, _______,
_______, _______, KC_MPRV, KC_VOLD, KC_MNXT, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, KC_APP, _______, KC_MUTE, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/layouts/community/65_ansi_blocker_split_bs/bcat/readme.md b/layouts/community/65_ansi_blocker_split_bs/bcat/readme.md
index 0726cbecee..5777c7c38f 100644
--- a/layouts/community/65_ansi_blocker_split_bs/bcat/readme.md
+++ b/layouts/community/65_ansi_blocker_split_bs/bcat/readme.md
@@ -12,6 +12,6 @@ keys, an HHKB-style (split) backspace, and media controls in the function layer
## Function layer
-![Function layer layout](https://i.imgur.com/CsxfVfd.png)
+![Function layer layout](https://i.imgur.com/s4hS9ZK.png)
([KLE](http://www.keyboard-layout-editor.com/#/gists/f29128427f674c43777f045e363d1b44))
diff --git a/layouts/community/split_3x6_3/bcat/config.h b/layouts/community/split_3x6_3/bcat/config.h
index b8743429cf..556fb90d5f 100644
--- a/layouts/community/split_3x6_3/bcat/config.h
+++ b/layouts/community/split_3x6_3/bcat/config.h
@@ -16,12 +16,13 @@
#pragma once
+#define BCAT_ORTHO_LAYERS
+
#if defined(KEYBOARD_crkbd_rev1)
# define EE_HANDS
-# if defined(RGB_MATRIX_ENABLE)
-/* Limit max RGB LED current to avoid tripping controller fuse. */
-# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
-# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150
+# if defined(OLED_ENABLE)
+# undef OLED_FONT_H
+# define OLED_FONT_H "lib/glcdfont.c"
# endif
#endif
diff --git a/layouts/community/split_3x6_3/bcat/keymap.c b/layouts/community/split_3x6_3/bcat/keymap.c
index 4f68c8f843..cfac93d1e3 100644
--- a/layouts/community/split_3x6_3/bcat/keymap.c
+++ b/layouts/community/split_3x6_3/bcat/keymap.c
@@ -18,20 +18,9 @@
#include "bcat.h"
-enum layer {
- LAYER_DEFAULT,
- LAYER_LOWER,
- LAYER_RAISE,
- LAYER_ADJUST,
-};
-
-#define LY_LWR MO(LAYER_LOWER)
-#define LY_RSE MO(LAYER_RAISE)
-
-#define KY_CSPC LCTL(KC_SPC)
-#define KY_ZMIN LCTL(KC_EQL)
-#define KY_ZMOUT LCTL(KC_MINS)
-#define KY_ZMRST LCTL(KC_0)
+#if defined(OLED_ENABLE)
+# include "bcat_oled.h"
+#endif
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
@@ -58,7 +47,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
/* Adjust layer: http://www.keyboard-layout-editor.com/#/gists/77e7572e077b36a23eb2086017e16fee */
[LAYER_ADJUST] = LAYOUT_split_3x6_3(
- _______, NK_TOGG, KC_MPLY, KC_VOLU, KC_MSTP, _______, EEP_RST, RESET, _______, _______, _______, _______,
+ _______, _______, KC_MPLY, KC_VOLU, KC_MSTP, _______, EEP_RST, RESET, _______, _______, _______, _______,
_______, _______, KC_MPRV, KC_VOLD, KC_MNXT, _______, RGB_RMOD, RGB_VAD, RGB_VAI, RGB_MOD, RGB_SPI, _______,
_______, _______, _______, KC_MUTE, _______, _______, RGB_HUI, RGB_SAD, RGB_SAI, RGB_HUD, RGB_SPD, _______,
_______, _______, _______, RGB_TOG, _______, _______
@@ -66,4 +55,16 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format on
};
-layer_state_t layer_state_set_keymap(layer_state_t state) { return update_tri_layer_state(state, LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST); }
+#if defined(OLED_ENABLE)
+oled_rotation_t oled_init_user(oled_rotation_t rotation) { return is_keyboard_master() ? OLED_ROTATION_270 : OLED_ROTATION_180; }
+
+void oled_task_keymap(const oled_keyboard_state_t *keyboard_state) {
+ render_oled_layers();
+ oled_advance_page(/*clearPageRemainder=*/false);
+ render_oled_indicators(keyboard_state->leds);
+ oled_advance_page(/*clearPageRemainder=*/false);
+ oled_advance_page(/*clearPageRemainder=*/false);
+ render_oled_wpm(keyboard_state->wpm);
+ render_oled_pet(/*col=*/0, /*line=*/12, keyboard_state);
+}
+#endif
diff --git a/layouts/community/split_3x6_3/bcat/readme.md b/layouts/community/split_3x6_3/bcat/readme.md
index c4bf891c40..b7b5d3de7d 100644
--- a/layouts/community/split_3x6_3/bcat/readme.md
+++ b/layouts/community/split_3x6_3/bcat/readme.md
@@ -117,7 +117,7 @@ better location.
## Adjust layer
-![Adjust layer layout](https://i.imgur.com/fZouko5.png)
+![Adjust layer layout](https://i.imgur.com/Q4rN6cQ.png)
([KLE](http://www.keyboard-layout-editor.com/#/gists/77e7572e077b36a23eb2086017e16fee))
diff --git a/layouts/community/split_3x6_3/bcat/rules.mk b/layouts/community/split_3x6_3/bcat/rules.mk
index 5ee614b192..29e52b92db 100644
--- a/layouts/community/split_3x6_3/bcat/rules.mk
+++ b/layouts/community/split_3x6_3/bcat/rules.mk
@@ -1,5 +1,9 @@
+BCAT_OLED_PET = luna
+
ifeq ($(strip $(KEYBOARD)), crkbd/rev1)
BOOTLOADER = atmel-dfu # Elite-C
+ OLED_ENABLE = yes # dual 128x32 OLED screens
+ OLED_DRIVER = SSD1306
RGB_MATRIX_ENABLE = yes # per-key RGB and underglow
endif
diff --git a/users/bcat/bcat.c b/users/bcat/bcat.c
index f21d282e43..3a407cfac0 100644
--- a/users/bcat/bcat.c
+++ b/users/bcat/bcat.c
@@ -16,16 +16,15 @@
#include "bcat.h"
-#if defined(RGBLIGHT_ENABLE)
-/* Adjust RGB static hue ranges for shorter gradients than default. */
-const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 127, 63, 31, 15};
-#endif
+#include "quantum.h"
static int8_t alt_tab_layer = -1;
+__attribute__((weak)) void process_record_oled(uint16_t keycode, const keyrecord_t *record) {}
__attribute__((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { return true; }
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ process_record_oled(keycode, record);
if (!process_record_keymap(keycode, record)) {
return false;
}
@@ -51,6 +50,9 @@ __attribute__((weak)) layer_state_t layer_state_set_keymap(layer_state_t state)
layer_state_t layer_state_set_user(layer_state_t state) {
state = layer_state_set_keymap(state);
+#if defined(BCAT_ORTHO_LAYERS)
+ state = update_tri_layer_state(state, LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);
+#endif
if (alt_tab_layer >= 0 && !layer_state_cmp(state, alt_tab_layer)) {
unregister_code(KC_LALT);
alt_tab_layer = -1;
diff --git a/users/bcat/bcat.h b/users/bcat/bcat.h
index 0dae774ec5..4a88acba7d 100644
--- a/users/bcat/bcat.h
+++ b/users/bcat/bcat.h
@@ -16,9 +16,43 @@
#pragma once
-#include "quantum.h"
+#include <stdbool.h>
+#include "keymap.h"
+
+/* Layer numbers shared across keymaps. */
+enum user_layer {
+ /* Base layers: */
+ LAYER_DEFAULT,
+
+#if defined(BCAT_ORTHO_LAYERS)
+ /* Function layers for ortho (and ergo) boards: */
+ LAYER_LOWER,
+ LAYER_RAISE,
+ LAYER_ADJUST,
+#else
+ /* Function layers for traditional boards: */
+ LAYER_FUNCTION_1,
+ LAYER_FUNCTION_2,
+#endif
+};
+
+/* Custom keycodes shared across keymaps. */
enum user_keycode {
MC_ALTT = SAFE_RANGE,
KEYMAP_SAFE_RANGE,
};
+
+/* Keycode aliases shared across keymaps. */
+#define KY_CSPC LCTL(KC_SPC)
+#define KY_ZMIN LCTL(KC_EQL)
+#define KY_ZMOUT LCTL(KC_MINS)
+#define KY_ZMRST LCTL(KC_0)
+
+#if defined(BCAT_ORTHO_LAYERS)
+# define LY_LWR MO(LAYER_LOWER)
+# define LY_RSE MO(LAYER_RAISE)
+#else
+# define LY_FN1 MO(LAYER_FUNCTION_1)
+# define LY_FN2 MO(LAYER_FUNCTION_2)
+#endif
diff --git a/users/bcat/bcat_oled.c b/users/bcat/bcat_oled.c
new file mode 100644
index 0000000000..390c9127b4
--- /dev/null
+++ b/users/bcat/bcat_oled.c
@@ -0,0 +1,216 @@
+/* Copyright 2021 Jonathan Rascher
+ *
+ * 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 "bcat_oled.h"
+
+#include "quantum.h"
+#include "bcat.h"
+
+#if defined(BCAT_OLED_PET)
+# include "bcat_oled_pet.h"
+#endif
+
+#define TRIANGLE_UP 0x1e
+#define TRIANGLE_DOWN 0x1f
+
+#if defined(BCAT_OLED_PET)
+static bool oled_pet_should_jump = false;
+#endif
+
+/* Should be overridden by the keymap to render the OLED contents. For split
+ * keyboards, this function is only called on the master side.
+ */
+__attribute__((weak)) void oled_task_keymap(const oled_keyboard_state_t *keyboard_state) {}
+
+bool oled_task_user(void) {
+#if defined(SPLIT_KEYBOARD)
+ if (is_keyboard_master()) {
+#endif
+ /* Custom OLED timeout implementation that only considers user activity.
+ * Allows the OLED to turn off in the middle of a continuous animation.
+ */
+ static const uint16_t TIMEOUT_MILLIS = 60000 /* 1 min */;
+
+ if (last_input_activity_elapsed() < TIMEOUT_MILLIS) {
+ if (!is_oled_on()) {
+ oled_on();
+ }
+ oled_keyboard_state_t keyboard_state = {
+ .mods = get_mods(),
+ .leds = host_keyboard_led_state(),
+ .wpm = get_current_wpm(),
+ };
+ oled_task_keymap(&keyboard_state);
+ } else if (is_oled_on()) {
+ oled_off();
+ }
+#if defined(SPLIT_KEYBOARD)
+ } else {
+ /* Display logo embedded at standard location in the OLED font on the
+ * slave side. By default, this is a "QMK firmware" logo, but many
+ * keyboards substitute their own logo. Occupies 21x3 character cells.
+ *
+ * Since the slave display buffer never changes, we don't need to worry
+ * about oled_render incorrectly turning the OLED on. Instead, we rely
+ * on SPLIT_OLED_ENABLE to propagate OLED on/off status from master.
+ */
+ static const char PROGMEM logo[] = {
+ // clang-format off
+ 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,
+ 0x00,
+ // clang-format on
+ };
+
+ oled_write_P(logo, /*invert=*/false);
+ }
+#endif
+
+ return false;
+}
+
+void render_oled_layers(void) {
+ oled_advance_char();
+ oled_advance_char();
+#if defined(BCAT_ORTHO_LAYERS)
+ oled_write_char(IS_LAYER_ON(LAYER_LOWER) ? TRIANGLE_DOWN : ' ', /*invert=*/false);
+ oled_advance_char();
+ oled_write_char(IS_LAYER_ON(LAYER_RAISE) ? TRIANGLE_UP : ' ', /*invert=*/false);
+#else
+ switch (get_highest_layer(layer_state)) {
+ case LAYER_FUNCTION_1:
+ oled_write_P(PSTR("FN1"), /*invert=*/false);
+ break;
+ case LAYER_FUNCTION_2:
+ oled_write_P(PSTR("FN2"), /*invert=*/false);
+ break;
+ default:
+ oled_write_P(PSTR(" "), /*invert=*/false);
+ break;
+ }
+#endif
+}
+
+void render_oled_indicators(led_t leds) {
+ oled_advance_char();
+ oled_advance_char();
+ oled_write_P(leds.num_lock ? PSTR("NUM") : PSTR(" "), /*invert=*/false);
+ oled_advance_char();
+ oled_advance_char();
+ oled_write_P(leds.caps_lock ? PSTR("CAP") : PSTR(" "), /*invert=*/false);
+ oled_advance_char();
+ oled_advance_char();
+ oled_write_P(leds.scroll_lock ? PSTR("SCR") : PSTR(" "), /*invert=*/false);
+}
+
+void render_oled_wpm(uint8_t wpm) {
+ static const uint16_t UPDATE_MILLIS = 100;
+ static uint32_t update_timeout = 0;
+
+ if (timer_expired32(timer_read32(), update_timeout)) {
+ oled_advance_char();
+ oled_advance_char();
+ oled_write_P(wpm > 0 ? PSTR("WPM") : PSTR(" "), /*invert=*/false);
+ if (wpm > 0) {
+ oled_advance_char();
+ oled_advance_char();
+ oled_write(get_u8_str(wpm, ' '), /*invert=*/false);
+ } else {
+ oled_advance_page(/*clearPageRemainder=*/true);
+ }
+
+ update_timeout = timer_read32() + UPDATE_MILLIS;
+ }
+}
+
+#if defined(BCAT_OLED_PET)
+void process_record_oled(uint16_t keycode, const keyrecord_t *record) {
+ switch (keycode) {
+ case KC_SPACE:
+ if (oled_pet_can_jump()) {
+ oled_pet_should_jump = record->event.pressed;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void redraw_oled_pet(uint8_t col, uint8_t line, bool jumping, oled_pet_state_t state) {
+ oled_set_cursor(col, line);
+ if (jumping) {
+ oled_write_raw_P(oled_pet_frame(state), oled_pet_frame_bytes());
+ oled_set_cursor(col, line + oled_pet_frame_lines());
+ oled_advance_page(/*clearPageRemainder=*/true);
+ } else {
+ oled_advance_page(/*clearPageRemainder=*/true);
+ oled_write_raw_P(oled_pet_frame(state), oled_pet_frame_bytes());
+ }
+}
+
+void render_oled_pet(uint8_t col, uint8_t line, const oled_keyboard_state_t *keyboard_state) {
+ /* Current animation to draw. We track changes to avoid redrawing the same
+ * frame repeatedly, allowing oled_pet_post_render to draw over the
+ * animation frame.
+ */
+ static oled_pet_state_t state = 0;
+ static bool state_changed = true;
+
+ /* Minimum time until the pet comes down after jumping. */
+ static const uint16_t JUMP_MILLIS = 200;
+ static bool jumping = false;
+
+ /* Time until the next animation or jump state change. */
+ static uint32_t update_timeout = 0;
+ static uint32_t jump_timeout = 0;
+
+ /* If the user pressed the jump key, immediately redraw instead of waiting
+ * for the animation frame to update. That way, the pet appears to respond
+ * to jump commands quickly rather than lagging. If the user released the
+ * jump key, wait for the jump timeout to avoid overly brief jumps.
+ */
+ bool redraw = state_changed;
+ if (oled_pet_should_jump && !jumping) {
+ redraw = true;
+ jumping = true;
+ jump_timeout = timer_read32() + JUMP_MILLIS;
+ } else if (!oled_pet_should_jump && jumping && timer_expired32(timer_read32(), jump_timeout)) {
+ redraw = true;
+ jumping = false;
+ }
+
+ /* Draw the actual animation, then move the cursor to the end of the
+ * rendered area. (Note that we take up an extra line to account for
+ * jumping, which shifts the animation up or down a line.)
+ */
+ if (redraw) {
+ redraw_oled_pet(col, line, jumping, state);
+ }
+ oled_pet_post_render(col, line + !jumping, keyboard_state, redraw);
+ oled_set_cursor(col, line + oled_pet_frame_lines() + 1);
+
+ /* If the update timer expired, recompute the pet's animation state. */
+ if (timer_expired32(timer_read32(), update_timeout)) {
+ oled_pet_state_t new_state = oled_pet_next_state(state, keyboard_state);
+ state_changed = new_state != state;
+ state = new_state;
+ update_timeout = timer_read32() + oled_pet_update_millis(keyboard_state);
+ } else {
+ state_changed = false;
+ }
+}
+#endif
diff --git a/users/bcat/bcat_oled.h b/users/bcat/bcat_oled.h
new file mode 100644
index 0000000000..f617e1f064
--- /dev/null
+++ b/users/bcat/bcat_oled.h
@@ -0,0 +1,55 @@
+/* Copyright 2021 Jonathan Rascher
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "led.h"
+
+/* Keyboard status passed to the oled_task_keymap function and used by the
+ * various keyboard pet implementations.
+ */
+typedef struct {
+ uint8_t mods;
+ led_t leds;
+ uint8_t wpm;
+} oled_keyboard_state_t;
+
+/* Note: Functions below assume a vertical OLED that is 32px (5 chars) wide. */
+
+/* Renders layer status at the cursor. Occupies 5x1 character cells. */
+void render_oled_layers(void);
+
+/* Renders LED indicators (Num/Caps/Scroll Lock) at the cursor. Occupies 5x3
+ * character cells.
+ */
+void render_oled_indicators(led_t leds);
+
+/* Renders calculated WPM count at the cursor. Occupies 5x2 character cells. */
+void render_oled_wpm(uint8_t wpm);
+
+#if defined(BCAT_OLED_PET)
+/* Renders an animated critter at the cursor that can respond to keystrokes,
+ * typing speed, etc. Should be about 5 character cells wide, but exact height
+ * varies depending on the specific OLED pet implementation linked in.
+ *
+ * The rendered image will be one line taller than the OLED pet's animation
+ * frame height to accommodate pets that "jump" when the spacebar is pressed.
+ */
+void render_oled_pet(uint8_t col, uint8_t line, const oled_keyboard_state_t *keyboard_state);
+#endif
diff --git a/users/bcat/bcat_oled_pet.h b/users/bcat/bcat_oled_pet.h
new file mode 100644
index 0000000000..ba8227ab61
--- /dev/null
+++ b/users/bcat/bcat_oled_pet.h
@@ -0,0 +1,73 @@
+/* Copyright 2021 Jonathan Rascher
+ *
+ * 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/>.
+ */
+
+/* Common interface for an OLED pet (animated critter that reacts to typing).
+ * Please link exactly one accompanying .c file to implement these functions.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "bcat_oled.h"
+
+/* Opaque token representing a single frame of the OLED pet animation.
+ * Different pet implementations have different valid state values, but the
+ * zero value must always represent the default state of the pet at startup.
+ */
+typedef uint16_t oled_pet_state_t;
+
+/* Returns the number of bytes used to represent the animation frame (in
+ * oled_write_raw_P format). Note that every state the pet supports is expected
+ * to have the same frame size.
+ */
+uint16_t oled_pet_frame_bytes(void);
+
+/* Returns the number of lines of the OLED occupied by the animation. Note that
+ * every state the pet supports is expected to have the same frame size. The
+ * returned value does not include the one line of padding that render_oled_pet
+ * uses to account for "jumping".
+ */
+uint8_t oled_pet_frame_lines(void);
+
+/* Returns whether or not the OLED pet should "jump" when the spacebar is
+ * pressed. (The render_oled_pet implementation shifts the animation frame up
+ * one line when this happens.)
+ */
+bool oled_pet_can_jump(void);
+
+/* Returns the delay before the next animation frame should be displayed. */
+uint16_t oled_pet_update_millis(const oled_keyboard_state_t *keyboard_state);
+
+/* Returns the state of the pet to be animated on the next animation tick. */
+oled_pet_state_t oled_pet_next_state(oled_pet_state_t state, const oled_keyboard_state_t *keyboard_state);
+
+/* Called after the OLED pet is rendered during each OLED task invocation.
+ * Receives the same keyboard state as render_oled_pet. The redraw param
+ * indicates whether or not an OLED frame was just redrawn, allowing a specific
+ * pet implementation to draw custom things atop its animation frames.
+ *
+ * When this function is called, the cursor will be in an unspecified location,
+ * not necessarily the top-left corner of the OLED pet.
+ */
+void oled_pet_post_render(uint8_t col, uint8_t line, const oled_keyboard_state_t *keyboard_state, bool redraw);
+
+/* Returns a PROGMEM pointer to the specified frame buffer for the specified
+ * state. The animation frame has length given by oled_pet_frame_bytes and is
+ * formatted as expected by oled_write_raw_P.
+ */
+const char *oled_pet_frame(oled_pet_state_t state);
diff --git a/users/bcat/bcat_oled_pet_isda.c b/users/bcat/bcat_oled_pet_isda.c
new file mode 100644
index 0000000000..98abddb13b
--- /dev/null
+++ b/users/bcat/bcat_oled_pet_isda.c
@@ -0,0 +1,134 @@
+/* Copyright 2018 sparrow666
+ * Copyright 2021 Jonathan Rascher
+ *
+ * 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/>.
+ */
+
+/* OLED pet "Isda" (animated unicorn) featuring artwork by OpenGameArt user
+ * sparrow666, licensed under GPL v2.0.
+ *
+ * The animation is 32x72 pixels (9 lines tall).
+ *
+ * Runs faster the quicker you type. Shows LED indicator (Num/Caps/Scroll Lock)
+ * status in the bottom-right corner.
+ *
+ * Named after the goddess Ehlonna's personal unicorn in the first D&D campaign
+ * I ever played. :)
+ *
+ * Artwork source: https://opengameart.org/content/unicorn-2
+ */
+
+#include "bcat_oled_pet.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "bcat_oled.h"
+#include "led.h"
+#include "oled_driver.h"
+#include "progmem.h"
+
+#define NUM_FRAMES 4
+#define FRAME_BYTES 288 /* (32 pixel) * (72 pixel) / (8 pixel/byte) */
+
+uint16_t oled_pet_frame_bytes(void) { return FRAME_BYTES; }
+uint8_t oled_pet_frame_lines(void) { return 9 /* (72 pixel) / (8 pixel/line) */; }
+bool oled_pet_can_jump(void) { return false; }
+
+uint16_t oled_pet_update_millis(const oled_keyboard_state_t *keyboard_state) {
+ static const uint16_t MIN_MILLIS = 75;
+ static const uint16_t MAX_MILLIS = 300;
+ static const uint8_t MAX_WPM = 150;
+ uint8_t wpm = keyboard_state->wpm;
+ if (wpm > MAX_WPM) {
+ wpm = MAX_WPM;
+ }
+ return MAX_MILLIS - (MAX_MILLIS - MIN_MILLIS) * wpm / MAX_WPM;
+}
+
+oled_pet_state_t oled_pet_next_state(oled_pet_state_t state, const oled_keyboard_state_t *keyboard_state) {
+ /* When the user stops typing, cycle the animation to frame 0 and stop. */
+ return state != 0 || keyboard_state->wpm > 0 ? (state + 1) % NUM_FRAMES : 0;
+}
+
+void oled_pet_post_render(uint8_t col, uint8_t line, const oled_keyboard_state_t *keyboard_state, bool redraw) {
+ /* Draws LED indicator status in the bottom-right corner of the OLED pet,
+ * atop the animation frame. Redrawn only when necessary, e.g., when LED
+ * status changes or the animation itself updated (which overwrites any
+ * previously drawn indicators).
+ */
+ static led_t prev_leds = {.raw = 0};
+ led_t leds = keyboard_state->leds;
+ if (redraw || leds.raw != prev_leds.raw) {
+ oled_set_cursor(col + 4, line + 4);
+ oled_write_char(leds.num_lock ? 'N' : ' ', /*invert=*/false);
+ oled_set_cursor(col + 4, line + 6);
+ oled_write_char(leds.caps_lock ? 'C' : ' ', /*invert=*/false);
+ oled_set_cursor(col + 4, line + 8);
+ oled_write_char(leds.scroll_lock ? 'S' : ' ', /*invert=*/false);
+ prev_leds = leds;
+ }
+}
+
+const char *oled_pet_frame(oled_pet_state_t state) {
+ static const char PROGMEM FRAMES[NUM_FRAMES][FRAME_BYTES] = {
+ // clang-format off
+ {
+ 0x00, 0x00, 0x00, 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, 0xa0, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x88, 0xd0, 0x78, 0x04, 0x28, 0x70, 0x60, 0x90, 0x88, 0xc4, 0x22, 0x19, 0x04, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x84, 0x8c, 0x08, 0x01, 0x01, 0x02, 0x02, 0x04, 0x88, 0xf0, 0x00,
+ 0xc0, 0xe0, 0xe0, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0xff, 0xff, 0xff, 0x7f, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x3c, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x03, 0xc6, 0x3c, 0x00, 0x80, 0x70, 0x1c, 0x0f, 0x03, 0x0f, 0x3f, 0xff, 0xff, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x80, 0xe0, 0xf8, 0xfe, 0x7f, 0x1f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x0e, 0x30, 0x40, 0x47, 0x4f, 0x77, 0x03, 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, 0x80, 0x40, 0xc0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0xa0, 0xf0, 0x08, 0x50, 0xe0, 0xc0, 0x20, 0x10, 0x88, 0x44, 0x32, 0x09, 0x06, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x11, 0x03, 0x02, 0x04, 0x04, 0x08, 0x10, 0xe0, 0x00,
+ 0xc0, 0xe0, 0xe0, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00,
+ 0x00, 0x1f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x03, 0x00, 0x00, 0x80, 0xc0, 0x20, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x3c, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x03, 0xc6, 0x3c, 0x00, 0x80, 0x70, 0x18, 0x0f, 0x03, 0x0f, 0x3f, 0xff, 0xff, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x38, 0x07, 0xc0, 0x38, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x7f, 0xff, 0xff, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x21, 0x20, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0f, 0x0f, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x00, 0x00, 0x00, 0x00, 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, 0xc0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0xa0, 0xf0, 0x08, 0x50, 0xe0, 0xc0, 0x20, 0x10, 0x88, 0x44, 0x32, 0x09, 0x06, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x11, 0x03, 0x02, 0x04, 0x04, 0x08, 0x10, 0xe0, 0x00,
+ 0xc0, 0xc0, 0xc0, 0x20, 0x20, 0x10, 0x08, 0x04, 0x03, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00,
+ 0x00, 0x1f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x03, 0x00, 0x00, 0x80, 0xc0, 0x20, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x03, 0xc3, 0xfe, 0xfe, 0xfc, 0x7c, 0x1c, 0x0c, 0x0c, 0x08, 0x10, 0x60, 0x83, 0x07, 0x18, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x71, 0x0e, 0x80, 0x70, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x0f, 0x3f, 0x7f, 0x7f, 0x78, 0xe0, 0x90, 0x88, 0x66, 0x11, 0x08, 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, 0x80, 0x40, 0xa0, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x88, 0xd0, 0x78, 0x04, 0x28, 0x70, 0x60, 0x90, 0x88, 0xc4, 0x22, 0x19, 0x04, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x84, 0x8c, 0x08, 0x01, 0x01, 0x02, 0x02, 0x04, 0x88, 0xf0, 0x00,
+ 0xc0, 0xe0, 0xe0, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0xff, 0xff, 0xff, 0x7f, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0xfc, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x03, 0xc6, 0xfc, 0xfc, 0xfc, 0x7c, 0x18, 0x08, 0x08, 0x08, 0x30, 0xc0, 0x03, 0x0c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xc0, 0xf8, 0xff, 0xff, 0x3f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x70, 0x80, 0x1f, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x3e, 0x3f, 0x3f, 0x1f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ // clang-format on
+ };
+ return FRAMES[state];
+}
diff --git a/users/bcat/bcat_oled_pet_luna.c b/users/bcat/bcat_oled_pet_luna.c
new file mode 100644
index 0000000000..f0397c9c05
--- /dev/null
+++ b/users/bcat/bcat_oled_pet_luna.c
@@ -0,0 +1,168 @@
+/* Copyright 2021 HellSingCoder
+ * Copyright 2021 Jonathan Rascher
+ *
+ * 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/>.
+ */
+
+/* OLED pet "Luna" (animated doggo) originally by HellSingCoder
+ * (https://www.simonepellegrino.com/) and licensed under GPL v2.0, adapted to
+ * fit the OLED pet framework in bcat's userspace.
+ *
+ * The animation is 32x24 pixels (3 lines tall).
+ *
+ * Walks or runs in response to typing speed. Sneaks when Ctrl is pressed and
+ * barks when Caps Lock is on. Jumps when space is pressed.
+ *
+ * Original source:
+ * https://github.com/qmk/qmk_firmware/blob/6dfe915e26d7147e6c2bed495d3b01cf5b21e6ec/keyboards/sofle/keymaps/helltm/keymap.c
+ */
+
+#include "bcat_oled_pet.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "bcat_oled.h"
+#include "keycode.h"
+#include "progmem.h"
+
+enum image {
+ IMAGE_IDLE,
+ IMAGE_WALK,
+ IMAGE_RUN,
+ IMAGE_SNEAK,
+ IMAGE_BARK,
+};
+
+typedef union {
+ oled_pet_state_t raw;
+ struct {
+ uint8_t image;
+ uint8_t frame;
+ };
+} luna_state_t;
+
+#define NUM_FRAMES 2
+#define FRAME_BYTES 96 /* (32 pixel) * (24 pixel) / (8 pixel/byte) */
+
+uint16_t oled_pet_frame_bytes(void) { return FRAME_BYTES; }
+uint8_t oled_pet_frame_lines(void) { return 3 /* (24 pixel) / (8 pixel/line) */; }
+bool oled_pet_can_jump(void) { return true; }
+
+uint16_t oled_pet_update_millis(const oled_keyboard_state_t *keyboard_state) { return 200; }
+
+oled_pet_state_t oled_pet_next_state(oled_pet_state_t state, const oled_keyboard_state_t *keyboard_state) {
+ luna_state_t luna_state = {.raw = state};
+ if (keyboard_state->leds.caps_lock) {
+ luna_state.image = IMAGE_BARK;
+ } else if (keyboard_state->mods & MOD_MASK_CTRL) {
+ luna_state.image = IMAGE_SNEAK;
+ } else if (keyboard_state->wpm >= 100) {
+ luna_state.image = IMAGE_RUN;
+ } else if (keyboard_state->wpm >= 25) {
+ luna_state.image = IMAGE_WALK;
+ } else {
+ luna_state.image = IMAGE_IDLE;
+ }
+ luna_state.frame = (luna_state.frame + 1) % NUM_FRAMES;
+ return luna_state.raw;
+}
+
+void oled_pet_post_render(uint8_t col, uint8_t line, const oled_keyboard_state_t *keyboard_state, bool redraw) {}
+
+const char *oled_pet_frame(oled_pet_state_t state) {
+ static const char PROGMEM IDLE_FRAMES[NUM_FRAMES][FRAME_BYTES] = {
+ // clang-format off
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ // clang-format on
+ };
+ static const char PROGMEM WALK_FRAMES[NUM_FRAMES][FRAME_BYTES] = {
+ // clang-format off
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ // clang-format on
+ };
+ static const char PROGMEM RUN_FRAMES[NUM_FRAMES][FRAME_BYTES] = {
+ // clang-format off
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ // clang-format on
+ };
+ static const char PROGMEM SNEAK_FRAMES[NUM_FRAMES][FRAME_BYTES] = {
+ // clang-format off
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ // clang-format on
+ };
+ static const char PROGMEM BARK_FRAMES[NUM_FRAMES][FRAME_BYTES] = {
+ // clang-format off
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ // clang-format on
+ };
+ luna_state_t luna_state = {.raw = state};
+ switch (luna_state.image) {
+ case IMAGE_WALK:
+ return WALK_FRAMES[luna_state.frame];
+ case IMAGE_RUN:
+ return RUN_FRAMES[luna_state.frame];
+ case IMAGE_SNEAK:
+ return SNEAK_FRAMES[luna_state.frame];
+ case IMAGE_BARK:
+ return BARK_FRAMES[luna_state.frame];
+ default:
+ return IDLE_FRAMES[luna_state.frame];
+ }
+}
diff --git a/users/bcat/bcat_rgblight.c b/users/bcat/bcat_rgblight.c
new file mode 100644
index 0000000000..cd6222262b
--- /dev/null
+++ b/users/bcat/bcat_rgblight.c
@@ -0,0 +1,22 @@
+/* Copyright 2021 Jonathan Rascher
+ *
+ * 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 <stdint.h>
+
+#include "progmem.h"
+
+/* Adjust RGB static hue ranges for shorter gradients than default. */
+const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 127, 63, 31, 15};
diff --git a/users/bcat/compile.sh b/users/bcat/compile.sh
new file mode 100755
index 0000000000..81551f0ec0
--- /dev/null
+++ b/users/bcat/compile.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+set -o errexit -o nounset
+
+usage () {
+ printf "\
+usage: ./users/bcat/compile.sh [-c] [-j N]
+
+Compiles all keyboards for which bcat maintains keymaps.
+
+optional arguments:
+ -c performs a clean build
+ -j N runs N make tasks in parallel
+ -v shows verbose output
+"
+}
+
+compile () {
+ local keyboard=$1 layout=${2:-}
+ FORCE_LAYOUT="$layout" SILENT="$opt_silent" make -j "$opt_parallel" "$keyboard":bcat
+}
+
+opt_parallel=1
+opt_silent=true
+
+while getopts :chj:v opt; do
+ case $opt in
+ c) opt_clean=1 ;;
+ j) opt_parallel=$OPTARG ;;
+ v) opt_silent=false ;;
+ h) usage; exit 0 ;;
+ \?) usage >&2; exit 2 ;;
+ esac
+done
+
+if [[ -n ${opt_clean:-} ]]; then
+ SILENT="$opt_silent" make clean
+fi
+
+compile 9key
+compile ai03/polaris 60_tsangan_hhkb
+compile cannonkeys/an_c 60_tsangan_hhkb
+compile cannonkeys/instant60 60_tsangan_hhkb
+compile crkbd/rev1 split_3x6_3
+compile dz60 60_ansi_split_bs_rshift
+compile dz60 60_tsangan_hhkb
+compile eco/rev2
+compile kbdfans/kbd67/hotswap 65_ansi_blocker_split_bs
+compile keebio/bdn9/rev1
+compile keebio/quefrency/rev1
+compile lily58/rev1
diff --git a/users/bcat/config.h b/users/bcat/config.h
index 5bb93f3833..7bb5d71bae 100644
--- a/users/bcat/config.h
+++ b/users/bcat/config.h
@@ -14,6 +14,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/* Enable NKRO by default. All my devices support this, and it enables me to
+ * dispense with the NK_TOGG key, thus saving firmware space by not compiling
+ * magic keycode support.
+ */
+#define FORCE_NKRO
+
/* Wait between tap_code register and unregister to fix flaky media keys. */
#undef TAP_CODE_DELAY
@@ -31,6 +37,22 @@
*/
#define TAPPING_FORCE_HOLD
+#if defined(OLED_ENABLE)
+/* The built-in OLED timeout wakes the OLED screen every time the buffer is
+ * updated, even if no user activity has occurred recently. This prevents the
+ * OLED from ever turning off during a continuously running animation. To avoid
+ * this, we disable the default timeout and implement our own in
+ * oled_task_user.
+ */
+# undef OLED_TIMEOUT
+# define OLED_DISABLE_TIMEOUT
+
+# if defined(SPLIT_KEYBOARD)
+/* Sync OLED on/off state between halves of split keyboards. */
+# define SPLIT_OLED_ENABLE
+# endif
+#endif
+
#if defined(RGB_MATRIX_ENABLE)
/* Turn off per-key RGB when the host goes to sleep. */
# define RGB_DISABLE_WHEN_USB_SUSPENDED
@@ -46,9 +68,42 @@
# define RGB_MATRIX_VAL_STEP 17
# define RGB_MATRIX_SPD_STEP 17
-/* Turn on additional RGB animations. */
+/* Enable specific per-key animation modes. */
+# define ENABLE_RGB_MATRIX_ALPHAS_MODS
+# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
+# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
+# define ENABLE_RGB_MATRIX_BAND_SAT
+# define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
+# define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
+# define ENABLE_RGB_MATRIX_BAND_VAL
+# define ENABLE_RGB_MATRIX_BREATHING
+# define ENABLE_RGB_MATRIX_CYCLE_ALL
+# define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
+# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
+# define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
+# define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
+# define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
+# define ENABLE_RGB_MATRIX_DUAL_BEACON
+# define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+# define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+# define ENABLE_RGB_MATRIX_HUE_BREATHING
+# define ENABLE_RGB_MATRIX_HUE_PENDULUM
+# define ENABLE_RGB_MATRIX_HUE_WAVE
+# define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+# define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
+# define ENABLE_RGB_MATRIX_PIXEL_RAIN
+# define ENABLE_RGB_MATRIX_RAINBOW_BEACON
+# define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+# define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+# define ENABLE_RGB_MATRIX_RAINDROPS
+
+/* Enable additional per-key animation modes that require a copy of the
+ * framebuffer (with accompanying storage cost).
+ */
# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
-# define RGB_MATRIX_KEYPRESSES
+# define ENABLE_RGB_MATRIX_DIGITAL_RAIN
+# define ENABLE_RGB_MATRIX_TYPING_HEATMAP
#endif
#if defined(RGBLIGHT_ENABLE)
@@ -64,8 +119,18 @@
# define RGBLIGHT_SAT_STEP 17
# define RGBLIGHT_VAL_STEP 17
-/* Turn on additional RGB animations. */
-# define RGBLIGHT_ANIMATIONS
+/* Enable specific underglow animation modes. (Skip TWINKLE because it seems to
+ * be broken on ARM: https://github.com/qmk/qmk_firmware/issues/15345.)
+ */
+# define RGBLIGHT_EFFECT_ALTERNATING
+# define RGBLIGHT_EFFECT_BREATHING
+# define RGBLIGHT_EFFECT_CHRISTMAS
+# define RGBLIGHT_EFFECT_KNIGHT
+# define RGBLIGHT_EFFECT_RAINBOW_MOOD
+# define RGBLIGHT_EFFECT_RAINBOW_SWIRL
+# define RGBLIGHT_EFFECT_RGB_TEST
+# define RGBLIGHT_EFFECT_SNAKE
+# define RGBLIGHT_EFFECT_STATIC_GRADIENT
#endif
#if defined(BACKLIGHT_ENABLE)
@@ -77,3 +142,9 @@
# define BACKLIGHT_LEVELS 7
#endif
+
+/* Turn off unused config options to reduce firmware size. */
+#define LAYER_STATE_8BIT
+#define NO_ACTION_ONESHOT
+#undef LOCKING_RESYNC_ENABLE
+#undef LOCKING_SUPPORT_ENABLE
diff --git a/users/bcat/readme.md b/users/bcat/readme.md
index 1922f95f4a..bb73a53bf8 100644
--- a/users/bcat/readme.md
+++ b/users/bcat/readme.md
@@ -6,6 +6,8 @@ keyboard-specific keymaps for boards without standard layout support. I derive
my keymaps from two canonical ones (preferred for typing and gaming,
respectively).
+You can build all keymaps I maintain at once using `./users/bcat/compile.sh`.
+
## Canonical keymaps
* [Split 3x6 + 3 thumb
diff --git a/users/bcat/rules.mk b/users/bcat/rules.mk
index 12c9a89bf4..bb4bb11d88 100644
--- a/users/bcat/rules.mk
+++ b/users/bcat/rules.mk
@@ -1,7 +1,10 @@
-SRC += bcat.c
-
-# Enable Bootmagic Lite to consistently reset to bootloader and clear EEPROM.
-BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
+# Enable Bootmagic Lite for keyboards that don't have an easily accessible
+# reset button, but keep it disabled for all others to reduce firmware size.
+ifneq ($(filter $(strip $(KEYBOARD)),ai03/polaris dz60 kbdfans/kbd67/hotswap),)
+ BOOTMAGIC_ENABLE = yes
+else
+ BOOTMAGIC_ENABLE = no
+endif
# Enable media keys on all keyboards.
EXTRAKEY_ENABLE = yes
@@ -16,21 +19,49 @@ NKRO_ENABLE = yes
# Enable link-time optimization to reduce binary size.
LTO_ENABLE = yes
-# Disable unused build options on all keyboards.
+# Include common utilities shared across all our keymaps.
+SRC += bcat.c
+
+# Include additional utilities that extend optional QMK features only enabled
+# on some keyboards.
+ifeq ($(strip $(OLED_ENABLE)), yes)
+ SRC += bcat_oled.c
+ WPM_ENABLE = yes # for WPM and animated "keyboard pet" widgets
+
+ # OLED pets (animated critters that react to typing) take up a lot of
+ # firmware space, so only compile one, and only if requested.
+ BCAT_OLED_PET ?= no
+ ifneq ($(strip $(BCAT_OLED_PET)), no)
+ SRC += bcat_oled_pet_$(strip $(BCAT_OLED_PET)).c
+ OPT_DEFS += -DBCAT_OLED_PET
+ endif
+endif
+
+ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
+ SRC += bcat_rgblight.c
+endif
+
+# Disable unwanted build options on all keyboards. (Mouse keys are turned off
+# due to https://github.com/qmk/qmk_firmware/issues/8323, and the rest are
+# turned off to reduce firmware size.)
COMMAND_ENABLE = no
CONSOLE_ENABLE = no
MOUSEKEY_ENABLE = no
TERMINAL_ENABLE = no
-# Disable unused hardware options on all keyboards.
+# Disable unwanted hardware options on all keyboards. (Some keyboards turn
+# these features on by default even though they aren't actually required.)
MIDI_ENABLE = no
SLEEP_LED_ENABLE = no
# Disable other unused options on all keyboards.
AUTO_SHIFT_ENABLE = no
COMBO_ENABLE = no
+GRAVE_ESC_ENABLE = no
KEY_LOCK_ENABLE = no
LEADER_ENABLE = no
+MAGIC_ENABLE = no
+SPACE_CADET_ENABLE = no
SWAP_HANDS_ENABLE = no
TAP_DANCE_ENABLE = no
UCIS_ENABLE = no