aboutsummaryrefslogtreecommitdiff
path: root/users
diff options
context:
space:
mode:
authorQMK Bot <hello@qmk.fm>2021-06-24 02:22:11 +0000
committerQMK Bot <hello@qmk.fm>2021-06-24 02:22:11 +0000
commitb69fa51ec39d2825067b11f065ff8e59e41d8dc9 (patch)
treec36f3c63b8472a1f5b951cc9e2e5a03df1532fee /users
parent1ea01765e19bf84b9a09954443b7d64be2bec0c7 (diff)
parent909d9c228fb03750170aa7ca49ea10d08a6e1113 (diff)
downloadqmk_firmware-b69fa51ec39d2825067b11f065ff8e59e41d8dc9.tar.gz
qmk_firmware-b69fa51ec39d2825067b11f065ff8e59e41d8dc9.zip
Merge remote-tracking branch 'origin/master' into develop
Diffstat (limited to 'users')
-rw-r--r--users/snowe/luna.c229
-rw-r--r--users/snowe/luna.h31
-rw-r--r--users/snowe/ocean_dream.c555
-rw-r--r--users/snowe/ocean_dream.h103
-rw-r--r--users/snowe/oled_setup.c141
-rw-r--r--users/snowe/oled_setup.h30
-rw-r--r--users/snowe/readme.md10
-rw-r--r--users/snowe/readme_ocean_dream.md258
-rw-r--r--users/snowe/rules.mk27
-rw-r--r--users/snowe/snowe.h43
-rw-r--r--users/snowe/wrappers.h92
11 files changed, 1519 insertions, 0 deletions
diff --git a/users/snowe/luna.c b/users/snowe/luna.c
new file mode 100644
index 000000000..4653abfae
--- /dev/null
+++ b/users/snowe/luna.c
@@ -0,0 +1,229 @@
1/*
2 * Copyright 2021 QMK Community
3 * Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "quantum.h"
20#include "luna.h"
21
22// KEYBOARD PET START
23
24// settings
25#define MIN_WALK_SPEED 10
26#define MIN_RUN_SPEED 40
27
28// advanced settings
29#define ANIM_FRAME_DURATION 200 // how long each frame lasts in ms
30#define ANIM_SIZE 96 // number of bytes in array. If you change sprites, minimize for adequate firmware size. max is 1024
31
32bool isSneaking = false;
33bool isJumping = false;
34bool showedJump = true;
35
36// status variables
37int current_wpm = 0;
38led_t led_usb_state = {
39 .num_lock = false,
40 .caps_lock = false,
41 .scroll_lock = false
42};
43
44// current frame
45uint8_t current_frame = 0;
46
47// timers
48uint32_t anim_timer = 0;
49uint32_t anim_sleep = 0;
50
51// logic
52void render_luna(int LUNA_X, int LUNA_Y) {
53
54 // Sit
55 static const char PROGMEM sit[2][ANIM_SIZE] = {
56 // 'sit1', 32x22px
57 {
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1c,
59 0x02, 0x05, 0x02, 0x24, 0x04, 0x04, 0x02, 0xa9, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x08, 0x68, 0x10, 0x08, 0x04, 0x03, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x82, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0c, 0x10, 0x10, 0x20, 0x20, 0x20, 0x28,
63 0x3e, 0x1c, 0x20, 0x20, 0x3e, 0x0f, 0x11, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 },
65
66 // 'sit2', 32x22px
67 {
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1c,
69 0x02, 0x05, 0x02, 0x24, 0x04, 0x04, 0x02, 0xa9, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x90, 0x08, 0x18, 0x60, 0x10, 0x08, 0x04, 0x03, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x82, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0c, 0x10, 0x10, 0x20, 0x20, 0x20, 0x28,
73 0x3e, 0x1c, 0x20, 0x20, 0x3e, 0x0f, 0x11, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
74 }
75 };
76
77 // Walk
78 static const char PROGMEM walk[2][ANIM_SIZE] = {
79 // 'walk1', 32x22px
80 {
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x90, 0x90, 0x90, 0xa0, 0xc0, 0x80, 0x80,
82 0x80, 0x70, 0x08, 0x14, 0x08, 0x90, 0x10, 0x10, 0x08, 0xa4, 0x78, 0x80, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
84 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x18, 0xea, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x20, 0x20, 0x3c, 0x0f, 0x11, 0x1f, 0x03,
86 0x06, 0x18, 0x20, 0x20, 0x3c, 0x0c, 0x12, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 },
88
89 // 'walk2', 32x22px
90 {
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x20, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00,
92 0x00, 0xe0, 0x10, 0x28, 0x10, 0x20, 0x20, 0x20, 0x10, 0x48, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x20, 0xf8, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
94 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x30, 0xd5, 0x20, 0x1f, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x30, 0x0c, 0x02, 0x05, 0x09, 0x12, 0x1e,
96 0x02, 0x1c, 0x14, 0x08, 0x10, 0x20, 0x2c, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 }
98 };
99
100 // Run
101 static const char PROGMEM run[2][ANIM_SIZE] = {
102 // 'run1', 32x22px
103 {
104 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x08, 0x08, 0xc8, 0xb0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
105 0x80, 0x40, 0x40, 0x3c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xc4, 0xa4, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc8, 0x58, 0x28, 0x2a, 0x10, 0x0f, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x09, 0x04, 0x04, 0x04, 0x04, 0x02, 0x03, 0x02, 0x01, 0x01,
109 0x02, 0x02, 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
110 },
111
112 // 'run2', 32x22px
113 {
114 0x00, 0x00, 0x00, 0xe0, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
115 0x80, 0x80, 0x78, 0x28, 0x08, 0x10, 0x20, 0x30, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0xb0, 0x50, 0x55, 0x20, 0x1f, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37,
119 0x02, 0x1e, 0x20, 0x20, 0x18, 0x0c, 0x14, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 }
121 };
122
123 // Bark
124 static const char PROGMEM bark[2][ANIM_SIZE] = {
125 // 'bark1', 32x22px
126 {
127 0x00, 0xc0, 0x20, 0x10, 0xd0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40,
128 0x3c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x80, 0xc8, 0x48, 0x28, 0x2a, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x02,
132 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 },
134
135 // 'bark2', 32x22px
136 {
137 0x00, 0xe0, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40,
138 0x40, 0x2c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x48, 0x28, 0x2a, 0x10, 0x0f, 0x20, 0x4a, 0x09, 0x10,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x02,
142 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 }
144 };
145
146 // Sneak
147 static const char PROGMEM sneak[2][ANIM_SIZE] = {
148 // 'sneak1', 32x22px
149 {
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0xc0, 0x40, 0x40, 0x80, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x1e, 0x21, 0xf0, 0x04, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04,
153 0x04, 0x04, 0x03, 0x01, 0x00, 0x00, 0x09, 0x01, 0x80, 0x80, 0xab, 0x04, 0xf8, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x20, 0x20, 0x3c, 0x0f, 0x11, 0x1f, 0x02, 0x06,
155 0x18, 0x20, 0x20, 0x38, 0x08, 0x10, 0x18, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
156 },
157
158 // 'sneak2', 32x22px
159 {
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0xe0, 0xa0, 0x20, 0x40, 0x80, 0xc0, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x3e, 0x41, 0xf0, 0x04, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x04,
163 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x40, 0x55, 0x82, 0x7c, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x30, 0x0c, 0x02, 0x05, 0x09, 0x12, 0x1e, 0x04,
165 0x18, 0x10, 0x08, 0x10, 0x20, 0x28, 0x34, 0x06, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
166 }
167 };
168
169 // animation
170 void animation_phase(void) {
171
172 // jump
173 if (isJumping || !showedJump) {
174
175 // clear
176 oled_set_cursor(LUNA_X,LUNA_Y +2);
177 oled_write(" ", false);
178
179 oled_set_cursor(LUNA_X,LUNA_Y -1);
180
181 showedJump = true;
182 } else {
183
184 // clear
185 oled_set_cursor(LUNA_X,LUNA_Y -1);
186 oled_write(" ", false);
187
188 oled_set_cursor(LUNA_X,LUNA_Y);
189 }
190
191 // switch frame
192 current_frame = (current_frame + 1) % 2;
193
194 // current status
195 if(led_usb_state.caps_lock) {
196 oled_write_raw_P(bark[abs(1 - current_frame)], ANIM_SIZE);
197
198 } else if(isSneaking) {
199 oled_write_raw_P(sneak[abs(1 - current_frame)], ANIM_SIZE);
200
201 } else if(current_wpm <= MIN_WALK_SPEED) {
202 oled_write_raw_P(sit[abs(1 - current_frame)], ANIM_SIZE);
203
204 } else if(current_wpm <= MIN_RUN_SPEED) {
205 oled_write_raw_P(walk[abs(1 - current_frame)], ANIM_SIZE);
206
207 } else {
208 oled_write_raw_P(run[abs(1 - current_frame)], ANIM_SIZE);
209 }
210 }
211
212 // animation timer
213 if(timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) {
214 anim_timer = timer_read32();
215 current_wpm = get_current_wpm();
216 animation_phase();
217 }
218
219 // this fixes the screen on and off bug
220 if (current_wpm > 0) {
221 oled_on();
222 anim_sleep = timer_read32();
223 } else if(timer_elapsed32(anim_sleep) > OLED_TIMEOUT) {
224 oled_off();
225 }
226
227}
228
229// KEYBOARD PET END \ No newline at end of file
diff --git a/users/snowe/luna.h b/users/snowe/luna.h
new file mode 100644
index 000000000..c96d7a12d
--- /dev/null
+++ b/users/snowe/luna.h
@@ -0,0 +1,31 @@
1/*
2 * Copyright 2021 QMK Community
3 * Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#pragma once
20
21extern bool isSneaking;
22extern bool isJumping;
23extern bool showedJump;
24
25// status variables
26extern led_t led_usb_state;
27//extern int current_wpm;
28
29
30void render_luna(int LUNA_X, int LUNA_Y);
31
diff --git a/users/snowe/ocean_dream.c b/users/snowe/ocean_dream.c
new file mode 100644
index 000000000..2f372628d
--- /dev/null
+++ b/users/snowe/ocean_dream.c
@@ -0,0 +1,555 @@
1/*
2 * Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ocean_dream.h"
19#include "quantum.h"
20#include "print.h"
21
22// Calculated Parameters
23#define TWINKLE_PROBABILITY_MODULATOR 100 / TWINKLE_PROBABILITY // CALCULATED: Don't Touch
24#define TOTAL_STARS STARS_PER_LINE *NUMBER_OF_STAR_LINES // CALCULATED: Don't Touch
25#define OCEAN_ANIMATION_MODULATOR NUMBER_OF_FRAMES / OCEAN_ANIMATION_SPEED // CALCULATED: Don't Touch
26#define SHOOTING_STAR_ANIMATION_MODULATOR NUMBER_OF_FRAMES / SHOOTING_STAR_ANIMATION_SPEED // CALCULATED: Don't Touch
27#define STAR_ANIMATION_MODULATOR NUMBER_OF_FRAMES / STAR_ANIMATION_SPEED // CALCULATED: Don't Touch
28
29uint8_t animation_counter = 0; // global animation counter.
30bool is_calm = false;
31uint32_t starry_night_anim_timer = 0;
32uint32_t starry_night_anim_sleep = 0;
33static int current_wpm = 0;
34
35static uint8_t increment_counter(uint8_t counter, uint8_t max) {
36 counter++;
37 if (counter >= max) {
38 return 0;
39 } else {
40 return counter;
41 }
42}
43
44#ifdef ENABLE_WAVE
45static uint8_t decrement_counter(uint8_t counter, uint8_t max) {
46 counter--;
47 if (counter < 0 || counter > max) {
48 return max;
49 } else {
50 return counter;
51 }
52}
53#endif
54
55#ifdef ENABLE_MOON // region
56# ifndef STATIC_MOON
57uint8_t moon_animation_frame = 0; // keeps track of current moon frame
58uint16_t moon_animation_counter = 0; // counts how many frames to wait before animating moon to next frame
59# endif
60
61# ifdef STATIC_MOON
62static const char PROGMEM moon[6] = {
63 0x18, 0x7E, 0xFF, 0xC3, 0x81, 0x81,
64};
65# endif
66
67# ifndef STATIC_MOON
68static const char PROGMEM moon_animation[14][8] = {
69 // clang-format off
70 { 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
71 { 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x42, 0x00, },
72 { 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xC3, 0x00, 0x00, },
73 { 0x3C, 0x7E, 0xFF, 0xFF, 0xC3, 0x81, 0x00, 0x00, },
74 { 0x3C, 0x7E, 0xFF, 0xC3, 0x81, 0x00, 0x00, 0x00, },
75 { 0x3C, 0x7E, 0xC3, 0x81, 0x81, 0x00, 0x00, 0x00, },
76 { 0x3C, 0x42, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, },
77 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
78 { 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x42, 0x3C, },
79 { 0x00, 0x00, 0x00, 0x81, 0x81, 0xC3, 0x7E, 0x3C, },
80 { 0x00, 0x00, 0x00, 0x81, 0xC3, 0xFF, 0x7E, 0x3C, },
81 { 0x00, 0x00, 0x81, 0xC3, 0xFF, 0xFF, 0x7E, 0x3C, },
82 { 0x00, 0x00, 0xC3, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
83 { 0x00, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
84 // clang-format on
85};
86# endif
87
88static void draw_moon(void) {
89# ifdef STATIC_MOON
90 oled_set_cursor(MOON_COLUMN, MOON_LINE);
91 oled_write_raw_P(moon, 6);
92# endif
93# ifndef STATIC_MOON
94 moon_animation_counter = increment_counter(moon_animation_counter, ANIMATE_MOON_EVERY_N_FRAMES);
95 if (moon_animation_counter == 0) {
96 moon_animation_frame = increment_counter(moon_animation_frame, 14);
97 oled_set_cursor(MOON_COLUMN, MOON_LINE);
98 oled_write_raw_P(moon_animation[moon_animation_frame], 8);
99 }
100# endif
101}
102#endif // endregion
103
104#ifdef ENABLE_WAVE // region
105uint8_t starry_night_wave_frame_width_counter = 31;
106uint8_t rough_waves_frame_counter = 0;
107
108// clang-format off
109static const char PROGMEM ocean_top[8][32] = {
110 // still ocean
111 {
112 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
113 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
114 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
115 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
116 },
117 // small ripples
118 {
119 0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
120 0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
121 0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
122 0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
123 },
124 // level 2 ripples
125 {
126 0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
127 0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
128 0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
129 0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
130 },
131 // level 3 waves
132 {
133 0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
134 0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
135 0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
136 0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
137 },
138 {
139 0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
140 0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
141 0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
142 0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
143 },
144 {
145 0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
146 0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
147 0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
148 0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
149 },
150};
151static const char PROGMEM ocean_bottom[8][32] = {
152 // still ocean
153 {
154 0x00, 0x40, 0x40, 0x41, 0x01, 0x01, 0x01, 0x21,
155 0x20, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x44,
156 0x44, 0x40, 0x40, 0x00, 0x00, 0x08, 0x08, 0x00,
157 0x01, 0x01, 0x01, 0x00, 0x40, 0x40, 0x00, 0x00,
158 },
159 // small ripples
160 {
161 0x00, 0x00, 0x40, 0x40, 0x01, 0x01, 0x01, 0x20,
162 0x20, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
163 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
164 0x00, 0x01, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00,
165 },
166 // level 2 ripples
167 {
168 0x00, 0x00, 0x40, 0x40, 0x01, 0x01, 0x01, 0x20,
169 0x20, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
170 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
171 0x00, 0x01, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00,
172 },
173 // level 3 waves
174 {
175 0x00, 0x40, 0x40, 0x42, 0x42, 0x03, 0x11, 0x11,
176 0x20, 0x20, 0x00, 0x00, 0x08, 0x0C, 0x0C, 0x04,
177 0x05, 0x41, 0x41, 0x21, 0x20, 0x00, 0x00, 0x08,
178 0x0A, 0x0A, 0x0B, 0x41, 0x41, 0x41, 0x41, 0x00,
179 },
180 {
181 0x10, 0x10, 0x00, 0x80, 0x84, 0xC4, 0x02, 0x06,
182 0x84, 0x44, 0xC0, 0x80, 0x80, 0x20, 0x20, 0x10,
183 0x08, 0x12, 0x91, 0x81, 0x42, 0x40, 0x00, 0x00,
184 0x10, 0x12, 0x22, 0x22, 0x24, 0x04, 0x84, 0x80,
185 },
186 {
187 0x08, 0x80, 0x80, 0x82, 0x82, 0x03, 0x21, 0x21,
188 0x10, 0x10, 0x00, 0x00, 0x04, 0x04, 0x0C, 0x08,
189 0x09, 0x41, 0x42, 0x22, 0x20, 0x00, 0x00, 0x08,
190 0x0A, 0x0A, 0x0B, 0x41, 0x43, 0x42, 0x42, 0x00,
191 },
192};
193// clang-format on
194
195static void animate_waves(void) {
196 starry_night_wave_frame_width_counter = decrement_counter(starry_night_wave_frame_width_counter, WIDTH - 1); // only 3 frames for last wave type
197 rough_waves_frame_counter = increment_counter(rough_waves_frame_counter, 3); // only 3 frames for last wave type
198
199 void draw_ocean(uint8_t frame, uint16_t offset, uint8_t byte_index) {
200 oled_write_raw_byte(pgm_read_byte(ocean_top[frame] + byte_index), offset);
201 oled_write_raw_byte(pgm_read_byte(ocean_bottom[frame] + byte_index), offset + WIDTH);
202 }
203
204 for (int i = 0; i < WIDTH; ++i) {
205 uint16_t offset = OCEAN_LINE * WIDTH + i;
206 uint8_t byte_index = starry_night_wave_frame_width_counter + i;
207 if (byte_index >= WIDTH) {
208 byte_index = byte_index - WIDTH;
209 }
210 if (is_calm || current_wpm <= WAVE_CALM) {
211 draw_ocean(0, offset, byte_index);
212 } else if (current_wpm <= WAVE_HEAVY_STORM) {
213 draw_ocean(1, offset, byte_index);
214 } else if (current_wpm <= WAVE_HURRICANE) {
215 draw_ocean(2, offset, byte_index);
216 } else {
217 draw_ocean(3 + rough_waves_frame_counter, offset, byte_index);
218 }
219 }
220}
221#endif // endregion
222
223#ifdef ENABLE_ISLAND // region
224uint8_t island_frame_1 = 0;
225
226// clang-format off
227// 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!)
228
229// To save space and allow the shooting stars to be seen, only draw the tree on every frame.
230// Tree is only 14bytes wide so we save 108 bytes on just the first row. Second row, the
231// first 18 bytes is always the same piece of land, so only store that once, which saves 90 bytes
232static const char PROGMEM islandRightTop[6][14] = {
233 {0x84, 0xEC, 0x6C, 0x3C, 0xF8, 0xFE, 0x3F, 0x6B, 0xDB, 0xB9, 0x30, 0x40, 0x00, 0x00,},
234 {0x80, 0xC3, 0xEE, 0x7C, 0xB8, 0xFC, 0xFE, 0x6F, 0xDB, 0x9B, 0xB2, 0x30, 0x00, 0x00,},
235 {0x00, 0xC0, 0xEE, 0x7F, 0x3D, 0xF8, 0xFC, 0x7E, 0x57, 0xDB, 0xDB, 0x8A, 0x00, 0x00,},
236 {0x00, 0xC0, 0xE6, 0x7F, 0x3B, 0xF9, 0xFC, 0xFC, 0xB6, 0xB3, 0x33, 0x61, 0x00, 0x00,},
237 {0x00, 0x00, 0x00, 0x00, 0x80, 0xEE, 0xFF, 0xFB, 0xF9, 0xFC, 0xDE, 0xB6, 0xB6, 0x24,},
238 {0x00, 0x00, 0x00, 0x00, 0xC0, 0xEE, 0xFE, 0xFF, 0xFB, 0xFD, 0xEE, 0xB6, 0xB6, 0x92,},
239};
240static const char PROGMEM islandRightBottom[6][14] = {
241 {0x41, 0x40, 0x60, 0x3E, 0x3F, 0x23, 0x20, 0x60, 0x41, 0x43, 0x40, 0x40, 0x40, 0x80,},
242 {0x40, 0x41, 0x60, 0x3E, 0x3F, 0x23, 0x20, 0x60, 0x40, 0x40, 0x41, 0x41, 0x40, 0x80,},
243 {0x40, 0x40, 0x61, 0x3D, 0x3F, 0x27, 0x21, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x80,},
244 {0x40, 0x43, 0x61, 0x3C, 0x3F, 0x27, 0x21, 0x60, 0x41, 0x43, 0x43, 0x42, 0x40, 0x80,},
245 {0x40, 0x40, 0x60, 0x3C, 0x3F, 0x27, 0x23, 0x63, 0x44, 0x40, 0x41, 0x41, 0x41, 0x81,},
246 {0x40, 0x40, 0x60, 0x3C, 0x3F, 0x27, 0x23, 0x63, 0x42, 0x42, 0x41, 0x41, 0x41, 0x80,},
247};
248static const char PROGMEM islandLeft[18] = {
249 0x80, 0x40, 0x40, 0x40, 0x40, 0x60,
250 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
251 0x20, 0x20, 0x20, 0x60, 0x40, 0x40,
252};
253// clang-format on
254
255static void animate_island(void) {
256 if (animation_counter == 0) {
257 island_frame_1 = increment_counter(island_frame_1, 2);
258 }
259
260 void draw_island_parts(uint8_t frame) {
261 oled_set_cursor(ISLAND_COLUMN + 3, ISLAND_LINE);
262 oled_write_raw_P(islandRightTop[frame], 14);
263 oled_set_cursor(ISLAND_COLUMN + 0, ISLAND_LINE + 1);
264 oled_write_raw_P(islandLeft, 18);
265 oled_set_cursor(ISLAND_COLUMN + 3, ISLAND_LINE + 1);
266 oled_write_raw_P(islandRightBottom[frame], 14);
267 }
268
269 if (is_calm || current_wpm < ISLAND_CALM) {
270 draw_island_parts(0);
271 } else if (current_wpm >= ISLAND_CALM && current_wpm < ISLAND_HEAVY_STORM) {
272 draw_island_parts(island_frame_1 + 1);
273 } else if (current_wpm >= ISLAND_HEAVY_STORM && current_wpm < ISLAND_HURRICANE) {
274 draw_island_parts(island_frame_1 + 2);
275 } else {
276 draw_island_parts(island_frame_1 + 4);
277 }
278}
279#endif // endregion
280
281#ifdef ENABLE_STARS // region
282bool stars_setup = false; // only setup stars once, then we just twinkle them
283struct Coordinate {
284 int x;
285 int y;
286 bool exists;
287};
288
289struct Coordinate stars[TOTAL_STARS]; // tracks all stars/coordinates
290
291/**
292 * Setup all the initial stars on the screen
293 * This function divides the screen into regions based on STARS_PER_LINE and NUMBER_OF_STAR_LINES
294 * where each line is made up of 8x8 pixel groups, that are populated by a single star.
295 *
296 * Not sure how this function will work with larger or smaller screens.
297 * It should be fine, as long as the screen width is a multiple of 8
298 */
299static void setup_stars(void) {
300 // For every line, split the line into STARS_PER_LINE, find a random point in that region, and turn the pixel on
301 // 36% probability it will not be added
302 // (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)
303 for (int line = 0; line < NUMBER_OF_STAR_LINES; ++line) {
304 for (int column_group = 0; column_group < STARS_PER_LINE; ++column_group) {
305 uint8_t rand_column = rand() % 10;
306 uint8_t rand_row = rand() % 10;
307 if (rand_column < 8 && rand_row < 8) {
308 int column_adder = column_group * 8;
309 int line_adder = line * 8;
310 int x = rand_column + column_adder;
311 int y = rand_row + line_adder;
312 oled_write_pixel(x, y, true);
313 stars[column_group + (line * STARS_PER_LINE)].x = x;
314 stars[column_group + (line * STARS_PER_LINE)].y = y;
315 stars[column_group + (line * STARS_PER_LINE)].exists = true;
316 } else {
317 stars[column_group + (line * STARS_PER_LINE)].exists = false;
318 }
319 }
320 }
321 stars_setup = true;
322}
323
324/**
325 * Twinkle the stars (move them one pixel in any direction) with a probability of 50% to twinkle any given star
326 */
327static void twinkle_stars(void) {
328 for (int line = 0; line < NUMBER_OF_STAR_LINES; ++line) {
329 for (int column_group = 0; column_group < STARS_PER_LINE; ++column_group) {
330 struct Coordinate star = stars[column_group + (line * STARS_PER_LINE)];
331
332 // skip stars that were never added
333 if (!star.exists) {
334 continue;
335 }
336 if (rand() % TWINKLE_PROBABILITY_MODULATOR == 0) {
337 oled_write_pixel(star.x, star.y, false); // black out pixel
338
339 // don't allow stars to leave their own region
340 if (star.x == (column_group * 8)) { // star is the farthest left it can go in its region
341 star.x++; // move it right immediately
342 } else if (star.x == (((column_group + 1) * 8) - 1)) { // star is farthest right it can go in its region
343 star.x--; // move it left immediately
344 }
345 if (star.y == (line * 8)) { // star is the farthest up it can go in its region
346 star.y++; // move it down immediately
347 } else if (star.y == (((line + 1) * 8) - 1)) { // star is farthest down it can go in its region
348 star.y--; // move it up immediately
349 }
350
351 // now decide direction
352 int new_x;
353 int x_choice = rand() % 3;
354 if (x_choice == 0) {
355 new_x = star.x - 1;
356 } else if (x_choice == 1) {
357 new_x = star.x + 1;
358 } else {
359 new_x = star.x;
360 }
361
362 int new_y;
363 int y_choice = rand() % 3;
364 if (y_choice == 0) {
365 new_y = star.y - 1;
366 } else if (y_choice == 1) {
367 new_y = star.y + 1;
368 } else {
369 new_y = star.y;
370 }
371
372 star.x = new_x;
373 star.y = new_y;
374 oled_write_pixel(new_x, new_y, true);
375 }
376
377 stars[column_group + (line * STARS_PER_LINE)] = star;
378 }
379 }
380}
381
382/**
383 * Setup the stars and then animate them on subsequent frames
384 */
385static void animate_stars(void) {
386 if (!stars_setup) {
387 setup_stars();
388 } else {
389 twinkle_stars();
390 }
391}
392#endif // endregion
393
394#ifdef ENABLE_SHOOTING_STARS // region
395bool shooting_stars_setup = false; // only setup shooting stars array once with defaults
396
397struct ShootingStar {
398 int x_1;
399 int y_1;
400 int x_2;
401 int y_2;
402 bool running;
403 int frame;
404 int delay;
405};
406
407struct ShootingStar shooting_stars[MAX_NUMBER_OF_SHOOTING_STARS]; // tracks all the shooting stars
408
409static void setup_shooting_star(struct ShootingStar *shooting_star) {
410 int column_to_start = rand() % (WIDTH / 2);
411 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.
412
413 shooting_star->x_1 = column_to_start;
414 shooting_star->y_1 = row_to_start;
415 shooting_star->x_2 = column_to_start + 1;
416 shooting_star->y_2 = row_to_start + 1;
417 shooting_star->running = true;
418 shooting_star->frame++;
419 shooting_star->delay = rand() % SHOOTING_STAR_DELAY;
420}
421
422static void move_shooting_star(struct ShootingStar *shooting_star) {
423 oled_write_pixel(shooting_star->x_1, shooting_star->y_1, false);
424 oled_write_pixel(shooting_star->x_2, shooting_star->y_2, false);
425
426 shooting_star->x_1++;
427 shooting_star->y_1++;
428 shooting_star->x_2++;
429 shooting_star->y_2++;
430 shooting_star->frame++;
431
432 oled_write_pixel(shooting_star->x_1, shooting_star->y_1, true);
433 oled_write_pixel(shooting_star->x_2, shooting_star->y_2, true);
434}
435
436static void finish_shooting_star(struct ShootingStar *shooting_star) {
437 oled_write_pixel(shooting_star->x_1, shooting_star->y_1, false);
438 oled_write_pixel(shooting_star->x_2, shooting_star->y_2, false);
439 shooting_star->running = false;
440 shooting_star->frame = 0;
441}
442
443static void animate_shooting_star(struct ShootingStar *shooting_star) {
444 if (shooting_star->frame > SHOOTING_STAR_FRAMES) {
445 finish_shooting_star(shooting_star);
446 return;
447 } else if (!shooting_star->running) {
448 setup_shooting_star(shooting_star);
449 } else {
450 if (shooting_star->delay == 0) {
451 move_shooting_star(shooting_star);
452 } else {
453 shooting_star->delay--;
454 }
455 }
456}
457
458static void animate_shooting_stars(void) {
459 if (is_calm) {
460 return;
461 }
462 if (!shooting_stars_setup) {
463 for (int i = 0; i < MAX_NUMBER_OF_SHOOTING_STARS; ++i) {
464 shooting_stars[i].running = false;
465 }
466 shooting_stars_setup = true;
467 }
468 /**
469 * Fixes issue with stars that were falling _while_ the
470 * wpm dropped below the condition for them to keep falling
471 */
472 void end_extra_stars(uint8_t starting_index) {
473 for (int shooting_star_index = starting_index; shooting_star_index < MAX_NUMBER_OF_SHOOTING_STARS; ++shooting_star_index) {
474 struct ShootingStar shooting_star = shooting_stars[shooting_star_index];
475 if (shooting_star.running) {
476 finish_shooting_star(&shooting_star);
477 shooting_stars[shooting_star_index] = shooting_star;
478 }
479 }
480 }
481
482 int number_of_shooting_stars = current_wpm / SHOOTING_STAR_WPM_INCREMENT;
483 number_of_shooting_stars = (number_of_shooting_stars > MAX_NUMBER_OF_SHOOTING_STARS) ? MAX_NUMBER_OF_SHOOTING_STARS : number_of_shooting_stars;
484
485 if (number_of_shooting_stars == 0) {
486 // make sure all shooting_stars are ended
487 end_extra_stars(0);
488 } else {
489 for (int shooting_star_index = 0; shooting_star_index < number_of_shooting_stars; ++shooting_star_index) {
490 struct ShootingStar shooting_star = shooting_stars[shooting_star_index];
491 animate_shooting_star(&shooting_star);
492 shooting_stars[shooting_star_index] = shooting_star;
493 }
494 end_extra_stars(number_of_shooting_stars);
495 }
496}
497#endif // endregion
498
499/**
500 * Main rendering function
501 *
502 * Calls all different animations at different rates
503 */
504void render_stars(void) {
505 // // animation timer
506 if (timer_elapsed32(starry_night_anim_timer) > STARRY_NIGHT_ANIM_FRAME_DURATION) {
507 starry_night_anim_timer = timer_read32();
508 current_wpm = get_current_wpm();
509
510#ifdef ENABLE_ISLAND
511 animate_island();
512#endif
513
514#ifdef ENABLE_SHOOTING_STARS
515 if (animation_counter % SHOOTING_STAR_ANIMATION_MODULATOR == 0) {
516 animate_shooting_stars();
517 }
518#endif
519
520#ifdef ENABLE_STARS
521 // TODO offsetting the star animation from the wave animation would look better,
522 // but if I do that, then the stars appear in the water because
523 // the ocean animation has to wait a bunch of frames to overwrite it.
524 // Possible solutions:
525 // 1. Only draw stars to the top of the island/ocean.
526 // 2. Draw ocean every frame, only move ocean on frames matching modulus
527 // Problems:
528 // 1. What if someone wants to move the island up a bit, or they want to have the stars reflect in the water?
529 // 2. More cpu intensive. And I'm already running out of cpu as it is...
530 if (animation_counter % STAR_ANIMATION_MODULATOR == 0) {
531 animate_stars();
532 }
533#endif
534
535#ifdef ENABLE_WAVE
536 if (animation_counter % OCEAN_ANIMATION_MODULATOR == 0) {
537 animate_waves();
538 }
539#endif
540
541#ifdef ENABLE_MOON
542 draw_moon();
543#endif
544
545 animation_counter = increment_counter(animation_counter, NUMBER_OF_FRAMES);
546 }
547
548 // this fixes the screen on and off bug
549 if (current_wpm > 0) {
550 oled_on();
551 starry_night_anim_sleep = timer_read32();
552 } else if (timer_elapsed32(starry_night_anim_sleep) > OLED_TIMEOUT) {
553 oled_off();
554 }
555}
diff --git a/users/snowe/ocean_dream.h b/users/snowe/ocean_dream.h
new file mode 100644
index 000000000..498375559
--- /dev/null
+++ b/users/snowe/ocean_dream.h
@@ -0,0 +1,103 @@
1/*
2 * Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19#include "quantum.h"
20
21/**
22 * Features:
23 * You can turn on and off features in this section
24 */
25#define ENABLE_MOON // Uses 182 bytes
26#define ENABLE_WAVE // Uses 844 bytes
27#define ENABLE_SHOOTING_STARS // Uses 872 bytes
28#define ENABLE_ISLAND
29#define ENABLE_STARS // Uses 606 bytes
30
31/**
32 * Global Settings
33 */
34#define STARRY_NIGHT_ANIM_FRAME_DURATION 30 // how long each frame lasts in ms
35#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
36#define WIDTH OLED_DISPLAY_HEIGHT // for vertical displays
37#define HEIGHT OLED_DISPLAY_WIDTH // for vertical displays
38
39/**
40 * Moon Parameters
41 */
42#define MOON_LINE 4 // the line you want the moon to appear at
43#define MOON_COLUMN 4 // the column you want the moon to appear at
44//#define STATIC_MOON // uncomment this to make the moon a static image, no animation
45#ifndef STATIC_MOON
46# define ANIMATE_MOON_EVERY_N_FRAMES 100 // animate the moon every n frames
47#endif
48
49/**
50 * Wave Parameters
51 */
52#define OCEAN_LINE 14 // Line you want to render the ocean starting at (best at oled_max_lines() - 2)
53#define WAVE_CALM 20 // render calm ocean under this WPM and ripple ocean at this WPM
54#define WAVE_HEAVY_STORM 40 // render medium ocean at this WPM
55#define WAVE_HURRICANE 60 // render heavy waves above this WPM
56// What number of frames you want to animate the ocean at.
57// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 30, would animate on every other frame, 20, every third frame, etc
58// Don't set equal to 0.
59#define OCEAN_ANIMATION_SPEED 1
60
61/**
62 * Shooting Star Parameters
63 */
64#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
65#define SHOOTING_STAR_FRAMES 16 // how many 2 pixel frames per shooting star. Increment this for longer shooting stars
66#define MAX_NUMBER_OF_SHOOTING_STARS 12 // maximum number of shooting stars that can be on screen at the same time
67#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.
68// What number of frames you want to animate the shooting stars at.
69// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 30, would animate on every other frame, 20, every third frame, etc
70// Don't set equal to 0.
71#define SHOOTING_STAR_ANIMATION_SPEED 30
72
73/**
74 * Star Parameters
75 */
76#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)
77#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)
78#define TWINKLE_PROBABILITY 25 // probability that any star twinkles on a given frame
79// What number of frames you want to animate the stars at.
80// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 20, would animate on every frame, 10, every other frame, etc
81// Don't set equal to 0.
82#define STAR_ANIMATION_SPEED 1
83
84/**
85 * Island Parameters
86 */
87#define ISLAND_LINE 12 // line that the island starts at. Island is 2 lines tall
88#define ISLAND_COLUMN 0 // column that the island starts at
89#define ISLAND_CALM 20 // WPM at which the palm tree calmly moves
90#define ISLAND_HEAVY_STORM 40 // WPM at which the heavy storm occurs
91#define ISLAND_HURRICANE 60 // WPM at which THE HURRICANE STARTS
92
93/*
94 * DON'T TOUCH
95 */
96
97extern bool is_calm;
98
99// timers
100extern uint32_t starry_night_anim_timer;
101extern uint32_t starry_night_anim_sleep;
102
103void render_stars(void);
diff --git a/users/snowe/oled_setup.c b/users/snowe/oled_setup.c
new file mode 100644
index 000000000..b3e04df45
--- /dev/null
+++ b/users/snowe/oled_setup.c
@@ -0,0 +1,141 @@
1/*
2 * Copyright QMK Community
3 * Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef OLED_DRIVER_ENABLE
20
21# include QMK_KEYBOARD_H
22# include "quantum.h"
23# include "snowe.h"
24
25# include <stdio.h> // for keylog?
26
27oled_rotation_t oled_init_user(oled_rotation_t rotation) {
28 if (!is_master) {
29 return OLED_ROTATION_270; // flips the display 180 degrees if offhand
30 }
31 return OLED_ROTATION_270;
32}
33
34# define L_BASE 0
35# define L_LOWER 2
36# define L_RAISE 4
37# define L_ADJUST 8
38
39void oled_render_layer_state(void) {
40 oled_write_P(PSTR("Layer"), false);
41 switch (layer_state) {
42 case L_BASE:
43 oled_write_ln_P(PSTR("Main"), false);
44 break;
45 case L_LOWER:
46 oled_write_ln_P(PSTR("Bot"), false);
47 break;
48 case L_RAISE:
49 oled_write_ln_P(PSTR("Top"), false);
50 break;
51 case L_ADJUST:
52 case L_ADJUST | L_LOWER:
53 case L_ADJUST | L_RAISE:
54 case L_ADJUST | L_LOWER | L_RAISE:
55 oled_write_ln_P(PSTR("Comb"), false);
56 break;
57 }
58}
59
60char keylog_str[24] = {};
61
62const char code_to_name[60] = {
63 ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
64 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
65 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
66 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
67 'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\',
68 '#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '};
69
70void set_keylog(uint16_t keycode, keyrecord_t *record) {
71 char name = ' ';
72 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
73 keycode = keycode & 0xFF;
74 }
75 if (keycode < 60) {
76 name = code_to_name[keycode];
77 }
78
79 // update keylog
80 snprintf(keylog_str, sizeof(keylog_str), "%dx%d, k%2d : %c", record->event.key.row, record->event.key.col, keycode, name);
81}
82
83void oled_render_keylog(void) { oled_write(keylog_str, false); }
84
85// void render_bootmagic_status(bool status) {
86// /* Show Ctrl-Gui Swap options */
87// static const char PROGMEM logo[][2][3] = {
88// {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}},
89// {{0x95, 0x96, 0}, {0xb5, 0xb6, 0}},
90// };
91// if (status) {
92// oled_write_ln_P(logo[0][0], false);
93// oled_write_ln_P(logo[0][1], false);
94// } else {
95// oled_write_ln_P(logo[1][0], false);
96// oled_write_ln_P(logo[1][1], false);
97// }
98//}
99void render_bootmagic_status(void) {
100 /* Show Ctrl-Gui Swap options */
101 static const char PROGMEM logo[][2][3] = {
102 {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}},
103 {{0x95, 0x96, 0}, {0xb5, 0xb6, 0}},
104 };
105 oled_write_P(PSTR("BTMGK"), false);
106 oled_write_P(PSTR(""), false);
107 if (!keymap_config.swap_lctl_lgui) {
108 oled_write_P(logo[1][0], false);
109 oled_write_P(PSTR(" "), false);
110 oled_write_P(logo[1][1], false);
111 } else {
112 oled_write_P(logo[0][0], false);
113 oled_write_P(PSTR(" "), false);
114 oled_write_P(logo[0][1], false);
115 }
116 oled_write_P(PSTR(" NKRO "), keymap_config.nkro);
117 oled_write_P(PSTR("WPM: "), false);
118
119 char wpm[6];
120 itoa(get_current_wpm(), wpm, 10);
121 oled_write_ln(wpm, false);
122}
123
124void oled_task_user(void) {
125 if (is_master) {
126 oled_render_layer_state();
127 oled_render_keylog();
128 render_bootmagic_status();
129
130# ifdef LUNA_ENABLE
131 led_usb_state = host_keyboard_led_state();
132 render_luna(0, 13);
133# endif
134 } else {
135# ifdef OCEAN_DREAM_ENABLE
136 render_stars();
137# endif
138 }
139}
140
141#endif // OLED_DRIVER_ENABLE
diff --git a/users/snowe/oled_setup.h b/users/snowe/oled_setup.h
new file mode 100644
index 000000000..031ce6bd0
--- /dev/null
+++ b/users/snowe/oled_setup.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "quantum.h"
21#ifdef OLED_DRIVER_ENABLE
22# include "oled_driver.h"
23# define OLED_RENDER_WPM_COUNTER " WPM: "
24#endif
25#ifdef LUNA_ENABLE
26# include "luna.h"
27#endif
28#ifdef OCEAN_DREAM_ENABLE
29# include "ocean_dream.h"
30#endif \ No newline at end of file
diff --git a/users/snowe/readme.md b/users/snowe/readme.md
new file mode 100644
index 000000000..ff45c9df2
--- /dev/null
+++ b/users/snowe/readme.md
@@ -0,0 +1,10 @@
1# Welcome
2
3Welcome to my userspace.
4
5There's nothing really outstanding here, except the [Ocean Dream](readme_ocean_dream.md)
6animation I made.
7
8A lot of the code for my wrappers/keymaps came from other users.
9
10I will probably update this with more in-depth information later.
diff --git a/users/snowe/readme_ocean_dream.md b/users/snowe/readme_ocean_dream.md
new file mode 100644
index 000000000..ca15dd47c
--- /dev/null
+++ b/users/snowe/readme_ocean_dream.md
@@ -0,0 +1,258 @@
1# Ocean Dream
2
3Tapping away at your IMX Corne with Box Jades, you feel yourself
4drifting off, into a soundscape of waves and rustling leaves.
5You open your eyes only to find yourself in an _Ocean Dream_.
6
7Introducing, **Ocean Dream**, an animation for keyboards with tall OLED
8screens. Built for 128x32 screens, this animation should work for 128x64
9at least, though it hasn't been tested there.
10
11Completely customizable, you can change everything about the animation,
12from the number of falling stars, to how likely a star is to twinkle, and
13even if the moon has phases or not.
14
15# Installation
16
17Installation is easy.
18
191. Add `ocean.h` and `ocean.c` to your keyboard folder or userspace.
202. In your `keymap.c` or wherever you handle your oled code, add
21```c
22# ifdef OCEAN_DREAM_ENABLE
23 render_stars();
24# endif
25```
26to `oled_task_user(void)`, where you would like (see [my keymap](../../keyboards/crkbd/keymaps/snowe/keymap.c) for an example)
273. In your `keymap.c` or wherever you handle your process_record code,
28 add an event that sets `is_calm` when you press `ctrl`
29```c
30bool process_record_user(uint16_t keycode, keyrecord_t *record) {
31 switch (keycode) {
32 case KC_LCTL:
33 case KC_RCTL:
34#ifdef OCEAN_DREAM_ENABLE
35 is_calm = (record->event.pressed) ? true : false;
36#endif
37 break;
38 }
39 return true;
40}
41```
424. In your `rules.mk` to make it easier to turn the animation on/off, add
43```makefile
44ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes)
45 #... your code here...
46
47 ifdef OCEAN_DREAM_ENABLE
48 ifeq ($(strip $(OCEAN_DREAM_ENABLE)), yes)
49 SRC += ocean_dream.c
50 OPT_DEFS += -DOCEAN_DREAM_ENABLE
51 endif
52 endif
53 ifndef OCEAN_DREAM_ENABLE
54 SRC += ocean_dream.c
55 OPT_DEFS += -DOCEAN_DREAM_ENABLE
56 endif
57endif
58```
59
60You're done! Now you can enable **Ocean Dream** by simply turning on the OLED feature
61```makefile
62OLED_DRIVER_ENABLE = yes
63```
64
65And if you want to disable it without turning off the OLED Driver you can simply set
66```makefile
67OCEAN_DREAM_ENABLE = no
68```
69
70# Settings
71
72**Ocean Dream** comes with several different animations, all individually configurable:
73
74* 🌌 Stars that twinkle
75* 🌠 Meteor showers that get more vibrant the faster you type
76* 🌊 Waves that get rougher the faster you type
77* 🏝 An island with a palm tree that blows in the wind the faster you type
78* 🌗 A moon that goes through the moon phases (or not, your choice!)
79
80Each feature can be individually turned on and off, with a simple `#define`.
81
82You can see all the options and more documentation by looking at `ocean_dream.h`.
83
84All options come enabled by default.
85
86## Global Flags:
87
88### Toggles:
89
90You can toggle on/off any features using these flags:
91
92* `ENABLE_MOON` // Uses 182 bytes
93* `ENABLE_WAVE` // Uses 844 bytes
94* `ENABLE_SHOOTING_STARS` // Uses 872 bytes
95* `ENABLE_ISLAND`
96* `ENABLE_STARS` // Uses 606 bytes
97
98### Global Configuration:
99
100* `STARRY_NIGHT_ANIM_FRAME_DURATION` - configures how long each frame lasts in ms
101* `NUMBER_OF_FRAMES` - configures the number of frames that constitute a single 'round trip' of animation.
102 Enables keeping animations in sync/timed with each other.
103 Probably shouldn't touch this, not sure how stuff will work if it's changed.
104 If changed should probably be multiple of 1, 2, 3, 4, and 5
105* `WIDTH` - for vertical displays, configures the width (the shortest measurement of your display). defaults to `OLED_DISPLAY_HEIGHT`
106* `HEIGHT` - for vertical displays, configures the height (the longest measurement of your display). defaults to `OLED_DISPLAY_WIDTH`
107
108## Stars
109
110### Description
111
112The 🌌 stars animation is a background of slowly twinkling stars.
113The stars are built on a grid of sorts, where each cell of the grid
114is 8x8 pixels with 1 star per cell. There is a probability of any
115star twinkling on any given frame, decided by the corresponding flags.
116
117### Flags
118
119Enabled with the `#define ENABLE_STARS` directive.
120
121The stars come with several configuration options:
122
123* `STARS_PER_LINE` - configures the number of stars per line. Defaulting to 4, this would
124 mean that you have 4 stars across each line (8x32 on a 128x32 display), where each star
125 is in a 8x8 grid
126* `NUMBER_OF_STAR_LINES` - configures the number of lines to fill up with stars.
127 Defaults to 16, filling the whole display.
128* `TWINKLE_PROBABILITY` - configures the probability of a star twinkling on a given frame.
129* `STAR_ANIMATION_SPEED` - configures the number of frames you want to animate the star at.
130 Must be equal to or lower than `NUMBER_OF_FRAMES`.
131 Example:
132 ```c
133 #define NUMBER_OF_FRAMES 20
134 #define STAR_ANIMATION_SPEED 5
135 ```
136 would result in the star animation happening every 4 frames. 20 would result in every frame,
137 1 would be once every 20 frames. This essentially changes how fast stars will twinkle, but
138 does not change the probability of the stars twinkling.
139
140## Moon
141
142### Description
143
144The 🌗 moon animation is an 8x8 animation of a moon, or, if you are running out of program memory, you
145can set it to just a static crescent moon, with no animation.
146
147### Flags
148
149Enabled with the `#define ENABLE_MOON` directive.
150
151The moon comes with only a few configuration options:
152
153* `STATIC_MOON` - include this directive if you want your moon to have no animation. It will simply be a static crescent
154 moon, only taking up 6 bytes of space. If you do not include this directive, then the moon will have an animation.
155 The default is a moon with animation.
156* `MOON_LINE` - defines the line that the moon sits on. Default is `4`. (see [reference](#reference))
157* `MOON_COLUMN` - defines the column that the moon sits at. Default is `4`. (see [reference](#reference))
158* `ANIMATE_MOON_EVERY_N_FRAMES` - only enabled when `STATIC_MOON` is disabled, this affects how often the moon changes phases.
159 Example:
160 ```c
161 #define STARRY_NIGHT_ANIM_FRAME_DURATION 30
162 #ifndef STATIC_MOON
163 # define ANIMATE_MOON_EVERY_N_FRAMES 100
164 #endif
165 ```
166 would result in the moon changing phases every 3000ms, or every 3 seconds.
167
168## Ocean
169
170### Description
171
172The 🌊 ocean animation is a full width animation of ocean waves, where the waves get rougher the faster you type.
173You can configure the boundaries for each degree of _wave ferocity_ as well as how fast the ocean/waves move.
174
175### Flags
176
177* `OCEAN_LINE` - where to render the ocean at. Defaults to `14`. (see [reference](#reference))
178* `OCEAN_ANIMATION_SPEED` - configures the number of frames you want to animate the ocean at.
179 Must be equal to or lower than `NUMBER_OF_FRAMES`.
180 Example:
181 ```c
182 #define NUMBER_OF_FRAMES 20
183 #define OCEAN_ANIMATION_SPEED 5
184 ```
185 would result in the ocean animation happening every 4 frames. 20 would result in every frame,
186 1 would be once every 20 frames. This essentially changes how fast the waves will move.
187* `WAVE_CALM` - Defines the WPM at which the _Wave Ferocity_ kicks up.
188 At any WPM between `WAVE_CALM` and `WAVE_HEAVY_STORM`, the waves will be just tiny ripples.
189* `WAVE_HEAVY_STORM` - Defines the WPM at which the _Wave Ferocity_ kicks up to medium.
190 At any WPM between `WAVE_HEAVY_STORM` and `WAVE_HURRICANE`, the waves will be medium sized waves.
191* `WAVE_HURRICANE` - Defines the WPM at which the _Wave Ferocity_ kicks up to the last notch.
192 At any WPM above `WAVE_HURRICANE`, the waves will be torrential.
193
194## Shooting Stars
195
196The 🌠 shooting star animation is a full screen animation that renders a meteor shower based on your typing speed. The
197faster you type, the more shooting stars there are!
198
199You can configure many parts of the shooting stars, from shower size, to speed, to length of each trail, to how spaced
200out they are.
201
202Note: Each frame of a shooting star is only 2 pixels in length. This is a design decision, and could probably be changed
203with a decent amount of work, but was chosen for looks and memory constraints.
204
205### Flags
206
207* `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
208* `SHOOTING_STAR_FRAMES` - how long each shooting star will be. A size of `16` will result in shooting stars that are 32 pixels long
209* `MAX_NUMBER_OF_SHOOTING_STARS` - maximum number of shooting stars that can be on screen at the same time
210* `SHOOTING_STAR_WPM_INCREMENT` - every n WPM increase, add an extra star, up to MAX_NUMBER_OF_SHOOTING_STARS
211 Example: an increment of 5 would result in 1 shooting star at 5-9wpm, 2 at 10-14, etc.
212* `SHOOTING_STAR_ANIMATION_SPEED` - configures the number of frames you want to animate the shooting stars at.
213 Must be equal to or lower than `NUMBER_OF_FRAMES`.
214 Example:
215 ```c
216 #define NUMBER_OF_FRAMES 20
217 #define SHOOTING_STAR_ANIMATION_SPEED 5
218 ```
219 would result in the shooting star animation happening every 4 frames. 20 would result in every frame,
220 1 would be once every 20 frames. This essentially changes how fast the stars move through the sky.
221
222
223## Island
224
225The 🏝 island animation is a 32w x 16h animation of a small island with a single palm tree blowing in the wind. The faster
226you type the harder the palm tree blows in the wind!
227
228Since this animation has significant black space to the left side of the tree, certain design decisions were made to allow the
229shooting stars to still show up in the sky there. This animation should work on any size screen >=32 pixels wide, and you
230can place it anywhere on the screen, but above the ocean is recommended.
231
232### Flags
233
234* `ISLAND_LINE` - where to render the island at. Defaults to `12`. The island is 2 lines tall. (see [reference](#reference))
235* `ISLAND_COLUMN` - where to render the island at. Defaults to `0`. The island is 32 pixels wide. (see [reference](#reference))
236* `ISLAND_CALM` - Defines the WPM at which the _Storm Ferocity_ kicks up.
237 At any WPM between `ISLAND_CALM` and `ISLAND_HEAVY_STORM`, the palm tree will just calmly blow in the wind.
238* `ISLAND_HEAVY_STORM` - Defines the WPM at which the _Storm Ferocity_ kicks up.
239 At any WPM between `ISLAND_HEAVY_STORM` and `ISLAND_HURRICANE`, the palm tree will be blowing hard in the wind
240* `ISLAND_HURRICANE` - Defines the WPM at which the _Storm Ferocity_ kicks up.
241 At any WPM above `ISLAND_HURRICANE`, the palm tree will almost be torn from its roots!
242
243
244# Reference
245
246Any reference to `_LINE` or `COLUMN` refers to setting a cursor position using `oled_set_cursor()`, which uses
247`OLED_FONT_WIDTH` and `OLED_FONT_HEIGHT` internally.
248This will be the top-leftmost pixel of the image, so `_LINE 1` would start at the 9th pixel down and `_COLUMN 1`
249would be the 7th pixel to the right, starting from the topleftmost pixel on the screen.
250
251This code has been untested with different font heights/widths, so you might have to adjust a bit to make it work if you
252have modified those values.
253
254# ToDo
255
256- [ ] don't require `is_calm` as a keyboard event. Not sure if the code will work without it currently.
257- [ ] make all the stars twinkle brightly based on keypresses rather than timed. Not just a movement twinkle, but a larger
258 'full' twinkle, where the star actually gets bigger. This will be quite difficult, thus is left out of the v1.
diff --git a/users/snowe/rules.mk b/users/snowe/rules.mk
new file mode 100644
index 000000000..a6e152c1c
--- /dev/null
+++ b/users/snowe/rules.mk
@@ -0,0 +1,27 @@
1
2
3ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes)
4 SRC += oled_setup.c
5
6 ifdef OCEAN_DREAM_ENABLE
7 ifeq ($(strip $(OCEAN_DREAM_ENABLE)), yes)
8 SRC += ocean_dream.c
9 OPT_DEFS += -DOCEAN_DREAM_ENABLE
10 endif
11 endif
12 ifndef OCEAN_DREAM_ENABLE
13 SRC += ocean_dream.c
14 OPT_DEFS += -DOCEAN_DREAM_ENABLE
15 endif
16
17 ifdef LUNA_ENABLE
18 ifeq ($(strip $(LUNA_ENABLE)), yes)
19 SRC += luna.c
20 OPT_DEFS += -DLUNA_ENABLE
21 endif
22 endif
23 ifndef LUNA_ENABLE
24 SRC += luna.c
25 OPT_DEFS += -DLUNA_ENABLE
26 endif
27endif
diff --git a/users/snowe/snowe.h b/users/snowe/snowe.h
new file mode 100644
index 000000000..4453b2646
--- /dev/null
+++ b/users/snowe/snowe.h
@@ -0,0 +1,43 @@
1/*
2Copyright 2021 Tyler Thrailkill <@snowe/@snowe2010>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18
19#pragma once
20#include QMK_KEYBOARD_H
21
22#ifndef QMK_FIRMWARE_SNOWE_H
23# define QMK_FIRMWARE_SNOWE_H ;
24#endif // QMK_FIRMWARE_SNOWE_H
25
26#include "wrappers.h"
27#include "keycode_aliases.h"
28
29#define IGNORE_MOD_TAP_INTERRUPT
30#undef PERMISSIVE_HOLD
31
32//#if defined(RGBLIGHT_ENABLE)
33//# include "rgb_stuff.h"
34//#endif
35//#if defined(RGB_MATRIX_ENABLE)
36//# include "rgb_matrix_stuff.h"
37//#endif
38#ifdef OLED_DRIVER_ENABLE
39# include "oled_setup.h"
40#endif
41
42
43enum layers { _MAIN, _LOWER, _UPPER, _ADJUST };
diff --git a/users/snowe/wrappers.h b/users/snowe/wrappers.h
new file mode 100644
index 000000000..485f8de54
--- /dev/null
+++ b/users/snowe/wrappers.h
@@ -0,0 +1,92 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * 2021 Tyler Thrailkill (@snowe/@snowe2010) <tyler.b.thrailkill@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19#include "snowe.h"
20
21/*
22Since our quirky block definitions are basically a list of comma separated
23arguments, we need a wrapper in order for these definitions to be
24expanded before being used as arguments to the LAYOUT_xxx macro.
25*/
26#if (!defined(LAYOUT) && defined(KEYMAP))
27# define LAYOUT KEYMAP
28#endif
29
30//#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__)
31//#define LAYOUT_ergodox_pretty_wrapper(...) LAYOUT_ergodox_pretty(__VA_ARGS__)
32#define KEYMAP_wrapper(...) LAYOUT(__VA_ARGS__)
33#define LAYOUT_wrapper(...) LAYOUT(__VA_ARGS__)
34//#define LAYOUT_ortho_4x12_wrapper(...) LAYOUT_ortho_4x12(__VA_ARGS__)
35//#define LAYOUT_ortho_5x12_wrapper(...) LAYOUT_ortho_5x12(__VA_ARGS__)
36//#define LAYOUT_gergo_wrapper(...) LAYOUT_gergo(__VA_ARGS__)
37
38/*
39Blocks for each of the four major keyboard layouts
40Organized so we can quickly adapt and modify all of them
41at once, rather than for each keyboard, one at a time.
42And this allows for much cleaner blocks in the keymaps.
43For instance Tap/Hold for Control on all of the layouts
44
45NOTE: These are all the same length. If you do a search/replace
46 then you need to add/remove underscores to keep the
47 lengths consistent.
48*/
49
50#define _________________QWERTY_L1_________________ KC_Q, KC_W, KC_E, KC_R, KC_T
51#define _________________QWERTY_L2_________________ KC_A, KC_S, KC_D, KC_F, KC_G
52#define _________________QWERTY_L3_________________ KC_Z, KC_X, KC_C, KC_V, KC_B
53
54#define _________________QWERTY_R1_________________ KC_Y, KC_U, KC_I, KC_O, KC_P
55#define _________________QWERTY_R2_________________ KC_H, KC_J, KC_K, KC_L, KC_SCLN
56#define _________________QWERTY_R3_________________ KC_N, KC_M, KC_COMM, KC_DOT, KC_SLASH
57
58
59#define ________________NUMBER_LEFT________________ KC_1, KC_2, KC_3, KC_4, KC_5
60#define ________________NUMBER_RIGHT_______________ KC_6, KC_7, KC_8, KC_9, KC_0
61//#define ________________NUMBER_RIGHT_______________ KC_6, KC_7, TD(TD_8_UP), KC_9, KC_0
62#define _________________FUNC_LEFT_________________ KC_F1, KC_F2, KC_F3, KC_F4, KC_F5
63#define _________________FUNC_RIGHT________________ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10
64
65#define ___________________BLANK___________________ _______, _______, _______, _______, _______
66
67
68#define _________________LOWER_L1__________________ KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC
69#define _________________LOWER_L2__________________ _________________FUNC_LEFT_________________
70#define _________________LOWER_L3__________________ _________________FUNC_RIGHT________________
71
72#define _________________LOWER_R1__________________ KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN
73#define _________________LOWER_R2__________________ _______, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR
74#define _________________LOWER_R3__________________ _______, KC_LEFT, KC_UP , KC_DOWN, KC_RGHT
75
76
77#define _________________RAISE_L1__________________ ________________NUMBER_LEFT________________
78#define _________________RAISE_L2__________________ _______, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC
79#define _________________RAISE_L3__________________ ___________________BLANK___________________
80
81#define _________________RAISE_R1__________________ ________________NUMBER_RIGHT_______________
82#define _________________RAISE_R2__________________ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, _______
83#define _________________RAISE_R3__________________ _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END
84
85
86
87#define _________________ADJUST_L1_________________ RGB_MOD, RGB_HUI, RGB_SAI, RGB_VAI, RGB_TOG
88#define _________________ADJUST_L2_________________ MU_TOG , CK_TOGG, AU_ON, AU_OFF, AG_NORM
89#define _________________ADJUST_L3_________________ RGB_RMOD,RGB_HUD,RGB_SAD, RGB_VAD, _______
90#define _________________ADJUST_R1_________________ _______, _______, _______, _______, _______
91#define _________________ADJUST_R2_________________ RESET, CG_TOGG, _______, _______, _______
92#define _________________ADJUST_R3_________________ _______, KC_MNXT, KC_VOLU, KC_VOLD, KC_MPLY