snowe keymap/userspace and Ocean Dream animation (#12477)

* Add snowe keymap/userspace & Ocean Dream animation

* Add snowe userspace with keymap wrappers and two animations
* Add crkbd keymap
* Add Ocean Dream animation, a cool full screen animation with:
* * twinkling stars
* * meteor showers
* * ocean waves
* * island with palm tree
* * moon with phases

* Disable Luna so travis build succeeds.

* Add more copyrights

* Add pragma once to keycode_aliases.h

Co-authored-by: Drashna Jaelre <drashna@live.com>

Co-authored-by: Drashna Jaelre <drashna@live.com>
This commit is contained in:
Tyler Thrailkill 2021-06-23 20:21:40 -06:00 committed by GitHub
parent 6e1ed1c9d3
commit 4a15eb593d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 1870 additions and 0 deletions

View file

@ -0,0 +1,55 @@
/*
This is the c configuration file for the keymap
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
//#define USE_MATRIX_I2C
/* Select hand configuration */
#define MASTER_LEFT
// #define MASTER_RIGHT
// #define EE_HANDS
#define USE_SERIAL_PD2
#define TAPPING_FORCE_HOLD
#define TAPPING_TERM 200
#define IGNORE_MOD_TAP_INTERRUPT
#undef PERMISSIVE_HOLD
#ifdef RGBLIGHT_ENABLE
#undef RGBLED_NUM
#define RGBLIGHT_ANIMATIONS
#define RGBLED_NUM 27
#define RGBLIGHT_LIMIT_VAL 120
#define RGBLIGHT_HUE_STEP 10
#define RGBLIGHT_SAT_STEP 17
#define RGBLIGHT_VAL_STEP 17
#endif
#define OLED_FONT_H "keyboards/crkbd/lib/glcdfont.c"
// fix for me putting alt under A and being a fast typist
#define IGNORE_MOD_TAP_INTERRUPT
//#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY
#define LAYER_STATE_8BIT

View file

@ -0,0 +1,81 @@
/*
* Copyright 2020 Drashna Jaelre <@drashna>
* Copyright 2021 Tyler Thrailkill <@snowe/@snowe2010>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#define GUI_ESC GUI_T(KC_ESC)
#define CTL_ESC CTL_T(KC_ESC)
#define SH_BKSP SFT_T(KC_BSPC)
#define SP_RAIS LT(_UPPER, KC_SPC)
#define LOWER MO(_LOWER)
#define RAISE MO(_UPPER)
#define ADJUST MO(_ADJUST)
#define TG_MODS TG(_MODS)
//#define TG_GAME TG(_GAMEPAD)
//#define OS_LWR OSL(_LOWER)
//#define OS_RSE OSL(_UPPER)
//#define KC_SEC1 KC_SECRET_1
//#define KC_SEC2 KC_SECRET_2
//#define KC_SEC3 KC_SECRET_3
//#define KC_SEC4 KC_SECRET_4
//#define KC_SEC5 KC_SECRET_5
#define QWERTY KC_QWERTY
#define DVORAK KC_DVORAK
#define COLEMAK KC_COLEMAK
#define WORKMAN KC_WORKMAN
#define KC_RESET RESET
#define KC_RST KC_RESET
#ifdef SWAP_HANDS_ENABLE
# define KC_C1R3 SH_TT
#else // SWAP_HANDS_ENABLE
# define KC_C1R3 KC_BSPC
#endif // SWAP_HANDS_ENABLE
#define BK_LWER LT(_LOWER, KC_BSPC)
#define SP_LWER LT(_LOWER, KC_SPC)
#define DL_RAIS LT(_UPPER, KC_DEL)
#define ET_RAIS LT(_UPPER, KC_ENTER)
#define SFT_ENT SFT_T(KC_ENTER)
#define SP_RAIS LT(_UPPER, KC_SPC)
/* OSM keycodes, to keep things clean and easy to change */
#define KC_MLSF OSM(MOD_LSFT)
#define KC_MRSF OSM(MOD_RSFT)
#define OS_LGUI OSM(MOD_LGUI)
#define OS_RGUI OSM(MOD_RGUI)
#define OS_LSFT OSM(MOD_LSFT)
#define OS_RSFT OSM(MOD_RSFT)
#define OS_LCTL OSM(MOD_LCTL)
#define OS_RCTL OSM(MOD_RCTL)
#define OS_LALT OSM(MOD_LALT)
#define OS_RALT OSM(MOD_RALT)
#define OS_MEH OSM(MOD_MEH)
#define OS_HYPR OSM(MOD_HYPR)
#define ALT_APP ALT_T(KC_APP)
#define MG_NKRO MAGIC_TOGGLE_NKRO
#define UC_IRNY UC(0x2E2E)
#define UC_CLUE UC(0x203D)

View file

@ -0,0 +1,190 @@
/*
Copyright 2019 @foostan
Copyright 2020 Drashna Jaelre <@drashna>
Copyright 2021 Tyler Thrailkill <@snowe/@snowe2010>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
#include "snowe.h"
// Symbols chart
// ↯ hyper key (ctrl, alt, shift, super)
// ⌘ command
// ⌥ option
// ⌃ control
// ⇧ shift
// ⌫ backspace
// ⌦ delete
// ⎋ escape
// ↩ enter
/* Wrapper
* ,-----------------------------------------------. .-----------------------------------------------.
* | Tab | K01 | K02 | K03 | K04 | K05 | | K06 | K07 | K08 | K09 | K0A | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | / | /K11 | K12 | K13 | K14 | K15 | | K16 | K17 | K18 | K19 | /K1A | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | / | /K21 | K22 | K23 | K24 | K25 | | K26 | K27 | K28 | K29 | /K2A | |
* `-----------------------. | | .-----------------------'
* |-------+-------+-------| |-------+-------+-------|
* | | / | /LWR | | /RAY | | R |
* `-----------------------' '-----------------------'
*/
// clang-format off
#define LAYOUT_crkbd_base( \
K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, \
K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, \
K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A \
) \
LAYOUT_wrapper( \
KC_TAB, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, KC_MINS, \
GUI_ESC, CTL_T(K11), K12, K13, K14, K15, K16, K17, K18, K19, ALT_T(K1A), KC_QUOT, \
HYPR_T(KC_DEL), ALT_T(K21), K22, K23, K24, K25, K26, K27, K28, K29, RCTL_T(K2A), KC_BSLS, \
KC_LCTL, LOWER, SH_BKSP, KC_ENTER, SP_RAIS, KC_LALT \
)
// clang-format on
#define LAYOUT_crkbd_base_wrapper(...) LAYOUT_crkbd_base(__VA_ARGS__)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off
/* QWERTY
* ,-----------------------------------------------. .-----------------------------------------------.
* | | Q | W | E | R | T | | Y | U | I | O | P | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | | A | S | D | F | G | | H | J | K | L | ; | ' |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | | Z | X | C | V | B | | N | M | , | . | / | |
* `-----------------------. | | .-----------------------'
* |-------+-------+-------| |-------+-------+-------|
* | | | | | | | |
* `-----------------------' '-----------------------'
*/
[_MAIN] = LAYOUT_crkbd_base_wrapper(
_________________QWERTY_L1_________________, _________________QWERTY_R1_________________,
_________________QWERTY_L2_________________, _________________QWERTY_R2_________________,
_________________QWERTY_L3_________________, _________________QWERTY_R3_________________
),
/* Lower
* ,-----------------------------------------------. .-----------------------------------------------.
* | ~ | ! | @ | # | $ | % | | ^ | & | * | ( | ) | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | | | | | | | | | _ | + | [ | ] | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | | | | | | | | | | | | | |
* `-----------------------. | | .-----------------------'
* |-------+-------+-------| |-------+-------+-------|
* | | | | | | | |
* `-----------------------' '-----------------------'
*/
[_LOWER] = LAYOUT_wrapper(
KC_TILDE, _________________LOWER_L1__________________, _________________LOWER_R1__________________, KC_F11,
KC_F12 , _________________LOWER_L2__________________, _________________LOWER_R2__________________, KC_PIPE,
_______ , _________________LOWER_L3__________________, _________________LOWER_R3__________________, _______,
_______, _______, _______, _______, _______, _______
),
/*
* ,-----------------------------------------------. .-----------------------------------------------.
* | | | | | | | | | | | | | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | | | | | | | | | | | | | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | | | | | | | | | | | | | |
* `-----------------------. | | .-----------------------'
* |-------+-------+-------| |-------+-------+-------|
* | | | | | | | |
* `-----------------------' '-----------------------'
*/
/* Raise
* ,-----------------------------------------------. .-----------------------------------------------.
* | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | | | | | | | | | | | | | |
* |-------+-------+-------+-------+-------+-------| |-------+-------+-------+-------+-------+-------|
* | | | | | | | | | home |pg down| pg up | end | |
* `-----------------------. | | .-----------------------'
* |-------+-------+-------| |-------+-------+-------|
* | | | | | | | |
* `-----------------------' '-----------------------'
*/
[_UPPER] = LAYOUT_wrapper( \
KC_GRV, _________________RAISE_L1__________________, _________________RAISE_R1__________________, _______,
_______, _________________RAISE_L2__________________, _________________RAISE_R2__________________, KC_BSLS,
_______, _________________RAISE_L3__________________, _________________RAISE_R3__________________, _______,
_______, _______, _______, _______, _______, _______
),
[_ADJUST] = LAYOUT_wrapper( \
_______, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET,
_______, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
_______, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY,
_______, _______, _______, _______, _______, _______
)
// clang-format on
};
layer_state_t layer_state_set_user(layer_state_t state) { return update_tri_layer_state(state, _LOWER, _UPPER, _ADJUST); }
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_LCTL:
case KC_RCTL:
#ifdef OCEAN_DREAM_ENABLE
is_calm = (record->event.pressed) ? true : false;
#endif
#ifdef LUNA_ENABLE
if (record->event.pressed) {
isSneaking = true;
} else {
isSneaking = false;
}
#endif
break;
case KC_SPC:
#ifdef LUNA_ENABLE
if (record->event.pressed) {
isJumping = true;
showedJump = false;
} else {
isJumping = false;
}
#endif
break;
}
return true;
}
// uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
// switch (keycode) {
// case ALT_T(KC_A):
// case SH_BKSP:
// return TAPPING_TERM + 500;
// default:
// return TAPPING_TERM;
// }
//}
//
// bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) {
// switch (keycode) {
// case ALT_T(KC_A):
// case SH_BKSP:
// return true;
// default:
// return false;
// }
//}

