Browse Source

[Keyboard] Add handwired/endgame48 board

pull/17135/head
Andrew Dunai 1 year ago
parent
commit
d1f4386a51
No known key found for this signature in database GPG Key ID: DC7797A711FFF6AF
19 changed files with 1279 additions and 0 deletions
  1. +1
    -0
      keyboards/handwired/endgame48/.gitignore
  2. +169
    -0
      keyboards/handwired/endgame48/config.h
  3. +110
    -0
      keyboards/handwired/endgame48/endgame48.c
  4. +37
    -0
      keyboards/handwired/endgame48/endgame48.h
  5. +240
    -0
      keyboards/handwired/endgame48/glcdfont_48_v2.c
  6. +60
    -0
      keyboards/handwired/endgame48/info.json
  7. +4
    -0
      keyboards/handwired/endgame48/keymaps/default/config.h
  8. +221
    -0
      keyboards/handwired/endgame48/keymaps/default/keymap.c
  9. +5
    -0
      keyboards/handwired/endgame48/keymaps/default/rules.mk
  10. +80
    -0
      keyboards/handwired/endgame48/keymaps/default/smoothled.c
  11. +15
    -0
      keyboards/handwired/endgame48/keymaps/default/smoothled.h
  12. +86
    -0
      keyboards/handwired/endgame48/menu.c
  13. +30
    -0
      keyboards/handwired/endgame48/menu.h
  14. +64
    -0
      keyboards/handwired/endgame48/readme.md
  15. +29
    -0
      keyboards/handwired/endgame48/rules.mk
  16. +58
    -0
      keyboards/handwired/endgame48/symbols.c
  17. +9
    -0
      keyboards/handwired/endgame48/symbols.h
  18. +33
    -0
      keyboards/handwired/endgame48/taphold.c
  19. +28
    -0
      keyboards/handwired/endgame48/taphold.h

+ 1
- 0
keyboards/handwired/endgame48/.gitignore View File

@ -0,0 +1 @@
/.ccls-cache

+ 169
- 0
keyboards/handwired/endgame48/config.h View File

@ -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 <ROW5
I2C> D0 F5 <COL1
ROW1> D4 F6 <COL2
ROW3> C6 F7 <COL3
COL7> D7 B1 <COL4
ENCA> E6 B3 <COL5
ENCB> B4 B2 <COL6
ROW2> B5 B7 D5 C7 F1 F0 B6 <ROW6
ROW4 ROW8
PS2C ROW7
*/
/* key matrix size */
#define MATRIX_ROWS 8
#define MATRIX_COLS 7
/* key matrix pins */
#define MATRIX_ROW_PINS { \
D4, B5, C6, B7, \
F4, B6, F1, F0 \
}
#define MATRIX_COL_PINS { \
F5, F6, F7, B1, B3, B2, \
D7 \
}
#define UNUSED_PINS
/* COL2ROW or ROW2COL */
#define DIODE_DIRECTION ROW2COL
/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 20
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->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<<PS2_CLOCK_BIT); \
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
UCSR1C = ((1 << UMSEL10) | \
(3 << UPM10) | \
(0 << USBS1) | \
(3 << UCSZ10) | \
(0 << UCPOL1)); \
UCSR1A = 0; \
UBRR1H = 0; \
UBRR1L = 0; \
} while (0)
#define PS2_USART_RX_INT_ON() do { \
UCSR1B = ((1 << RXCIE1) | \
(1 << RXEN1)); \
} while (0)
#define PS2_USART_RX_POLL_ON() do { \
UCSR1B = (1 << RXEN1); \
} while (0)
#define PS2_USART_OFF() do { \
UCSR1C = 0; \
UCSR1B &= ~((1 << RXEN1) | \
(1 << TXEN1)); \
} while (0)
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1))
#define PS2_USART_RX_DATA UDR1
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1)))
#define PS2_USART_RX_VECT USART1_RX_vect
#endif
#ifdef PS2_USE_INT
/* Note: pins are swapped, so re-soldering is needed to test both modes */
#define PS2_CLOCK_PIN D2
#define PS2_DATA_PIN D5
#define PS2_INT_INIT() do { \
EICRA |= ((1<<ISC21) | \
(0<<ISC20)); \
} while (0)
#define PS2_INT_ON() do { \
EIMSK |= (1<<INT2); \
} while (0)
#define PS2_INT_OFF() do { \
EIMSK &= ~(1<<INT2); \
} while (0)
#define PS2_INT_VECT INT2_vect
#endif
#endif

