diff --git a/keyboards/rocketboard_16/config.h b/keyboards/rocketboard_16/config.h index a82514e0b..cd99fcc73 100644 --- a/keyboards/rocketboard_16/config.h +++ b/keyboards/rocketboard_16/config.h @@ -45,12 +45,12 @@ along with this program. If not, see . #define RGBLIGHT_ANIMATIONS #define RGB_DI_PIN A4 #define RGBLED_NUM 16 -#define RGBLIGHT_LIMIT_VAL 128 #define RGBLIGHT_VAL_STEP 8 #define RGBLIGHT_SLEEP // OLED stuff #define OLED_DISPLAY_128X64 +#define OLED_FONT_H "custom_font.h" // Allows for rotary encoder volume control #define TAP_CODE_DELAY 20 diff --git a/keyboards/rocketboard_16/custom_font.h b/keyboards/rocketboard_16/custom_font.h new file mode 100644 index 000000000..1f41f25b7 --- /dev/null +++ b/keyboards/rocketboard_16/custom_font.h @@ -0,0 +1,244 @@ +/* +Copyright 2021 Seth Bonner +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#include "progmem.h" + +static const unsigned char PROGMEM font[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, + 0x00, 0x18, 0x3C, 0x18, 0x00, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, + 0x00, 0x18, 0x24, 0x18, 0x00, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00, + 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x00, + 0x26, 0x29, 0x79, 0x29, 0x26, 0x00, + 0x40, 0x7F, 0x05, 0x05, 0x07, 0x00, + 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x00, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00, + 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00, + 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, + 0x00, 0x66, 0x89, 0x95, 0x6A, 0x00, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00, + 0x08, 0x04, 0x7E, 0x04, 0x08, 0x00, + 0x10, 0x20, 0x7E, 0x20, 0x10, 0x00, + 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, + 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x00, + 0x1E, 0x10, 0x10, 0x10, 0x10, 0x00, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x00, + 0x30, 0x38, 0x3E, 0x38, 0x30, 0x00, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, + 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, + 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, + 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00, + 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, + 0x00, 0x80, 0x70, 0x30, 0x00, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, + 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, + 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, + 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, 0x00, + 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00, + 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, + 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, + 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00, + 0x41, 0x21, 0x11, 0x09, 0x07, 0x00, + 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, + 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, + 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, + 0x00, 0x41, 0x22, 0x14, 0x08, 0x00, + 0x02, 0x01, 0x59, 0x09, 0x06, 0x00, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00, + 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00, + 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, + 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, + 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00, + 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, + 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, + 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00, + 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, + 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, + 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, + 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00, + 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, + 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, + 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, + 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, + 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, + 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, + 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00, + 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, + 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, + 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, + 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, + 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, + 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, + 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00, + 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, + 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00, + 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, + 0x00, 0x03, 0x07, 0x08, 0x00, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, 0x00, + 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00, + 0x38, 0x44, 0x44, 0x44, 0x28, 0x00, + 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00, + 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, + 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, + 0x18, 0x24, 0x24, 0x1C, 0x78, 0x00, + 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, + 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00, + 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00, + 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, + 0xFC, 0x18, 0x24, 0x24, 0x18, 0x00, + 0x18, 0x24, 0x24, 0x18, 0xFC, 0x00, + 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00, + 0x48, 0x54, 0x54, 0x54, 0x24, 0x00, + 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00, + 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00, + 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, + 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, + 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, + 0x4C, 0x10, 0x10, 0x10, 0x7C, 0x00, + 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, + 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, 0x00, + 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00, + 0x02, 0x1E, 0xF2, 0x86, 0x84, 0x8C, + 0x98, 0xD0, 0x70, 0x60, 0x40, 0x60, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x60, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, + 0x10, 0x10, 0x10, 0x34, 0x24, 0x24, + 0x00, 0x44, 0x44, 0x48, 0x08, 0x08, + 0x10, 0x14, 0x14, 0x20, 0x24, 0x24, + 0x00, 0x0C, 0x0C, 0x70, 0x70, 0x70, + 0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, + 0x00, 0x60, 0x60, 0x06, 0x06, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, + 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x00, 0x83, 0x83, 0x80, 0x18, 0x18, + 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, + 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, + 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x00, + 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x81, 0x81, 0x81, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x24, 0x26, 0x42, 0x42, 0x44, 0x24, + 0x18, 0x00, 0x00, 0x81, 0x81, 0x42, + 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x78, 0x4F, 0x61, 0x21, 0x31, + 0x19, 0x0B, 0x0E, 0x06, 0x02, 0x06, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x06, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/keyboards/rocketboard_16/keycode_lookup.c b/keyboards/rocketboard_16/keycode_lookup.c new file mode 100644 index 000000000..9e1c5f92a --- /dev/null +++ b/keyboards/rocketboard_16/keycode_lookup.c @@ -0,0 +1,407 @@ +/* Copyright 2021 Seth Bonner + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "keycode_lookup.h" +#include "print.h" +#include "via.h" + +#define num_keycodes (sizeof(lookup_table)/sizeof(lookup_table[0])) +static char UNKNOWN_KEYCODE[] = "UNKNOWN"; + +int cmp(const void *v1, const void *v2) +{ + const lookup_table_t *c1 = v1; + const lookup_table_t *c2 = v2; + + return (c1->keycode - c2->keycode); +} + +/* + Returns a pointer to a string containing the string describing the keycode, such as those found here: + https://beta.docs.qmk.fm/using-qmk/simple-keycodes/keycodes + + Will return a string that says "UNKNOWN" if the keycode cannot be found. +*/ +char* translate_keycode_to_string(uint16_t code) +{ + lookup_table_t * result = NULL; + lookup_table_t target = {.key_string = "", .keycode = code}; + char * return_p; + + result = bsearch(&target, lookup_table, num_keycodes, sizeof(lookup_table_t), cmp); + + if(result != NULL) + { + return_p = result->key_string; + } + else + { + return_p = UNKNOWN_KEYCODE; + } + + return (return_p); +} + +lookup_table_t lookup_table[366] = +{ + {"KC_NO", KC_NO}, + {"KC_TRNS", KC_TRNS}, + {"KC_A", KC_A}, + {"KC_B", KC_B}, + {"KC_C", KC_C}, + {"KC_D", KC_D}, + {"KC_E", KC_E}, + {"KC_F", KC_F}, + {"KC_G", KC_G}, + {"KC_H", KC_H}, + {"KC_I", KC_I}, + {"KC_J", KC_J}, + {"KC_K", KC_K}, + {"KC_L", KC_L}, + {"KC_M", KC_M}, + {"KC_N", KC_N}, + {"KC_O", KC_O}, + {"KC_P", KC_P}, + {"KC_Q", KC_Q}, + {"KC_R", KC_R}, + {"KC_S", KC_S}, + {"KC_T", KC_T}, + {"KC_U", KC_U}, + {"KC_V", KC_V}, + {"KC_W", KC_W}, + {"KC_X", KC_X}, + {"KC_Y", KC_Y}, + {"KC_Z", KC_Z}, + {"KC_1", KC_1}, + {"KC_2", KC_2}, + {"KC_3", KC_3}, + {"KC_4", KC_4}, + {"KC_5", KC_5}, + {"KC_6", KC_6}, + {"KC_7", KC_7}, + {"KC_8", KC_8}, + {"KC_9", KC_9}, + {"KC_0", KC_0}, + {"KC_ENT", KC_ENT}, + {"KC_ESC", KC_ESC}, + {"KC_BSPC", KC_BSPC}, + {"KC_TAB", KC_TAB}, + {"KC_SPC", KC_SPC}, + {"KC_MINS", KC_MINS}, + {"KC_EQL", KC_EQL}, + {"KC_LBRC", KC_LBRC}, + {"KC_RBRC", KC_RBRC}, + {"KC_BSLS", KC_BSLS}, + {"KC_NUHS", KC_NUHS}, + {"KC_SCLN", KC_SCLN}, + {"KC_QUOT", KC_QUOT}, + {"KC_GRV", KC_GRV}, + {"KC_ZKHK", KC_ZKHK}, + {"KC_COMM", KC_COMM}, + {"KC_DOT", KC_DOT}, + {"KC_SLSH", KC_SLSH}, + {"KC_CAPS", KC_CAPS}, + {"KC_F1", KC_F1}, + {"KC_F2", KC_F2}, + {"KC_F3", KC_F3}, + {"KC_F4", KC_F4}, + {"KC_F5", KC_F5}, + {"KC_F6", KC_F6}, + {"KC_F7", KC_F7}, + {"KC_F8", KC_F8}, + {"KC_F9", KC_F9}, + {"KC_F10", KC_F10}, + {"KC_F11", KC_F11}, + {"KC_F12", KC_F12}, + {"KC_PSCR", KC_PSCR}, + {"KC_SLCK", KC_SLCK}, + {"KC_PAUS", KC_PAUS}, + {"KC_INS", KC_INS}, + {"KC_HOME", KC_HOME}, + {"KC_PGUP", KC_PGUP}, + {"KC_DEL", KC_DEL}, + {"KC_END", KC_END}, + {"KC_PGDN", KC_PGDN}, + {"KC_RGHT", KC_RGHT}, + {"KC_LEFT", KC_LEFT}, + {"KC_DOWN", KC_DOWN}, + {"KC_UP", KC_UP}, + {"KC_NLCK", KC_NLCK}, + {"KC_PSLS", KC_PSLS}, + {"KC_PAST", KC_PAST}, + {"KC_PMNS", KC_PMNS}, + {"KC_PPLS", KC_PPLS}, + {"KC_PENT", KC_PENT}, + {"KC_P1", KC_P1}, + {"KC_P2", KC_P2}, + {"KC_P3", KC_P3}, + {"KC_P4", KC_P4}, + {"KC_P5", KC_P5}, + {"KC_P6", KC_P6}, + {"KC_P7", KC_P7}, + {"KC_P8", KC_P8}, + {"KC_P9", KC_P9}, + {"KC_P0", KC_P0}, + {"KC_PDOT", KC_PDOT}, + {"KC_NUBS", KC_NUBS}, + {"KC_APP", KC_APP}, + {"KC_POWER", KC_POWER}, + {"KC_PEQL", KC_PEQL}, + {"KC_F13", KC_F13}, + {"KC_F14", KC_F14}, + {"KC_F15", KC_F15}, + {"KC_F16", KC_F16}, + {"KC_F17", KC_F17}, + {"KC_F18", KC_F18}, + {"KC_F19", KC_F19}, + {"KC_F20", KC_F20}, + {"KC_F21", KC_F21}, + {"KC_F22", KC_F22}, + {"KC_F23", KC_F23}, + {"KC_F24", KC_F24}, + {"KC_EXECUTE", KC_EXECUTE}, + {"KC_HELP", KC_HELP}, + {"KC_MENU", KC_MENU}, + {"KC_SELECT", KC_SELECT}, + {"KC_STOP", KC_STOP}, + {"KC_AGAIN", KC_AGAIN}, + {"KC_UNDO", KC_UNDO}, + {"KC_CUT", KC_CUT}, + {"KC_COPY", KC_COPY}, + {"KC_PASTE", KC_PASTE}, + {"KC_FIND", KC_FIND}, + {"KC_LCAP", KC_LCAP}, + {"KC_LNUM", KC_LNUM}, + {"KC_LSCR", KC_LSCR}, + {"KC_PCMM", KC_PCMM}, + {"KC_KP_EQUAL_AS400", KC_KP_EQUAL_AS400}, + {"KC_RO", KC_RO}, + {"KC_KANA", KC_KANA}, + {"KC_JYEN", KC_JYEN}, + {"KC_HENK", KC_HENK}, + {"KC_MHEN", KC_MHEN}, + {"KC_INT6", KC_INT6}, + {"KC_INT7", KC_INT7}, + {"KC_INT8", KC_INT8}, + {"KC_INT9", KC_INT9}, + {"KC_HAEN", KC_HAEN}, + {"KC_HANJ", KC_HANJ}, + {"KC_LANG3", KC_LANG3}, + {"KC_LANG4", KC_LANG4}, + {"KC_LANG5", KC_LANG5}, + {"KC_LANG6", KC_LANG6}, + {"KC_LANG7", KC_LANG7}, + {"KC_LANG8", KC_LANG8}, + {"KC_LANG9", KC_LANG9}, + {"KC_ERAS", KC_ERAS}, + {"KC_SYSREQ", KC_SYSREQ}, + {"KC_CANCEL", KC_CANCEL}, + {"KC_CLR", KC_CLR}, + {"KC_CLEAR", KC_CLEAR}, + {"KC_PRIOR", KC_PRIOR}, + {"KC_OUT", KC_OUT}, + {"KC_OPER", KC_OPER}, + {"KC_CLEAR_AGAIN", KC_CLEAR_AGAIN}, + {"KC_CRSEL", KC_CRSEL}, + {"KC_EXSEL", KC_EXSEL}, + {"KC_PWR", KC_PWR}, + {"KC_SLEP", KC_SLEP}, + {"KC_WAKE", KC_WAKE}, + {"KC_MUTE", KC_MUTE}, + {"KC_VOLU", KC_VOLU}, + {"KC_VOLD", KC_VOLD}, + {"KC_MNXT", KC_MNXT}, + {"KC_MPRV", KC_MPRV}, + {"KC_MSTP", KC_MSTP}, + {"KC_MPLY", KC_MPLY}, + {"KC_MSEL", KC_MSEL}, + {"KC_EJCT", KC_EJCT}, + {"KC_MAIL", KC_MAIL}, + {"KC_CALC", KC_CALC}, + {"KC_MYCM", KC_MYCM}, + {"KC_WWW_SEARCH", KC_WWW_SEARCH}, + {"KC_WWW_HOME", KC_WWW_HOME}, + {"KC_WWW_BACK", KC_WWW_BACK}, + {"KC_WWW_FORWARD", KC_WWW_FORWARD}, + {"KC_WWW_STOP", KC_WWW_STOP}, + {"KC_WWW_REFRESH", KC_WWW_REFRESH}, + {"KC_WWW_FAVORITES", KC_WWW_FAVORITES}, + {"KC_MFFD", KC_MFFD}, + {"KC_MRWD", KC_MRWD}, + {"KC_BRIU", KC_BRIU}, + {"KC_BRID", KC_BRID}, + {"KC_FN0", KC_FN0}, + {"KC_FN1", KC_FN1}, + {"KC_FN2", KC_FN2}, + {"KC_FN3", KC_FN3}, + {"KC_FN4", KC_FN4}, + {"KC_FN5", KC_FN5}, + {"KC_FN6", KC_FN6}, + {"KC_FN7", KC_FN7}, + {"KC_FN8", KC_FN8}, + {"KC_FN9", KC_FN9}, + {"KC_FN10", KC_FN10}, + {"KC_FN11", KC_FN11}, + {"KC_FN12", KC_FN12}, + {"KC_FN13", KC_FN13}, + {"KC_FN14", KC_FN14}, + {"KC_FN15", KC_FN15}, + {"KC_FN16", KC_FN16}, + {"KC_FN17", KC_FN17}, + {"KC_FN18", KC_FN18}, + {"KC_FN19", KC_FN19}, + {"KC_FN20", KC_FN20}, + {"KC_FN21", KC_FN21}, + {"KC_FN22", KC_FN22}, + {"KC_FN23", KC_FN23}, + {"KC_FN24", KC_FN24}, + {"KC_FN25", KC_FN25}, + {"KC_FN26", KC_FN26}, + {"KC_FN27", KC_FN27}, + {"KC_FN28", KC_FN28}, + {"KC_FN29", KC_FN29}, + {"KC_FN30", KC_FN30}, + {"KC_FN31", KC_FN31}, + {"KC_LCTL", KC_LCTL}, + {"KC_LSFT", KC_LSFT}, + {"KC_LALT", KC_LALT}, + {"KC_LGUI", KC_LGUI}, + {"KC_RCTL", KC_RCTL}, + {"KC_RSFT", KC_RSFT}, + {"KC_RALT", KC_RALT}, + {"KC_RGUI", KC_RGUI}, + {"KC_MS_UP", KC_MS_UP}, + {"KC_MS_DOWN", KC_MS_DOWN}, + {"KC_MS_LEFT", KC_MS_LEFT}, + {"KC_MS_RIGHT", KC_MS_RIGHT}, + {"KC_MS_BTN1", KC_MS_BTN1}, + {"KC_MS_BTN2", KC_MS_BTN2}, + {"KC_MS_BTN3", KC_MS_BTN3}, + {"KC_MS_BTN4", KC_MS_BTN4}, + {"KC_MS_BTN5", KC_MS_BTN5}, + {"KC_MS_WH_UP", KC_MS_WH_UP}, + {"KC_MS_WH_DOWN", KC_MS_WH_DOWN}, + {"KC_MS_WH_LEFT", KC_MS_WH_LEFT}, + {"KC_MS_WH_RIGHT", KC_MS_WH_RIGHT}, + {"KC_MS_ACCEL0", KC_MS_ACCEL0}, + {"KC_MS_ACCEL1", KC_MS_ACCEL1}, + {"KC_MS_ACCEL2", KC_MS_ACCEL2}, + {"KC_EXLM", KC_EXLM}, + {"KC_AT", KC_AT}, + {"KC_HASH", KC_HASH}, + {"KC_DLR", KC_DLR}, + {"KC_PERC", KC_PERC}, + {"KC_CIRC", KC_CIRC}, + {"KC_AMPR", KC_AMPR}, + {"KC_ASTR", KC_ASTR}, + {"KC_LPRN", KC_LPRN}, + {"KC_RPRN", KC_RPRN}, + {"KC_UNDS", KC_UNDS}, + {"KC_PLUS", KC_PLUS}, + {"KC_LCBR", KC_LCBR}, + {"KC_RCBR", KC_RCBR}, + {"KC_PIPE", KC_PIPE}, + {"KC_COLN", KC_COLN}, + {"KC_DQUO", KC_DQUO}, + {"KC_TILD", KC_TILD}, + {"KC_LT", KC_LT}, + {"KC_GT", KC_GT}, + {"KC_QUES", KC_QUES}, + {"RESET", RESET}, + {"DEBUG", DEBUG}, + {"MAGIC_TOGGLE_NKRO", MAGIC_TOGGLE_NKRO}, + {"KC_GESC", KC_GESC}, + {"AU_ON", AU_ON}, + {"AU_OFF", AU_OFF}, + {"AU_TOG", AU_TOG}, + {"CLICKY_TOGGLE", CLICKY_TOGGLE}, + {"CLICKY_ENABLE", CLICKY_ENABLE}, + {"CLICKY_DISABLE", CLICKY_DISABLE}, + {"CLICKY_UP", CLICKY_UP}, + {"CLICKY_DOWN", CLICKY_DOWN}, + {"CLICKY_RESET", CLICKY_RESET}, + {"MU_ON", MU_ON}, + {"MU_OFF", MU_OFF}, + {"MU_TOG", MU_TOG}, + {"MU_MOD", MU_MOD}, + {"BL_ON", BL_ON}, + {"BL_OFF", BL_OFF}, + {"BL_DEC", BL_DEC}, + {"BL_INC", BL_INC}, + {"BL_TOGG", BL_TOGG}, + {"BL_STEP", BL_STEP}, + {"BL_BRTG", BL_BRTG}, + {"RGB_TOG", RGB_TOG}, + {"RGB_MOD", RGB_MOD}, + {"RGB_RMOD", RGB_RMOD}, + {"RGB_HUI", RGB_HUI}, + {"RGB_HUD", RGB_HUD}, + {"RGB_SAI", RGB_SAI}, + {"RGB_SAD", RGB_SAD}, + {"RGB_VAI", RGB_VAI}, + {"RGB_VAD", RGB_VAD}, + {"RGB_SPI", RGB_SPI}, + {"RGB_SPD", RGB_SPD}, + {"RGB_M_P", RGB_M_P}, + {"RGB_M_B", RGB_M_B}, + {"RGB_M_R", RGB_M_R}, + {"RGB_M_SW", RGB_M_SW}, + {"RGB_M_SN", RGB_M_SN}, + {"RGB_M_K", RGB_M_K}, + {"RGB_M_X", RGB_M_X}, + {"RGB_M_G", RGB_M_G}, + {"KC_LSPO", KC_LSPO}, + {"KC_RSPC", KC_RSPC}, + {"KC_SFTENT", KC_SFTENT}, + {"KC_LCPO", KC_LCPO}, + {"KC_RCPC", KC_RCPC}, + {"KC_LAPO", KC_LAPO}, + {"KC_RAPC", KC_RAPC}, + {"FN_MO13", FN_MO13}, + {"FN_MO23", FN_MO23}, + {"MACRO00", MACRO00}, + {"MACRO01", MACRO01}, + {"MACRO02", MACRO02}, + {"MACRO03", MACRO03}, + {"MACRO04", MACRO04}, + {"MACRO05", MACRO05}, + {"MACRO06", MACRO06}, + {"MACRO07", MACRO07}, + {"MACRO08", MACRO08}, + {"MACRO09", MACRO09}, + {"MACRO10", MACRO10}, + {"MACRO11", MACRO11}, + {"MACRO12", MACRO12}, + {"MACRO13", MACRO13}, + {"MACRO14", MACRO14}, + {"MACRO15", MACRO15}, + {"USER00", USER00}, + {"USER01", USER01}, + {"USER02", USER02}, + {"USER03", USER03}, + {"USER04", USER04}, + {"USER05", USER05}, + {"USER06", USER06}, + {"USER07", USER07}, + {"USER08", USER08}, + {"USER09", USER09}, + {"USER10", USER10}, + {"USER11", USER11}, + {"USER12", USER12}, + {"USER13", USER13}, + {"USER14", USER14}, + {"USER15", USER15} +}; diff --git a/keyboards/rocketboard_16/keycode_lookup.h b/keyboards/rocketboard_16/keycode_lookup.h new file mode 100644 index 000000000..f51dcfd52 --- /dev/null +++ b/keyboards/rocketboard_16/keycode_lookup.h @@ -0,0 +1,29 @@ +/* Copyright 2021 Seth Bonner + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "quantum.h" + +typedef struct +{ + char key_string[17]; + uint16_t keycode; +} lookup_table_t; + +char* translate_keycode_to_string(uint16_t code); + +extern lookup_table_t lookup_table[366]; diff --git a/keyboards/rocketboard_16/keymaps/default/keymap.c b/keyboards/rocketboard_16/keymaps/default/keymap.c index 0c3ee96d4..050ab9f5b 100644 --- a/keyboards/rocketboard_16/keymaps/default/keymap.c +++ b/keyboards/rocketboard_16/keymaps/default/keymap.c @@ -12,29 +12,41 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include QMK_KEYBOARD_H +#include "keycode_lookup.h" +#include +#ifdef CONSOLE_ENABLE +#include "print.h" +#endif // 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. // Layer names don't all need to be of the same length, obviously, and you can also skip them // entirely and just use numbers. #define _BASE 0 +#define _SPEC 1 // Special layer // Use the following format to create custom key codes to make macros out of and such -/* 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] = { - [_BASE] = LAYOUT_default( - RGB_MODE_FORWARD, KC_NUMLOCK, - KC_KP_7, KC_KP_8, KC_KP_9, KC_DELETE, - 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_0, RGB_TOG, KC_AUDIO_MUTE, KC_AUDIO_VOL_DOWN - ) + [_BASE] = LAYOUT_default( + RGB_MODE_FORWARD, KC_NUMLOCK, + KC_KP_7, KC_KP_8, KC_KP_9, KC_DELETE, + KC_KP_4, KC_KP_5, KC_KP_6, KC_END, + KC_KP_1, KC_KP_2, KC_KP_3, KC_F13, + 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){ @@ -56,35 +68,321 @@ bool encoder_update_user(uint8_t index, bool clockwise){ #ifdef OLED_ENABLE -static void render_logo(void) { - static const char PROGMEM qmk_logo[] = { - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, - 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, - 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00 - }; +#define ANIM_FRAMES 3 +#define ANIM_FRAME_DURATION 110 // Number of milliseconds per frame (no faster than 110ms, last line struggles) +#define BACKGROUND_FRAMES 21 +#define ROCKET_CENTER_POS 3 +#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; } -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 % - char c_light_level[3]; - itoa(light_level, c_light_level, 10); +void oled_task_user(void) +{ + // Playing the animation + if((timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) && (splash_dur_counter < SPLASH_DUR)) + { + 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 - oled_write_ln(PSTR(""), false); // Add a newline - // Host Keyboard LED Status - led_t led_state = host_keyboard_led_state(); - oled_write(led_state.num_lock ? PSTR(" |NUM|") : PSTR(" | |"), false); - oled_write(led_state.caps_lock ? PSTR("|CAP|") : PSTR("| |"), false); - oled_write(led_state.scroll_lock ? PSTR("|SCR| ") : PSTR("| | "), false); + // Move the rocket up and down + if((rocket_pos_change / 9) == 0) + { + rocket_y_position = ROCKET_CENTER_POS; + } + else if((rocket_pos_change / 9) == 1) + { + 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 - oled_write(PSTR(" BKLT: "), false); - oled_write(c_light_level, false); - oled_write_ln(PSTR("% "), false); + // Renders the scene piece by piece + render_stars(8, background_frame); // Render star background + render_exhaust(6, rocket_y_position + 1, current_frame); // Render exhaust + 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 diff --git a/keyboards/rocketboard_16/keymaps/via/keymap.c b/keyboards/rocketboard_16/keymaps/via/keymap.c index 0c3ee96d4..050ab9f5b 100644 --- a/keyboards/rocketboard_16/keymaps/via/keymap.c +++ b/keyboards/rocketboard_16/keymaps/via/keymap.c @@ -12,29 +12,41 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include QMK_KEYBOARD_H +#include "keycode_lookup.h" +#include +#ifdef CONSOLE_ENABLE +#include "print.h" +#endif // 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. // Layer names don't all need to be of the same length, obviously, and you can also skip them // entirely and just use numbers. #define _BASE 0 +#define _SPEC 1 // Special layer // Use the following format to create custom key codes to make macros out of and such -/* 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] = { - [_BASE] = LAYOUT_default( - RGB_MODE_FORWARD, KC_NUMLOCK, - KC_KP_7, KC_KP_8, KC_KP_9, KC_DELETE, - 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_0, RGB_TOG, KC_AUDIO_MUTE, KC_AUDIO_VOL_DOWN - ) + [_BASE] = LAYOUT_default( + RGB_MODE_FORWARD, KC_NUMLOCK, + KC_KP_7, KC_KP_8, KC_KP_9, KC_DELETE, + KC_KP_4, KC_KP_5, KC_KP_6, KC_END, + KC_KP_1, KC_KP_2, KC_KP_3, KC_F13, + 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){ @@ -56,35 +68,321 @@ bool encoder_update_user(uint8_t index, bool clockwise){ #ifdef OLED_ENABLE -static void render_logo(void) { - static const char PROGMEM qmk_logo[] = { - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, - 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, - 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00 - }; +#define ANIM_FRAMES 3 +#define ANIM_FRAME_DURATION 110 // Number of milliseconds per frame (no faster than 110ms, last line struggles) +#define BACKGROUND_FRAMES 21 +#define ROCKET_CENTER_POS 3 +#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; } -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 % - char c_light_level[3]; - itoa(light_level, c_light_level, 10); +void oled_task_user(void) +{ + // Playing the animation + if((timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) && (splash_dur_counter < SPLASH_DUR)) + { + 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 - oled_write_ln(PSTR(""), false); // Add a newline - // Host Keyboard LED Status - led_t led_state = host_keyboard_led_state(); - oled_write(led_state.num_lock ? PSTR(" |NUM|") : PSTR(" | |"), false); - oled_write(led_state.caps_lock ? PSTR("|CAP|") : PSTR("| |"), false); - oled_write(led_state.scroll_lock ? PSTR("|SCR| ") : PSTR("| | "), false); + // Move the rocket up and down + if((rocket_pos_change / 9) == 0) + { + rocket_y_position = ROCKET_CENTER_POS; + } + else if((rocket_pos_change / 9) == 1) + { + 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 - oled_write(PSTR(" BKLT: "), false); - oled_write(c_light_level, false); - oled_write_ln(PSTR("% "), false); + // Renders the scene piece by piece + render_stars(8, background_frame); // Render star background + render_exhaust(6, rocket_y_position + 1, current_frame); // Render exhaust + 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 diff --git a/keyboards/rocketboard_16/rules.mk b/keyboards/rocketboard_16/rules.mk index b1450c779..f8e2b217c 100644 --- a/keyboards/rocketboard_16/rules.mk +++ b/keyboards/rocketboard_16/rules.mk @@ -2,7 +2,18 @@ MCU = STM32F103 # Bootloader selection -BOOTLOADER = stm32duino +# BOOTLOADER = stm32duino + +# Custom loader configuration +MCU_LDSCRIPT = STM32F103xB_stm32duino_bootloader +OPT_DEFS += -DBOOTLOADER_STM32DUINO +BOARD = STM32_F103_STM32DUINO +STM32_BOOTLOADER_ADDRESS = 0x80000000 +DFU_ARGS = -d 1EAF:0003 -a 2 -R +DFU_SUFFIX_ARGS = -v 1EAF -p 0003 + +# Extra include +SRC += keycode_lookup.c # Build Options # change yes to no to disable @@ -24,5 +35,9 @@ OLED_ENABLE = yes OLED_DRIVER = SSD1306 ENCODER_ENABLE = yes +RAW_ENABLE = yes # Enables HID RAW communication between the board and the PC + # Enter lower-power sleep mode when on the ChibiOS idle thread OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE + +LTO_ENABLE = yes