From 27e6e27d3a2ff9d91bcf0f189cdc39509bef0335 Mon Sep 17 00:00:00 2001 From: Jay Greco Date: Sun, 2 Apr 2023 12:12:06 -0700 Subject: [PATCH] [Keyboard] Add nullbits SNAP keyboard (#18916) Co-authored-by: Ryan --- keyboards/nullbitsco/snap/config.h | 87 +++++ keyboards/nullbitsco/snap/info.json | 24 ++ .../snap/keymaps/bongo_reactive/bongo.h | 121 ++++++ .../keymaps/bongo_reactive/bongo_graphics.h | 262 +++++++++++++ .../snap/keymaps/bongo_reactive/config.h | 35 ++ .../snap/keymaps/bongo_reactive/keymap.c | 133 +++++++ .../snap/keymaps/bongo_reactive/rules.mk | 4 + .../bongo_reactive_single_oled/bongo.h | 121 ++++++ .../bongo_graphics.h | 262 +++++++++++++ .../bongo_reactive_single_oled/config.h | 29 ++ .../bongo_reactive_single_oled/keymap.c | 87 +++++ .../bongo_reactive_single_oled/rules.mk | 5 + .../nullbitsco/snap/keymaps/default/keymap.c | 105 ++++++ .../nullbitsco/snap/keymaps/iso/keymap.c | 104 ++++++ .../nullbitsco/snap/keymaps/oled/config.h | 27 ++ .../nullbitsco/snap/keymaps/oled/keymap.c | 163 ++++++++ .../snap/keymaps/oled/oled_graphics.h | 82 ++++ .../nullbitsco/snap/keymaps/oled/rules.mk | 5 + .../nullbitsco/snap/keymaps/typehud/config.h | 46 +++ .../nullbitsco/snap/keymaps/typehud/keymap.c | 157 ++++++++ .../nullbitsco/snap/keymaps/typehud/readme.md | 51 +++ .../nullbitsco/snap/keymaps/typehud/rules.mk | 7 + .../nullbitsco/snap/keymaps/typehud/typehud.c | 349 ++++++++++++++++++ .../nullbitsco/snap/keymaps/typehud/typehud.h | 87 +++++ .../nullbitsco/snap/keymaps/via/config.h | 20 + .../nullbitsco/snap/keymaps/via/keymap.c | 59 +++ .../nullbitsco/snap/keymaps/via/rules.mk | 2 + keyboards/nullbitsco/snap/matrix.c | 126 +++++++ keyboards/nullbitsco/snap/readme.md | 26 ++ keyboards/nullbitsco/snap/rules.mk | 23 ++ keyboards/nullbitsco/snap/snap.c | 127 +++++++ keyboards/nullbitsco/snap/snap.h | 106 ++++++ 32 files changed, 2842 insertions(+) create mode 100644 keyboards/nullbitsco/snap/config.h create mode 100644 keyboards/nullbitsco/snap/info.json create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive/bongo.h create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive/bongo_graphics.h create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive/config.h create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive/keymap.c create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive/rules.mk create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/bongo.h create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/bongo_graphics.h create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/config.h create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/keymap.c create mode 100644 keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/rules.mk create mode 100644 keyboards/nullbitsco/snap/keymaps/default/keymap.c create mode 100644 keyboards/nullbitsco/snap/keymaps/iso/keymap.c create mode 100644 keyboards/nullbitsco/snap/keymaps/oled/config.h create mode 100644 keyboards/nullbitsco/snap/keymaps/oled/keymap.c create mode 100644 keyboards/nullbitsco/snap/keymaps/oled/oled_graphics.h create mode 100644 keyboards/nullbitsco/snap/keymaps/oled/rules.mk create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/config.h create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/keymap.c create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/readme.md create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/rules.mk create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/typehud.c create mode 100644 keyboards/nullbitsco/snap/keymaps/typehud/typehud.h create mode 100644 keyboards/nullbitsco/snap/keymaps/via/config.h create mode 100644 keyboards/nullbitsco/snap/keymaps/via/keymap.c create mode 100644 keyboards/nullbitsco/snap/keymaps/via/rules.mk create mode 100644 keyboards/nullbitsco/snap/matrix.c create mode 100644 keyboards/nullbitsco/snap/readme.md create mode 100644 keyboards/nullbitsco/snap/rules.mk create mode 100644 keyboards/nullbitsco/snap/snap.c create mode 100644 keyboards/nullbitsco/snap/snap.h diff --git a/keyboards/nullbitsco/snap/config.h b/keyboards/nullbitsco/snap/config.h new file mode 100644 index 00000000000..ae0a5018bec --- /dev/null +++ b/keyboards/nullbitsco/snap/config.h @@ -0,0 +1,87 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +// clang-format off +#pragma once + +/* Used to set host for remote KB if VUSB detect doesn't work. */ +// #define KEYBOARD_HOST // Force host mode +// #define KEYBOARD_REMOTE // Force remote mode + +// Workarounds for sleep/wake issues +#define USB_SUSPEND_WAKEUP_DELAY 250 + +// NOTE: There is a bug in AVR deep sleep, which +// causes the MCU to stop responding in some cases. +// Disabling the watchdog prevents the MCU from entering +// power down, while still turning off LEDs, audio, etc. +// See qmk_firmware/issues/20087 for background +#undef WDT_vect + +/* split config */ +// #define SPLIT_USB_DETECT // Enable if you have issues with USB +#define SOFT_SERIAL_PIN E6 +#define SPLIT_HAND_PIN B6 +#define DISABLE_SYNC_TIMER +#define SPLIT_HAND_PIN_LOW_IS_LEFT + +/* key matrix size */ +#define MATRIX_ROWS 12 +#define MATRIX_COLS 9 +#define MATRIX_MUX_COLS 3 + +/* + * Keyboard Matrix Assignments + * The snap uses a demultiplexer for the cols. + * to free up more IOs for awesomeness! + * See matrix.c for more details. +*/ +// Left side +#define MATRIX_ROW_PINS { D4, C6, D7, F4, B4, B5 } +#define MATRIX_COL_MUX_PINS { F7, F6, F5 } + +//Right side +#define MATRIX_ROW_PINS_RIGHT { F4, F5, F6, F7, B1, B3 } +#define MATRIX_COL_MUX_PINS_RIGHT { D7, C6, D4 } +#define MATRIX_EXT_PIN_RIGHT B6 + +/* Optional SMT LED pins */ +#define RGB_DI_PIN B2 +#define RGBLED_NUM 10 +#define RGBLED_SPLIT { 5, 5 } +#define RGBLIGHT_LED_MAP { 8, 9, 0, 1, 2, 6, 7, 3, 4, 5 } +#define RGBLIGHT_SLEEP +#define RGBLIGHT_EFFECT_BREATHING +#define RGBLIGHT_EFFECT_RAINBOW_MOOD +#define RGBLIGHT_EFFECT_RAINBOW_SWIRL +#define RGBLIGHT_EFFECT_SNAKE +#define RGBLIGHT_EFFECT_KNIGHT +#define RGBLIGHT_EFFECT_CHRISTMAS +#define RGBLIGHT_EFFECT_STATIC_GRADIENT +#define RGBLIGHT_EFFECT_RGB_TEST +#define RGBLIGHT_EFFECT_ALTERNATING +#define RGBLIGHT_EFFECT_TWINKLE + +/* Optional encoder pins */ +#define ENCODERS_PAD_A { B3 } +#define ENCODERS_PAD_B { B1 } +#define ENCODERS_PAD_A_RIGHT { B4 } +#define ENCODERS_PAD_B_RIGHT { B5 } + +/* Optional speaker pin */ +#define AUDIO_PIN B6 + +/* Optional split transactions */ +#define SPLIT_OLED_ENABLE diff --git a/keyboards/nullbitsco/snap/info.json b/keyboards/nullbitsco/snap/info.json new file mode 100644 index 00000000000..6567ccde85a --- /dev/null +++ b/keyboards/nullbitsco/snap/info.json @@ -0,0 +1,24 @@ +{ + "keyboard_name": "SNAP", + "manufacturer": "nullbits", + "url": "https://nullbits.co/snap/", + "usb": { + "vid": "0x6E61", + "pid": "0x6063", + "device_version": "0.0.1" + }, + "debounce": 10, + "processor": "atmega32u4", + "bootloader": "atmel-dfu", + "layouts": { + "LAYOUT_all": { + "layout": [{"label":"Esc", "x":1, "y":0}, {"label":"F1", "x":2, "y":0}, {"label":"F2", "x":3, "y":0}, {"label":"F3", "x":4, "y":0}, {"label":"F4", "x":5, "y":0}, {"label":"F5", "x":6, "y":0}, {"label":"F6", "x":7, "y":0}, {"label":"F7", "x":8, "y":0}, {"label":"F8", "x":9, "y":0}, {"label":"F9", "x":10, "y":0}, {"label":"F10", "x":11, "y":0}, {"label":"F11", "x":12, "y":0}, {"label":"F12", "x":13, "y":0}, {"label":"PrtSc", "x":14, "y":0}, {"label":"Pause", "x":15, "y":0}, {"label":"M", "x":0, "y":1}, {"label":"~", "x":1, "y":1}, {"label":"!", "x":2, "y":1}, {"label":"@", "x":3, "y":1}, {"label":"#", "x":4, "y":1}, {"label":"$", "x":5, "y":1}, {"label":"%", "x":6, "y":1}, {"label":"^", "x":7, "y":1}, {"label":"&", "x":8, "y":1}, {"label":"*", "x":9, "y":1}, {"label":"(", "x":10, "y":1}, {"label":")", "x":11, "y":1}, {"label":"_", "x":12, "y":1}, {"label":"+", "x":13, "y":1}, {"label":"Bksp1", "x":14, "y":1}, {"label":"Bksp2", "x":15, "y":1}, {"label":"Home", "x":16, "y":1}, {"label":"M", "x":0, "y":2}, {"label":"Tab", "x":1, "y":2, "w":1.5}, {"label":"Q", "x":2.5, "y":2}, {"label":"W", "x":3.5, "y":2}, {"label":"E", "x":4.5, "y":2}, {"label":"R", "x":5.5, "y":2}, {"label":"T", "x":6.5, "y":2}, {"label":"Y", "x":7.5, "y":2}, {"label":"U", "x":8.5, "y":2}, {"label":"I", "x":9.5, "y":2}, {"label":"O", "x":10.5, "y":2}, {"label":"P", "x":11.5, "y":2}, {"label":"{", "x":12.5, "y":2}, {"label":"}", "x":13.5, "y":2}, {"label":"|", "x":14.5, "y":2, "w":1.5}, {"label":"End", "x":16, "y":2}, {"label":"M", "x":0, "y":3}, {"label":"Caps Lock", "x":1, "y":3, "w":1.75}, {"label":"A", "x":2.75, "y":3}, {"label":"S", "x":3.75, "y":3}, {"label":"D", "x":4.75, "y":3}, {"label":"F", "x":5.75, "y":3}, {"label":"G", "x":6.75, "y":3}, {"label":"H", "x":7.75, "y":3}, {"label":"J", "x":8.75, "y":3}, {"label":"K", "x":9.75, "y":3}, {"label":"L", "x":10.75, "y":3}, {"label":":", "x":11.75, "y":3}, {"label":"\"", "x":12.75, "y":3}, {"label":"Enter", "x":13.75, "y":3, "w":2.25}, {"label":"Page Up", "x":16, "y":3}, {"label":"M", "x":0, "y":4}, {"label":"Shift", "x":1, "y":4, "w":1.25}, {"label":"#", "x":2.25, "y":4}, {"label":"Z", "x":3.25, "y":4}, {"label":"X", "x":4.25, "y":4}, {"label":"C", "x":5.25, "y":4}, {"label":"V", "x":6.25, "y":4}, {"label":"B", "x":7.25, "y":4}, {"label":"N", "x":8.25, "y":4}, {"label":"M", "x":9.25, "y":4}, {"label":"<", "x":10.25, "y":4}, {"label":">", "x":11.25, "y":4}, {"label":"?", "x":12.25, "y":4}, {"label":"Shift", "x":13.25, "y":4, "w":1.75}, {"label":"\u2191", "x":15, "y":4}, {"label":"Page Down", "x":16, "y":4}, {"label":"M", "x":0, "y":5}, {"label":"Ctrl", "x":1, "y":5, "w":1.25}, {"label":"Win", "x":2.25, "y":5, "w":1.25}, {"label":"Alt", "x":3.5, "y":5, "w":1.25}, {"label":"Fn", "x":4.75, "y":5, "w":1.25}, {"label":"Space", "x":6, "y":5, "w":2.25}, {"label":"Space", "x":8.25, "y":5, "w":2.75}, {"label":"Alt", "x":11, "y":5}, {"label":"Fn", "x":12, "y":5}, {"label":"Ctrl", "x":13, "y":5}, {"label":"\u2190", "x":14, "y":5}, {"label":"\u2193", "x":15, "y":5}, {"label":"\u2192", "x":16, "y":5}] + }, + "LAYOUT_ansi": { + "layout": [{"label":"Esc", "x":1, "y":0}, {"label":"F1", "x":2, "y":0}, {"label":"F2", "x":3, "y":0}, {"label":"F3", "x":4, "y":0}, {"label":"F4", "x":5, "y":0}, {"label":"F5", "x":6, "y":0}, {"label":"F6", "x":7, "y":0}, {"label":"F7", "x":8, "y":0}, {"label":"F8", "x":9, "y":0}, {"label":"F9", "x":10, "y":0}, {"label":"F10", "x":11, "y":0}, {"label":"F11", "x":12, "y":0}, {"label":"F12", "x":13, "y":0}, {"label":"PrtSc", "x":14, "y":0}, {"label":"Pause", "x":15, "y":0}, {"label":"M", "x":0, "y":1}, {"label":"~", "x":1, "y":1}, {"label":"!", "x":2, "y":1}, {"label":"@", "x":3, "y":1}, {"label":"#", "x":4, "y":1}, {"label":"$", "x":5, "y":1}, {"label":"%", "x":6, "y":1}, {"label":"^", "x":7, "y":1}, {"label":"&", "x":8, "y":1}, {"label":"*", "x":9, "y":1}, {"label":"(", "x":10, "y":1}, {"label":")", "x":11, "y":1}, {"label":"_", "x":12, "y":1}, {"label":"+", "x":13, "y":1}, {"label":"Bksp", "x":14, "y":1, "w":2}, {"label":"Home", "x":16, "y":1}, {"label":"M", "x":0, "y":2}, {"label":"Tab", "x":1, "y":2, "w":1.5}, {"label":"Q", "x":2.5, "y":2}, {"label":"W", "x":3.5, "y":2}, {"label":"E", "x":4.5, "y":2}, {"label":"R", "x":5.5, "y":2}, {"label":"T", "x":6.5, "y":2}, {"label":"Y", "x":7.5, "y":2}, {"label":"U", "x":8.5, "y":2}, {"label":"I", "x":9.5, "y":2}, {"label":"O", "x":10.5, "y":2}, {"label":"P", "x":11.5, "y":2}, {"label":"{", "x":12.5, "y":2}, {"label":"}", "x":13.5, "y":2}, {"label":"|", "x":14.5, "y":2, "w":1.5}, {"label":"End", "x":16, "y":2}, {"label":"M", "x":0, "y":3}, {"label":"Caps Lock", "x":1, "y":3, "w":1.75}, {"label":"A", "x":2.75, "y":3}, {"label":"S", "x":3.75, "y":3}, {"label":"D", "x":4.75, "y":3}, {"label":"F", "x":5.75, "y":3}, {"label":"G", "x":6.75, "y":3}, {"label":"H", "x":7.75, "y":3}, {"label":"J", "x":8.75, "y":3}, {"label":"K", "x":9.75, "y":3}, {"label":"L", "x":10.75, "y":3}, {"label":":", "x":11.75, "y":3}, {"label":"\"", "x":12.75, "y":3}, {"label":"Enter", "x":13.75, "y":3, "w":2.25}, {"label":"Page Up", "x":16, "y":3}, {"label":"M", "x":0, "y":4}, {"label":"Shift", "x":1, "y":4, "w":2.25}, {"label":"Z", "x":3.25, "y":4}, {"label":"X", "x":4.25, "y":4}, {"label":"C", "x":5.25, "y":4}, {"label":"V", "x":6.25, "y":4}, {"label":"B", "x":7.25, "y":4}, {"label":"N", "x":8.25, "y":4}, {"label":"M", "x":9.25, "y":4}, {"label":"<", "x":10.25, "y":4}, {"label":">", "x":11.25, "y":4}, {"label":"?", "x":12.25, "y":4}, {"label":"Shift", "x":13.25, "y":4, "w":1.75}, {"label":"\u2191", "x":15, "y":4}, {"label":"Page Down", "x":16, "y":4}, {"label":"M", "x":0, "y":5}, {"label":"Ctrl", "x":1, "y":5, "w":1.25}, {"label":"Win", "x":2.25, "y":5, "w":1.25}, {"label":"Alt", "x":3.5, "y":5, "w":1.25}, {"label":"Fn", "x":4.75, "y":5, "w":1.25}, {"label":"Space", "x":6, "y":5, "w":2.25}, {"label":"Space", "x":8.25, "y":5, "w":2.75}, {"label":"Alt", "x":11, "y":5}, {"label":"Fn", "x":12, "y":5}, {"label":"Ctrl", "x":13, "y":5}, {"label":"\u2190", "x":14, "y":5}, {"label":"\u2193", "x":15, "y":5}, {"label":"\u2192", "x":16, "y":5}] + }, + "LAYOUT_iso": { + "layout": [{"label":"Esc", "x":1, "y":0}, {"label":"F1", "x":2, "y":0}, {"label":"F2", "x":3, "y":0}, {"label":"F3", "x":4, "y":0}, {"label":"F4", "x":5, "y":0}, {"label":"F5", "x":6, "y":0}, {"label":"F6", "x":7, "y":0}, {"label":"F7", "x":8, "y":0}, {"label":"F8", "x":9, "y":0}, {"label":"F9", "x":10, "y":0}, {"label":"F10", "x":11, "y":0}, {"label":"F11", "x":12, "y":0}, {"label":"F12", "x":13, "y":0}, {"label":"PrtSc", "x":14, "y":0}, {"label":"Pause", "x":15, "y":0}, {"label":"M", "x":0, "y":1}, {"label":"~", "x":1, "y":1}, {"label":"!", "x":2, "y":1}, {"label":"@", "x":3, "y":1}, {"label":"#", "x":4, "y":1}, {"label":"$", "x":5, "y":1}, {"label":"%", "x":6, "y":1}, {"label":"^", "x":7, "y":1}, {"label":"&", "x":8, "y":1}, {"label":"*", "x":9, "y":1}, {"label":"(", "x":10, "y":1}, {"label":")", "x":11, "y":1}, {"label":"_", "x":12, "y":1}, {"label":"+", "x":13, "y":1}, {"label":"Bksp", "x":14, "y":1, "w":2}, {"label":"Home", "x":16, "y":1}, {"label":"M", "x":0, "y":2}, {"label":"Tab", "x":1, "y":2, "w":1.5}, {"label":"Q", "x":2.5, "y":2}, {"label":"W", "x":3.5, "y":2}, {"label":"E", "x":4.5, "y":2}, {"label":"R", "x":5.5, "y":2}, {"label":"T", "x":6.5, "y":2}, {"label":"Y", "x":7.5, "y":2}, {"label":"U", "x":8.5, "y":2}, {"label":"I", "x":9.5, "y":2}, {"label":"O", "x":10.5, "y":2}, {"label":"P", "x":11.5, "y":2}, {"label":"{", "x":12.5, "y":2}, {"label":"}", "x":13.5, "y":2}, {"label":"Enter", "x":14.75, "y":2, "w":1.25, "h":2}, {"label":"End", "x":16, "y":2}, {"label":"M", "x":0, "y":3}, {"label":"Caps Lock", "x":1, "y":3, "w":1.75}, {"label":"A", "x":2.75, "y":3}, {"label":"S", "x":3.75, "y":3}, {"label":"D", "x":4.75, "y":3}, {"label":"F", "x":5.75, "y":3}, {"label":"G", "x":6.75, "y":3}, {"label":"H", "x":7.75, "y":3}, {"label":"J", "x":8.75, "y":3}, {"label":"K", "x":9.75, "y":3}, {"label":"L", "x":10.75, "y":3}, {"label":":", "x":11.75, "y":3}, {"label":"\"", "x":12.75, "y":3}, {"label":"\"", "x":13.75, "y":3}, {"label":"Page Up", "x":16, "y":3}, {"label":"M", "x":0, "y":4}, {"label":"Shift", "x":1, "y":4, "w":1.25}, {"label":"#", "x":2.25, "y":4}, {"label":"Z", "x":3.25, "y":4}, {"label":"X", "x":4.25, "y":4}, {"label":"C", "x":5.25, "y":4}, {"label":"V", "x":6.25, "y":4}, {"label":"B", "x":7.25, "y":4}, {"label":"N", "x":8.25, "y":4}, {"label":"M", "x":9.25, "y":4}, {"label":"<", "x":10.25, "y":4}, {"label":">", "x":11.25, "y":4}, {"label":"?", "x":12.25, "y":4}, {"label":"Shift", "x":13.25, "y":4, "w":1.75}, {"label":"\u2191", "x":15, "y":4}, {"label":"Page Down", "x":16, "y":4}, {"label":"M", "x":0, "y":5}, {"label":"Ctrl", "x":1, "y":5, "w":1.25}, {"label":"Win", "x":2.25, "y":5, "w":1.25}, {"label":"Alt", "x":3.5, "y":5, "w":1.25}, {"label":"Fn", "x":4.75, "y":5, "w":1.25}, {"label":"Space", "x":6, "y":5, "w":2.25}, {"label":"Space", "x":8.25, "y":5, "w":2.75}, {"label":"Alt", "x":11, "y":5}, {"label":"Fn", "x":12, "y":5}, {"label":"Ctrl", "x":13, "y":5}, {"label":"\u2190", "x":14, "y":5}, {"label":"\u2193", "x":15, "y":5}, {"label":"\u2192", "x":16, "y":5}] + } + } +} diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive/bongo.h b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/bongo.h new file mode 100644 index 00000000000..0cf1de3045b --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/bongo.h @@ -0,0 +1,121 @@ +/* Copyright 2021 Chris Tanaka + * + * 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 . + */ + +#include "bongo_graphics.h" +#include QMK_KEYBOARD_H + +#define _IDLE_FRAMES 5 +#define _PREP_FRAMES 1 +#define _TAP_FRAMES 2 +#define _ANIM_BYTES 512 // Number of bytes in array (max is 1024) +#define _IDLE_FRAME_DURATION 175 +#define _TAP_FRAME_DURATION 75 +#define _PREP_TIMEOUT 750 + +enum anim_states +{ + Idle, + Prep, + Tap +}; + +static uint8_t anim_state = Idle; +static uint8_t anim_duration = _IDLE_FRAME_DURATION; +static uint32_t anim_timer = 0; + +static uint8_t idle_frame = 0; +static uint8_t tap_frame = 0; + +static uint32_t prep_timer = 0; + +// Decompress and write a precompressed bitmap frame to the OLED. +// Documentation and python compression script available at: +// https://github.com/nullbitsco/squeez-o +#ifdef USE_OLED_BITMAP_COMPRESSION +static void oled_write_compressed_P(const char* input_block_map, const char* input_block_list) { + uint16_t block_index = 0; + for (uint16_t i = 0; i < NUM_OLED_BYTES; i++) { + uint8_t bit = i % 8; + uint8_t map_index = i / 8; + uint8_t _block_map = (uint8_t)pgm_read_byte_near(input_block_map + map_index); + uint8_t nonzero_byte = (_block_map & (1 << bit)); + if (nonzero_byte) { + const char data = (const char)pgm_read_byte_near(input_block_list + block_index++); + oled_write_raw_byte(data, i); + } else { + const char data = (const char)0x00; + oled_write_raw_byte(data, i); + } + } +} +#endif + +static void animate(uint8_t x, uint8_t y) { + oled_set_cursor(x, y); + + // Update frame + switch (anim_state) { + case Idle: + idle_frame = (idle_frame + 1) % _IDLE_FRAMES; + #ifdef USE_OLED_BITMAP_COMPRESSION + oled_write_compressed_P(idle_block_map[abs(1 - idle_frame)], idle[abs(1 - idle_frame)]); + #else + oled_write_raw_P(idle[abs(1 - idle_frame)], sizeof(idle[abs(1 - idle_frame)])); + #endif + break; + case Prep: + #ifdef USE_OLED_BITMAP_COMPRESSION + oled_write_compressed_P(prep_block_map[0], prep[0]); + #else + oled_write_raw_P(prep[0], sizeof(prep[0])); + #endif + break; + case Tap: + tap_frame = (tap_frame + 1) % _TAP_FRAMES; + #ifdef USE_OLED_BITMAP_COMPRESSION + oled_write_compressed_P(tap_block_map[abs(1 - tap_frame)], tap[abs(1 - tap_frame)]); + #else + oled_write_raw_P(tap[abs(1 - tap_frame)], sizeof(tap[abs(1 - tap_frame)])); + #endif + break; + default: + break; + } +} + +void bongo_render(uint8_t x, uint8_t y) { + if (timer_elapsed32(anim_timer) > anim_duration) { + anim_timer = timer_read32(); + animate(x, y); + } + + if (anim_state == Prep && timer_elapsed32(prep_timer) > _PREP_TIMEOUT) { + anim_state = Idle; + anim_duration = _IDLE_FRAME_DURATION; + } +} + +void bongo_process_record(keyrecord_t *record) { + if (record->event.pressed) { + anim_state = Tap; + anim_duration = _TAP_FRAME_DURATION; + } else { + if (anim_state == Tap) { + anim_state = Prep; + prep_timer = timer_read32(); + } + } +} diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive/bongo_graphics.h b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/bongo_graphics.h new file mode 100644 index 00000000000..0b7915ea720 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/bongo_graphics.h @@ -0,0 +1,262 @@ +/* Copyright 2022 Jay Greco + * + * 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 . + */ + +#pragma once + +#define _IDLE_FRAMES 5 +#define _PREP_FRAMES 1 +#define _TAP_FRAMES 2 +#define _ANIM_BYTES 512 + +#define NUM_OLED_BYTES 512 +#define USE_OLED_BITMAP_COMPRESSION + +#ifdef USE_OLED_BITMAP_COMPRESSION +static const char PROGMEM idle_block_map[_IDLE_FRAMES][64] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x48, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x48, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x79, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + } +}; + +static const char PROGMEM idle[_IDLE_FRAMES][164] = +{ + { + 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18, 0x04, 0x02, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, + 0x04, 0x04, 0x02, 0x02, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, 0x04, 0x04, + 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, + 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, + 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, + 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x01, + 0x01, 0x01 + }, + { + 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, + 0x01, 0x01, 0x80, 0x80, 0x60, 0x60, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, + 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, + 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0xc0, 0x30, 0x0c, 0x03, 0x80, 0x86, 0x86, 0x40, 0x40, 0x40, 0x40, 0x21, 0x22, 0x22, 0x20, + 0x11, 0x11, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, + 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, + 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, + 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x01, 0x01, 0x01 + }, + { + 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, + 0x80, 0x80, 0x7e, 0x82, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01, + 0x01, 0x80, 0x80, 0x60, 0x60, 0x01, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, + 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, + 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0xc0, 0x30, 0x0c, 0x03, 0x80, 0x86, 0x86, 0x40, 0x40, 0x40, 0x40, 0x21, 0x22, 0x22, 0x20, + 0x11, 0x11, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, + 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, + 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, + 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x01, 0x01, 0x01 + }, + { + 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, + 0x80, 0x80, 0x1c, 0x34, 0xc4, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, + 0x01, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, + 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, + 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, + 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, + 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x01, + 0x01, 0x01 + }, + { + 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18, 0x04, 0x02, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x06, 0x0d, 0x31, 0xc1, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, + 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, + 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x83, 0x83, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, + 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, + 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, + 0x18, 0x01, 0x01, 0x01 + } +}; + +static const char PROGMEM prep_block_map[_PREP_FRAMES][64] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xbb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } +}; + +static const char PROGMEM prep[_PREP_FRAMES][158] = +{ + { + 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, + 0x20, 0x40, 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x84, 0x44, 0x44, 0x42, + 0x82, 0x01, 0x01, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, 0x64, 0x18, 0x04, + 0x12, 0xc2, 0xca, 0x24, 0x88, 0xf0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, + 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x0c, 0x03, 0x02, 0x18, 0x19, 0x05, 0xfe, 0x80, + 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, + 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x80, 0x80, + 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, + 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01 + } +}; + +static const char PROGMEM tap_block_map[_TAP_FRAMES][64] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xbb, 0xff, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00 + } +}; + +static const char PROGMEM tap[_TAP_FRAMES][179] = +{ + { + 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, + 0x20, 0x40, 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, 0x64, 0x18, 0x04, + 0x12, 0xc2, 0xca, 0x24, 0x88, 0xf0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, + 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, + 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, + 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, + 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x98, 0xc0, 0x88, 0x88, 0x8c, + 0x9c, 0x1c, 0x1e, 0x0e, 0x06 + }, + { + 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, + 0x20, 0x40, 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x84, 0x44, 0x44, 0x42, + 0x82, 0x01, 0x01, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, 0x04, 0x04, 0x08, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, + 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x0c, 0x03, 0x02, 0x18, 0x19, 0x05, 0xfe, 0x80, + 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, + 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, + 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, + 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x06, 0x0f, 0x0f, 0x07, 0x03, 0x03, 0x61, 0xf0, 0xf8, 0xfc, 0x60, 0x01, 0x01, 0x01, 0x3c, 0x78, + 0xf8, 0xf0, 0x70 + } +}; + +#else +static const char PROGMEM idle[_IDLE_FRAMES][_ANIM_BYTES] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x40, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xc0, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x86, 0x86, 0x40, 0x40, 0x40, 0x40, 0x21, 0x22, 0x22, 0x20, 0x11, 0x11, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 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, 0x7e, 0x82, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x60, 0x60, 0x00, 0x01, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xc0, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x86, 0x86, 0x40, 0x40, 0x40, 0x40, 0x21, 0x22, 0x22, 0x20, 0x11, 0x11, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 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, 0x1c, 0x34, 0xc4, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x06, 0x0d, 0x31, 0xc1, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 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 prep[_PREP_FRAMES][_ANIM_BYTES] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x84, 0x44, 0x44, 0x42, 0x82, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x64, 0x18, 0x04, 0x12, 0xc2, 0xca, 0x24, 0x88, 0xf0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x02, 0x18, 0x19, 0x00, 0x05, 0xfe, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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 + } +}; + +static const char PROGMEM tap[_TAP_FRAMES][_ANIM_BYTES] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x64, 0x18, 0x04, 0x12, 0xc2, 0xca, 0x24, 0x88, 0xf0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x98, 0xc0, 0x88, 0x88, 0x8c, 0x9c, 0x1c, 0x1e, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x84, 0x44, 0x44, 0x42, 0x82, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x02, 0x18, 0x19, 0x00, 0x05, 0xfe, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0f, 0x0f, 0x07, 0x03, 0x03, 0x61, 0xf0, 0xf8, 0xfc, 0x60, 0x01, 0x01, 0x01, 0x3c, 0x78, 0xf8, 0xf0, 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 + } +}; +#endif diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive/config.h b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/config.h new file mode 100644 index 00000000000..49590197aed --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/config.h @@ -0,0 +1,35 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ + +#pragma once + +/* space savers */ +#define DYNAMIC_KEYMAP_LAYER_COUNT 3 +#define NO_ACTION_TAPPING +#define NO_ACTION_ONESHOT +#define TAPPING_FORCE_HOLD + +#define OLED_BRIGHTNESS 128 +#define OLED_TIMEOUT 30000 + +// Selectively undefine to save space +// VIA support won't fit otherwise +#ifdef RGBLIGHT_ENABLE +#undef RGBLIGHT_EFFECT_TWINKLE +#endif //RGB LIGHT_ENABLE + +// Split Options +#define SPLIT_TRANSPORT_MIRROR diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive/keymap.c b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/keymap.c new file mode 100644 index 00000000000..4ffa21f9ee1 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/keymap.c @@ -0,0 +1,133 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#include QMK_KEYBOARD_H +#include "bongo.h" + +// NOTE: +// In order to get the slave oled to receive keypresses: +// See: https://zenn.dev/teppeis/articles/2021-05-qmk-fire-process-record-in-slave + +// clang-format off +enum layers { + _BASE, + _VIA1, + _VIA2 +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_all( + KC_ESC, 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_PSCR, KC_PAUS, + KC_F13, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_HOME, + KC_F14, 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_BSLS, KC_END, + KC_F15, KC_CAPS, 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_PGUP, + KC_F16, KC_LSFT, KC_NUHS, 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_PGDN, + KC_F17, KC_LCTL, KC_LGUI, KC_LALT, MO(_VIA1), KC_SPC, KC_SPC, MO(_VIA1), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [_VIA1] = LAYOUT_all( + QK_BOOT,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ), + [_VIA2] = LAYOUT_all( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ) +}; +// clang-format on + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MPRV, KC_MNXT) }, + [_VIA1] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, + [_VIA2] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) } +}; +#endif + +oled_rotation_t oled_init_user(oled_rotation_t rotation) { + if (is_keyboard_left()) + return OLED_ROTATION_0; + else + return OLED_ROTATION_180; +} + +static void render_status(void) { + oled_set_cursor(0, 0); + oled_write_P(PSTR("SNAP75 "), false); + oled_write_P(PSTR("Layer "), false); + switch (get_highest_layer(layer_state)) { + case _VIA1: + oled_write_P(PSTR("FN1 "), false); + break; + case _VIA2: + oled_write_P(PSTR("FN2 "), false); + break; + default: // use BASE case as default + oled_write_P(PSTR("Base"), false); + } + + // Host Keyboard LED Status + oled_set_cursor(0, 1); + static uint8_t persistent_led_state = 0; + uint8_t led_usb_state = host_keyboard_leds(); + + // Only update if the LED state has changed + // Otherwise, the OLED will not turn off if an LED is on. + if (persistent_led_state != led_usb_state) { + persistent_led_state = led_usb_state; + + oled_write_ln_P(PSTR(""), false); + + if (IS_LED_ON(led_usb_state, USB_LED_CAPS_LOCK)) { + oled_set_cursor(0, 1); + oled_write_P(PSTR("CAPS"), false); + } + + if (IS_LED_ON(led_usb_state, USB_LED_NUM_LOCK)) { + oled_set_cursor(5, 1); + oled_write_P(PSTR("NUM"), true); + } + + if (IS_LED_ON(led_usb_state, USB_LED_SCROLL_LOCK)) { + oled_set_cursor(9, 1); + oled_write_P(PSTR("SCR"), false); + } + } +} + +bool oled_task_user(void) { + if (is_keyboard_master()) { + render_status(); + } else { + bongo_render(0, 0); + } + return true; +} + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + bongo_process_record(record); + return true; +} + +bool should_process_keypress(void) { + return true; +} diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive/rules.mk b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/rules.mk new file mode 100644 index 00000000000..7e580bfd749 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive/rules.mk @@ -0,0 +1,4 @@ +OLED_ENABLE = yes +OLED_DRIVER = SSD1306 +VIA_ENABLE = yes +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/bongo.h b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/bongo.h new file mode 100644 index 00000000000..0cf1de3045b --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/bongo.h @@ -0,0 +1,121 @@ +/* Copyright 2021 Chris Tanaka + * + * 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 . + */ + +#include "bongo_graphics.h" +#include QMK_KEYBOARD_H + +#define _IDLE_FRAMES 5 +#define _PREP_FRAMES 1 +#define _TAP_FRAMES 2 +#define _ANIM_BYTES 512 // Number of bytes in array (max is 1024) +#define _IDLE_FRAME_DURATION 175 +#define _TAP_FRAME_DURATION 75 +#define _PREP_TIMEOUT 750 + +enum anim_states +{ + Idle, + Prep, + Tap +}; + +static uint8_t anim_state = Idle; +static uint8_t anim_duration = _IDLE_FRAME_DURATION; +static uint32_t anim_timer = 0; + +static uint8_t idle_frame = 0; +static uint8_t tap_frame = 0; + +static uint32_t prep_timer = 0; + +// Decompress and write a precompressed bitmap frame to the OLED. +// Documentation and python compression script available at: +// https://github.com/nullbitsco/squeez-o +#ifdef USE_OLED_BITMAP_COMPRESSION +static void oled_write_compressed_P(const char* input_block_map, const char* input_block_list) { + uint16_t block_index = 0; + for (uint16_t i = 0; i < NUM_OLED_BYTES; i++) { + uint8_t bit = i % 8; + uint8_t map_index = i / 8; + uint8_t _block_map = (uint8_t)pgm_read_byte_near(input_block_map + map_index); + uint8_t nonzero_byte = (_block_map & (1 << bit)); + if (nonzero_byte) { + const char data = (const char)pgm_read_byte_near(input_block_list + block_index++); + oled_write_raw_byte(data, i); + } else { + const char data = (const char)0x00; + oled_write_raw_byte(data, i); + } + } +} +#endif + +static void animate(uint8_t x, uint8_t y) { + oled_set_cursor(x, y); + + // Update frame + switch (anim_state) { + case Idle: + idle_frame = (idle_frame + 1) % _IDLE_FRAMES; + #ifdef USE_OLED_BITMAP_COMPRESSION + oled_write_compressed_P(idle_block_map[abs(1 - idle_frame)], idle[abs(1 - idle_frame)]); + #else + oled_write_raw_P(idle[abs(1 - idle_frame)], sizeof(idle[abs(1 - idle_frame)])); + #endif + break; + case Prep: + #ifdef USE_OLED_BITMAP_COMPRESSION + oled_write_compressed_P(prep_block_map[0], prep[0]); + #else + oled_write_raw_P(prep[0], sizeof(prep[0])); + #endif + break; + case Tap: + tap_frame = (tap_frame + 1) % _TAP_FRAMES; + #ifdef USE_OLED_BITMAP_COMPRESSION + oled_write_compressed_P(tap_block_map[abs(1 - tap_frame)], tap[abs(1 - tap_frame)]); + #else + oled_write_raw_P(tap[abs(1 - tap_frame)], sizeof(tap[abs(1 - tap_frame)])); + #endif + break; + default: + break; + } +} + +void bongo_render(uint8_t x, uint8_t y) { + if (timer_elapsed32(anim_timer) > anim_duration) { + anim_timer = timer_read32(); + animate(x, y); + } + + if (anim_state == Prep && timer_elapsed32(prep_timer) > _PREP_TIMEOUT) { + anim_state = Idle; + anim_duration = _IDLE_FRAME_DURATION; + } +} + +void bongo_process_record(keyrecord_t *record) { + if (record->event.pressed) { + anim_state = Tap; + anim_duration = _TAP_FRAME_DURATION; + } else { + if (anim_state == Tap) { + anim_state = Prep; + prep_timer = timer_read32(); + } + } +} diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/bongo_graphics.h b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/bongo_graphics.h new file mode 100644 index 00000000000..0b7915ea720 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/bongo_graphics.h @@ -0,0 +1,262 @@ +/* Copyright 2022 Jay Greco + * + * 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 . + */ + +#pragma once + +#define _IDLE_FRAMES 5 +#define _PREP_FRAMES 1 +#define _TAP_FRAMES 2 +#define _ANIM_BYTES 512 + +#define NUM_OLED_BYTES 512 +#define USE_OLED_BITMAP_COMPRESSION + +#ifdef USE_OLED_BITMAP_COMPRESSION +static const char PROGMEM idle_block_map[_IDLE_FRAMES][64] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x48, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x48, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x79, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00 + } +}; + +static const char PROGMEM idle[_IDLE_FRAMES][164] = +{ + { + 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18, 0x04, 0x02, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, + 0x04, 0x04, 0x02, 0x02, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, 0x04, 0x04, + 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, + 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, + 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, + 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x01, + 0x01, 0x01 + }, + { + 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, + 0x01, 0x01, 0x80, 0x80, 0x60, 0x60, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, + 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, + 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0xc0, 0x30, 0x0c, 0x03, 0x80, 0x86, 0x86, 0x40, 0x40, 0x40, 0x40, 0x21, 0x22, 0x22, 0x20, + 0x11, 0x11, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, + 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, + 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, + 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x01, 0x01, 0x01 + }, + { + 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, + 0x80, 0x80, 0x7e, 0x82, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01, + 0x01, 0x80, 0x80, 0x60, 0x60, 0x01, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, + 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, + 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0xc0, 0x30, 0x0c, 0x03, 0x80, 0x86, 0x86, 0x40, 0x40, 0x40, 0x40, 0x21, 0x22, 0x22, 0x20, + 0x11, 0x11, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, + 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, + 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, + 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x01, 0x01, 0x01 + }, + { + 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, + 0x80, 0x80, 0x1c, 0x34, 0xc4, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, + 0x01, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, + 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, + 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, + 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, + 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x01, + 0x01, 0x01 + }, + { + 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18, 0x04, 0x02, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x06, 0x0d, 0x31, 0xc1, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, + 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, + 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x83, 0x83, 0x40, 0x40, + 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, 0x80, 0x80, 0x80, 0x80, + 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, + 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, + 0x18, 0x01, 0x01, 0x01 + } +}; + +static const char PROGMEM prep_block_map[_PREP_FRAMES][64] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xbb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } +}; + +static const char PROGMEM prep[_PREP_FRAMES][158] = +{ + { + 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, + 0x20, 0x40, 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x84, 0x44, 0x44, 0x42, + 0x82, 0x01, 0x01, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, 0x64, 0x18, 0x04, + 0x12, 0xc2, 0xca, 0x24, 0x88, 0xf0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, + 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x0c, 0x03, 0x02, 0x18, 0x19, 0x05, 0xfe, 0x80, + 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, + 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x80, 0x80, + 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, + 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01 + } +}; + +static const char PROGMEM tap_block_map[_TAP_FRAMES][64] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x79, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xbb, 0xff, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00 + } +}; + +static const char PROGMEM tap[_TAP_FRAMES][179] = +{ + { + 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, + 0x20, 0x40, 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, 0x64, 0x18, 0x04, + 0x12, 0xc2, 0xca, 0x24, 0x88, 0xf0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, + 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, + 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, + 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, + 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x98, 0xc0, 0x88, 0x88, 0x8c, + 0x9c, 0x1c, 0x1e, 0x0e, 0x06 + }, + { + 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, + 0x20, 0x40, 0x40, 0x80, 0x80, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x84, 0x44, 0x44, 0x42, + 0x82, 0x01, 0x01, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x30, 0x30, 0x01, 0x02, 0x04, 0x04, 0x08, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, + 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0xe0, 0x18, 0x06, 0x01, 0x0c, 0x03, 0x02, 0x18, 0x19, 0x05, 0xfe, 0x80, + 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, + 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x01, 0x86, 0x98, 0x60, + 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, + 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x06, 0x0f, 0x0f, 0x07, 0x03, 0x03, 0x61, 0xf0, 0xf8, 0xfc, 0x60, 0x01, 0x01, 0x01, 0x3c, 0x78, + 0xf8, 0xf0, 0x70 + } +}; + +#else +static const char PROGMEM idle[_IDLE_FRAMES][_ANIM_BYTES] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x40, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xc0, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x86, 0x86, 0x40, 0x40, 0x40, 0x40, 0x21, 0x22, 0x22, 0x20, 0x11, 0x11, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 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, 0x7e, 0x82, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x60, 0x60, 0x00, 0x01, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xc0, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x86, 0x86, 0x40, 0x40, 0x40, 0x40, 0x21, 0x22, 0x22, 0x20, 0x11, 0x11, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 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, 0x1c, 0x34, 0xc4, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x18, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x06, 0x0d, 0x31, 0xc1, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x18, 0x00, 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, 0x00, 0x00, 0x00, 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 prep[_PREP_FRAMES][_ANIM_BYTES] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x84, 0x44, 0x44, 0x42, 0x82, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x64, 0x18, 0x04, 0x12, 0xc2, 0xca, 0x24, 0x88, 0xf0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x02, 0x18, 0x19, 0x00, 0x05, 0xfe, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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 + } +}; + +static const char PROGMEM tap[_TAP_FRAMES][_ANIM_BYTES] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x64, 0x18, 0x04, 0x12, 0xc2, 0xca, 0x24, 0x88, 0xf0, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x41, 0x42, 0x24, 0x98, 0xc0, 0x88, 0x88, 0x8c, 0x9c, 0x1c, 0x1e, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 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, 0x3f, 0xc1, 0x01, 0x01, 0x02, 0x02, 0x04, 0x84, 0x44, 0x44, 0x42, 0x82, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 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, 0xe0, 0x18, 0x06, 0x01, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x02, 0x18, 0x19, 0x00, 0x05, 0xfe, 0x80, 0x83, 0x83, 0x40, 0x40, 0x40, 0x40, 0x20, 0x21, 0x21, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x30, 0x40, 0x80, 0x80, 0x00, 0x00, 0x01, 0x86, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0f, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0f, 0x0f, 0x07, 0x03, 0x03, 0x61, 0xf0, 0xf8, 0xfc, 0x60, 0x01, 0x01, 0x01, 0x3c, 0x78, 0xf8, 0xf0, 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 + } +}; +#endif diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/config.h b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/config.h new file mode 100644 index 00000000000..8cfcb4d0e8a --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/config.h @@ -0,0 +1,29 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ + +#pragma once + +#define OLED_BRIGHTNESS 128 +#define OLED_TIMEOUT 30000 + +/* space savers */ +#define DYNAMIC_KEYMAP_LAYER_COUNT 3 +#define NO_ACTION_TAPPING +#define NO_ACTION_ONESHOT +#define TAPPING_FORCE_HOLD + +// Split Options +#define SPLIT_TRANSPORT_MIRROR diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/keymap.c b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/keymap.c new file mode 100644 index 00000000000..07d01e606a2 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/keymap.c @@ -0,0 +1,87 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#include QMK_KEYBOARD_H +#include "bongo.h" + +// NOTE: +// In order to get the slave oled to receive keypresses: +// See: https://zenn.dev/teppeis/articles/2021-05-qmk-fire-process-record-in-slave + +// clang-format off +enum layers { + _BASE, + _VIA1, + _VIA2 +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_all( + KC_ESC, 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_PSCR, KC_PAUS, + KC_F13, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_HOME, + KC_F14, 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_BSLS, KC_END, + KC_F15, KC_CAPS, 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_PGUP, + KC_F16, KC_LSFT, KC_NUHS, 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_PGDN, + KC_F17, KC_LCTL, KC_LGUI, KC_LALT, MO(_VIA1), KC_SPC, KC_SPC, MO(_VIA1), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [_VIA1] = LAYOUT_all( + QK_BOOT,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ), + [_VIA2] = LAYOUT_all( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ) +}; +// clang-format on + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MPRV, KC_MNXT) }, + [_VIA1] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, + [_VIA2] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) } +}; +#endif + +oled_rotation_t oled_init_user(oled_rotation_t rotation) { + if (is_keyboard_left()) + return OLED_ROTATION_0; + else + return OLED_ROTATION_180; +} + +bool oled_task_user(void) { + if (is_keyboard_master()) { + bongo_render(0, 0); + } + return true; +} + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + bongo_process_record(record); + return true; +} + +bool should_process_keypress(void) { + return true; +} diff --git a/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/rules.mk b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/rules.mk new file mode 100644 index 00000000000..d0a184e961f --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/bongo_reactive_single_oled/rules.mk @@ -0,0 +1,5 @@ +OLED_ENABLE = yes +OLED_DRIVER = SSD1306 +WPM_ENABLE = yes +VIA_ENABLE = yes +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/nullbitsco/snap/keymaps/default/keymap.c b/keyboards/nullbitsco/snap/keymaps/default/keymap.c new file mode 100644 index 00000000000..5178b503496 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/default/keymap.c @@ -0,0 +1,105 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#include QMK_KEYBOARD_H +#include "common/remote_kb.h" + +// clang-format off +enum layers { + _BASE = 0, + _FUNC +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_ansi( + KC_ESC, 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_PSCR, KC_PAUS, + KC_F13, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_HOME, + KC_F14, 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_BSLS, KC_END, + KC_F15, KC_CAPS, 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_PGUP, + KC_F16, 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_PGDN, + KC_F17, KC_LCTL, KC_LGUI, KC_LALT, MO(_FUNC), KC_SPC, KC_BSPC, MO(_FUNC), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [_FUNC] = LAYOUT_ansi( + QK_BOOT, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + RGB_TOG, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, KC_MPRV, KC_MPLY, KC_MNXT + ), +}; +// clang-format on + +// RGB config, for changing RGB settings on non-VIA firmware +#ifdef RGBLIGHT_ENABLE +void change_RGB(bool clockwise) { + bool shift = get_mods() & MOD_MASK_SHIFT; + bool alt = get_mods() & MOD_MASK_ALT; + bool ctrl = get_mods() & MOD_MASK_CTRL; + +#ifdef CONSOLE_ENABLE + dprintf("Mods: %u\n", get_mods()); +#endif + + if (clockwise) { + if (alt) { + rgblight_increase_hue(); + } else if (ctrl) { + rgblight_increase_val(); + } else if (shift) { + rgblight_increase_sat(); + } else { + rgblight_step(); + } + + } else { + if (alt) { + rgblight_decrease_hue(); + } else if (ctrl) { + rgblight_decrease_val(); + } else if (shift) { + rgblight_decrease_sat(); + } else { + rgblight_step_reverse(); + } + } +} +#endif + +bool encoder_update_user(uint8_t index, bool clockwise) { + // change RGB settings and don't do anything else + if (!layer_state_is(_BASE)) { + #ifdef RGBLIGHT_ENABLE + change_RGB(clockwise); + #endif + return false; + } + /* Left encoder */ + if (index == 0) { + if (clockwise) { + tap_code_delay(KC_VOLU, 10); + } else { + tap_code_delay(KC_VOLD, 10); + } + /* Right encoder */ + } else if (index == 1) { + if (clockwise) { + tap_code_delay(KC_MNXT, 10); + } else { + tap_code_delay(KC_MPRV, 10); + } + } + return true; +} diff --git a/keyboards/nullbitsco/snap/keymaps/iso/keymap.c b/keyboards/nullbitsco/snap/keymaps/iso/keymap.c new file mode 100644 index 00000000000..3c3b828263e --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/iso/keymap.c @@ -0,0 +1,104 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#include QMK_KEYBOARD_H + +// clang-format off +enum layers { + _BASE = 0, + _FUNC +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_iso( + KC_ESC, 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_PSCR, KC_PAUS, + KC_F13, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_HOME, + KC_F14, 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_ENT, KC_END, + KC_F15, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_BSLS, KC_PGUP, + KC_F16, KC_LSFT, KC_NUHS, 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_PGDN, + KC_F17, KC_LCTL, KC_LGUI, KC_LALT, MO(_FUNC), KC_SPC, KC_SPC, MO(_FUNC), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [_FUNC] = LAYOUT_iso( + QK_BOOT, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + RGB_TOG, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, KC_MPRV, KC_MPLY, KC_MNXT + ), +}; +// clang-format on + +// RGB config, for changing RGB settings on non-VIA firmwares +#ifdef RGBLIGHT_ENABLE +void change_RGB(bool clockwise) { + bool shift = get_mods() & MOD_MASK_SHIFT; + bool alt = get_mods() & MOD_MASK_ALT; + bool ctrl = get_mods() & MOD_MASK_CTRL; + +#ifdef CONSOLE_ENABLE + dprintf("Mods: %u\n", get_mods()); +#endif + + if (clockwise) { + if (alt) { + rgblight_increase_hue(); + } else if (ctrl) { + rgblight_increase_val(); + } else if (shift) { + rgblight_increase_sat(); + } else { + rgblight_step(); + } + + } else { + if (alt) { + rgblight_decrease_hue(); + } else if (ctrl) { + rgblight_decrease_val(); + } else if (shift) { + rgblight_decrease_sat(); + } else { + rgblight_step_reverse(); + } + } +} +#endif + +bool encoder_update_user(uint8_t index, bool clockwise) { + if (layer_state_is(1)) { + // change RGB settings + #ifdef RGBLIGHT_ENABLE + change_RGB(clockwise); + #endif + } else { + if (index == 0) { + // Left encoder: Volume control + if (clockwise) { + tap_code(KC_VOLU); + } else { + tap_code(KC_VOLD); + } + } else if (index == 1) { + // Right encoder: skip forward/back + if (clockwise) { + tap_code(KC_MNXT); + } else { + tap_code(KC_MPRV); + } + } + } + return true; +} diff --git a/keyboards/nullbitsco/snap/keymaps/oled/config.h b/keyboards/nullbitsco/snap/keymaps/oled/config.h new file mode 100644 index 00000000000..d2000ce5898 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/oled/config.h @@ -0,0 +1,27 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ + +#pragma once + +/* space savers */ +#define DYNAMIC_KEYMAP_LAYER_COUNT 3 +#define NO_ACTION_TAPPING +#define NO_ACTION_ONESHOT +#define TAPPING_FORCE_HOLD + +#define OLED_BRIGHTNESS 128 +#define OLED_TIMEOUT 30000 +#define OLED_UPDATE_INTERVAL 250 diff --git a/keyboards/nullbitsco/snap/keymaps/oled/keymap.c b/keyboards/nullbitsco/snap/keymaps/oled/keymap.c new file mode 100644 index 00000000000..4e566fa3ee1 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/oled/keymap.c @@ -0,0 +1,163 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#include QMK_KEYBOARD_H +#include "oled_graphics.h" + +// clang-format off +enum layers { + _BASE, + _VIA1, + _VIA2 +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_all( + KC_ESC, 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_PSCR, KC_PAUS, + KC_F13, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_HOME, + KC_F14, 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_BSLS, KC_END, + KC_F15, KC_CAPS, 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_PGUP, + KC_F16, KC_LSFT, KC_NUHS, 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_PGDN, + KC_F17, KC_LCTL, KC_LGUI, KC_LALT, MO(_VIA1), KC_SPC, KC_SPC, MO(_VIA1), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [_VIA1] = LAYOUT_all( + QK_BOOT,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ), + [_VIA2] = LAYOUT_all( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ) +}; +// clang-format on + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MPRV, KC_MNXT) }, + [_VIA1] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, + [_VIA2] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) } +}; +#endif + + +// Decompress and write a precompressed bitmap frame to the OLED. +// Documentation and python compression script available at: +// https://github.com/nullbitsco/squeez-o +#ifdef USE_OLED_BITMAP_COMPRESSION +static void oled_write_compressed_P(const char* input_block_map, const char* input_block_list) { + uint16_t block_index = 0; + for (uint16_t i = 0; i < NUM_OLED_BYTES; i++) { + uint8_t bit = i % 8; + uint8_t map_index = i / 8; + uint8_t _block_map = (uint8_t)pgm_read_byte_near(input_block_map + map_index); + uint8_t nonzero_byte = (_block_map & (1 << bit)); + if (nonzero_byte) { + const char data = (const char)pgm_read_byte_near(input_block_list + block_index++); + oled_write_raw_byte(data, i); + } else { + const char data = (const char)0x00; + oled_write_raw_byte(data, i); + } + } +} +#endif + +oled_rotation_t oled_init_user(oled_rotation_t rotation) { + if (is_keyboard_left()) + return OLED_ROTATION_0; + else + return OLED_ROTATION_180; +} + +static void render_nullbits_logo(void) { +#ifdef USE_OLED_BITMAP_COMPRESSION + oled_write_compressed_P(nullbits_logo_block_map, nullbits_logo_bmp); +#else + oled_write_raw_P(nullbits_logo, sizeof(nullbits_logo)); +#endif +} + +static void render_status(void) { + oled_set_cursor(0, 0); + oled_write_P(PSTR("SNAP75 "), false); + oled_write_P(PSTR("Layer "), false); + switch (get_highest_layer(layer_state)) { + case _VIA1: + oled_write_P(PSTR("FN1 "), false); + break; + case _VIA2: + oled_write_P(PSTR("FN2 "), false); + break; + default: // use BASE case as default + oled_write_P(PSTR("Base"), false); + } + + // Host Keyboard LED Status + oled_set_cursor(0, 1); + static uint8_t persistent_led_state = 0; + uint8_t led_usb_state = host_keyboard_leds(); + + // Only update if the LED state has changed + // Otherwise, the OLED will not turn off if an LED is on. + if (persistent_led_state != led_usb_state) { + persistent_led_state = led_usb_state; + + oled_write_ln_P(PSTR(""), false); + + if (IS_LED_ON(led_usb_state, USB_LED_CAPS_LOCK)) { + oled_set_cursor(0, 1); + oled_write_P(PSTR("CAPS"), false); + } + + if (IS_LED_ON(led_usb_state, USB_LED_NUM_LOCK)) { + oled_set_cursor(5, 1); + oled_write_P(PSTR("NUM"), true); + } + + if (IS_LED_ON(led_usb_state, USB_LED_SCROLL_LOCK)) { + oled_set_cursor(9, 1); + oled_write_P(PSTR("SCR"), false); + } + } + + // WPM and max WPM + oled_set_cursor(0, 2); + oled_write_P(PSTR("WPM "), false); + uint8_t current_wpm = get_current_wpm(); + oled_write(get_u8_str(current_wpm, '0'), true); + + oled_set_cursor(8, 2); + oled_write_P(PSTR("MAX "), false); + static uint8_t max_wpm; + max_wpm = MAX(max_wpm, current_wpm); + oled_write(get_u8_str(max_wpm, '0'), true); +} + +bool oled_task_user(void) { + if (is_keyboard_master()) { + render_status(); + } else { + render_nullbits_logo(); + } + return true; +} diff --git a/keyboards/nullbitsco/snap/keymaps/oled/oled_graphics.h b/keyboards/nullbitsco/snap/keymaps/oled/oled_graphics.h new file mode 100644 index 00000000000..487bb5974ea --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/oled/oled_graphics.h @@ -0,0 +1,82 @@ +/* Copyright 2022 Jay Greco + * + * 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 . + */ + +#pragma once + +#define NUM_OLED_BYTES 512 +#define USE_OLED_BITMAP_COMPRESSION + +#ifdef USE_OLED_BITMAP_COMPRESSION +static const char PROGMEM nullbits_logo_block_map[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7c, 0x78, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xf7, 0x0f, 0x1e, 0x3c, 0x3c, 0x7c, 0xf8, 0x3f, 0xf0, 0xf9, 0x3f, 0xff, 0x0f, 0x00, + 0x00, 0x80, 0xf7, 0x1f, 0x1e, 0x3c, 0x3c, 0x7c, 0xf8, 0xff, 0xe1, 0xf9, 0xbf, 0xff, 0x0f, 0x00, + 0x00, 0x80, 0x07, 0x1e, 0xfe, 0x3f, 0x3c, 0x7c, 0xf8, 0xff, 0xe1, 0xc1, 0x83, 0xff, 0x0f, 0x00 +}; + +static const char PROGMEM nullbits_logo_bmp[] = { + 0xf6, 0xff, 0xff, 0xfe, 0xe4, 0xfe, 0xff, 0xfe, 0xf4, 0xfe, 0xff, 0xfe, 0xfe, 0xc0, 0xe0, 0xe0, + 0xe0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0xe0, + 0xe0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xc0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0x80, 0x01, 0xc3, 0xe3, 0xe3, 0xc3, 0xc0, + 0xe0, 0xe0, 0xfe, 0xfe, 0xff, 0xfe, 0xe0, 0xe0, 0xe0, 0xc0, 0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, + 0xe0, 0xe0, 0xc0, 0xe0, 0xe0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0x03, 0x03, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x03, 0x03, 0x07, 0x0f, 0xff, 0xff, + 0xfe, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x01, + 0x01, 0x1e, 0x3f, 0x7f, 0xff, 0xfb, 0xf3, 0xf1, 0xe1, 0xe1, 0xe1, 0xc1, 0x81, 0x01, 0x7f, 0xff, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x0f, 0x3f, 0x7f, 0xff, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, + 0x7f, 0x3f, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0x7f, + 0xf0, 0xf0, 0xf0, 0xf8, 0x78, 0x7e, 0x3f, 0x3f, 0x1f, 0x07, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, + 0xff, 0xff, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xfb, 0x7f, 0x7f, 0x3f, 0x1f +}; + +#else +static const char PROGMEM nullbits_logo[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf6, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xfe, 0xff, 0xfe, 0xf4, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0xe0, 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, 0xc0, + 0xe0, 0xe0, 0xe0, 0x00, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xc3, 0xe3, 0xe3, 0xc3, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0xfe, 0xfe, + 0xff, 0xfe, 0xe0, 0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xc0, 0xe0, 0xe0, 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, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01, 0x03, 0x03, 0x07, 0x0f, 0xff, 0xff, 0xfe, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x01, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x01, 0x01, 0x01, 0x00, 0x1e, 0x3f, 0x7f, 0xff, 0xfb, 0xf3, 0xf1, 0xe1, 0xe1, + 0xe1, 0xc1, 0x81, 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, 0x7f, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x3f, 0x7f, 0xff, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0x7f, 0x3f, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x7f, 0xf0, 0xf0, 0xf0, 0xf8, 0x78, 0x7e, 0x3f, 0x3f, 0x1f, + 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xfb, + 0x7f, 0x7f, 0x3f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif diff --git a/keyboards/nullbitsco/snap/keymaps/oled/rules.mk b/keyboards/nullbitsco/snap/keymaps/oled/rules.mk new file mode 100644 index 00000000000..d0a184e961f --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/oled/rules.mk @@ -0,0 +1,5 @@ +OLED_ENABLE = yes +OLED_DRIVER = SSD1306 +WPM_ENABLE = yes +VIA_ENABLE = yes +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/config.h b/keyboards/nullbitsco/snap/keymaps/typehud/config.h new file mode 100644 index 00000000000..62c11709a23 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/config.h @@ -0,0 +1,46 @@ +/* Copyright 2022 Chris Tanaka + * + * 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 . + */ + +#pragma once + +/* space savers */ +#define DYNAMIC_KEYMAP_LAYER_COUNT 3 +#define NO_ACTION_TAPPING +#define NO_ACTION_ONESHOT +#define TAPPING_FORCE_HOLD + +// Old configuration +#define OLED_BRIGHTNESS 128 +#define OLED_TIMEOUT 30000 +#define OLED_UPDATE_INTERVAL 200 + +// Selectively undefine to save space +// VIA support won't fit otherwise +#ifdef RGBLIGHT_ENABLE +#undef RGBLIGHT_EFFECT_TWINKLE +#endif //RGB LIGHT_ENABLE + +// Split configuration +#define SPLIT_TRANSPORT_MIRROR +#define SPLIT_WPM_ENABLE + +// Typehud configuration +#define TYPEHUD_FILLGRAPH +#define TYPEHUD_MATRIX_COLS 16 +// #define TYPEHUD_MASTER +// #define TYPEHUD_MATRIX_ROTATE_90 +// #define TYPEHUD_MATRIX_ROTATE_180 +// #define TYPEHUD_MATRIX_ROTATE_270 diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/keymap.c b/keyboards/nullbitsco/snap/keymaps/typehud/keymap.c new file mode 100644 index 00000000000..ea3fc2e8ebf --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/keymap.c @@ -0,0 +1,157 @@ +/* Copyright 2022 Chris Tanaka + * + * 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 . + */ + +#include QMK_KEYBOARD_H +#include "typehud.h" + +// clang-format off +enum layers { + _BASE, + _VIA1, + _VIA2 +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_all( + KC_ESC, 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_PSCR, KC_PAUS, + KC_F13, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_HOME, + KC_F14, 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_BSLS, KC_END, + KC_F15, KC_CAPS, 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_PGUP, + KC_F16, KC_LSFT, KC_NUHS, 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_PGDN, + KC_F17, KC_LCTL, KC_LGUI, KC_LALT, MO(_VIA1), KC_SPC, KC_SPC, MO(_VIA1), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [_VIA1] = LAYOUT_all( + QK_BOOT,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ), + [_VIA2] = LAYOUT_all( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ) +}; +// clang-format on + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MPRV, KC_MNXT) }, + [_VIA1] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, + [_VIA2] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) } +}; +#endif + +oled_rotation_t oled_init_user(oled_rotation_t rotation) { + oled_clear(); + +#ifdef TYPEHUD_MASTER + if (is_keyboard_master()) { +#else + if (!is_keyboard_master()) { +#endif + typehud_init(); + } + + if (is_keyboard_left()) + return OLED_ROTATION_0; + else + return OLED_ROTATION_180; +} + +static void render_status(void) { + oled_set_cursor(0, 0); + oled_write_P(PSTR("SNAP75 "), false); + oled_write_P(PSTR("Layer "), false); + switch (get_highest_layer(layer_state)) { + case _VIA1: + oled_write_P(PSTR("FN1 "), false); + break; + case _VIA2: + oled_write_P(PSTR("FN2 "), false); + break; + default: // use BASE case as default + oled_write_P(PSTR("Base"), false); + } + + // Host Keyboard LED Status + oled_set_cursor(0, 1); + static uint8_t persistent_led_state = 0; + uint8_t led_usb_state = host_keyboard_leds(); + + // Only update if the LED state has changed + // Otherwise, the OLED will not turn off if an LED is on. + if (persistent_led_state != led_usb_state) { + persistent_led_state = led_usb_state; + + oled_write_ln_P(PSTR(" "), false); + + if (IS_LED_ON(led_usb_state, USB_LED_CAPS_LOCK)) { + oled_set_cursor(0, 1); + oled_write_P(PSTR("CAPS"), false); + } + + if (IS_LED_ON(led_usb_state, USB_LED_NUM_LOCK)) { + oled_set_cursor(5, 1); + oled_write_P(PSTR("NUM"), true); + } + + if (IS_LED_ON(led_usb_state, USB_LED_SCROLL_LOCK)) { + oled_set_cursor(9, 1); + oled_write_P(PSTR("SCR"), false); + } + } + + // WPM and max WPM + oled_set_cursor(0, 2); + oled_write_P(PSTR("WPM "), false); + uint8_t current_wpm = get_current_wpm(); + oled_write(get_u8_str(current_wpm, '0'), true); + + oled_set_cursor(8, 2); + oled_write_P(PSTR("MAX "), false); + static uint8_t max_wpm; + max_wpm = MAX(max_wpm, current_wpm); + oled_write(get_u8_str(max_wpm, '0'), true); +} + +bool oled_task_user(void) { +#ifdef TYPEHUD_MASTER + if (is_keyboard_master()) { +#else + if (!is_keyboard_master()) { +#endif + typehud_render(); + } else { + render_status(); + } + + return true; +} + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + typehud_process_record(record); + return true; +} + +bool should_process_keypress(void) { + return true; +} diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/readme.md b/keyboards/nullbitsco/snap/keymaps/typehud/readme.md new file mode 100644 index 00000000000..d5f50f310c8 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/readme.md @@ -0,0 +1,51 @@ +# Typehud Keymap + +VIA compatible keymap that displays a live wpm HUD on your OLED. + + + +## Configuration + +Configuration options (other than the keymap itself) can be found in `typehud/config.h`. + +### Graph Type + +By default the graph is filled. For a non-filled graph remove or comment out the following line: + +```c +#define TYPEHUD_FILLGRAPH +``` + +### Keyboard Matrix Orientation + +To change the keyboard matrix orientation add one of the following: + +- `TYPEHUD_MATRIX_ROTATE_90` +- `TYPEHUD_MATRIX_ROTATE_180` +- `TYPEHUD_MATRIX_ROTATE_270` + +### Keyboard Matrix Key Overrides + +If the number of physical keys doesn't match the keyboard matrix rows/columns you can override it: + +```c +#define TYPEHUD_MATRIX_ROWS 6 +#define TYPEHUD_MATRIX_COLS 16 +``` + +In addition if the position of the physical keys doesn't match the matrix you can override it. Negative numbers will shift the keys left/up and positive numbers will shift the keys right/down: + +```c +#define TYPEHUD_MATRIX_ROW_SHIFT -1 +#define TYPEHUD_MATRIX_COL_SHIFT -2 +``` + +### Split Keyboard Side + +For split keyboards, the keymap assumes it will be rendered to the slave side. + +To render to master instead, add the following configuration line: + +```c +#define TYPEHUD_MASTER +``` diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/rules.mk b/keyboards/nullbitsco/snap/keymaps/typehud/rules.mk new file mode 100644 index 00000000000..151e44f4aac --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/rules.mk @@ -0,0 +1,7 @@ +OLED_ENABLE = yes +OLED_DRIVER = SSD1306 +WPM_ENABLE = yes +VIA_ENABLE = yes +ENCODER_MAP_ENABLE = yes + +SRC += typehud.c diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/typehud.c b/keyboards/nullbitsco/snap/keymaps/typehud/typehud.c new file mode 100644 index 00000000000..ad884f843b8 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/typehud.c @@ -0,0 +1,349 @@ +/* Copyright 2023 Jay Greco + * + * 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 . + */ + +#include "typehud.h" + +static bool is_initialized; +static uint16_t timer; +static int8_t bar_height; +static uint8_t wpm_arr[_GRAPH_WIDTH]; +static uint8_t point_arr[_GRAPH_WIDTH]; + + +static void + render_graph(uint8_t wpm), + render_caret(void), + render_axis(void), + render_bar(void), + render_init(void); + +/* + * Renders the wpm counter. + */ +static void render_wpm(uint8_t wpm) { + oled_set_cursor(0, 0); + oled_write("WPM", false); + oled_set_cursor(0, 1); + oled_write(get_u8_str(wpm, '0'), false); +} + +/* + * Renders the keyboard matrix. + */ +static void render_matrix(keyrecord_t *record) { + uint8_t x = _MATRIX_X; + uint8_t y = _MATRIX_Y; + uint8_t width = _MATRIX_WIDTH; + uint8_t height = _MATRIX_HEIGHT; +#ifdef SPLIT_KEYBOARD + uint8_t rows = _NML_MATRIX_ROWS; + uint8_t cols = _NML_MATRIX_COLS; +#endif + + // On initial render draw the matrix outline + if (!is_initialized) { + for (uint8_t i = 1; i <= width - 2; i++) { + oled_write_pixel(x + i, y, true); + oled_write_pixel(x + i, y + height - 1, true); + } + for (uint8_t j = 1; j <= height - 2; j++) { + oled_write_pixel(x, y + j, true); + oled_write_pixel(x + width - 1, y + j, true); + } + return; + } + + // Determine position based on matrix rotation + // For split keyboards the keys on the right half get appended as additional rows and + // have their columns reset at 0 +#ifdef SPLIT_KEYBOARD + uint8_t row = (record->event.key.row % rows); + uint8_t col = record->event.key.col; + if (record->event.key.row >= rows) { + col += (cols / 2); + } +#else + uint8_t row = record->event.key.row; + uint8_t col = record->event.key.col; +#endif + +#ifdef TYPEHUD_MATRIX_ROW_SHIFT + row += TYPEHUD_MATRIX_ROW_SHIFT; +#endif +#ifdef TYPEHUD_MATRIX_COL_SHIFT + col += TYPEHUD_MATRIX_COL_SHIFT; +#endif + + // Scale position to key size + uint8_t size = _MATRIX_SIZE; + row *= size; + col *= size; + + // Render key in matrix + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { +#if defined(TYPEHUD_MATRIX_ROTATE_90) + uint8_t key_x = x + width - 1 - size - row; + uint8_t key_y = y + 1 + col; +#elif defined(TYPEHUD_MATRIX_ROTATE_180) + uint8_t key_x = x + width - 1 - size - col; + uint8_t key_y = y + height - 1 - size - row; +#elif defined(TYPEHUD_MATRIX_ROTATE_270) + uint8_t key_x = x + 1 + row; + uint8_t key_y = y + height - 1 - size - col; +#else + uint8_t key_x = x + 1 + col; + uint8_t key_y = y + 1 + row; +#endif + oled_write_pixel(key_x + i, key_y + j, record->event.pressed); + } + } +} + +/* + * Renders the graph. + */ +static void render_graph(uint8_t wpm) { + uint8_t x = _GRAPH_X; + uint8_t y = _GRAPH_Y + _GRAPH_HEIGHT; + uint8_t width = _GRAPH_WIDTH; + uint8_t height = _GRAPH_HEIGHT; + + // Handle intial graph render + if (!is_initialized) { + for (uint8_t i = 0; i < width; i++) { + oled_write_pixel(x + i, y, true); + } + return; + } + + uint8_t i = 0; + + // Shift all graph points except last to the left and re-render + for (; i < width - 1; i++) { + int8_t point_delta = point_arr[i + 1] - point_arr[i]; + +#ifdef TYPEHUD_FILLGRAPH + if (point_delta < 0) { +#else + if (point_delta != 0) { +#endif + oled_write_pixel(x + i, y - point_arr[i], false); + } + + wpm_arr[i] = wpm_arr[i + 1]; + point_arr[i] = point_arr[i + 1]; + + if (point_delta != 0) { + oled_write_pixel(x + i, y - point_arr[i], true); + } + } + + // Clear last graph point + if (wpm > wpm_arr[i] && point_arr[i] + 1 <= height) { +#ifndef TYPEHUD_FILLGRAPH + oled_write_pixel(x + i, y - point_arr[i], false); +#endif + point_arr[i] = point_arr[i] + 1; + } else if ((wpm < wpm_arr[i] && point_arr[i] - 1 >= 0) || (wpm <= 0 && point_arr[i] > 0)) { + oled_write_pixel(x + i, y - point_arr[i], false); + point_arr[i] = point_arr[i] - 1; + } + + // Render last graph point + wpm_arr[i] = wpm; + + if (point_arr[i] != point_arr[i - 1]) { + oled_write_pixel(x + i, y - point_arr[i], true); + } +} + +/* + * Renders the caret. + */ +static void render_caret(void) { + uint8_t x = _GRAPH_X + _GRAPH_WIDTH + _GRAPH_RPAD + _CARET_WIDTH; + uint8_t y = 0; + uint8_t width = _CARET_WIDTH; + uint8_t height = _CARET_HEIGHT; + uint8_t g_width = _GRAPH_WIDTH; + uint8_t g_height = _GRAPH_HEIGHT; + + // Handle initial caret render + if (!is_initialized) { + y = g_height - point_arr[g_width - 1]; + + for (uint8_t i = 0; i < width; i++) { + for (uint8_t j = i; j < height - i; j++) { + oled_write_pixel(x - i, y - j, true); + } + } + return; + } + + // Handle caret updates and re-render + int8_t point_delta = point_arr[g_width - 1] - point_arr[g_width - 2]; + if (point_delta > 0) { + y = g_height - point_arr[g_width - 2]; + if (y - height + 1 > 0) { + for (uint8_t i = 0; i < width; i++) { + oled_write_pixel(x - i, y - i, false); + oled_write_pixel(x - i, y - height + i, true); + } + } + } else if (point_delta < 0) { + y = g_height - point_arr[g_width - 1]; + if (y - height + 1 > 0) { + for (uint8_t i = 0; i < width; i++) { + oled_write_pixel(x - i, y - height + i, false); + oled_write_pixel(x - i, y - i, true); + } + } + } +} + +/* + * Renders the axis. + */ +static void render_axis(void) { + uint8_t x = _AXIS_X; + uint8_t y = _AXIS_HEIGHT; + uint8_t width = _AXIS_WIDTH; + uint8_t height = _AXIS_HEIGHT; + uint8_t tick_width = _AXIS_TICK_WIDTH; + uint8_t subtick_width = _AXIS_SUBTICK_WIDTH; + uint8_t interval = _AXIS_INTERVAL; + uint8_t tick_interval = _AXIS_TICK_INTERVAL; + + for (uint8_t j = 0; j <= height; j += interval) { + uint8_t curr_tick_width = 0; + + // Determine tick width and draw extra point if at interval + if (j % tick_interval == 0) { + curr_tick_width = tick_width; + oled_write_pixel(x, y - j, true); + } else { + curr_tick_width = subtick_width; + } + + // Draw tick + for (uint8_t i = 0; i < curr_tick_width; i++) { + oled_write_pixel(x + width - i, y - j, true); + } + } +} + +/* + * Renders the input bar. + */ +static void render_bar(void) { + uint8_t x = _BAR_X; + uint8_t width = _BAR_WIDTH; + uint8_t height = _BAR_HEIGHT; + + // Increment bar height + bar_height = (bar_height + 1) % height; + + // When bar resets back to 0, clear bar pixels + if (bar_height % height == 0) { + for (uint8_t i = 0; i < width; i++) { + for (uint8_t j = 0; j < height; j++) { + oled_write_pixel(x + i, j, false); + } + } + } + + // Draw new bar pixels + for (uint8_t i = 0; i < width; i++) { + oled_write_pixel(x + i, height - bar_height, true); + } +} + +/* + * Renders the initial frame for all components. + */ +static void render_init(void) { + render_graph(0); + render_caret(); + render_matrix(NULL); + render_axis(); +} + +/* + * Initializes and resets the typehud. + */ +void typehud_init(void) { + // Reset variables + is_initialized = false; + timer = 0; + bar_height = -1; + + for (uint8_t i = 0; i < _GRAPH_WIDTH; i++) { + wpm_arr[i] = 0; + point_arr[i] = 0; + } + + // Draw the initial graph + for (uint8_t i = 0; i < _GRAPH_WIDTH; i++) { + oled_write_pixel(_GRAPH_X + i, _GRAPH_HEIGHT, true); + } +} + +/* + * Renders the typehud. + */ +void typehud_render(void) { + uint8_t wpm = get_current_wpm(); + + // Run initial rendering once + if (!is_initialized) { + render_init(); + is_initialized = true; + } + + // Render wpm + render_wpm(wpm); + + // Render next graph and caret frame when timer reaches refresh rate + if (timer_elapsed(timer) > _GRAPH_REFRESH) { + render_graph(wpm); + render_caret(); + timer = timer_read(); + } +} + +/* + * Handles keypresses for the typehud. + */ +void typehud_process_record(keyrecord_t *record) { + // For split keyboards, only draw on correct side +#ifdef SPLIT_KEYBOARD +# ifdef TYPEHUD_MASTER + if (!is_keyboard_master()) { +# else + if (is_keyboard_master()) { +# endif + return; + } +#endif + // Render/update matrix + render_matrix(record); + + // Render/update input bar on keypress + if (record->event.pressed) { + render_bar(); + } +} diff --git a/keyboards/nullbitsco/snap/keymaps/typehud/typehud.h b/keyboards/nullbitsco/snap/keymaps/typehud/typehud.h new file mode 100644 index 00000000000..c3ed876c422 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/typehud/typehud.h @@ -0,0 +1,87 @@ +/* Copyright 2022 Chris Tanaka + * + * 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 . + */ + +#include QMK_KEYBOARD_H + +// clang-format off +#define _OLED_WIDTH (OLED_DISPLAY_WIDTH - 1) +#define _OLED_HEIGHT (OLED_DISPLAY_HEIGHT - 1) + +#ifdef SPLIT_KEYBOARD +#define _PHYSICAL_PARTS 2 +#else +#define _PHYSICAL_PARTS 1 +#endif + +#ifdef TYPEHUD_MATRIX_ROWS +#define _NML_MATRIX_ROWS TYPEHUD_MATRIX_ROWS +#else +# ifdef SPLIT_KEYBOARD +#define _NML_MATRIX_ROWS (MATRIX_ROWS / 2) +# else +#define _NML_MATRIX_ROWS MATRIX_ROWS +# endif +#endif + +#ifdef TYPEHUD_MATRIX_COLS +#define _NML_MATRIX_COLS TYPEHUD_MATRIX_COLS +#else +#define _NML_MATRIX_COLS (MATRIX_COLS * _PHYSICAL_PARTS) +#endif + +#define _MATRIX_SIZE 2 +#if defined(TYPEHUD_MATRIX_ROTATE_90) || defined(TYPEHUD_MATRIX_ROTATE_270) +#define _MATRIX_WIDTH (_NML_MATRIX_ROWS * _MATRIX_SIZE + 2) +#define _MATRIX_HEIGHT (_NML_MATRIX_COLS * _MATRIX_SIZE + 2) +#else +#define _MATRIX_WIDTH (_NML_MATRIX_COLS * _MATRIX_SIZE + 2) +#define _MATRIX_HEIGHT (_NML_MATRIX_ROWS * _MATRIX_SIZE + 2) +#endif +#define _MATRIX_X 0 +#define _MATRIX_Y (_OLED_HEIGHT - _MATRIX_HEIGHT + 1) +#define _MATRIX_RPAD 2 +#define _MATRIX_PAD_WIDTH (_MATRIX_WIDTH + _MATRIX_RPAD) + +#define _BAR_WIDTH 3 +#define _BAR_HEIGHT _OLED_HEIGHT +#define _BAR_X (_OLED_WIDTH - _BAR_WIDTH) + +#define _AXIS_WIDTH 5 +#define _AXIS_HEIGHT _OLED_HEIGHT +#define _AXIS_TICK_WIDTH 3 +#define _AXIS_SUBTICK_WIDTH 2 +#define _AXIS_INTERVAL 3 +#define _AXIS_TICK_INTERVAL 15 +#define _AXIS_RPAD 2 +#define _AXIS_PAD_WIDTH (_AXIS_WIDTH + _AXIS_RPAD) +#define _AXIS_X (_OLED_WIDTH - _BAR_WIDTH - _AXIS_PAD_WIDTH) + +#define _CARET_WIDTH 3 +#define _CARET_HEIGHT 5 + +#define _GRAPH_RPAD 2 +#define _GRAPH_MAX_WIDTH (_OLED_WIDTH - _BAR_WIDTH - _AXIS_PAD_WIDTH - _CARET_WIDTH - _GRAPH_RPAD - _MATRIX_PAD_WIDTH) +#define _GRAPH_WIDTH (_GRAPH_MAX_WIDTH - 4) +#define _GRAPH_HEIGHT 31 +#define _GRAPH_REFRESH 300 +#define _GRAPH_X (_MATRIX_WIDTH + _MATRIX_RPAD) +#define _GRAPH_Y 0 +// clang-format on + +void + typehud_init(void), + typehud_render(void), + typehud_process_record(keyrecord_t *record); diff --git a/keyboards/nullbitsco/snap/keymaps/via/config.h b/keyboards/nullbitsco/snap/keymaps/via/config.h new file mode 100644 index 00000000000..578a939d545 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/via/config.h @@ -0,0 +1,20 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +// clang-format off +#pragma once + +/* space savers */ +#define DYNAMIC_KEYMAP_LAYER_COUNT 3 diff --git a/keyboards/nullbitsco/snap/keymaps/via/keymap.c b/keyboards/nullbitsco/snap/keymaps/via/keymap.c new file mode 100644 index 00000000000..291c4c6f165 --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/via/keymap.c @@ -0,0 +1,59 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#include QMK_KEYBOARD_H + +// clang-format off +enum layers { + _BASE, + _VIA1, + _VIA2 +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_all( + KC_ESC, 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_PSCR, KC_PAUS, + KC_F13, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_HOME, + KC_F14, 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_BSLS, KC_END, + KC_F15, KC_CAPS, 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_PGUP, + KC_F16, KC_LSFT, KC_NUHS, 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_PGDN, + KC_F17, KC_LCTL, KC_LGUI, KC_LALT, MO(_VIA1), KC_SPC, KC_SPC, MO(_VIA1), KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [_VIA1] = LAYOUT_all( + QK_BOOT,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ), + [_VIA2] = LAYOUT_all( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO + ) +}; +// clang-format on + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MPRV, KC_MNXT) }, + [_VIA1] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) }, + [_VIA2] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) } +}; +#endif diff --git a/keyboards/nullbitsco/snap/keymaps/via/rules.mk b/keyboards/nullbitsco/snap/keymaps/via/rules.mk new file mode 100644 index 00000000000..f1adcab005e --- /dev/null +++ b/keyboards/nullbitsco/snap/keymaps/via/rules.mk @@ -0,0 +1,2 @@ +VIA_ENABLE = yes +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/nullbitsco/snap/matrix.c b/keyboards/nullbitsco/snap/matrix.c new file mode 100644 index 00000000000..ceb9cd89841 --- /dev/null +++ b/keyboards/nullbitsco/snap/matrix.c @@ -0,0 +1,126 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#include +#include +#include +#include "util.h" +#include "matrix.h" +#include "split_util.h" +#include "quantum.h" + +#define VIRT_COLS_PER_HAND 1 +#define PHYS_COLS_PER_HAND (MATRIX_COLS - VIRT_COLS_PER_HAND) +#define ROWS_PER_HAND (MATRIX_ROWS / 2) +#define COL_SHIFTER ((uint32_t)1) +#define EXT_PIN_ROW 2 +#define EXT_PIN_COL 8 + +// Row & column pins +static uint8_t row_pins_left[MATRIX_ROWS] = MATRIX_ROW_PINS; +static uint8_t col_pins_left[MATRIX_MUX_COLS] = MATRIX_COL_MUX_PINS; +static uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT; +static uint8_t col_pins_right[MATRIX_MUX_COLS] = MATRIX_COL_MUX_PINS_RIGHT; +static uint8_t* row_pins = row_pins_left; +static uint8_t* col_pins = col_pins_left; + +// Internal functions +static void init_pins(void) { + // Set cols to outputs, low + for (uint8_t pin = 0; pin < MATRIX_MUX_COLS; pin++) { + setPinOutput(col_pins[pin]); + } + + // Unselect cols + for (uint8_t bit = 0; bit < MATRIX_MUX_COLS; bit++) { + writePinLow(col_pins[bit]); + } + + // Set rows to input, pullup + for (uint8_t pin = 0; pin < ROWS_PER_HAND; pin++) { + setPinInputHigh(row_pins[pin]); + } + + // Set extended pin (only on right side) + if (!isLeftHand) { + // Set extended pin to input, pullup + setPinInputHigh(MATRIX_EXT_PIN_RIGHT); + } +} + +static void select_col(uint8_t col) { + // Drive demux with correct column address + for (uint8_t bit = 0; bit < MATRIX_MUX_COLS; bit++) { + uint8_t state = (col & (0b1 << bit)) >> bit; + writePin(col_pins[bit], !state); + } +} + +static void read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { + select_col(current_col % PHYS_COLS_PER_HAND); + wait_us(5); + + // Read each row sequentially + for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { + if (readPin(row_pins[row_index]) == 0) { + current_matrix[row_index] |= (COL_SHIFTER << current_col); + } else { + current_matrix[row_index] &= ~(COL_SHIFTER << current_col); + } + } +} + +static void read_ext_pin(matrix_row_t current_matrix[]) { + // Read the state of the extended matrix pin + if (!isLeftHand) { + if (readPin(MATRIX_EXT_PIN_RIGHT) == 0) { + current_matrix[EXT_PIN_ROW] |= (COL_SHIFTER << EXT_PIN_COL); + } else { + current_matrix[EXT_PIN_ROW] &= ~(COL_SHIFTER << EXT_PIN_COL); + } + } +} + +void matrix_init_custom(void) { + if (!isLeftHand) { + row_pins = row_pins_right; + col_pins = col_pins_right; + } + + init_pins(); +} + +bool matrix_scan_custom(matrix_row_t current_matrix[]) { + matrix_row_t last_matrix[MATRIX_ROWS]; + memcpy(last_matrix, current_matrix, sizeof(last_matrix)); + + #ifdef DEBUG_SLOW_MATRIX + // Slow for debugging + wait_ms(1000); + #endif + + // Set col, read rows + for (uint8_t current_col = 0; current_col < PHYS_COLS_PER_HAND; current_col++) { + read_rows_on_col(current_matrix, current_col); + } + + // Read extended pin and store in matrix + read_ext_pin(current_matrix); + + // Check if the matrix changed + bool changed = memcmp(last_matrix, current_matrix, sizeof(last_matrix)) != 0; + + return changed; +} diff --git a/keyboards/nullbitsco/snap/readme.md b/keyboards/nullbitsco/snap/readme.md new file mode 100644 index 00000000000..e1b95faec6f --- /dev/null +++ b/keyboards/nullbitsco/snap/readme.md @@ -0,0 +1,26 @@ +# SNAP + +![SNAP](https://nullbits.co/static/img/snap10.jpg) + +A unique, tweakable split 75% keyboard kit built by nullbits. [More info at nullbits.co](https://nullbits.co/snap/) + +* Keyboard Maintainer: [Jay Greco](https://github.com/jaygreco) +* Hardware Supported: SNAP Rev1, Pro Micro comaptible MCUs. +* Hardware Availability: [nullbits.co](https://nullbits.co/) + +Note: If you are seeing issues with MacOS and keyboard hangs after sleep, make sure `NO_USB_STARTUP_CHECK = yes` is set in your rules.mk. + +Adds experimental "Remote Keyboard" functionality, which forwards keystrokes from an external macropad, keyboard, or numpad over UART/TRRS, removing the need for an additional USB connection. + +Make example for this keyboard (after setting up your build environment): + + make nullbitsco/snap:default + +## Bootloader + +Enter the bootloader in 2 ways: + +* **Physical reset button**: Briefly press the reset button located near the MCU on the the PCB +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). diff --git a/keyboards/nullbitsco/snap/rules.mk b/keyboards/nullbitsco/snap/rules.mk new file mode 100644 index 00000000000..79ba7d6eb6f --- /dev/null +++ b/keyboards/nullbitsco/snap/rules.mk @@ -0,0 +1,23 @@ +# Build Options +# change yes to no to disable +# +BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite +MOUSEKEY_ENABLE = no # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +CONSOLE_ENABLE = no # Console for debug +COMMAND_ENABLE = no # Commands for debug and configuration +NKRO_ENABLE = no # Enable N-Key Rollover +BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality +AUDIO_ENABLE = no # Audio output +SPLIT_KEYBOARD = yes # Split common +LTO_ENABLE = yes # Use Link Time Optimization +ENCODER_ENABLE = yes # Enables the use of one or more encoders +SPACE_CADET_ENABLE = no # Enables the use of Space Cadet +RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow +CUSTOM_MATRIX = lite # Split custom matrix + +# Project specific files +SRC += common/bitc_led.c \ + common/remote_kb.c \ + matrix.c \ + uart.c diff --git a/keyboards/nullbitsco/snap/snap.c b/keyboards/nullbitsco/snap/snap.c new file mode 100644 index 00000000000..1ec6e5cf009 --- /dev/null +++ b/keyboards/nullbitsco/snap/snap.c @@ -0,0 +1,127 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#include QMK_KEYBOARD_H + +// Macro variables +bool is_alt_tab_active = false; +uint16_t alt_tab_timer = 0; +bool muted = false; + +void matrix_init_kb(void) { + set_bitc_LED(LED_OFF); + matrix_init_remote_kb(); + matrix_init_user(); +} + +void keyboard_post_init_kb(void) { + #ifdef CONSOLE_ENABLE + debug_enable = true; + debug_matrix = true; + #endif + keyboard_post_init_user(); +} + +void matrix_scan_kb(void) { + matrix_scan_remote_kb(); + matrix_scan_user(); + + if (is_alt_tab_active) { + if (timer_elapsed(alt_tab_timer) > 1000) { + unregister_code(KC_LALT); + is_alt_tab_active = false; + } + } +} + +// Use Bit-C LED to show CAPS LOCK and NUM LOCK status +void led_update_ports(led_t led_state) { + set_bitc_LED(led_state.caps_lock ? LED_DIM : LED_OFF); +} + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { + // If console is enabled, it will print the matrix position and status of each key pressed + #ifdef CONSOLE_ENABLE + dprintf("kc: 0x%04X, col: %u, row: %u, pressed: %b, time: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed, record->event.time); + #endif + + process_record_remote_kb(keycode, record); + if (!process_record_user(keycode, record)) return false; + + switch (keycode) { + case QK_BOOT: + if (record->event.pressed) { + set_bitc_LED(LED_DIM); + #ifdef RGBLIGHT_ENABLE + rgblight_disable_noeeprom(); + #endif + #ifdef OLED_ENABLE + oled_off(); + #endif + bootloader_jump(); // jump to bootloader + } + return false; + + case DISC_MUTE: + if (record->event.pressed) { + tap_code(KC_F23); + #ifdef RGBLIGHT_ENABLE + if (!rgblight_is_enabled()) break; + + if (muted) { + rgblight_enable_noeeprom(); + } else { + rgblight_timer_disable(); + uint8_t val = rgblight_get_val(); + rgblight_sethsv_range(255, 255, val, 1, 5); + } + #endif + muted = !muted; + } + break; + + case SUPER_ALT_TAB: + if (record->event.pressed) { + if (!is_alt_tab_active) { + is_alt_tab_active = true; + register_code(KC_LALT); + } + alt_tab_timer = timer_read(); + register_code(KC_TAB); + } else { + unregister_code(KC_TAB); + } + break; + + default: + break; + } + + return true; +} + +#ifdef ENCODER_ENABLE +bool encoder_update_kb(uint8_t index, bool clockwise) { + if (!encoder_update_user(index, clockwise)) { return false; } + if (index == 0) { + if (clockwise) { + tap_code_delay(KC_VOLU, 10); + } else { + tap_code_delay(KC_VOLD, 10); + } + } + return true; +} +#endif diff --git a/keyboards/nullbitsco/snap/snap.h b/keyboards/nullbitsco/snap/snap.h new file mode 100644 index 00000000000..00dacc3d8f0 --- /dev/null +++ b/keyboards/nullbitsco/snap/snap.h @@ -0,0 +1,106 @@ +/* Copyright 2021 Jay Greco + * + * 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 . + */ +#pragma once + +#define _____ KC_NO + +#include "quantum.h" +#include "common/remote_kb.h" +#include "common/bitc_led.h" + +#ifdef VIA_ENABLE +enum custom_keycodes { + DISC_MUTE = QK_USER_0, + SUPER_ALT_TAB +}; +#else +enum custom_keycodes { + DISC_MUTE = SAFE_RANGE, + SUPER_ALT_TAB +}; +#endif + +// clang-format off +#define LAYOUT_all( \ + R1C7L, R1C6L, R1C5L, R1C4L, R1C3L, R1C2L, R1C1L, R1C8R, R1C7R, R1C6R, R1C5R, R1C4R, R1C3R, R1C2R, R1C1R, \ +R2C8L, R2C7L, R2C6L, R2C5L, R2C4L, R2C3L, R2C2L, R2C1L, R2C8R, R2C7R, R2C6R, R2C5R, R2C4R, R2C3R, R2C2R, R2C1R, R3CXR, \ +R3C8L, R3C7L, R3C6L, R3C5L, R3C4L, R3C3L, R3C1L, R3C8R, R3C7R, R3C6R, R3C5R, R3C4R, R3C3R, R3C2R, R4C1R, R3C1R, \ +R4C8L, R4C7L, R4C6L, R4C5L, R4C4L, R4C3L, R4C1L, R4C8R, R4C7R, R4C6R, R4C5R, R4C4R, R4C3R, R4C2R, R5C1R, \ +R5C8L, R5C7L, R5C6L, R5C5L, R5C4L, R5C3L, R5C2L, R5C1L, R5C8R, R5C7R, R5C6R, R5C5R, R5C4R, R5C3R, R5C2R, R6C1R, \ +R6C8L, R6C7L, R6C6L, R6C5L, R6C3L, R6C1L, R6C8R, R6C7R, R6C6R, R6C5R, R6C4R, R6C3R, R6C2R \ +) { \ + /* Left */ \ + {_____, R1C7L, R1C6L, R1C5L, R1C4L, R1C3L, R1C2L, R1C1L, _____}, \ + {R2C8L, R2C7L, R2C6L, R2C5L, R2C4L, R2C3L, R2C2L, R2C1L, _____}, \ + {R3C8L, R3C7L, R3C6L, R3C5L, R3C4L, R3C3L, _____, R3C1L, _____}, \ + {R4C8L, R4C7L, R4C6L, R4C5L, R4C4L, R4C3L, _____, R4C1L, _____}, \ + {R5C8L, R5C7L, R5C6L, R5C5L, R5C4L, R5C3L, R5C2L, R5C1L, _____}, \ + {R6C8L, R6C7L, R6C6L, R6C5L, _____, R6C3L, _____, R6C1L, _____}, \ + /* Right */ \ + {R1C8R, R1C7R, R1C6R, R1C5R, R1C4R, R1C3R, R1C2R, R1C1R, _____}, \ + {R2C8R, R2C7R, R2C6R, R2C5R, R2C4R, R2C3R, R2C2R, R2C1R, _____}, \ + {R3C8R, R3C7R, R3C6R, R3C5R, R3C4R, R3C3R, R3C2R, R3C1R, R3CXR}, \ + {R4C8R, R4C7R, R4C6R, R4C5R, R4C4R, R4C3R, R4C2R, R4C1R, _____}, \ + {R5C8R, R5C7R, R5C6R, R5C5R, R5C4R, R5C3R, R5C2R, R5C1R, _____}, \ + {R6C8R, R6C7R, R6C6R, R6C5R, R6C4R, R6C3R, R6C2R, R6C1R, _____} \ +} + +#define LAYOUT_iso( \ + R1C7L, R1C6L, R1C5L, R1C4L, R1C3L, R1C2L, R1C1L, R1C8R, R1C7R, R1C6R, R1C5R, R1C4R, R1C3R, R1C2R, R1C1R, \ +R2C8L, R2C7L, R2C6L, R2C5L, R2C4L, R2C3L, R2C2L, R2C1L, R2C8R, R2C7R, R2C6R, R2C5R, R2C4R, R2C3R, R2C2R, R3CXR, \ +R3C8L, R3C7L, R3C6L, R3C5L, R3C4L, R3C3L, R3C1L, R3C8R, R3C7R, R3C6R, R3C5R, R3C4R, R3C3R, R3C2R, R4C1R, R3C1R, \ +R4C8L, R4C7L, R4C6L, R4C5L, R4C4L, R4C3L, R4C1L, R4C8R, R4C7R, R4C6R, R4C5R, R4C4R, R4C3R, R4C2R, R5C1R, \ +R5C8L, R5C7L, R5C6L, R5C5L, R5C4L, R5C3L, R5C2L, R5C1L, R5C8R, R5C7R, R5C6R, R5C5R, R5C4R, R5C3R, R5C2R, R6C1R, \ +R6C8L, R6C7L, R6C6L, R6C5L, R6C3L, R6C1L, R6C8R, R6C7R, R6C6R, R6C5R, R6C4R, R6C3R, R6C2R \ +) { /* Left */ \ + {_____, R1C7L, R1C6L, R1C5L, R1C4L, R1C3L, R1C2L, R1C1L, _____}, \ + {R2C8L, R2C7L, R2C6L, R2C5L, R2C4L, R2C3L, R2C2L, R2C1L, _____}, \ + {R3C8L, R3C7L, R3C6L, R3C5L, R3C4L, R3C3L, _____, R3C1L, _____}, \ + {R4C8L, R4C7L, R4C6L, R4C5L, R4C4L, R4C3L, _____, R4C1L, _____}, \ + {R5C8L, R5C7L, R5C6L, R5C5L, R5C4L, R5C3L, R5C2L, R5C1L ,_____}, \ + {R6C8L, R6C7L, R6C6L, R6C5L, _____, R6C3L, _____, R6C1L, _____}, \ + /* Right */ \ + {R1C8R, R1C7R, R1C6R, R1C5R, R1C4R, R1C3R, R1C2R, R1C1R, _____}, \ + {R2C8R, R2C7R, R2C6R, R2C5R, R2C4R, R2C3R, R2C2R, _____, _____}, \ + {R3C8R, R3C7R, R3C6R, R3C5R, R3C4R, R3C3R, R3C2R, R3C1R, R3CXR}, \ + {R4C8R, R4C7R, R4C6R, R4C5R, R4C4R, R4C3R, R4C2R, R4C1R, _____}, \ + {R5C8R, R5C7R, R5C6R, R5C5R, R5C4R, R5C3R, R5C2R, R5C1R, _____}, \ + {R6C8R, R6C7R, R6C6R, R6C5R, R6C4R, R6C3R, R6C2R, R6C1R, _____} \ +} + +#define LAYOUT_ansi( \ + R1C7L, R1C6L, R1C5L, R1C4L, R1C3L, R1C2L, R1C1L, R1C8R, R1C7R, R1C6R, R1C5R, R1C4R, R1C3R, R1C2R, R1C1R, \ +R2C8L, R2C7L, R2C6L, R2C5L, R2C4L, R2C3L, R2C2L, R2C1L, R2C8R, R2C7R, R2C6R, R2C5R, R2C4R, R2C3R, R2C2R, R3CXR, \ +R3C8L, R3C7L, R3C6L, R3C5L, R3C4L, R3C3L, R3C1L, R3C8R, R3C7R, R3C6R, R3C5R, R3C4R, R3C3R, R3C2R, R4C1R, R3C1R, \ +R4C8L, R4C7L, R4C6L, R4C5L, R4C4L, R4C3L, R4C1L, R4C8R, R4C7R, R4C6R, R4C5R, R4C4R, R4C3R, R4C2R, R5C1R, \ +R5C8L, R5C7L, R5C5L, R5C4L, R5C3L, R5C2L, R5C1L, R5C8R, R5C7R, R5C6R, R5C5R, R5C4R, R5C3R, R5C2R, R6C1R, \ +R6C8L, R6C7L, R6C6L, R6C5L, R6C3L, R6C1L, R6C8R, R6C7R, R6C6R, R6C5R, R6C4R, R6C3R, R6C2R \ +) { /* Left */ \ + {_____, R1C7L, R1C6L, R1C5L, R1C4L, R1C3L, R1C2L, R1C1L, _____}, \ + {R2C8L, R2C7L, R2C6L, R2C5L, R2C4L, R2C3L, R2C2L, R2C1L, _____}, \ + {R3C8L, R3C7L, R3C6L, R3C5L, R3C4L, R3C3L, _____, R3C1L, _____}, \ + {R4C8L, R4C7L, R4C6L, R4C5L, R4C4L, R4C3L, _____, R4C1L, _____}, \ + {R5C8L, R5C7L, _____, R5C5L, R5C4L, R5C3L, R5C2L, R5C1L, _____}, \ + {R6C8L, R6C7L, R6C6L, R6C5L, _____, R6C3L, _____, R6C1L, _____}, \ + /* Right */ \ + {R1C8R, R1C7R, R1C6R, R1C5R, R1C4R, R1C3R, R1C2R, R1C1R, _____}, \ + {R2C8R, R2C7R, R2C6R, R2C5R, R2C4R, R2C3R, R2C2R, _____, _____}, \ + {R3C8R, R3C7R, R3C6R, R3C5R, R3C4R, R3C3R, R3C2R, R3C1R, R3CXR}, \ + {R4C8R, R4C7R, R4C6R, R4C5R, R4C4R, R4C3R, R4C2R, R4C1R, _____}, \ + {R5C8R, R5C7R, R5C6R, R5C5R, R5C4R, R5C3R, R5C2R, R5C1R, _____}, \ + {R6C8R, R6C7R, R6C6R, R6C5R, R6C4R, R6C3R, R6C2R, R6C1R, _____} \ +} +// clang-format on