+ 110
- 0
keyboards/handwired/endgame48/endgame48.c View File

@ -0,0 +1,110 @@
// Copyright 2022 Andrew Dunai (@and3rson)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "endgame48.h"
#include "quantum.h"
#include "raw_hid.h"
#include "bitwise.h"
#include "oled/oled_driver.h"
#include "symbols.h"
#include "string.h"
#include "stdio.h"
#include "eeprom.h"
#include "encoder.h"
#include "menu.h"
#include "rgblight.h"
volatile static uint32_t reset_requested = 0;
void oled_paint(void);
void request_reset(void) {
reset_requested = timer_read32();
oled_clear();
oled_write_P(logo, false);
oled_write_P(resetIcon, false);
oled_write("\nREADY\n FOR \nFLASH", false);
for (int i = 0; i < 16; i++) {
oled_render();
}
rgblight_setrgb((DEBUG_COLOR >> 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;
}

+ 37
- 0
keyboards/handwired/endgame48/endgame48.h View File

@ -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

+ 240
- 0
keyboards/handwired/endgame48/glcdfont_48_v2.c View File

@ -0,0 +1,240 @@
#pragma once
#ifdef __AVR__
#include <avr/io.h>
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#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,
};

+ 60
- 0
keyboards/handwired/endgame48/info.json View File

@ -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 } ]
}
}
}

+ 4
- 0
keyboards/handwired/endgame48/keymaps/default/config.h View File

@ -0,0 +1,4 @@
// Copyright 2022 Andrew Dunai (@and3rson)
// SPDX-License-Identifier: GPL-2.0-or-later
#define OLED_TIMEOUT 30000

+ 221
- 0
keyboards/handwired/endgame48/keymaps/default/keymap.c View File

@ -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
RESETDEBUGSLEEPWAKE 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;
}

+ 5
- 0
keyboards/handwired/endgame48/keymaps/default/rules.mk View File

@ -0,0 +1,5 @@
ifndef QUANTUM_DIR
include ../../../../Makefile
endif
SRC += smoothled.c

+ 80
- 0
keyboards/handwired/endgame48/keymaps/default/smoothled.c View File

@ -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();
}

+ 15
- 0
keyboards/handwired/endgame48/keymaps/default/smoothled.h View File

@ -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);

+ 86
- 0
keyboards/handwired/endgame48/menu.c View File

@ -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;
}

+ 30
- 0
keyboards/handwired/endgame48/menu.h View File

@ -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);

+ 64
- 0
keyboards/handwired/endgame48/readme.md View File