View file

@ -0,0 +1,25 @@
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = no # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = no # Console for debug(+400)
COMMAND_ENABLE = no # Commands for debug and configuration
NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
AUDIO_ENABLE = no # Audio output on port C6
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight.
LEADER_ENABLE = no
MIDI_ENABLE = no # MIDI controls
UNICODE_ENABLE = no # Unicode
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
SWAP_HANDS_ENABLE = no # Enable one-hand typing
RGBLIGHT_TWINKLE = no
OLED_DRIVER_ENABLE = yes
RGB_MATRIX_ENABLE = yes
OCEAN_DREAM_ENABLE = yes
LUNA_ENABLE = no # disabled so travis build succeeds
# if firmware size over limit, try this option
CFLAGS += -flto
WPM_ENABLE = yes

229
users/snowe/luna.c Normal file
View file

@ -0,0 +1,229 @@
/*
* Copyright 2021 QMK Community
* Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "quantum.h"
#include "luna.h"
// KEYBOARD PET START
// settings
#define MIN_WALK_SPEED 10
#define MIN_RUN_SPEED 40
// advanced settings
#define ANIM_FRAME_DURATION 200 // how long each frame lasts in ms
#define ANIM_SIZE 96 // number of bytes in array. If you change sprites, minimize for adequate firmware size. max is 1024
bool isSneaking = false;
bool isJumping = false;
bool showedJump = true;
// status variables
int current_wpm = 0;
led_t led_usb_state = {
.num_lock = false,
.caps_lock = false,
.scroll_lock = false
};
// current frame
uint8_t current_frame = 0;
// timers
uint32_t anim_timer = 0;
uint32_t anim_sleep = 0;
// logic
void render_luna(int LUNA_X, int LUNA_Y) {
// Sit
static const char PROGMEM sit[2][ANIM_SIZE] = {
// 'sit1', 32x22px
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1c,
0x02, 0x05, 0x02, 0x24, 0x04, 0x04, 0x02, 0xa9, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x08, 0x68, 0x10, 0x08, 0x04, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x82, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0c, 0x10, 0x10, 0x20, 0x20, 0x20, 0x28,
0x3e, 0x1c, 0x20, 0x20, 0x3e, 0x0f, 0x11, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
// 'sit2', 32x22px
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1c,
0x02, 0x05, 0x02, 0x24, 0x04, 0x04, 0x02, 0xa9, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x90, 0x08, 0x18, 0x60, 0x10, 0x08, 0x04, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x82, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0c, 0x10, 0x10, 0x20, 0x20, 0x20, 0x28,
0x3e, 0x1c, 0x20, 0x20, 0x3e, 0x0f, 0x11, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}
};
// Walk
static const char PROGMEM walk[2][ANIM_SIZE] = {
// 'walk1', 32x22px
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x90, 0x90, 0x90, 0xa0, 0xc0, 0x80, 0x80,
0x80, 0x70, 0x08, 0x14, 0x08, 0x90, 0x10, 0x10, 0x08, 0xa4, 0x78, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x18, 0xea, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x20, 0x20, 0x3c, 0x0f, 0x11, 0x1f, 0x03,
0x06, 0x18, 0x20, 0x20, 0x3c, 0x0c, 0x12, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
// 'walk2', 32x22px
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x20, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00,
0x00, 0xe0, 0x10, 0x28, 0x10, 0x20, 0x20, 0x20, 0x10, 0x48, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x20, 0xf8, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x30, 0xd5, 0x20, 0x1f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x30, 0x0c, 0x02, 0x05, 0x09, 0x12, 0x1e,
0x02, 0x1c, 0x14, 0x08, 0x10, 0x20, 0x2c, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}
};
// Run
static const char PROGMEM run[2][ANIM_SIZE] = {
// 'run1', 32x22px
{
0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x08, 0x08, 0xc8, 0xb0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x40, 0x40, 0x3c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xc4, 0xa4, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc8, 0x58, 0x28, 0x2a, 0x10, 0x0f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x09, 0x04, 0x04, 0x04, 0x04, 0x02, 0x03, 0x02, 0x01, 0x01,
0x02, 0x02, 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
},
// 'run2', 32x22px
{
0x00, 0x00, 0x00, 0xe0, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x80, 0x80, 0x78, 0x28, 0x08, 0x10, 0x20, 0x30, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0xb0, 0x50, 0x55, 0x20, 0x1f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37,
0x02, 0x1e, 0x20, 0x20, 0x18, 0x0c, 0x14, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}
};
// Bark
static const char PROGMEM bark[2][ANIM_SIZE] = {
// 'bark1', 32x22px
{
0x00, 0xc0, 0x20, 0x10, 0xd0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40,
0x3c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xc8, 0x48, 0x28, 0x2a, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x02,
0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
// 'bark2', 32x22px
{
0x00, 0xe0, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40,
0x40, 0x2c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x48, 0x28, 0x2a, 0x10, 0x0f, 0x20, 0x4a, 0x09, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x02,
0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}
};
// Sneak
static const char PROGMEM sneak[2][ANIM_SIZE] = {
// 'sneak1', 32x22px
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0x40, 0x40, 0x80, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x21, 0xf0, 0x04, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04,
0x04, 0x04, 0x03, 0x01, 0x00, 0x00, 0x09, 0x01, 0x80, 0x80, 0xab, 0x04, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x20, 0x20, 0x3c, 0x0f, 0x11, 0x1f, 0x02, 0x06,
0x18, 0x20, 0x20, 0x38, 0x08, 0x10, 0x18, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
},
// 'sneak2', 32x22px
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe0, 0xa0, 0x20, 0x40, 0x80, 0xc0, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3e, 0x41, 0xf0, 0x04, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x04,
0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x40, 0x55, 0x82, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x30, 0x0c, 0x02, 0x05, 0x09, 0x12, 0x1e, 0x04,
0x18, 0x10, 0x08, 0x10, 0x20, 0x28, 0x34, 0x06, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
}
};
// animation
void animation_phase(void) {
// jump
if (isJumping || !showedJump) {
// clear
oled_set_cursor(LUNA_X,LUNA_Y +2);
oled_write(" ", false);
oled_set_cursor(LUNA_X,LUNA_Y -1);
showedJump = true;
} else {
// clear
oled_set_cursor(LUNA_X,LUNA_Y -1);
oled_write(" ", false);
oled_set_cursor(LUNA_X,LUNA_Y);
}
// switch frame
current_frame = (current_frame + 1) % 2;
// current status
if(led_usb_state.caps_lock) {
oled_write_raw_P(bark[abs(1 - current_frame)], ANIM_SIZE);
} else if(isSneaking) {
oled_write_raw_P(sneak[abs(1 - current_frame)], ANIM_SIZE);
} else if(current_wpm <= MIN_WALK_SPEED) {
oled_write_raw_P(sit[abs(1 - current_frame)], ANIM_SIZE);
} else if(current_wpm <= MIN_RUN_SPEED) {
oled_write_raw_P(walk[abs(1 - current_frame)], ANIM_SIZE);
} else {
oled_write_raw_P(run[abs(1 - current_frame)], ANIM_SIZE);
}
}
// animation timer
if(timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) {
anim_timer = timer_read32();
current_wpm = get_current_wpm();
animation_phase();
}
// this fixes the screen on and off bug
if (current_wpm > 0) {
oled_on();
anim_sleep = timer_read32();
} else if(timer_elapsed32(anim_sleep) > OLED_TIMEOUT) {
oled_off();
}
}
// KEYBOARD PET END

31
users/snowe/luna.h Normal file
View file

@ -0,0 +1,31 @@
/*
* Copyright 2021 QMK Community
* Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
extern bool isSneaking;
extern bool isJumping;
extern bool showedJump;
// status variables
extern led_t led_usb_state;
//extern int current_wpm;
void render_luna(int LUNA_X, int LUNA_Y);

555
users/snowe/ocean_dream.c Normal file
View file

@ -0,0 +1,555 @@
/*
* Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ocean_dream.h"
#include "quantum.h"
#include "print.h"
// Calculated Parameters
#define TWINKLE_PROBABILITY_MODULATOR 100 / TWINKLE_PROBABILITY // CALCULATED: Don't Touch
#define TOTAL_STARS STARS_PER_LINE *NUMBER_OF_STAR_LINES // CALCULATED: Don't Touch
#define OCEAN_ANIMATION_MODULATOR NUMBER_OF_FRAMES / OCEAN_ANIMATION_SPEED // CALCULATED: Don't Touch
#define SHOOTING_STAR_ANIMATION_MODULATOR NUMBER_OF_FRAMES / SHOOTING_STAR_ANIMATION_SPEED // CALCULATED: Don't Touch
#define STAR_ANIMATION_MODULATOR NUMBER_OF_FRAMES / STAR_ANIMATION_SPEED // CALCULATED: Don't Touch
uint8_t animation_counter = 0; // global animation counter.
bool is_calm = false;
uint32_t starry_night_anim_timer = 0;
uint32_t starry_night_anim_sleep = 0;
static int current_wpm = 0;
static uint8_t increment_counter(uint8_t counter, uint8_t max) {
counter++;
if (counter >= max) {
return 0;
} else {
return counter;
}
}
#ifdef ENABLE_WAVE
static uint8_t decrement_counter(uint8_t counter, uint8_t max) {
counter--;
if (counter < 0 || counter > max) {
return max;
} else {
return counter;
}
}
#endif
#ifdef ENABLE_MOON // region
# ifndef STATIC_MOON
uint8_t moon_animation_frame = 0; // keeps track of current moon frame
uint16_t moon_animation_counter = 0; // counts how many frames to wait before animating moon to next frame
# endif
# ifdef STATIC_MOON
static const char PROGMEM moon[6] = {
0x18, 0x7E, 0xFF, 0xC3, 0x81, 0x81,
};
# endif
# ifndef STATIC_MOON
static const char PROGMEM moon_animation[14][8] = {
// clang-format off
{ 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
{ 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x42, 0x00, },
{ 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xC3, 0x00, 0x00, },
{ 0x3C, 0x7E, 0xFF, 0xFF, 0xC3, 0x81, 0x00, 0x00, },
{ 0x3C, 0x7E, 0xFF, 0xC3, 0x81, 0x00, 0x00, 0x00, },
{ 0x3C, 0x7E, 0xC3, 0x81, 0x81, 0x00, 0x00, 0x00, },
{ 0x3C, 0x42, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
{ 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x42, 0x3C, },
{ 0x00, 0x00, 0x00, 0x81, 0x81, 0xC3, 0x7E, 0x3C, },
{ 0x00, 0x00, 0x00, 0x81, 0xC3, 0xFF, 0x7E, 0x3C, },
{ 0x00, 0x00, 0x81, 0xC3, 0xFF, 0xFF, 0x7E, 0x3C, },
{ 0x00, 0x00, 0xC3, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
{ 0x00, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
// clang-format on
};
# endif
static void draw_moon(void) {
# ifdef STATIC_MOON
oled_set_cursor(MOON_COLUMN, MOON_LINE);
oled_write_raw_P(moon, 6);
# endif
# ifndef STATIC_MOON
moon_animation_counter = increment_counter(moon_animation_counter, ANIMATE_MOON_EVERY_N_FRAMES);
if (moon_animation_counter == 0) {
moon_animation_frame = increment_counter(moon_animation_frame, 14);
oled_set_cursor(MOON_COLUMN, MOON_LINE);
oled_write_raw_P(moon_animation[moon_animation_frame], 8);
}
# endif
}
#endif // endregion
#ifdef ENABLE_WAVE // region
uint8_t starry_night_wave_frame_width_counter = 31;
uint8_t rough_waves_frame_counter = 0;
// clang-format off
static const char PROGMEM ocean_top[8][32] = {
// still ocean
{
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
},
// small ripples
{
0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
},
// level 2 ripples
{
0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
},
// level 3 waves
{
0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
},
{
0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
},
{
0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
},
};
static const char PROGMEM ocean_bottom[8][32] = {
// still ocean
{
0x00, 0x40, 0x40, 0x41, 0x01, 0x01, 0x01, 0x21,
0x20, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x44,
0x44, 0x40, 0x40, 0x00, 0x00, 0x08, 0x08, 0x00,
0x01, 0x01, 0x01, 0x00, 0x40, 0x40, 0x00, 0x00,
},
// small ripples
{
0x00, 0x00, 0x40, 0x40, 0x01, 0x01, 0x01, 0x20,
0x20, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x01, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00,
},
// level 2 ripples
{
0x00, 0x00, 0x40, 0x40, 0x01, 0x01, 0x01, 0x20,
0x20, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x01, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00,
},
// level 3 waves
{
0x00, 0x40, 0x40, 0x42, 0x42, 0x03, 0x11, 0x11,
0x20, 0x20, 0x00, 0x00, 0x08, 0x0C, 0x0C, 0x04,
0x05, 0x41, 0x41, 0x21, 0x20, 0x00, 0x00, 0x08,
0x0A, 0x0A, 0x0B, 0x41, 0x41, 0x41, 0x41, 0x00,
},
{
0x10, 0x10, 0x00, 0x80, 0x84, 0xC4, 0x02, 0x06,
0x84, 0x44, 0xC0, 0x80, 0x80, 0x20, 0x20, 0x10,
0x08, 0x12, 0x91, 0x81, 0x42, 0x40, 0x00, 0x00,
0x10, 0x12, 0x22, 0x22, 0x24, 0x04, 0x84, 0x80,
},
{
0x08, 0x80, 0x80, 0x82, 0x82, 0x03, 0x21, 0x21,
0x10, 0x10, 0x00, 0x00, 0x04, 0x04, 0x0C, 0x08,
0x09, 0x41, 0x42, 0x22, 0x20, 0x00, 0x00, 0x08,
0x0A, 0x0A, 0x0B, 0x41, 0x43, 0x42, 0x42, 0x00,
},
};
// clang-format on
static void animate_waves(void) {
starry_night_wave_frame_width_counter = decrement_counter(starry_night_wave_frame_width_counter, WIDTH - 1); // only 3 frames for last wave type
rough_waves_frame_counter = increment_counter(rough_waves_frame_counter, 3); // only 3 frames for last wave type
void draw_ocean(uint8_t frame, uint16_t offset, uint8_t byte_index) {
oled_write_raw_byte(pgm_read_byte(ocean_top[frame] + byte_index), offset);
oled_write_raw_byte(pgm_read_byte(ocean_bottom[frame] + byte_index), offset + WIDTH);
}
for (int i = 0; i < WIDTH; ++i) {
uint16_t offset = OCEAN_LINE * WIDTH + i;
uint8_t byte_index = starry_night_wave_frame_width_counter + i;
if (byte_index >= WIDTH) {
byte_index = byte_index - WIDTH;
}
if (is_calm || current_wpm <= WAVE_CALM) {
draw_ocean(0, offset, byte_index);
} else if (current_wpm <= WAVE_HEAVY_STORM) {
draw_ocean(1, offset, byte_index);
} else if (current_wpm <= WAVE_HURRICANE) {
draw_ocean(2, offset, byte_index);
} else {
draw_ocean(3 + rough_waves_frame_counter, offset, byte_index);
}
}
}
#endif // endregion
#ifdef ENABLE_ISLAND // region
uint8_t island_frame_1 = 0;
// clang-format off
// only use 46 bytes (first 18 are blank, so we don't write them, makes it smaller and we can see the shooting stars properly!)
// To save space and allow the shooting stars to be seen, only draw the tree on every frame.
// Tree is only 14bytes wide so we save 108 bytes on just the first row. Second row, the
// first 18 bytes is always the same piece of land, so only store that once, which saves 90 bytes
static const char PROGMEM islandRightTop[6][14] = {
{0x84, 0xEC, 0x6C, 0x3C, 0xF8, 0xFE, 0x3F, 0x6B, 0xDB, 0xB9, 0x30, 0x40, 0x00, 0x00,},
{0x80, 0xC3, 0xEE, 0x7C, 0xB8, 0xFC, 0xFE, 0x6F, 0xDB, 0x9B, 0xB2, 0x30, 0x00, 0x00,},
{0x00, 0xC0, 0xEE, 0x7F, 0x3D, 0xF8, 0xFC, 0x7E, 0x57, 0xDB, 0xDB, 0x8A, 0x00, 0x00,},
{0x00, 0xC0, 0xE6, 0x7F, 0x3B, 0xF9, 0xFC, 0xFC, 0xB6, 0xB3, 0x33, 0x61, 0x00, 0x00,},
{0x00, 0x00, 0x00, 0x00, 0x80, 0xEE, 0xFF, 0xFB, 0xF9, 0xFC, 0xDE, 0xB6, 0xB6, 0x24,},
{0x00, 0x00, 0x00, 0x00, 0xC0, 0xEE, 0xFE, 0xFF, 0xFB, 0xFD, 0xEE, 0xB6, 0xB6, 0x92,},
};
static const char PROGMEM islandRightBottom[6][14] = {
{0x41, 0x40, 0x60, 0x3E, 0x3F, 0x23, 0x20, 0x60, 0x41, 0x43, 0x40, 0x40, 0x40, 0x80,},
{0x40, 0x41, 0x60, 0x3E, 0x3F, 0x23, 0x20, 0x60, 0x40, 0x40, 0x41, 0x41, 0x40, 0x80,},
{0x40, 0x40, 0x61, 0x3D, 0x3F, 0x27, 0x21, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x80,},
{0x40, 0x43, 0x61, 0x3C, 0x3F, 0x27, 0x21, 0x60, 0x41, 0x43, 0x43, 0x42, 0x40, 0x80,},
{0x40, 0x40, 0x60, 0x3C, 0x3F, 0x27, 0x23, 0x63, 0x44, 0x40, 0x41, 0x41, 0x41, 0x81,},
{0x40, 0x40, 0x60, 0x3C, 0x3F, 0x27, 0x23, 0x63, 0x42, 0x42, 0x41, 0x41, 0x41, 0x80,},
};
static const char PROGMEM islandLeft[18] = {
0x80, 0x40, 0x40, 0x40, 0x40, 0x60,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x60, 0x40, 0x40,
};
// clang-format on
static void animate_island(void) {
if (animation_counter == 0) {
island_frame_1 = increment_counter(island_frame_1, 2);
}
void draw_island_parts(uint8_t frame) {
oled_set_cursor(ISLAND_COLUMN + 3, ISLAND_LINE);
oled_write_raw_P(islandRightTop[frame], 14);
oled_set_cursor(ISLAND_COLUMN + 0, ISLAND_LINE + 1);
oled_write_raw_P(islandLeft, 18);
oled_set_cursor(ISLAND_COLUMN + 3, ISLAND_LINE + 1);
oled_write_raw_P(islandRightBottom[frame], 14);
}
if (is_calm || current_wpm < ISLAND_CALM) {
draw_island_parts(0);
} else if (current_wpm >= ISLAND_CALM && current_wpm < ISLAND_HEAVY_STORM) {
draw_island_parts(island_frame_1 + 1);
} else if (current_wpm >= ISLAND_HEAVY_STORM && current_wpm < ISLAND_HURRICANE) {
draw_island_parts(island_frame_1 + 2);
} else {
draw_island_parts(island_frame_1 + 4);
}
}
#endif // endregion
#ifdef ENABLE_STARS // region
bool stars_setup = false; // only setup stars once, then we just twinkle them
struct Coordinate {
int x;
int y;
bool exists;
};
struct Coordinate stars[TOTAL_STARS]; // tracks all stars/coordinates
/**
* Setup all the initial stars on the screen
* This function divides the screen into regions based on STARS_PER_LINE and NUMBER_OF_STAR_LINES
* where each line is made up of 8x8 pixel groups, that are populated by a single star.
*
* Not sure how this function will work with larger or smaller screens.
* It should be fine, as long as the screen width is a multiple of 8
*/
static void setup_stars(void) {
// For every line, split the line into STARS_PER_LINE, find a random point in that region, and turn the pixel on
// 36% probability it will not be added
// (said another way, 80% chance it will start out lit in the x direction, then 80% chance it will start out lit in the y direction = 64% probability it will start out lit at all)
for (int line = 0; line < NUMBER_OF_STAR_LINES; ++line) {
for (int column_group = 0; column_group < STARS_PER_LINE; ++column_group) {
uint8_t rand_column = rand() % 10;
uint8_t rand_row = rand() % 10;
if (rand_column < 8 && rand_row < 8) {
int column_adder = column_group * 8;
int line_adder = line * 8;
int x = rand_column + column_adder;
int y = rand_row + line_adder;
oled_write_pixel(x, y, true);
stars[column_group + (line * STARS_PER_LINE)].x = x;
stars[column_group + (line * STARS_PER_LINE)].y = y;
stars[column_group + (line * STARS_PER_LINE)].exists = true;
} else {
stars[column_group + (line * STARS_PER_LINE)].exists = false;
}
}
}
stars_setup = true;
}
/**
* Twinkle the stars (move them one pixel in any direction) with a probability of 50% to twinkle any given star
*/
static void twinkle_stars(void) {
for (int line = 0; line < NUMBER_OF_STAR_LINES; ++line) {
for (int column_group = 0; column_group < STARS_PER_LINE; ++column_group) {
struct Coordinate star = stars[column_group + (line * STARS_PER_LINE)];
// skip stars that were never added
if (!star.exists) {
continue;
}
if (rand() % TWINKLE_PROBABILITY_MODULATOR == 0) {
oled_write_pixel(star.x, star.y, false); // black out pixel
// don't allow stars to leave their own region
if (star.x == (column_group * 8)) { // star is the farthest left it can go in its region
star.x++; // move it right immediately
} else if (star.x == (((column_group + 1) * 8) - 1)) { // star is farthest right it can go in its region
star.x--; // move it left immediately
}
if (star.y == (line * 8)) { // star is the farthest up it can go in its region
star.y++; // move it down immediately
} else if (star.y == (((line + 1) * 8) - 1)) { // star is farthest down it can go in its region
star.y--; // move it up immediately
}
// now decide direction
int new_x;
int x_choice = rand() % 3;
if (x_choice == 0) {
new_x = star.x - 1;
} else if (x_choice == 1) {
new_x = star.x + 1;
} else {
new_x = star.x;
}
int new_y;
int y_choice = rand() % 3;
if (y_choice == 0) {
new_y = star.y - 1;
} else if (y_choice == 1) {
new_y = star.y + 1;
} else {
new_y = star.y;
}
star.x = new_x;
star.y = new_y;
oled_write_pixel(new_x, new_y, true);
}
stars[column_group + (line * STARS_PER_LINE)] = star;
}
}
}
/**
* Setup the stars and then animate them on subsequent frames
*/
static void animate_stars(void) {
if (!stars_setup) {
setup_stars();
} else {
twinkle_stars();
}
}
#endif // endregion
#ifdef ENABLE_SHOOTING_STARS // region
bool shooting_stars_setup = false; // only setup shooting stars array once with defaults
struct ShootingStar {
int x_1;
int y_1;
int x_2;
int y_2;
bool running;
int frame;
int delay;
};
struct ShootingStar shooting_stars[MAX_NUMBER_OF_SHOOTING_STARS]; // tracks all the shooting stars
static void setup_shooting_star(struct ShootingStar *shooting_star) {
int column_to_start = rand() % (WIDTH / 2);
int row_to_start = rand() % (HEIGHT - 48); // shooting_stars travel diagonally 1 down, 1 across. So the lowest a shooting_star can start and not 'hit' the ocean is 32 above the ocean.
shooting_star->x_1 = column_to_start;
shooting_star->y_1 = row_to_start;
shooting_star->x_2 = column_to_start + 1;
shooting_star->y_2 = row_to_start + 1;
shooting_star->running = true;
shooting_star->frame++;
shooting_star->delay = rand() % SHOOTING_STAR_DELAY;
}
static void move_shooting_star(struct ShootingStar *shooting_star) {
oled_write_pixel(shooting_star->x_1, shooting_star->y_1, false);
oled_write_pixel(shooting_star->x_2, shooting_star->y_2, false);
shooting_star->x_1++;
shooting_star->y_1++;
shooting_star->x_2++;
shooting_star->y_2++;
shooting_star->frame++;
oled_write_pixel(shooting_star->x_1, shooting_star->y_1, true);
oled_write_pixel(shooting_star->x_2, shooting_star->y_2, true);
}
static void finish_shooting_star(struct ShootingStar *shooting_star) {
oled_write_pixel(shooting_star->x_1, shooting_star->y_1, false);
oled_write_pixel(shooting_star->x_2, shooting_star->y_2, false);
shooting_star->running = false;
shooting_star->frame = 0;
}
static void animate_shooting_star(struct ShootingStar *shooting_star) {
if (shooting_star->frame > SHOOTING_STAR_FRAMES) {
finish_shooting_star(shooting_star);
return;
} else if (!shooting_star->running) {
setup_shooting_star(shooting_star);
} else {
if (shooting_star->delay == 0) {
move_shooting_star(shooting_star);
} else {
shooting_star->delay--;
}
}
}
static void animate_shooting_stars(void) {
if (is_calm) {
return;
}
if (!shooting_stars_setup) {
for (int i = 0; i < MAX_NUMBER_OF_SHOOTING_STARS; ++i) {
shooting_stars[i].running = false;
}
shooting_stars_setup = true;
}
/**
* Fixes issue with stars that were falling _while_ the
* wpm dropped below the condition for them to keep falling
*/
void end_extra_stars(uint8_t starting_index) {
for (int shooting_star_index = starting_index; shooting_star_index < MAX_NUMBER_OF_SHOOTING_STARS; ++shooting_star_index) {
struct ShootingStar shooting_star = shooting_stars[shooting_star_index];
if (shooting_star.running) {
finish_shooting_star(&shooting_star);
shooting_stars[shooting_star_index] = shooting_star;
}
}
}
int number_of_shooting_stars = current_wpm / SHOOTING_STAR_WPM_INCREMENT;
number_of_shooting_stars = (number_of_shooting_stars > MAX_NUMBER_OF_SHOOTING_STARS) ? MAX_NUMBER_OF_SHOOTING_STARS : number_of_shooting_stars;
if (number_of_shooting_stars == 0) {
// make sure all shooting_stars are ended
end_extra_stars(0);
} else {
for (int shooting_star_index = 0; shooting_star_index < number_of_shooting_stars; ++shooting_star_index) {
struct ShootingStar shooting_star = shooting_stars[shooting_star_index];
animate_shooting_star(&shooting_star);
shooting_stars[shooting_star_index] = shooting_star;
}
end_extra_stars(number_of_shooting_stars);
}
}
#endif // endregion
/**
* Main rendering function
*
* Calls all different animations at different rates
*/
void render_stars(void) {
// // animation timer
if (timer_elapsed32(starry_night_anim_timer) > STARRY_NIGHT_ANIM_FRAME_DURATION) {
starry_night_anim_timer = timer_read32();
current_wpm = get_current_wpm();
#ifdef ENABLE_ISLAND
animate_island();
#endif
#ifdef ENABLE_SHOOTING_STARS
if (animation_counter % SHOOTING_STAR_ANIMATION_MODULATOR == 0) {
animate_shooting_stars();
}
#endif
#ifdef ENABLE_STARS
// TODO offsetting the star animation from the wave animation would look better,
// but if I do that, then the stars appear in the water because
// the ocean animation has to wait a bunch of frames to overwrite it.
// Possible solutions:
// 1. Only draw stars to the top of the island/ocean.
// 2. Draw ocean every frame, only move ocean on frames matching modulus
// Problems:
// 1. What if someone wants to move the island up a bit, or they want to have the stars reflect in the water?
// 2. More cpu intensive. And I'm already running out of cpu as it is...
if (animation_counter % STAR_ANIMATION_MODULATOR == 0) {
animate_stars();
}
#endif
#ifdef ENABLE_WAVE
if (animation_counter % OCEAN_ANIMATION_MODULATOR == 0) {
animate_waves();
}
#endif
#ifdef ENABLE_MOON
draw_moon();
#endif
animation_counter = increment_counter(animation_counter, NUMBER_OF_FRAMES);
}
// this fixes the screen on and off bug
if (current_wpm > 0) {
oled_on();
starry_night_anim_sleep = timer_read32();
} else if (timer_elapsed32(starry_night_anim_sleep) > OLED_TIMEOUT) {
oled_off();
}
}

