[Keyboard] Update rocketboard_16 with *most* of its final features (#12537)

This commit is contained in:
Seth 2021-09-11 00:32:29 -07:00 committed by GitHub
parent 737a497bb6
commit fd71c3dffa

View file

@ -12,29 +12,41 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include QMK_KEYBOARD_H #include QMK_KEYBOARD_H
#include "keycode_lookup.h"
#include <string.h>
#ifdef CONSOLE_ENABLE
#include "print.h"
#endif
// Each layer gets a name for readability, which is then used in the keymap matrix below. // Each layer gets a name for readability, which is then used in the keymap matrix below.
// The underscores don't mean anything - you can have a layer called STUFF or any other name. // The underscores don't mean anything - you can have a layer called STUFF or any other name.
// Layer names don't all need to be of the same length, obviously, and you can also skip them // Layer names don't all need to be of the same length, obviously, and you can also skip them
// entirely and just use numbers. // entirely and just use numbers.
#define _BASE 0 #define _BASE 0
#define _SPEC 1 // Special layer
// Use the following format to create custom key codes to make macros out of and such // Use the following format to create custom key codes to make macros out of and such
/*
enum custom_keycodes { enum custom_keycodes {
FOO = SAFE_RANGE, KC_EXAM = SAFE_RANGE // "Examine" key code to show the keycode of a key pressed afterwards on the OLED
}; };
*/
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_BASE] = LAYOUT_default( [_BASE] = LAYOUT_default(
RGB_MODE_FORWARD, KC_NUMLOCK, RGB_MODE_FORWARD, KC_NUMLOCK,
KC_KP_7, KC_KP_8, KC_KP_9, KC_DELETE, KC_KP_7, KC_KP_8, KC_KP_9, KC_DELETE,
KC_KP_4, KC_KP_5, KC_KP_6, KC_END, KC_KP_4, KC_KP_5, KC_KP_6, KC_END,
KC_KP_1, KC_KP_2, KC_KP_3, KC_AUDIO_VOL_UP, KC_KP_1, KC_KP_2, KC_KP_3, KC_F13,
KC_KP_0, RGB_TOG, KC_AUDIO_MUTE, KC_AUDIO_VOL_DOWN KC_KP_0, MO(1), KC_KP_DOT, KC_KP_ENTER
) ),
[_SPEC] = LAYOUT_default(
RGB_MODE_REVERSE, KC_AUDIO_MUTE,
KC_NO, KC_NO, KC_NO, KC_EXAM,
KC_NO, KC_NO, KC_NO, KC_NO,
RESET, RGB_TOG, RGB_SPI, RGB_SPD,
KC_NO, _______, KC_NO, KC_NO
)
}; };
bool encoder_update_user(uint8_t index, bool clockwise){ bool encoder_update_user(uint8_t index, bool clockwise){
@ -56,35 +68,321 @@ bool encoder_update_user(uint8_t index, bool clockwise){
#ifdef OLED_ENABLE #ifdef OLED_ENABLE
static void render_logo(void) { #define ANIM_FRAMES 3
static const char PROGMEM qmk_logo[] = { #define ANIM_FRAME_DURATION 110 // Number of milliseconds per frame (no faster than 110ms, last line struggles)
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, #define BACKGROUND_FRAMES 21
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, #define ROCKET_CENTER_POS 3
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00 #define SPLASH_DUR 100 // Measured in frames, see above for frame length (note, 231 is used as a key value later on, CTRL+F for uses of this to make sure everything is good)
};
oled_write(qmk_logo, false); uint32_t anim_timer = 0;
uint8_t current_frame = 0;
uint8_t rocket_y_position = 3;
uint8_t rocket_pos_change = 0;
uint8_t background_frame = 0;
uint8_t splash_dur_counter = 0;
bool examine_engaged = false;
uint16_t examined_keycode = KC_NO;
char lastKeycodeString[32] = { 0 };
const char star_background [8] [21] =
{
{0x88, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x93},
{0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00},
{0x00, 0x8F, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00},
{0x8D, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x8B, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x8A, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x8F, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x8F},
{0x00, 0x8B, 0x00, 0x00, 0x91, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x90, 0x00, 0x00, 0x8C, 0x00, 0x00},
};
static void oled_write_ln_centered(const char * data, bool inverted)
{
if(strlen(data) >= 21) // If more than 1 line of text is passed in, return without doing anything
{
return;
}
// Character buffer to build up the string in
char line_buf[21];
// Amount to offset string from left side
uint8_t offset = (21 - strlen(data))/2;
// Formatted string centering... look, it works, don't ask how...
snprintf(line_buf, 21, "%*s%s%*s\0", offset, "", data, offset, ""); // Centers data within 21 character buffer with null termination
oled_write_ln(line_buf, inverted);
}
// Prints the exhaust characters in an order determined by the phase for animation purposes
// startX - The x axis starting point in characters for the exhaust (3 behind the rocket)
// startY - The y axis starting point in characters for the exhaust (middle of the rocket)
// phase - The "phase" of the animation, no real rhyme or reason to the exact number, but each frame move +1 to make the animation work
static void render_exhaust(uint8_t startX, uint8_t startY, uint8_t phase)
{
oled_set_cursor(startX, startY);
oled_write_char(0x85 + (phase % 3), false);
phase++;
oled_write_char(0x85 + (phase % 3), false);
phase++;
oled_write_char(0x85 + (phase % 3), false);
}
// Renders the "stars" behind the rocket
// startY - The starting Y location (in characters) of the rocket so that stars aren't rendered on top of the rocket
static void render_stars(uint8_t startY, uint8_t phase)
{
// Line 0
oled_set_cursor(0, 0);
for(int i = 0; i < 21; i++)
{
oled_write_char(star_background[0][(i + phase) % 21], false);
}
// Line 1
oled_set_cursor(0, 1);
for(int i = 0; i < 21; i++)
{
oled_write_char(star_background[1][(i + phase) % 21], false);
}
// Line 2
oled_set_cursor(0, 2);
for(int i = 0; i < 21; i++)
{
oled_write_char(star_background[2][(i + phase) % 21], false);
}
// Line 3
oled_set_cursor(0, 3);
for(int i = 0; i < 21; i++)
{
oled_write_char(star_background[3][(i + phase) % 21], false);
}
// Line 4
oled_set_cursor(0, 4);
for(int i = 0; i < 21; i++)
{
oled_write_char(star_background[4][(i + phase) % 21], false);
}
// Line 5
oled_set_cursor(0, 5);
for(int i = 0; i < 21; i++)
{
oled_write_char(star_background[5][(i + phase) % 21], false);
}
// Line 6
oled_set_cursor(0, 6);
for(int i = 0; i < 21; i++)
{
oled_write_char(star_background[6][(i + phase) % 21], false);
}
// Line 7
oled_set_cursor(0, 7);
for(int i = 0; i < 21; i++)
{
oled_write_char(star_background[7][(i + phase) % 21], false);
}
}
static void render_logo(uint8_t startX, uint8_t startY)
{
oled_set_cursor(startX, startY);
oled_write_char(0x80, false);
oled_write_char(0x81, false);
oled_write_char(0x82, false);
oled_write_char(0x83, false);
oled_write_char(0x84, false);
oled_set_cursor(startX, startY + 1);
oled_write_char(0xA0, false);
oled_write_char(0xA1, false);
oled_write_char(0xA2, false);
oled_write_char(0xA3, false);
oled_write_char(0xA4, false);
oled_write_char(0xA5, false);
oled_set_cursor(startX, startY + 2);
oled_write_char(0xC0, false);
oled_write_char(0xC1, false);
oled_write_char(0xC2, false);
oled_write_char(0xC3, false);
oled_write_char(0xC4, false);
} }
oled_rotation_t oled_init_user(oled_rotation_t rotation) { return OLED_ROTATION_180; } oled_rotation_t oled_init_user(oled_rotation_t rotation) { return OLED_ROTATION_180; }
void oled_task_user(void) { void oled_task_user(void)
uint8_t light_level = rgblight_get_val(); {
light_level = (uint8_t)(100.0 * ((float)light_level/(float)RGBLIGHT_LIMIT_VAL)); // Convert to % // Playing the animation
char c_light_level[3]; if((timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) && (splash_dur_counter < SPLASH_DUR))
itoa(light_level, c_light_level, 10); {
anim_timer = timer_read32(); // read the current timer value
current_frame = (current_frame + 1) % ANIM_FRAMES; // Frame in the exhaust animation
background_frame = (background_frame + 1) % BACKGROUND_FRAMES; // Frame in the star animation
render_logo(); // Render the QMK logo // Move the rocket up and down
oled_write_ln(PSTR(""), false); // Add a newline if((rocket_pos_change / 9) == 0)
// Host Keyboard LED Status {
led_t led_state = host_keyboard_led_state(); rocket_y_position = ROCKET_CENTER_POS;
oled_write(led_state.num_lock ? PSTR(" |NUM|") : PSTR(" | |"), false); }
oled_write(led_state.caps_lock ? PSTR("|CAP|") : PSTR("| |"), false); else if((rocket_pos_change / 9) == 1)
oled_write(led_state.scroll_lock ? PSTR("|SCR| ") : PSTR("| | "), false); {
rocket_y_position = ROCKET_CENTER_POS + 1;
}
else if((rocket_pos_change / 9) == 2)
{
rocket_y_position = ROCKET_CENTER_POS;
}
if((rocket_pos_change / 9) == 3)
{
rocket_y_position = ROCKET_CENTER_POS - 1;
}
oled_write_ln(PSTR(""), false); // Add a newline // Renders the scene piece by piece
oled_write(PSTR(" BKLT: "), false); render_stars(8, background_frame); // Render star background
oled_write(c_light_level, false); render_exhaust(6, rocket_y_position + 1, current_frame); // Render exhaust
oled_write_ln(PSTR("% "), false); render_logo(9, rocket_y_position); // Render the rocket
// Timing for rocket position change
if(rocket_pos_change < 36)
{
rocket_pos_change++;
}
else
{
rocket_pos_change = 0;
}
splash_dur_counter++;
}
else if((splash_dur_counter >= SPLASH_DUR) && (splash_dur_counter != 231)) // Should only run once at end of splash screen duration
{
splash_dur_counter = 231; // Nice known value
oled_clear(); // Clear the screen
}
// After the splash screen
if(splash_dur_counter == 231)
{
uint8_t light_level = rgblight_get_val();
light_level = (uint8_t)(100.0 * ((float)light_level/(float)RGBLIGHT_LIMIT_VAL)); // Convert to %
char c_light_level[3];
itoa(light_level, c_light_level, 10);
// Display lock LED statuses
led_t led_state = host_keyboard_led_state();
if(led_state.num_lock)
{
oled_write(PSTR(" |"), false);
oled_write(PSTR("NUM"), true);
oled_write(PSTR("|"), false);
}
else
{
oled_write(PSTR(" |NUM|"), false);
}
if(led_state.caps_lock)
{
oled_write(PSTR("|"), false);
oled_write(PSTR("CAP"), true);
oled_write(PSTR("|"), false);
}
else
{
oled_write(PSTR("|CAP|"), false);
}
if(led_state.scroll_lock)
{
oled_write(PSTR("|"), false);
oled_write(PSTR("SCR"), true);
oled_write(PSTR("| "), false);
}
else
{
oled_write(PSTR("|SCR| "), false);
}
// Print the examine info
if(examine_engaged == true)
{
oled_set_cursor(0, 2);
oled_write_ln(PSTR(" Keycode: "), false);
oled_write_ln_centered(lastKeycodeString, false);
}
else
{
oled_set_cursor(0, 2);
oled_write_ln(PSTR(" "), false);
oled_write_ln(PSTR(" "), false);
}
// Print the backlight % bottom right
oled_set_cursor(11, 7);
oled_write(PSTR("BKLT: "), false);
oled_write(c_light_level, false);
oled_write(PSTR("%"), false);
// Print the layer number in bottom left
oled_set_cursor(0, 7);
oled_write(PSTR("L: "), false);
switch (get_highest_layer(layer_state))
{
case 0:
oled_write(PSTR("0"), false);
break;
case 1:
oled_write(PSTR("1"), false);
break;
case 2:
oled_write(PSTR("2"), false);
break;
case 3:
oled_write(PSTR("3"), false);
break;
default:
oled_write(PSTR("Und"), false);
break;
}
}
}
// Process the extra/extended keycode functionality
bool process_record_user(uint16_t keycode, keyrecord_t *record)
{
bool ret = true; // True will allow QMK to process the key as usual after the function runs, false skips QMK processing after this function runs
switch (keycode)
{
case KC_EXAM:
if(record->event.pressed) // On pressed, flip bool examine_engaged
{
if(examine_engaged == false)
{
examine_engaged = true;
}
else
{
examine_engaged = false;
}
ret = false;
}
else // On release do nothing
{
ret = false;
}
break;
default: // For any key other than EX, simply let QMK process after saving away what it was
memset(lastKeycodeString, 0, sizeof(lastKeycodeString));
memcpy(lastKeycodeString, translate_keycode_to_string(keycode), sizeof(((lookup_table_t *)0)->key_string));
ret = true;
break;
}
return ret;
} }
#endif #endif