@ -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 I<sup>2</sup>C 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 ┿ <ROW5
│ │
I2C> ┿ D0 F5 ┿ <COL1
│ ╱╲ │
ROW1> ┿ D4 ╱ ╲ F6 ┿ <COL2
│ ╱ ╲ │
ROW3> ┿ C6 ╲ ╱ F7 ┿ <COL3
│ ╲ ╱ │
COL7> ┿ D7 ╲╱ B1 ┿ <COL4
│ │
ENCA> ┿ E6 B3 ┿ <COL5
│ │
ENCB> ┿ B4 B2 ┿ <COL6
│ │
ROW2> │ B5 B7 D5 C7 F1 F0 B6 ┿ <ROW6
╰────╂──╂──╂──╂──╂─────╯
┃ ┃ ┃ ┃
ROW4 ┛ ┃ ┃ ┗ ROW8
┃ ┃
PS2C ┛ ┗ ROW7
```

+ 29
- 0
keyboards/handwired/endgame48/rules.mk View File

@ -0,0 +1,29 @@
# MCU name
MCU = atmega32u4
BOOTLOADER = atmel-dfu
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
# https://github.com/qmk/qmk_firmware/blob/master/docs/faq_debug.md
DEBUG_ENABLE = no # HID prints
COMMAND_ENABLE = no # Commands for debug and configuration
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
NKRO_ENABLE = no # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
AUDIO_ENABLE = no
RGBLIGHT_ENABLE = yes
ENCODER_ENABLE = yes
OLED_ENABLE = yes
PS2_MOUSE_ENABLE = no
# PS2_USE_USART = yes
# PS2_USE_INT = yes
DEBOUNCE_TYPE = sym_eager_pk
SRC += taphold.c symbols.c menu.c
# https://thomasbaart.nl/2018/12/01/reducing-firmware-size-in-qmk/
EXTRAFLAGS += -flto

+ 58
- 0
keyboards/handwired/endgame48/symbols.c View File

@ -0,0 +1,58 @@
// Copyright 2022 Andrew Dunai (@and3rson)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "symbols.h"
const char PROGMEM logo[12] = {
0x8f, 0x90, 0x91, 0x92, 0x93,
0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
/* '4', '8', ' ', 'v', '2', */
'\n',
0
};
const char PROGMEM layerIcons[4][26] = {
{
' ', ' ', ' ', ' ', ' ',
0x20, 0x80, 0x81, 0x82, 0x20,
0x20, 0xa0, 0xa1, 0xa2, 0x20,
0x20, 0xc0, 0xc1, 0xc2, 0x20,
' ', ' ', ' ', ' ', ' ', 0
},
{
' ', ' ', ' ', ' ', ' ',
0x20, 0x83, 0x84, 0x85, 0x20,
0x20, 0xa3, 0xa4, 0xa5, 0x20,
0x20, 0xc3, 0xc4, 0xc5, 0x20,
' ', ' ', ' ', ' ', ' ', 0
},
{
' ', ' ', ' ', ' ', ' ',
0x20, 0x86, 0x87, 0x88, 0x20,
0x20, 0xa6, 0xa7, 0xa8, 0x20,
0x20, 0xc6, 0xc7, 0xc8, 0x20,
' ', ' ', ' ', ' ', ' ', 0
},
{
' ', ' ', ' ', ' ', ' ',
0x20, 0x89, 0x8a, 0x8b, 0x20,
0x20, 0xa9, 0xaa, 0xab, 0x20,
0x20, 0xc9, 0xca, 0xcb, 0x20,
' ', ' ', ' ', ' ', ' ', 0
},
};
const char PROGMEM resetIcon[26] = {
' ', ' ', ' ', ' ', ' ',
' ', 0x8c, 0x8d, 0x8e, ' ',
' ', 0xac, 0xad, 0xae, ' ',
' ', 0xcc, 0xcd, 0xce, ' ',
' ', ' ', ' ', ' ', ' ', 0
};
const char PROGMEM mods[4][3] = {
{0x94, 0x95},
{0x96, 0x97},
{0x98, 0x99},
{0x9a, 0x9b},
};

+ 9
- 0
keyboards/handwired/endgame48/symbols.h View File

@ -0,0 +1,9 @@
// Copyright 2022 Andrew Dunai (@and3rson)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "endgame48.h"
extern const char PROGMEM logo[12];
extern const char PROGMEM layerIcons[4][26];
extern const char PROGMEM resetIcon[26];
extern const char PROGMEM mods[4][3];

+ 33
- 0
keyboards/handwired/endgame48/taphold.c View File

@ -0,0 +1,33 @@
// Copyright 2022 Andrew Dunai (@and3rson)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "taphold.h"
bool taphold_process(uint16_t keycode, keyrecord_t *record) {
for (int i = 0; i < taphold_config_size; i++) {
taphold_t *config = &taphold_config[i];
if (config->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;
}

+ 28
- 0
keyboards/handwired/endgame48/taphold.h View File

@ -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);

Loading…
Cancel
Save