103
users/snowe/ocean_dream.h Normal file
View file

@ -0,0 +1,103 @@
/*
* Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "quantum.h"
/**
* Features:
* You can turn on and off features in this section
*/
#define ENABLE_MOON // Uses 182 bytes
#define ENABLE_WAVE // Uses 844 bytes
#define ENABLE_SHOOTING_STARS // Uses 872 bytes
#define ENABLE_ISLAND
#define ENABLE_STARS // Uses 606 bytes
/**
* Global Settings
*/
#define STARRY_NIGHT_ANIM_FRAME_DURATION 30 // how long each frame lasts in ms
#define NUMBER_OF_FRAMES 20 // Self explanatory. Probably shouldn't touch this, not sure how stuff will work if it's changed. If changed should be multiple of 1, 2, 3, 4, and 5
#define WIDTH OLED_DISPLAY_HEIGHT // for vertical displays
#define HEIGHT OLED_DISPLAY_WIDTH // for vertical displays
/**
* Moon Parameters
*/
#define MOON_LINE 4 // the line you want the moon to appear at
#define MOON_COLUMN 4 // the column you want the moon to appear at
//#define STATIC_MOON // uncomment this to make the moon a static image, no animation
#ifndef STATIC_MOON
# define ANIMATE_MOON_EVERY_N_FRAMES 100 // animate the moon every n frames
#endif
/**
* Wave Parameters
*/
#define OCEAN_LINE 14 // Line you want to render the ocean starting at (best at oled_max_lines() - 2)
#define WAVE_CALM 20 // render calm ocean under this WPM and ripple ocean at this WPM
#define WAVE_HEAVY_STORM 40 // render medium ocean at this WPM
#define WAVE_HURRICANE 60 // render heavy waves above this WPM
// What number of frames you want to animate the ocean at.
// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 30, would animate on every other frame, 20, every third frame, etc
// Don't set equal to 0.
#define OCEAN_ANIMATION_SPEED 1
/**
* Shooting Star Parameters
*/
#define SHOOTING_STAR_DELAY 12 // delay modulus for time between shooting stars. Decides number of frames to delay, e.g. 12 means 0-11 frames of delay between each shooting star
#define SHOOTING_STAR_FRAMES 16 // how many 2 pixel frames per shooting star. Increment this for longer shooting stars
#define MAX_NUMBER_OF_SHOOTING_STARS 12 // maximum number of shooting stars that can be on screen at the same time
#define SHOOTING_STAR_WPM_INCREMENT 10 // every n WPM increase, add an extra star, up to MAX_NUMBER_OF_SHOOTING_STARS, e.g. an increment of 5 would result in 1 shooting star at 5-9wpm, 2 at 10-14, etc.
// What number of frames you want to animate the shooting stars at.
// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 30, would animate on every other frame, 20, every third frame, etc
// Don't set equal to 0.
#define SHOOTING_STAR_ANIMATION_SPEED 30
/**
* Star Parameters
*/
#define STARS_PER_LINE 4 // number of stars per line (for a display that is 128x32, this would be 4 stars spread out evenly over the 32byte width, one every 8 bytes)
#define NUMBER_OF_STAR_LINES 16 // number of lines to fill up with stars (for a display that is 128x32, 16 bytes are filled with the ocean animation, so that leaves 112 pixels left over. The number of lines depends on your OLED_FONT_HEIGHT)
#define TWINKLE_PROBABILITY 25 // probability that any star twinkles on a given frame
// What number of frames you want to animate the stars at.
// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 20, would animate on every frame, 10, every other frame, etc
// Don't set equal to 0.
#define STAR_ANIMATION_SPEED 1
/**
* Island Parameters
*/
#define ISLAND_LINE 12 // line that the island starts at. Island is 2 lines tall
#define ISLAND_COLUMN 0 // column that the island starts at
#define ISLAND_CALM 20 // WPM at which the palm tree calmly moves
#define ISLAND_HEAVY_STORM 40 // WPM at which the heavy storm occurs
#define ISLAND_HURRICANE 60 // WPM at which THE HURRICANE STARTS
/*
* DON'T TOUCH
*/
extern bool is_calm;
// timers
extern uint32_t starry_night_anim_timer;
extern uint32_t starry_night_anim_sleep;
void render_stars(void);

