diff --git a/keyboards/handwired/endgame48/.gitignore b/keyboards/handwired/endgame48/.gitignore new file mode 100644 index 00000000000..7aaaec612ab --- /dev/null +++ b/keyboards/handwired/endgame48/.gitignore @@ -0,0 +1 @@ +/.ccls-cache diff --git a/keyboards/handwired/endgame48/config.h b/keyboards/handwired/endgame48/config.h new file mode 100644 index 00000000000..ee368a4a33e --- /dev/null +++ b/keyboards/handwired/endgame48/config.h @@ -0,0 +1,169 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef CONFIG_H +#define CONFIG_H + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6060 +#define DEVICE_VER 0x0001 +#define MANUFACTURER Andrew Dunai +#define PRODUCT Endgame48 (v2) +#define DESCRIPTION A 12x4 split ortholinear keyboard with encoder + +/* + ┌────────┐ + ╭──────┤ ├──────╮ + RGB> ┿ D3 │ │ RAW ┿ + │ │ │ │ + PS2D> ┿ D2 └────────┘ GND ┿ + │ │ + ┿ GND RST ┿ + │ [] [] │ + ┿ GND VCC ┿ + │ │ + I2C> ┿ D1 ||| || || F4 ┿ ┿ D0 F5 ┿ ┿ D4 ╱ ╲ F6 ┿ ┿ C6 ╲ ╱ F7 ┿ ┿ D7 ╲╱ B1 ┿ ┿ E6 B3 ┿ ┿ B4 B2 ┿ │ B5 B7 D5 C7 F1 F0 B6 ┿ mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* prevent stuck modifiers */ +#define PREVENT_STUCK_MODIFIERS + +/* RGB underglow */ +#define RGB_DI_PIN D3 + +#ifdef RGB_DI_PIN +#define RGBLED_NUM 12 +#define RGBLIGHT_HUE_STEP 8 +#define RGBLIGHT_SAT_STEP 8 +#define RGBLIGHT_VAL_STEP 8 +#define RGBLIGHT_DEFAULT_VAL 0 +#endif + +/* Encoders */ +#define ENCODERS_PAD_A { E6 } +#define ENCODERS_PAD_B { B4 } +#define ENCODER_RESOLUTION 4 + +/* Tapping config */ +#define TAPPING_TERM 90 +#define PERMISSIVE_HOLD +#define TAPPING_FORCE_HOLD + +/* Reduce firmware size */ +#define NO_ACTION_ONESHOT + +/* Font */ +#define OLED_FONT_H "glcdfont_48_v2.c" + +/* Trackpoint */ +#define PS2_MOUSE_INIT_DELAY 200 + +#ifdef PS2_USE_USART +#define PS2_CLOCK_PIN D5 +#define PS2_DATA_PIN D2 + +/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ +/* set DDR of CLOCK as input to be slave */ +#define PS2_USART_INIT() do { \ + PS2_CLOCK_DDR &= ~(1<> 16) & 0xFF, (DEBUG_COLOR >> 8) & 0xFF, DEBUG_COLOR & 0xFF); + reset_keyboard(); +} + +void mute(void) { + tap_code(KC_MUTE); +} + +void init_eeprom_menu(menu_t *this) { + for (uint16_t i = 0; i < this->count; i++) { + uint8_t b = eeprom_read_byte((uint8_t *)i); + sprintf(this->items[i].title, "%02X:%02X", i, b); + } +} + +static menu_t list_eeprom_menu = { + .title = "EEPRM", + .count = 64, + .items = (menu_item_t[64]){}, + .opened = init_eeprom_menu, +}; + +menu_t main_menu = { + .title = "CFG", + .count = 5, + .items = + (menu_item_t[]){ + { + .title = "Mute", + .func = mute, + }, + { + .title = "RGB", + .func = rgblight_toggle_noeeprom, + }, + { + .title = "Reset", + .func = request_reset, + }, + { + .title = "LsEE", + .submenu = &list_eeprom_menu, + }, + { + .title = "DelEE", + .func = eeconfig_init, + }, + }, +}; + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { + if (!menu_process_record(keycode, record)) { + return false; + } + return process_record_user(keycode, record); +} + +bool encoder_update_kb(uint8_t index, bool clockwise) { + if (!menu_encoder_update(index, clockwise)) { + return false; + } + return encoder_update_user(index, clockwise); +} + +oled_rotation_t oled_init_kb(oled_rotation_t rotation) { + return OLED_ROTATION_270; +} + +static uint32_t last_render = 0; + +bool oled_task_kb(void) { + if (timer_elapsed32(last_render) > 100) { + last_render = timer_read32(); + if (!menu_oled_task()) { + return false; + } + oled_task_user(); + } + return false; +} diff --git a/keyboards/handwired/endgame48/endgame48.h b/keyboards/handwired/endgame48/endgame48.h new file mode 100644 index 00000000000..95d5b73376b --- /dev/null +++ b/keyboards/handwired/endgame48/endgame48.h @@ -0,0 +1,37 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef ENDGAME48_H +#define ENDGAME48_H + +#include "quantum.h" +#include "config.h" + +#define DEBUG_COLOR 0xFFFF00 + +#define NOPE KC_NO + +enum eg_custom_keycodes { + KC_EGMENU = SAFE_RANGE, + EG_SAFE_RANGE, +}; + +#define LAYOUT( \ + K00, K01, K02, K03, K04, K05, K40, K41, K42, K43, K44, K45, \ + K10, K11, K12, K13, K14, K15, K50, K51, K52, K53, K54, K55, \ + K20, K21, K22, K23, K24, K25, K60, K61, K62, K63, K64, K65, \ + K30, K31, K32, K33, K34, K35, K76, K70, K71, K72, K73, K74, K75 \ +) { \ + {K00, K01, K02, K03, K04, K05, NOPE}, \ + {K10, K11, K12, K13, K14, K15, NOPE}, \ + {K20, K21, K22, K23, K24, K25, NOPE}, \ + {K30, K31, K32, K33, K34, K35, NOPE}, \ + {K40, K41, K42, K43, K44, K45, NOPE}, \ + {K50, K51, K52, K53, K54, K55, NOPE}, \ + {K60, K61, K62, K63, K64, K65, NOPE}, \ + {K70, K71, K72, K73, K74, K75, K76} \ +} + +void request_reset(void); + +#endif diff --git a/keyboards/handwired/endgame48/glcdfont_48_v2.c b/keyboards/handwired/endgame48/glcdfont_48_v2.c new file mode 100644 index 00000000000..b643abb14ca --- /dev/null +++ b/keyboards/handwired/endgame48/glcdfont_48_v2.c @@ -0,0 +1,240 @@ +#pragma once + +#ifdef __AVR__ + #include + #include +#elif defined(ESP8266) + #include +#else + #define PROGMEM +#endif + +// Helidox 8x6 font with QMK Firmware Logo +// Online editor: http://teripom.x0.com/ +// New online editor: https://joric.github.io/qle/ +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, 0x00, 0x08, 0x08, 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, 0xA4, 0xA4, 0x9C, 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, 0x90, 0x90, 0x90, 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, + 0x00, 0xF0, 0xFC, 0xFE, 0xFE, 0x3F, + 0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x9F, + 0xFF, 0xFE, 0xFE, 0xFC, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x0F, + 0x1F, 0xFE, 0xFE, 0xF8, 0x00, 0x00, + 0x00, 0xF0, 0xFC, 0xFE, 0xFE, 0x3F, + 0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x1F, + 0x3F, 0xFE, 0xFE, 0xFC, 0xF0, 0x00, + 0x03, 0x0F, 0x3F, 0xFF, 0xFF, 0xFC, + 0xF0, 0xC0, 0x00, 0x00, 0xC0, 0xF0, + 0xFC, 0xFF, 0xFF, 0x3F, 0x0F, 0x03, + 0x3E, 0x2A, 0x22, 0x00, 0x3E, 0x0C, + 0x18, 0x3E, 0x00, 0x3E, 0x22, 0x1C, + 0x00, 0x1C, 0x22, 0x32, 0x00, 0x3C, + 0x0A, 0x3C, 0x00, 0x3E, 0x04, 0x08, + 0x04, 0x3E, 0x00, 0x3E, 0x2A, 0x22, + 0x00, 0x3E, 0x22, 0x22, 0x00, 0x02, + 0x3E, 0x02, 0x00, 0x3E, 0x20, 0x20, + 0x00, 0x3C, 0x0A, 0x3C, 0x00, 0x3E, + 0x20, 0x20, 0x02, 0x3E, 0x02, 0x00, + 0x00, 0x24, 0x2A, 0x12, 0x00, 0x3E, + 0x0A, 0x02, 0x00, 0x02, 0x3E, 0x02, + 0x00, 0x3E, 0x22, 0x32, 0x00, 0x3E, + 0x20, 0x3E, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, + 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, + 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0xC0, 0xF8, 0xFF, 0xFF, + 0xFF, 0xE7, 0xE0, 0xE0, 0xE7, 0xFF, + 0xFF, 0xFF, 0xF8, 0xC0, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, + 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x7E, + 0xFF, 0xE7, 0xE7, 0x81, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC3, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xC3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x04, 0x1F, 0x00, 0x1F, 0x15, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x0C, + 0x10, 0x0C, 0x00, 0x1D, 0x15, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, + 0xF9, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, + 0xFC, 0x7F, 0x7F, 0x3F, 0x0F, 0x00, + 0xF0, 0xFE, 0xFF, 0xFF, 0x0F, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x0F, 0xFF, 0xFF, 0xFE, 0xF0, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, + 0xF8, 0x7F, 0x7F, 0x1F, 0x00, 0x00, + 0x00, 0x0F, 0x3F, 0x7F, 0x7F, 0xFC, + 0xF8, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, + 0xFC, 0x7F, 0x7F, 0x3F, 0x0F, 0x00, + 0xC0, 0xF0, 0xFC, 0xFF, 0xFF, 0x3F, + 0x0F, 0x03, 0x00, 0x00, 0x03, 0x0F, + 0x3F, 0xFF, 0xFF, 0xFC, 0xF0, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 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/handwired/endgame48/info.json b/keyboards/handwired/endgame48/info.json new file mode 100644 index 00000000000..c629e5327b8 --- /dev/null +++ b/keyboards/handwired/endgame48/info.json @@ -0,0 +1,60 @@ +{ + "keyboard_name": "Endgame48", + "url": "", + "maintainer": "and3rson", + "layouts": { + "LAYOUT": { + "layout": [ + { "w": 1, "x": 0, "y": 0 }, + { "w": 1, "x": 1, "y": 0 }, + { "w": 1, "x": 2, "y": 0 }, + { "w": 1, "x": 3, "y": 0 }, + { "w": 1, "x": 4, "y": 0 }, + { "w": 1, "x": 5, "y": 0 }, + { "w": 1, "x": 7, "y": 0 }, + { "w": 1, "x": 8, "y": 0 }, + { "w": 1, "x": 9, "y": 0 }, + { "w": 1, "x": 10, "y": 0 }, + { "w": 1, "x": 11, "y": 0 }, + { "w": 1, "x": 12, "y": 0 }, + { "w": 1, "x": 0, "y": 1 }, + { "w": 1, "x": 1, "y": 1 }, + { "w": 1, "x": 2, "y": 1 }, + { "w": 1, "x": 3, "y": 1 }, + { "w": 1, "x": 4, "y": 1 }, + { "w": 1, "x": 5, "y": 1 }, + { "w": 1, "x": 7, "y": 1 }, + { "w": 1, "x": 8, "y": 1 }, + { "w": 1, "x": 9, "y": 1 }, + { "w": 1, "x": 10, "y": 1 }, + { "w": 1, "x": 11, "y": 1 }, + { "w": 1, "x": 12, "y": 1 }, + { "w": 1, "x": 0, "y": 2 }, + { "w": 1, "x": 1, "y": 2 }, + { "w": 1, "x": 2, "y": 2 }, + { "w": 1, "x": 3, "y": 2 }, + { "w": 1, "x": 4, "y": 2 }, + { "w": 1, "x": 5, "y": 2 }, + { "w": 1, "x": 7, "y": 2 }, + { "w": 1, "x": 8, "y": 2 }, + { "w": 1, "x": 9, "y": 2 }, + { "w": 1, "x": 10, "y": 2 }, + { "w": 1, "x": 11, "y": 2 }, + { "w": 1, "x": 12, "y": 2 }, + { "w": 1, "x": 0, "y": 3 }, + { "w": 1, "x": 1, "y": 3 }, + { "w": 1, "x": 2, "y": 3 }, + { "w": 1, "x": 3, "y": 3 }, + { "w": 1, "x": 4, "y": 3 }, + { "w": 1, "x": 5, "y": 3 }, + { "w": 1, "x": 6, "y": 3 }, + { "w": 1, "x": 7, "y": 3 }, + { "w": 1, "x": 8, "y": 3 }, + { "w": 1, "x": 9, "y": 3 }, + { "w": 1, "x": 10, "y": 3 }, + { "w": 1, "x": 11, "y": 3 }, + { "w": 1, "x": 12, "y": 3 } ] + } + } +} + diff --git a/keyboards/handwired/endgame48/keymaps/default/config.h b/keyboards/handwired/endgame48/keymaps/default/config.h new file mode 100644 index 00000000000..0f16d2a4a35 --- /dev/null +++ b/keyboards/handwired/endgame48/keymaps/default/config.h @@ -0,0 +1,4 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#define OLED_TIMEOUT 30000 diff --git a/keyboards/handwired/endgame48/keymaps/default/keymap.c b/keyboards/handwired/endgame48/keymaps/default/keymap.c new file mode 100644 index 00000000000..d427776258a --- /dev/null +++ b/keyboards/handwired/endgame48/keymaps/default/keymap.c @@ -0,0 +1,221 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "endgame48.h" +#include "config.h" +#include "taphold.h" +#include "rgblight.h" +#include "oled/oled_driver.h" +#include "smoothled.h" +#include "stdio.h" +#include "string.h" +#include "symbols.h" + +#define ________ KC_TRNS + +#define _MAIN 0 +#define _ALPHA 1 +#define _BETA 2 +#define _SIGMA 3 + +#define F_DASH "\x9c\x9d" + +uint32_t layer_colors[4] = { + 0x4020FF, + 0xFF0010, + 0x20FF00, + 0x40FFFF +}; + +enum custom_keycodes { + KC_MAIN = EG_SAFE_RANGE, + KC_ALPHA, + KC_BETA, +}; + +/* TapHold is my own implementation of the `LT` macro. It's processed in `process_record_user()`. */ +uint16_t taphold_config_size = 3; +taphold_t taphold_config[] = { + {.key=KC_ALPHA, .mode=TAPHOLD_LAYER, .shortAction=KC_ESC, .longAction=_ALPHA}, + {.key=KC_BETA, .mode=TAPHOLD_LAYER, .shortAction=KC_EQL, .longAction=_BETA}, + {.key=KC_LCTRL, .mode=TAPHOLD_MOD, .shortAction=KC_MINS, .longAction=KC_LCTRL}, +}; +uint32_t taphold_timeout = 100; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Main layer + ┏━━━━━┳━━━━━┯━━━━━┯━━━━━┯━━━━━┯━━━━━┓┏┳━┳┓┏━━━━━┯━━━━━┯━━━━━┯━━━━━┯━━━━━┳━━━━━┓ + ┃ TAB ┃ Q │ W │ E │ R │ T ┃┃┃ ┃┃┃ Y │ U │ I │ O │ P ┃ BSP ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨┃┃ ┃┃┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃𝛼/ESC┃ A │ S │ D │ F │ G ┃┃┃ ┃┃┃ H │ J │ K │ L │ ; ┃ RET ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨┗┻━┻┛┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃SHIFT┃ Z │ X │ C │ V │ B ┃ ┃ N │ M │ , │ . │ / ┃LCTRL┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨ ┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃CTRL ┃ │ │ ALT │ GUI │SPACE┃ (o) ┃SPACE│ 𝛽/= │ ' │ │ ┃ ┃ + ┗━━━━━┻━━━━━┷━━━━━┷━━━━━┷━━━━━┷━━━━━┛ ┗━━━━━┷━━━━━┷━━━━━┷━━━━━┷━━━━━┻━━━━━┛ + */ + [_MAIN] = LAYOUT( \ + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \ + KC_ALPHA,KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT, \ + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_LCTRL,\ + KC_LCTRL,________,________,KC_LALT, KC_LGUI, KC_SPC, KC_EGMENU,KC_SPC, KC_BETA, KC_QUOT, ________,________,________\ + ), + + /* 𝛼 layer + ┏━━━━━┳━━━━━┯━━━━━┯━━━━━┯━━━━━┯━━━━━┓┏┳━┳┓┏━━━━━┯━━━━━┯━━━━━┯━━━━━┯━━━━━┳━━━━━┓ + ┃ ┃PREV │PLAY │NEXT │ │ ┃┃┃ ┃┃┃ - │ ^^^ │ ^ │ vvv │ ~ ┃ DEL ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨┃┃ ┃┃┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃ │VOL -│VOL +│ │ ┃┃┃ ┃┃┃HOME │ <-- │ v │ --> │ ` ┃ \ ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨┗┻━┻┛┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃ │ │ │ │ ┃ ┃ END │ = │ [ │ ] │ ( ┃ ) ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨ ┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃ │ │ │ │ ┃ (o) ┃ │ │ │ │ ┃ ┃ + ┗━━━━━┻━━━━━┷━━━━━┷━━━━━┷━━━━━┷━━━━━┛ ┗━━━━━┷━━━━━┷━━━━━┷━━━━━┷━━━━━┻━━━━━┛ + */ + [_ALPHA] = LAYOUT( \ + ________,KC_MPRV, KC_MPLY, KC_MNXT, ________,________, KC_MINS, KC_PGUP, KC_UP, KC_PGDN, KC_TILD, KC_DEL, \ + ________,________,KC_VOLD, KC_VOLU, ________,________, KC_HOME, KC_LEFT, KC_DOWN, KC_RIGHT,KC_GRV, KC_BSLS, \ + ________,________,________,________,________,________, KC_END, KC_EQL, KC_LBRC, KC_RBRC, LSFT(KC_9),LSFT(KC_0),\ + ________,________,________,________,________,________,________,________,________,________,________,________,________\ + ), + + /* 𝛽 layer + ┏━━━━━┳━━━━━┯━━━━━┯━━━━━┯━━━━━┯━━━━━┓┏┳━┳┓┏━━━━━┯━━━━━┯━━━━━┯━━━━━┯━━━━━┳━━━━━┓ + ┃ RGB ┃ 1 │ 2 │ 3 │ 4 │ 5 ┃┃┃ ┃┃┃ 6 │ 7 │ 8 │ 9 │ 0 ┃ F12 ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨┃┃ ┃┃┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃ F1 │ F2 │ F3 │ F4 │ F5 ┃┃┃ ┃┃┃ F6 │ F7 │ F8 │ F9 │ F10 ┃ F11 ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨┗┻━┻┛┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃RESET│DEBUG│SLEEP│WAKE │EGMNU ┃ ┃ │ │ { │ } │ ┃ ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨ ┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃ │ │ │ │ ┃ (o) ┃PTSCR│ │ │ │ ┃ ┃ + ┗━━━━━┻━━━━━┷━━━━━┷━━━━━┷━━━━━┷━━━━━┛ ┗━━━━━┷━━━━━┷━━━━━┷━━━━━┷━━━━━┻━━━━━┛ + */ + [_BETA] = LAYOUT( \ + RGB_TOG, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_F12, \ + ________,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, \ + ________,RESET, DEBUG, KC_PWR, KC_WAKE, KC_EGMENU, ________,________,KC_LCBR, KC_RCBR, ________,________,\ + ________,________,________,________,________,KC_MUTE, ________,KC_PSCR, ________,________,________,________,________\ + ), + /* Σ layer + ┏━━━━━┳━━━━━┯━━━━━┯━━━━━┯━━━━━┯━━━━━┓┏┳━┳┓┏━━━━━┯━━━━━┯━━━━━┯━━━━━┯━━━━━┳━━━━━┓ + ┃ ┃ │ │ │ │ ┃┃┃ ┃┃┃ │ │ │ │ ┃ ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨┃┃ ┃┃┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃ │ │ │ │ ┃┃┃ ┃┃┃ │ │ │ │ ┃ ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨┗┻━┻┛┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃ │ │ │ │ ┃ ┃ │ │ │ │ ┃ ┃ + ┣━━━━━╉─────┼─────┼─────┼─────┼─────┨ ┣─────┼─────┼─────┼─────┼─────╊━━━━━┫ + ┃ ┃ │ │ │ │ ┃ (o) ┃ │ │ │ │ ┃ ┃ + ┗━━━━━┻━━━━━┷━━━━━┷━━━━━┷━━━━━┷━━━━━┛ ┗━━━━━┷━━━━━┷━━━━━┷━━━━━┷━━━━━┻━━━━━┛ + */ + [_SIGMA] = LAYOUT( \ + ________,________,________,________,________,________, ________,________,________,________,________,________,\ + ________,________,________,________,________,________, ________,________,________,________,________,________,\ + ________,________,________,________,________,________, ________,________,________,________,________,________,\ + ________,________,________,________,________,________,________,________,________,________,________,________,________\ + ), +}; + +static bool alpha_pressed = false; +static bool beta_pressed = false; + +static bool ctrl_pressed = false; +static bool alt_pressed = false; +static bool shift_pressed = false; +static bool gui_pressed = false; + +static volatile uint32_t last_scan; +static volatile uint32_t scan_interval; + +void matrix_init_user(void) { + smoothled_set(layer_colors[0], 1500, swimOut); +} + +void matrix_scan_user(void) { + uint32_t now = timer_read32(); + scan_interval = now - last_scan; + last_scan = now; + smoothled_process(); +} + +void suspend_power_down_user(void) { + smoothled_set(0, 0, swimIn); +} + +void suspend_wakeup_init_user(void) { + smoothled_set(layer_colors[_MAIN], 1500, swimOut); +} + +layer_state_t layer_state_set_user(layer_state_t state) { + layer_state_t prevState = update_tri_layer_state(layer_state, _ALPHA, _BETA, _SIGMA); + state = update_tri_layer_state(state, _ALPHA, _BETA, _SIGMA); + uint8_t prevLayer = biton32(prevState); + uint8_t layer = biton32(state); + smoothled_set(layer_colors[layer], 250, prevLayer < layer ? swimOut : swimIn); + return state; +} + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + if (keycode == KC_LCTRL) ctrl_pressed = record->event.pressed; + if (keycode == KC_LALT) alt_pressed = record->event.pressed; + if (keycode == KC_LSFT) shift_pressed = record->event.pressed; + if (keycode == KC_LGUI) gui_pressed = record->event.pressed; + + if (keycode == RESET) { + request_reset(); + return false; + } + + if (keycode == KC_ALPHA) alpha_pressed = record->event.pressed; + if (keycode == KC_BETA) beta_pressed = record->event.pressed; + + return taphold_process(keycode, record); +} + +bool encoder_update_user(uint8_t index, bool clockwise) { + if (index == 0) { + if (alpha_pressed) { + if (clockwise) { + tap_code(KC_VOLU); + } else { + tap_code(KC_VOLD); + } + } else if (beta_pressed) { + if (clockwise) { + tap_code(KC_PGDN); + } else { + tap_code(KC_PGUP); + } + } else { + if (clockwise) { + tap_code(KC_MS_WH_DOWN); + } else { + tap_code(KC_MS_WH_UP); + } + } + } + return false; +} + +bool oled_task_user(void) { + oled_write_P(logo, false); + + uint8_t current_layer = biton32(layer_state); + + oled_write_P(layerIcons[current_layer], current_layer != _MAIN); + + oled_write_P(PSTR("\n\n"), false); + + char mod_data[12] = F_DASH " " F_DASH F_DASH " " F_DASH "\n\0"; + if (ctrl_pressed) memcpy(mod_data, mods[0], 2); + if (alt_pressed) memcpy(mod_data +3, mods[1], 2); + if (shift_pressed) memcpy(mod_data + 5, mods[2], 2); + if (gui_pressed) memcpy(mod_data + 8, mods[3], 2); + oled_write(mod_data, false); + + char buf[10] = " "; + buf[sprintf(buf, "%2lums", scan_interval ? scan_interval : 1L)] = ' '; + buf[5] = 0; + oled_write(buf, false); + + return false; +} diff --git a/keyboards/handwired/endgame48/keymaps/default/rules.mk b/keyboards/handwired/endgame48/keymaps/default/rules.mk new file mode 100644 index 00000000000..f7e0e9bb7a9 --- /dev/null +++ b/keyboards/handwired/endgame48/keymaps/default/rules.mk @@ -0,0 +1,5 @@ +ifndef QUANTUM_DIR + include ../../../../Makefile +endif + +SRC += smoothled.c diff --git a/keyboards/handwired/endgame48/keymaps/default/smoothled.c b/keyboards/handwired/endgame48/keymaps/default/smoothled.c new file mode 100644 index 00000000000..86c43fe4cd4 --- /dev/null +++ b/keyboards/handwired/endgame48/keymaps/default/smoothled.c @@ -0,0 +1,80 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "endgame48.h" +#include "smoothled.h" +#include "math.h" +#include "string.h" + +static LED_TYPE source[RGBLED_NUM] = {}; +static LED_TYPE current[RGBLED_NUM] = {}; +static LED_TYPE target[RGBLED_NUM] = {}; +static uint32_t duration = 1500; +static int32_t smoothledTimer = -1; +static animFunc_t animFunc; + +const float RGBLED_STEP = 1.0f / ((float)RGBLED_NUM); + +void smoothled_set(uint32_t color, uint32_t newDuration, animFunc_t newAnimFunc) { + smoothledTimer = timer_read32(); + LED_TYPE next = {.r = (color >> 16) & 0xFF, .g = (color >> 8) & 0xFF, .b = color & 0xFF}; + for (uint8_t p = 0; p < RGBLED_NUM; p++) { + source[p] = current[p]; + target[p] = next; + } + duration = newDuration; + animFunc = newAnimFunc; +} + +LED_TYPE swimOut(LED_TYPE a, LED_TYPE b, float k, uint8_t x) { + k = pow(k, 2); + /* Center */ + x = fabs(5.5 - ((float)x)); + /* Time range for current LED */ + float start = RGBLED_STEP * x; + float end = RGBLED_STEP * (x + 1); + if (k <= start) { + k = 0; + } else if (k >= end) { + k = 1; + } else { + k = (k - start) / RGBLED_STEP; + } + float rk = 1.0f - k; + return (LED_TYPE){ + .r = rk * a.r + k * b.r, + .g = rk * a.g + k * b.g, + .b = rk * a.b + k * b.b, + }; +} + +LED_TYPE swimIn(LED_TYPE a, LED_TYPE b, float k, uint8_t x) { + if (x < RGBLED_NUM / 2) { + x = RGBLED_NUM / 2 - x - 1; + } else { + x = RGBLED_NUM - (x - RGBLED_NUM / 2 - 1); + } + return swimOut(a, b, k, x); +} + +void smoothled_process(void) { + if (smoothledTimer == -1) { + return; + } + smoothled_render(); +} + +void smoothled_render(void) { + uint32_t passed = timer_elapsed32(smoothledTimer); + if (passed > duration) { + passed = duration; + smoothledTimer = -1; + } + float k = ((float)passed) / duration; + for (uint8_t p = 0; p < RGBLED_NUM; p++) { + current[p] = animFunc(source[p], target[p], k, p); + /* This is much faster than calling rgblight_setrgb_at every iteration */ + led[p] = current[p]; + } + rgblight_set(); +} diff --git a/keyboards/handwired/endgame48/keymaps/default/smoothled.h b/keyboards/handwired/endgame48/keymaps/default/smoothled.h new file mode 100644 index 00000000000..14125365d58 --- /dev/null +++ b/keyboards/handwired/endgame48/keymaps/default/smoothled.h @@ -0,0 +1,15 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "quantum.h" +#include "config.h" +#include "rgblight.h" + +typedef LED_TYPE (*animFunc_t)(LED_TYPE, LED_TYPE, float, uint8_t); + +LED_TYPE swimIn(LED_TYPE, LED_TYPE, float, uint8_t); +LED_TYPE swimOut(LED_TYPE, LED_TYPE, float, uint8_t); + +void smoothled_set(uint32_t color, uint32_t newDuration, animFunc_t newAnimFunc); +void smoothled_process(void); +void smoothled_render(void); diff --git a/keyboards/handwired/endgame48/menu.c b/keyboards/handwired/endgame48/menu.c new file mode 100644 index 00000000000..6a5560c929d --- /dev/null +++ b/keyboards/handwired/endgame48/menu.c @@ -0,0 +1,86 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "menu.h" + +static int8_t menu_depth = -1; +static menu_t *menus[8]; + +#define MENU_OPENED menu_depth != -1 +#define MENU_CURRENT menus[menu_depth] +#define MENU_MAX_ITEMS 10 + +bool menu_process_record(uint16_t keycode, keyrecord_t *record) { + if (MENU_OPENED) { + /* Menu is open */ + if (record->event.pressed) { + if (keycode == KC_EGMENU) { + menu_t *menu = MENU_CURRENT; + menu_item_t item = menu->items[menu->current]; + if (item.submenu != NULL) { + item.submenu->current = 0; + item.submenu->scroll = 0; + menus[++menu_depth] = item.submenu; + item.submenu->opened(item.submenu); + } else if (item.func != NULL) { + item.func(); + menu_depth = -1; + } + } else { + menu_depth--; + } + } + return false; + } else if (keycode == KC_EGMENU) { + /* Menu is not open, KC_EGMENU pressed */ + if (record->event.pressed) { + main_menu.current = 0; + main_menu.scroll = 0; + menus[++menu_depth] = &main_menu; + } + return false; + } + return true; +} + +bool menu_encoder_update(uint8_t index, bool clockwise) { + if (MENU_OPENED) { + menu_t *menu = MENU_CURRENT; + if (clockwise) { + if (menu->current < menu->count - 1) { + menu->current++; + } + if (menu->current - menu->scroll >= MENU_MAX_ITEMS) { + menu->scroll++; + } + } else { + if (menu->current) { + menu->current--; + } + if (menu->current < menu->scroll) { + menu->scroll--; + } + } + return false; + } + return true; +} + +bool menu_oled_task(void) { + if (MENU_OPENED) { + oled_clear(); + oled_write_P(logo, false); + menu_t *menu = MENU_CURRENT; + char title[7] = " \0\0"; + sprintf(title, "%-5s", menu->title); + title[5] = '\n'; + oled_write(title, false); + for (uint8_t i = menu->scroll; i < (menu->count >= MENU_MAX_ITEMS ? menu->scroll + MENU_MAX_ITEMS : menu->count); i++) { + char buf[6] = " \0"; + sprintf(buf, "%-5s", menu->items[i].title); + oled_write(buf, menu->current == i); + } + return false; + } + return true; +} diff --git a/keyboards/handwired/endgame48/menu.h b/keyboards/handwired/endgame48/menu.h new file mode 100644 index 00000000000..f4a67f88c48 --- /dev/null +++ b/keyboards/handwired/endgame48/menu.h @@ -0,0 +1,30 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "quantum.h" +#include "stdint.h" +#include "endgame48.h" +#include "symbols.h" +#include "oled/oled_driver.h" +#include "stdio.h" + +typedef struct menu_item_t { + char title[6]; + void (*func)(void); + struct menu_t *submenu; +} menu_item_t; + +typedef struct menu_t { + char *title; + uint8_t count; + uint8_t current; + uint8_t scroll; + void (*opened)(struct menu_t *); + menu_item_t *items; +} menu_t; + +extern menu_t main_menu; + +bool menu_process_record(uint16_t keycode, keyrecord_t *record); +bool menu_encoder_update(uint8_t index, bool clockwise); +bool menu_oled_task(void); diff --git a/keyboards/handwired/endgame48/readme.md b/keyboards/handwired/endgame48/readme.md new file mode 100644 index 00000000000..8cff97d5c30 --- /dev/null +++ b/keyboards/handwired/endgame48/readme.md @@ -0,0 +1,64 @@ +# Endgame48 + +![Endgame48](https://i.imgur.com/asU6f9G.jpeg) + +Puchi-C based 40% keyboard with rotary encoder and I2C OLED. + +* Keyboard Maintainer: Andrew Dunai +* Hardware Supported: Puchi-C handwired +* Hardware Availability: [Keycapsss.com](https://keycapsss.com) + + +Make example for this keyboard (after setting up your build environment): + + make handwired/endgame48:default:dfu + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). + +## Details + +- Puchi-C based handwired keyboard +- 2x custom 1.25mm stainless steel plates +- Kailh Choc White (clicky) +- Rotary encoder +- 0.91" 128x32 I2C OLED +- WS2812 strip (12 LEDs) +- OLED menu (triggered with encoder press) which allows you to view EEPROM, reset keyboard, toggle RGB, etc. +- Handwiring is fun! + +## Pinout + +`PS2D` and `PS2C` are PS/2 `DATA` & `CLOCK` lines. They are not used in this revision but are reserved for future. + +``` + ┌────────┐ + ╭──────┤ ├──────╮ + RGB> ┿ D3 │ │ RAW ┿ + │ │ │ │ + PS2D> ┿ D2 └────────┘ GND ┿ + │ │ + ┿ GND RST ┿ + │ [] [] │ + ┿ GND VCC ┿ + │ │ + I2C> ┿ D1 ||| || || F4 ┿ ┿ D0 F5 ┿ ┿ D4 ╱ ╲ F6 ┿ ┿ C6 ╲ ╱ F7 ┿ ┿ D7 ╲╱ B1 ┿ ┿ E6 B3 ┿ ┿ B4 B2 ┿ │ B5 B7 D5 C7 F1 F0 B6 ┿ key == keycode && record->event.pressed) { + if (config->mode == TAPHOLD_LAYER) { + layer_on(config->longAction); + } else { + register_code(config->longAction); + } + config->time = timer_read32(); + config->keypos = record->event.key; + return false; + } else if (KEYEQ(record->event.key, config->keypos) && !record->event.pressed) { + if (config->mode == TAPHOLD_LAYER) { + layer_off(config->longAction); + } else { + unregister_code(config->longAction); + } + if (timer_elapsed32(config->time) < taphold_timeout) { + register_code(config->shortAction); + unregister_code(config->shortAction); + } + config->keypos.row = 255; + return false; + } + } + return true; +} diff --git a/keyboards/handwired/endgame48/taphold.h b/keyboards/handwired/endgame48/taphold.h new file mode 100644 index 00000000000..08ddbdc091a --- /dev/null +++ b/keyboards/handwired/endgame48/taphold.h @@ -0,0 +1,28 @@ +// Copyright 2022 Andrew Dunai (@and3rson) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "quantum.h" + +typedef enum taphold_mode_t { + TAPHOLD_LAYER, + TAPHOLD_MOD +} taphold_mode_t; + +typedef struct taphold_t { + uint16_t key; + uint32_t time; + taphold_mode_t mode; + uint16_t shortAction; + uint16_t longAction; + keypos_t keypos; + /* We store key pos to properly release the key */ + /* even when a different layer is active and the key has a different action now */ +} taphold_t; + +extern taphold_t taphold_config[]; +extern uint16_t taphold_config_size; +/* Dual keys tap/hold timeout. */ +/* If key is tapped for less than this value, send key in addition to primary action after completing the action. */ +extern uint32_t taphold_timeout; + +bool taphold_process(uint16_t keycode, keyrecord_t *record);