141
users/snowe/oled_setup.c Normal file
View file

@ -0,0 +1,141 @@
/*
* Copyright QMK Community
* Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef OLED_DRIVER_ENABLE
# include QMK_KEYBOARD_H
# include "quantum.h"
# include "snowe.h"
# include <stdio.h> // for keylog?
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
if (!is_master) {
return OLED_ROTATION_270; // flips the display 180 degrees if offhand
}
return OLED_ROTATION_270;
}
# define L_BASE 0
# define L_LOWER 2
# define L_RAISE 4
# define L_ADJUST 8
void oled_render_layer_state(void) {
oled_write_P(PSTR("Layer"), false);
switch (layer_state) {
case L_BASE:
oled_write_ln_P(PSTR("Main"), false);
break;
case L_LOWER:
oled_write_ln_P(PSTR("Bot"), false);
break;
case L_RAISE:
oled_write_ln_P(PSTR("Top"), false);
break;
case L_ADJUST:
case L_ADJUST | L_LOWER:
case L_ADJUST | L_RAISE:
case L_ADJUST | L_LOWER | L_RAISE:
oled_write_ln_P(PSTR("Comb"), false);
break;
}
}
char keylog_str[24] = {};
const char code_to_name[60] = {
' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\',
'#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '};
void set_keylog(uint16_t keycode, keyrecord_t *record) {
char name = ' ';
if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
keycode = keycode & 0xFF;
}
if (keycode < 60) {
name = code_to_name[keycode];
}
// update keylog
snprintf(keylog_str, sizeof(keylog_str), "%dx%d, k%2d : %c", record->event.key.row, record->event.key.col, keycode, name);
}
void oled_render_keylog(void) { oled_write(keylog_str, false); }
// void render_bootmagic_status(bool status) {
// /* Show Ctrl-Gui Swap options */
// static const char PROGMEM logo[][2][3] = {
// {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}},
// {{0x95, 0x96, 0}, {0xb5, 0xb6, 0}},
// };
// if (status) {
// oled_write_ln_P(logo[0][0], false);
// oled_write_ln_P(logo[0][1], false);
// } else {
// oled_write_ln_P(logo[1][0], false);
// oled_write_ln_P(logo[1][1], false);
// }
//}
void render_bootmagic_status(void) {
/* Show Ctrl-Gui Swap options */
static const char PROGMEM logo[][2][3] = {
{{0x97, 0x98, 0}, {0xb7, 0xb8, 0}},
{{0x95, 0x96, 0}, {0xb5, 0xb6, 0}},
};
oled_write_P(PSTR("BTMGK"), false);
oled_write_P(PSTR(""), false);
if (!keymap_config.swap_lctl_lgui) {
oled_write_P(logo[1][0], false);
oled_write_P(PSTR(" "), false);
oled_write_P(logo[1][1], false);
} else {
oled_write_P(logo[0][0], false);
oled_write_P(PSTR(" "), false);
oled_write_P(logo[0][1], false);
}
oled_write_P(PSTR(" NKRO "), keymap_config.nkro);
oled_write_P(PSTR("WPM: "), false);
char wpm[6];
itoa(get_current_wpm(), wpm, 10);
oled_write_ln(wpm, false);
}
void oled_task_user(void) {
if (is_master) {
oled_render_layer_state();
oled_render_keylog();
render_bootmagic_status();
# ifdef LUNA_ENABLE
led_usb_state = host_keyboard_led_state();
render_luna(0, 13);
# endif
} else {
# ifdef OCEAN_DREAM_ENABLE
render_stars();
# endif
}
}
#endif // OLED_DRIVER_ENABLE

30
users/snowe/oled_setup.h Normal file
View file

@ -0,0 +1,30 @@
/*
* Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "quantum.h"
#ifdef OLED_DRIVER_ENABLE
# include "oled_driver.h"
# define OLED_RENDER_WPM_COUNTER " WPM: "
#endif
#ifdef LUNA_ENABLE
# include "luna.h"
#endif
#ifdef OCEAN_DREAM_ENABLE
# include "ocean_dream.h"
#endif

10
users/snowe/readme.md Normal file
View file

@ -0,0 +1,10 @@
# Welcome
Welcome to my userspace.
There's nothing really outstanding here, except the [Ocean Dream](readme_ocean_dream.md)
animation I made.
A lot of the code for my wrappers/keymaps came from other users.
I will probably update this with more in-depth information later.

View file

@ -0,0 +1,258 @@
# Ocean Dream
Tapping away at your IMX Corne with Box Jades, you feel yourself
drifting off, into a soundscape of waves and rustling leaves.
You open your eyes only to find yourself in an _Ocean Dream_.
Introducing, **Ocean Dream**, an animation for keyboards with tall OLED
screens. Built for 128x32 screens, this animation should work for 128x64
at least, though it hasn't been tested there.
Completely customizable, you can change everything about the animation,
from the number of falling stars, to how likely a star is to twinkle, and
even if the moon has phases or not.
# Installation
Installation is easy.
1. Add `ocean.h` and `ocean.c` to your keyboard folder or userspace.
2. In your `keymap.c` or wherever you handle your oled code, add
```c
# ifdef OCEAN_DREAM_ENABLE
render_stars();
# endif
```
to `oled_task_user(void)`, where you would like (see [my keymap](../../keyboards/crkbd/keymaps/snowe/keymap.c) for an example)
3. In your `keymap.c` or wherever you handle your process_record code,
add an event that sets `is_calm` when you press `ctrl`
```c
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_LCTL:
case KC_RCTL:
#ifdef OCEAN_DREAM_ENABLE
is_calm = (record->event.pressed) ? true : false;
#endif
break;
}
return true;
}
```
4. In your `rules.mk` to make it easier to turn the animation on/off, add
```makefile
ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes)
#... your code here...
ifdef OCEAN_DREAM_ENABLE
ifeq ($(strip $(OCEAN_DREAM_ENABLE)), yes)
SRC += ocean_dream.c
OPT_DEFS += -DOCEAN_DREAM_ENABLE
endif
endif
ifndef OCEAN_DREAM_ENABLE
SRC += ocean_dream.c
OPT_DEFS += -DOCEAN_DREAM_ENABLE
endif
endif
```
You're done! Now you can enable **Ocean Dream** by simply turning on the OLED feature
```makefile
OLED_DRIVER_ENABLE = yes
```
And if you want to disable it without turning off the OLED Driver you can simply set
```makefile
OCEAN_DREAM_ENABLE = no
```
# Settings
**Ocean Dream** comes with several different animations, all individually configurable:
* 🌌 Stars that twinkle
* 🌠 Meteor showers that get more vibrant the faster you type
* 🌊 Waves that get rougher the faster you type
* 🏝 An island with a palm tree that blows in the wind the faster you type
* 🌗 A moon that goes through the moon phases (or not, your choice!)
Each feature can be individually turned on and off, with a simple `#define`.
You can see all the options and more documentation by looking at `ocean_dream.h`.
All options come enabled by default.
## Global Flags:
### Toggles:
You can toggle on/off any features using these flags:
* `ENABLE_MOON` // Uses 182 bytes
* `ENABLE_WAVE` // Uses 844 bytes
* `ENABLE_SHOOTING_STARS` // Uses 872 bytes
* `ENABLE_ISLAND`
* `ENABLE_STARS` // Uses 606 bytes
### Global Configuration:
* `STARRY_NIGHT_ANIM_FRAME_DURATION` - configures how long each frame lasts in ms
* `NUMBER_OF_FRAMES` - configures the number of frames that constitute a single 'round trip' of animation.
Enables keeping animations in sync/timed with each other.
Probably shouldn't touch this, not sure how stuff will work if it's changed.
If changed should probably be multiple of 1, 2, 3, 4, and 5
* `WIDTH` - for vertical displays, configures the width (the shortest measurement of your display). defaults to `OLED_DISPLAY_HEIGHT`
* `HEIGHT` - for vertical displays, configures the height (the longest measurement of your display). defaults to `OLED_DISPLAY_WIDTH`
## Stars
### Description
The 🌌 stars animation is a background of slowly twinkling stars.
The stars are built on a grid of sorts, where each cell of the grid
is 8x8 pixels with 1 star per cell. There is a probability of any
star twinkling on any given frame, decided by the corresponding flags.
### Flags
Enabled with the `#define ENABLE_STARS` directive.
The stars come with several configuration options:
* `STARS_PER_LINE` - configures the number of stars per line. Defaulting to 4, this would
mean that you have 4 stars across each line (8x32 on a 128x32 display), where each star
is in a 8x8 grid
* `NUMBER_OF_STAR_LINES` - configures the number of lines to fill up with stars.
Defaults to 16, filling the whole display.
* `TWINKLE_PROBABILITY` - configures the probability of a star twinkling on a given frame.
* `STAR_ANIMATION_SPEED` - configures the number of frames you want to animate the star at.
Must be equal to or lower than `NUMBER_OF_FRAMES`.
Example:
```c
#define NUMBER_OF_FRAMES 20
#define STAR_ANIMATION_SPEED 5
```
would result in the star animation happening every 4 frames. 20 would result in every frame,
1 would be once every 20 frames. This essentially changes how fast stars will twinkle, but
does not change the probability of the stars twinkling.
## Moon
### Description
The 🌗 moon animation is an 8x8 animation of a moon, or, if you are running out of program memory, you
can set it to just a static crescent moon, with no animation.
### Flags
Enabled with the `#define ENABLE_MOON` directive.
The moon comes with only a few configuration options:
* `STATIC_MOON` - include this directive if you want your moon to have no animation. It will simply be a static crescent
moon, only taking up 6 bytes of space. If you do not include this directive, then the moon will have an animation.
The default is a moon with animation.
* `MOON_LINE` - defines the line that the moon sits on. Default is `4`. (see [reference](#reference))
* `MOON_COLUMN` - defines the column that the moon sits at. Default is `4`. (see [reference](#reference))
* `ANIMATE_MOON_EVERY_N_FRAMES` - only enabled when `STATIC_MOON` is disabled, this affects how often the moon changes phases.
Example:
```c
#define STARRY_NIGHT_ANIM_FRAME_DURATION 30
#ifndef STATIC_MOON
# define ANIMATE_MOON_EVERY_N_FRAMES 100
#endif
```
would result in the moon changing phases every 3000ms, or every 3 seconds.
## Ocean
### Description
The 🌊 ocean animation is a full width animation of ocean waves, where the waves get rougher the faster you type.
You can configure the boundaries for each degree of _wave ferocity_ as well as how fast the ocean/waves move.
### Flags
* `OCEAN_LINE` - where to render the ocean at. Defaults to `14`. (see [reference](#reference))
* `OCEAN_ANIMATION_SPEED` - configures the number of frames you want to animate the ocean at.
Must be equal to or lower than `NUMBER_OF_FRAMES`.
Example:
```c
#define NUMBER_OF_FRAMES 20
#define OCEAN_ANIMATION_SPEED 5
```
would result in the ocean animation happening every 4 frames. 20 would result in every frame,
1 would be once every 20 frames. This essentially changes how fast the waves will move.
* `WAVE_CALM` - Defines the WPM at which the _Wave Ferocity_ kicks up.
At any WPM between `WAVE_CALM` and `WAVE_HEAVY_STORM`, the waves will be just tiny ripples.
* `WAVE_HEAVY_STORM` - Defines the WPM at which the _Wave Ferocity_ kicks up to medium.
At any WPM between `WAVE_HEAVY_STORM` and `WAVE_HURRICANE`, the waves will be medium sized waves.
* `WAVE_HURRICANE` - Defines the WPM at which the _Wave Ferocity_ kicks up to the last notch.
At any WPM above `WAVE_HURRICANE`, the waves will be torrential.
## Shooting Stars
The 🌠 shooting star animation is a full screen animation that renders a meteor shower based on your typing speed. The
faster you type, the more shooting stars there are!
You can configure many parts of the shooting stars, from shower size, to speed, to length of each trail, to how spaced
out they are.
Note: Each frame of a shooting star is only 2 pixels in length. This is a design decision, and could probably be changed
with a decent amount of work, but was chosen for looks and memory constraints.
### Flags
* `SHOOTING_STAR_DELAY` - Decides number of frames to delay, based on modulus, e.g. 12 means 0-11 frames of delay between each shooting star
* `SHOOTING_STAR_FRAMES` - how long each shooting star will be. A size of `16` will result in shooting stars that are 32 pixels long
* `MAX_NUMBER_OF_SHOOTING_STARS` - maximum number of shooting stars that can be on screen at the same time
* `SHOOTING_STAR_WPM_INCREMENT` - every n WPM increase, add an extra star, up to MAX_NUMBER_OF_SHOOTING_STARS
Example: an increment of 5 would result in 1 shooting star at 5-9wpm, 2 at 10-14, etc.
* `SHOOTING_STAR_ANIMATION_SPEED` - configures the number of frames you want to animate the shooting stars at.
Must be equal to or lower than `NUMBER_OF_FRAMES`.
Example:
```c
#define NUMBER_OF_FRAMES 20
#define SHOOTING_STAR_ANIMATION_SPEED 5
```
would result in the shooting star animation happening every 4 frames. 20 would result in every frame,
1 would be once every 20 frames. This essentially changes how fast the stars move through the sky.
## Island
The 🏝 island animation is a 32w x 16h animation of a small island with a single palm tree blowing in the wind. The faster
you type the harder the palm tree blows in the wind!
Since this animation has significant black space to the left side of the tree, certain design decisions were made to allow the
shooting stars to still show up in the sky there. This animation should work on any size screen >=32 pixels wide, and you
can place it anywhere on the screen, but above the ocean is recommended.
### Flags
* `ISLAND_LINE` - where to render the island at. Defaults to `12`. The island is 2 lines tall. (see [reference](#reference))
* `ISLAND_COLUMN` - where to render the island at. Defaults to `0`. The island is 32 pixels wide. (see [reference](#reference))
* `ISLAND_CALM` - Defines the WPM at which the _Storm Ferocity_ kicks up.
At any WPM between `ISLAND_CALM` and `ISLAND_HEAVY_STORM`, the palm tree will just calmly blow in the wind.
* `ISLAND_HEAVY_STORM` - Defines the WPM at which the _Storm Ferocity_ kicks up.
At any WPM between `ISLAND_HEAVY_STORM` and `ISLAND_HURRICANE`, the palm tree will be blowing hard in the wind
* `ISLAND_HURRICANE` - Defines the WPM at which the _Storm Ferocity_ kicks up.
At any WPM above `ISLAND_HURRICANE`, the palm tree will almost be torn from its roots!
# Reference
Any reference to `_LINE` or `COLUMN` refers to setting a cursor position using `oled_set_cursor()`, which uses
`OLED_FONT_WIDTH` and `OLED_FONT_HEIGHT` internally.
This will be the top-leftmost pixel of the image, so `_LINE 1` would start at the 9th pixel down and `_COLUMN 1`
would be the 7th pixel to the right, starting from the topleftmost pixel on the screen.
This code has been untested with different font heights/widths, so you might have to adjust a bit to make it work if you
have modified those values.
# ToDo
- [ ] don't require `is_calm` as a keyboard event. Not sure if the code will work without it currently.
- [ ] make all the stars twinkle brightly based on keypresses rather than timed. Not just a movement twinkle, but a larger
'full' twinkle, where the star actually gets bigger. This will be quite difficult, thus is left out of the v1.

27
users/snowe/rules.mk Normal file
View file

@ -0,0 +1,27 @@
ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes)
SRC += oled_setup.c
ifdef OCEAN_DREAM_ENABLE
ifeq ($(strip $(OCEAN_DREAM_ENABLE)), yes)
SRC += ocean_dream.c
OPT_DEFS += -DOCEAN_DREAM_ENABLE
endif
endif
ifndef OCEAN_DREAM_ENABLE
SRC += ocean_dream.c
OPT_DEFS += -DOCEAN_DREAM_ENABLE
endif
ifdef LUNA_ENABLE
ifeq ($(strip $(LUNA_ENABLE)), yes)
SRC += luna.c
OPT_DEFS += -DLUNA_ENABLE
endif
endif
ifndef LUNA_ENABLE
SRC += luna.c
OPT_DEFS += -DLUNA_ENABLE
endif
endif

43
users/snowe/snowe.h Normal file
View file

@ -0,0 +1,43 @@
/*
Copyright 2021 Tyler Thrailkill <@snowe/@snowe2010>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include QMK_KEYBOARD_H
#ifndef QMK_FIRMWARE_SNOWE_H
# define QMK_FIRMWARE_SNOWE_H ;
#endif // QMK_FIRMWARE_SNOWE_H
#include "wrappers.h"
#include "keycode_aliases.h"
#define IGNORE_MOD_TAP_INTERRUPT
#undef PERMISSIVE_HOLD
//#if defined(RGBLIGHT_ENABLE)
//# include "rgb_stuff.h"
//#endif
//#if defined(RGB_MATRIX_ENABLE)
//# include "rgb_matrix_stuff.h"
//#endif
#ifdef OLED_DRIVER_ENABLE
# include "oled_setup.h"
#endif
enum layers { _MAIN, _LOWER, _UPPER, _ADJUST };

92
users/snowe/wrappers.h Normal file
View file

@ -0,0 +1,92 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "snowe.h"
/*
Since our quirky block definitions are basically a list of comma separated
arguments, we need a wrapper in order for these definitions to be
expanded before being used as arguments to the LAYOUT_xxx macro.
*/
#if (!defined(LAYOUT) && defined(KEYMAP))
# define LAYOUT KEYMAP
#endif
//#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__)
//#define LAYOUT_ergodox_pretty_wrapper(...) LAYOUT_ergodox_pretty(__VA_ARGS__)
#define KEYMAP_wrapper(...) LAYOUT(__VA_ARGS__)
#define LAYOUT_wrapper(...) LAYOUT(__VA_ARGS__)
//#define LAYOUT_ortho_4x12_wrapper(...) LAYOUT_ortho_4x12(__VA_ARGS__)
//#define LAYOUT_ortho_5x12_wrapper(...) LAYOUT_ortho_5x12(__VA_ARGS__)
//#define LAYOUT_gergo_wrapper(...) LAYOUT_gergo(__VA_ARGS__)
/*
Blocks for each of the four major keyboard layouts
Organized so we can quickly adapt and modify all of them
at once, rather than for each keyboard, one at a time.
And this allows for much cleaner blocks in the keymaps.
For instance Tap/Hold for Control on all of the layouts
NOTE: These are all the same length. If you do a search/replace
then you need to add/remove underscores to keep the
lengths consistent.
*/
#define _________________QWERTY_L1_________________ KC_Q, KC_W, KC_E, KC_R, KC_T
#define _________________QWERTY_L2_________________ KC_A, KC_S, KC_D, KC_F, KC_G
#define _________________QWERTY_L3_________________ KC_Z, KC_X, KC_C, KC_V, KC_B
#define _________________QWERTY_R1_________________ KC_Y, KC_U, KC_I, KC_O, KC_P
#define _________________QWERTY_R2_________________ KC_H, KC_J, KC_K, KC_L, KC_SCLN
#define _________________QWERTY_R3_________________ KC_N, KC_M, KC_COMM, KC_DOT, KC_SLASH
#define ________________NUMBER_LEFT________________ KC_1, KC_2, KC_3, KC_4, KC_5
#define ________________NUMBER_RIGHT_______________ KC_6, KC_7, KC_8, KC_9, KC_0
//#define ________________NUMBER_RIGHT_______________ KC_6, KC_7, TD(TD_8_UP), KC_9, KC_0
#define _________________FUNC_LEFT_________________ KC_F1, KC_F2, KC_F3, KC_F4, KC_F5
#define _________________FUNC_RIGHT________________ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10
#define ___________________BLANK___________________ _______, _______, _______, _______, _______
#define _________________LOWER_L1__________________ KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC
#define _________________LOWER_L2__________________ _________________FUNC_LEFT_________________
#define _________________LOWER_L3__________________ _________________FUNC_RIGHT________________
#define _________________LOWER_R1__________________ KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN
#define _________________LOWER_R2__________________ _______, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR
#define _________________LOWER_R3__________________ _______, KC_LEFT, KC_UP , KC_DOWN, KC_RGHT
#define _________________RAISE_L1__________________ ________________NUMBER_LEFT________________
#define _________________RAISE_L2__________________ _______, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC
#define _________________RAISE_L3__________________ ___________________BLANK___________________
#define _________________RAISE_R1__________________ ________________NUMBER_RIGHT_______________
#define _________________RAISE_R2__________________ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, _______
#define _________________RAISE_R3__________________ _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END
#define _________________ADJUST_L1_________________ RGB_MOD, RGB_HUI, RGB_SAI, RGB_VAI, RGB_TOG
#define _________________ADJUST_L2_________________ MU_TOG , CK_TOGG, AU_ON, AU_OFF, AG_NORM
#define _________________ADJUST_L3_________________ RGB_RMOD,RGB_HUD,RGB_SAD, RGB_VAD, _______
#define _________________ADJUST_R1_________________ _______, _______, _______, _______, _______
#define _________________ADJUST_R2_________________ RESET, CG_TOGG, _______, _______, _______
#define _________________ADJUST_R3_________________ _______, KC_MNXT, KC_VOLU, KC_VOLD, KC_MPLY