Moved files to subdir

This commit is contained in:
2022-07-09 14:03:53 -07:00
parent 238d32cf77
commit 754279cbfb
32 changed files with 0 additions and 0 deletions

View File

@ -0,0 +1,110 @@
#ifdef RGB_MATRIX_DATAPOINTER_ENABLED
#ifndef DISABLE_RGB_MATRIX_FFT_ANIM
RGB_MATRIX_EFFECT(FFT_ANIM)
#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
// Maps fft columns to leds.
// fft_col_to_array[i] returns an array of leds in the ith bin of the fft.
// Negative indices are "invisible" leds.
// Use them when your keyboard has gaps.
//
// This layout is for the Ergodox EZ.
static int8_t fft_col_to_array[10][5] = {
{ 47, 43, 38, 33, 28 },
{ 46, 42, 37, 32, 27 },
{ 45, 41, 36, 31, 26 },
{ 44, 40, 35, 30, 25 },
{ -1, 39, 34, 29, 24 },
{ -1, 15, 10, 5, 0 },
{ 20, 16, 11, 6, 1 },
{ 21, 17, 12, 7, 2 },
{ 22, 18, 13, 8, 3 },
{ 23, 19, 14, 9, 4 }
};
// TODO:
// Dynamic color settings
bool FFT_ANIM(effect_params_t* params) {
RGB_MATRIX_USE_LIMITS(led_min, led_max);
// REQUIRED for any animation that uses this pointer.
// Clears any previous data.
if (params->init) {
rgb_matrix_anim_data = NULL;
return led_max < DRIVER_LED_TOTAL;
};
if (rgb_matrix_anim_data == NULL) {
// If animation data is empty, turn off all leds and exit.
for (uint8_t i = led_min; i < led_max; i++) {
rgb_matrix_set_color(
i,
0x00, 0x00, 0x00
);
}
} else {
// Data should be a pointer to 10 uint8_ts, each representing
// the height of a bar on the display.
uint8_t* data = (uint8_t*) rgb_matrix_anim_data;
for (uint8_t bin = 0; bin < 10; bin++) {
// Scale data values
uint8_t d = data[bin];
uint8_t bin_height = d / 50;
// Brightness of topmost key
uint8_t last_brightness = ((d % 50)/50.0) * 0xFF;
// Turn off leds that should be off.
// There are 5 keys in each column.
for (uint8_t i = bin_height; i < 6; i++) {
// Ignore negative indices.
// See fft_col_to_array definition.
if (fft_col_to_array[bin][i] < 0) {
continue;
}
rgb_matrix_set_color(
fft_col_to_array[bin][i],
0x00, 0x00, 0x00
);
}
// Turn on leds that should be on.
for (uint8_t i = 0; i < bin_height; i++) {
// Ignore negative indices.
// See fft_col_to_array definition.
if (fft_col_to_array[bin][i] < 0) {
continue;
}
// If this is the topmost lit key, its
// brightness depends on the height of the bar.
if (i == bin_height - 1) {
rgb_matrix_set_color(
fft_col_to_array[bin][i],
last_brightness, 0x00, last_brightness
);
// If this isn't the topmost key,
// it has a plain full-brightness color.
} else {
rgb_matrix_set_color(
fft_col_to_array[bin][i],
0x00, 0x00, 0xFF
);
}
}
}
}
return led_max < DRIVER_LED_TOTAL;
}
#endif
#endif
#endif

View File

@ -0,0 +1,537 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
Copyright 2015 ZSA Technology Labs Inc (@zsa)
Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna)
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 <http://www.gnu.org/licenses/>.
*/
#include "betalupi_ergodox.h"
#include "rawhid.h"
extern inline void ergodox_board_led_on(void);
extern inline void ergodox_right_led_1_on(void);
extern inline void ergodox_right_led_2_on(void);
extern inline void ergodox_right_led_3_on(void);
extern inline void ergodox_right_led_on(uint8_t led);
extern inline void ergodox_board_led_off(void);
extern inline void ergodox_right_led_1_off(void);
extern inline void ergodox_right_led_2_off(void);
extern inline void ergodox_right_led_3_off(void);
extern inline void ergodox_right_led_off(uint8_t led);
extern inline void ergodox_led_all_on(void);
extern inline void ergodox_led_all_off(void);
extern inline void ergodox_right_led_1_set(uint8_t n);
extern inline void ergodox_right_led_2_set(uint8_t n);
extern inline void ergodox_right_led_3_set(uint8_t n);
extern inline void ergodox_right_led_set(uint8_t led, uint8_t n);
extern inline void ergodox_led_all_set(uint8_t n);
keyboard_config_t keyboard_config;
bool i2c_initialized = 0;
i2c_status_t mcp23018_status = 0x20;
void matrix_init_kb(void) {
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
TCCR1A = 0b10101001; // set and configure fast PWM
TCCR1B = 0b00001001; // set and configure fast PWM
// (tied to Vcc for hardware convenience)
DDRB &= ~(1<<4); // set B(4) as input
PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
// unused pins - C7, D4, D5, D7, E6
// set as input with internal pull-up enabled
DDRC &= ~(1<<7);
DDRD &= ~(1<<5 | 1<<4);
DDRE &= ~(1<<6);
PORTC |= (1<<7);
PORTD |= (1<<5 | 1<<4);
PORTE |= (1<<6);
keyboard_config.raw = eeconfig_read_kb();
#ifdef RGB_MATRIX_ENABLE
if (keyboard_config.rgb_matrix_enable) {
rgb_matrix_set_flags(LED_FLAG_ALL);
} else {
rgb_matrix_set_flags(LED_FLAG_NONE);
}
#endif
ergodox_blink_all_leds();
matrix_init_user();
}
void ergodox_blink_all_leds(void) {
ergodox_led_all_off();
ergodox_led_all_set(LED_BRIGHTNESS_DEFAULT);
ergodox_right_led_1_on();
_delay_ms(50);
ergodox_right_led_2_on();
_delay_ms(50);
ergodox_right_led_3_on();
_delay_ms(50);
ergodox_right_led_1_off();
_delay_ms(50);
ergodox_right_led_2_off();
_delay_ms(50);
ergodox_right_led_3_off();
ergodox_led_all_off();
}
uint8_t init_mcp23018(void) {
mcp23018_status = 0x20;
// I2C subsystem
// uint8_t sreg_prev;
// sreg_prev=SREG;
// cli();
if (i2c_initialized == 0) {
i2c_init(); // on pins D(1,0)
i2c_initialized = true;
_delay_ms(1000);
}
// i2c_init(); // on pins D(1,0)
// _delay_ms(1000);
// set pin direction
// - unused : input : 1
// - input : input : 1
// - driving : output : 0
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
i2c_stop();
// set pull-up
// - unused : on : 1
// - input : on : 1
// - driving : off : 0
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
out:
i2c_stop();
// SREG=sreg_prev;
return mcp23018_status;
}
#ifdef SWAP_HANDS_ENABLE
__attribute__ ((weak))
// swap-hands action needs a matrix to define the swap
const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
/* Left hand, matrix positions */
{{0,13}, {1,13}, {2,13}, {3,13}, {4,13}, {5,13}},
{{0,12}, {1,12}, {2,12}, {3,12}, {4,12}, {5,12}},
{{0,11}, {1,11}, {2,11}, {3,11}, {4,11}, {5,11}},
{{0,10}, {1,10}, {2,10}, {3,10}, {4,10}, {5,10}},
{{0,9}, {1,9}, {2,9}, {3,9}, {4,9}, {5,9}},
{{0,8}, {1,8}, {2,8}, {3,8}, {4,8}, {5,8}},
{{0,7}, {1,7}, {2,7}, {3,7}, {4,7}, {5,7}},
/* Right hand, matrix positions */
{{0,6}, {1,6}, {2,6}, {3,6}, {4,6}, {5,6}},
{{0,5}, {1,5}, {2,5}, {3,5}, {4,5}, {5,5}},
{{0,4}, {1,4}, {2,4}, {3,4}, {4,4}, {5,4}},
{{0,3}, {1,3}, {2,3}, {3,3}, {4,3}, {5,3}},
{{0,2}, {1,2}, {2,2}, {3,2}, {4,2}, {5,2}},
{{0,1}, {1,1}, {2,1}, {3,1}, {4,1}, {5,1}},
{{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {5,0}},
};
#endif
#ifdef RGB_MATRIX_ENABLE
void suspend_power_down_kb(void) {
rgb_matrix_set_suspend_state(true);
suspend_power_down_user();
}
void suspend_wakeup_init_kb(void) {
rgb_matrix_set_suspend_state(false);
suspend_wakeup_init_user();
}
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
//{driver, R location, G location, B location}
{0, C3_1, C2_1, C4_1}, // LED1 on right
{0, C6_1, C5_1, C7_1}, // LED2
{0, C4_2, C3_2, C5_2}, // LED3
{0, C7_2, C6_2, C8_2}, // LED4
{0, C2_3, C1_3, C3_3}, // LED5
{0, C5_3, C4_3, C6_3}, // LED6
{0, C8_3, C7_3, C9_3}, // LED7
{0, C2_4, C1_4, C3_4}, // LED8
{0, C6_4, C5_4, C7_4}, // LED9
{0, C2_5, C1_5, C3_5}, // LED10
{0, C7_5, C6_5, C8_5}, // LED11
{0, C2_6, C1_6, C3_6}, // LED12
{0, C5_6, C4_6, C6_6}, // LED13
{0, C8_6, C7_6, C9_6}, // LED14
{0, C2_7, C1_7, C3_7}, // LED15
{0, C5_7, C4_7, C6_7}, // LED16
{0, C2_8, C1_8, C3_8}, // LED17
{0, C5_8, C4_8, C6_8}, // LED18
{0, C3_9, C2_9, C4_9}, // LED19
{0, C6_9, C5_9, C7_9}, // LED20
{0, C4_10, C3_10, C5_10}, // LED21
{0, C7_10, C6_10, C8_10}, // LED22
{0, C2_11, C1_11, C3_11}, // LED23
{0, C5_11, C4_11, C6_11}, // LED24
{1, C3_1, C2_1, C4_1}, // LED1 on left
{1, C6_1, C5_1, C7_1}, // LED2
{1, C4_2, C3_2, C5_2}, // LED3
{1, C7_2, C6_2, C8_2}, // LED4
{1, C2_3, C1_3, C3_3}, // LED5
{1, C5_3, C4_3, C6_3}, // LED6
{1, C8_3, C7_3, C9_3}, // LED7
{1, C2_4, C1_4, C3_4}, // LED8
{1, C6_4, C5_4, C7_4}, // LED9
{1, C2_5, C1_5, C3_5}, // LED10
{1, C7_5, C6_5, C8_5}, // LED11
{1, C2_6, C1_6, C3_6}, // LED12
{1, C5_6, C4_6, C6_6}, // LED13
{1, C8_6, C7_6, C9_6}, // LED14
{1, C2_7, C1_7, C3_7}, // LED15
{1, C5_7, C4_7, C6_7}, // LED16
{1, C2_8, C1_8, C3_8}, // LED17
{1, C5_8, C4_8, C6_8}, // LED18
{1, C3_9, C2_9, C4_9}, // LED19
{1, C6_9, C5_9, C7_9}, // LED20
{1, C4_10, C3_10, C5_10}, // LED21
{1, C7_10, C6_10, C8_10}, // LED22
{1, C2_11, C1_11, C3_11}, // LED23
{1, C5_11, C4_11, C6_11} // LED24
};
led_config_t g_led_config = { {
// Key matrix to LED index
{ NO_LED, NO_LED, NO_LED, NO_LED, NO_LED, NO_LED },
{ 28, 33, 38, 43, 47, NO_LED },
{ 27, 32, 37, 42, 46, NO_LED },
{ 26, 31, 36, 41, 45, NO_LED },
{ 25, 30, 35, 40, 44, NO_LED },
{ 24, 29, 34, 39, NO_LED, NO_LED },
{ NO_LED, NO_LED, NO_LED, NO_LED, NO_LED, NO_LED },
{ NO_LED, NO_LED, NO_LED, NO_LED, NO_LED, NO_LED },
{ 0, 5, 10, 15, NO_LED, NO_LED },
{ 1, 6, 11, 16, 20, NO_LED },
{ 2, 7, 12, 17, 21, NO_LED },
{ 3, 8, 13, 18, 22, NO_LED },
{ 4, 9, 14, 19, 23, NO_LED },
{ NO_LED, NO_LED, NO_LED, NO_LED, NO_LED, NO_LED }
}, {
// LED index to physical position
{ 137, 0 }, { 154, 0 }, { 172, 0 }, { 189, 0 }, { 206, 0 }, { 137, 12 },
{ 154, 12 }, { 172, 12 }, { 189, 12 }, { 206, 12 }, { 137, 25 }, { 154, 25 },
{ 172, 25 }, { 189, 25 }, { 206, 25 }, { 137, 38 }, { 154, 38 }, { 172, 38 },
{ 189, 38 }, { 206, 38 }, { 154, 51 }, { 172, 51 }, { 189, 51 }, { 206, 51 },
{ 86, 0 }, { 68, 0 }, { 51, 0 }, { 34, 0 }, { 17, 0 }, { 86, 12 },
{ 68, 12 }, { 51, 12 }, { 34, 12 }, { 17, 12 }, { 86, 25 }, { 68, 25 },
{ 51, 25 }, { 34, 25 }, { 17, 25 }, { 86, 38 }, { 68, 38 }, { 51, 38 },
{ 34, 38 }, { 17, 38 }, { 68, 51 }, { 51, 51 }, { 34, 51 }, { 17, 51 }
}, {
// LED index to flag
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 1, 1, 1, 1,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4,
4, 4, 1, 1, 1, 1
} };
#endif
void keyboard_post_init_kb(void) {
// Start with matrix enabled
// (We enable RGB effects and layer colors seperately)
#ifdef RGB_MATRIX_ENABLE
rgb_matrix_enable_noeeprom();
#endif
// Start with backlight disabled
#ifdef RGBLIGHT_ENABLE
#ifdef RGBLIGHT_OFF_AT_START
rgblight_disable_noeeprom();
#endif
#endif
keyboard_post_init_user();
}
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case LED_LEVEL:
if (record->event.pressed) {
keyboard_config.led_level++;
if (keyboard_config.led_level > 4) {
keyboard_config.led_level = 0;
}
ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4 );
eeconfig_update_kb(keyboard_config.raw);
layer_state_set_kb(layer_state);
}
break;
#ifdef RGB_MATRIX_ENABLE
case TOGGLE_LAYER_COLOR:
if (record->event.pressed) {
keyboard_config.disable_layer_led ^= 1;
if (keyboard_config.disable_layer_led) {
rgb_matrix_set_color_all(0, 0, 0);
}
eeconfig_update_kb(keyboard_config.raw);
}
break;
case RGB_TOG:
if (record->event.pressed) {
switch (rgb_matrix_get_flags()) {
case LED_FLAG_ALL: {
rgb_matrix_set_flags(LED_FLAG_NONE);
keyboard_config.rgb_matrix_enable = false;
rgb_matrix_set_color_all(0, 0, 0);
}
break;
default: {
rgb_matrix_set_flags(LED_FLAG_ALL);
keyboard_config.rgb_matrix_enable = true;
}
break;
}
eeconfig_update_kb(keyboard_config.raw);
}
hid_send_state();
return false;
case RGB_MOD:
// Tell the host whenever we change animation mode.
hid_send_state();
return true;
#endif
// Custom RGBLIGHT macros
#ifdef RGBLIGHT_ENABLE
#ifdef RGBLIGHT_NO_EEPROM
case LIGHT_TOG:
if (record->event.pressed) {
rgblight_toggle_noeeprom();
}
break;
case LIGHT_MOD:
if (record->event.pressed) {
rgblight_step_noeeprom();
}
break;
case LIGHT_HUI:
if (record->event.pressed) {
rgblight_increase_hue_noeeprom();
}
break;
case LIGHT_HUD:
if (record->event.pressed) {
rgblight_decrease_hue_noeeprom();
}
break;
case LIGHT_SAI:
if (record->event.pressed) {
rgblight_increase_sat_noeeprom();
}
break;
case LIGHT_SAD:
if (record->event.pressed) {
rgblight_decrease_sat_noeeprom();
}
break;
case LIGHT_VAI:
if (record->event.pressed) {
rgblight_increase_val_noeeprom();
}
break;
case LIGHT_VAD:
if (record->event.pressed) {
rgblight_decrease_val_noeeprom();
}
break;
case LIGHT_SPI:
if (record->event.pressed) {
rgblight_increase_speed_noeeprom();
}
break;
case LIGHT_SPD:
if (record->event.pressed) {
rgblight_decrease_speed_noeeprom();
}
break;
#else
case LIGHT_TOG:
if (record->event.pressed) {
rgblight_toggle();
}
break;
case LIGHT_MOD:
if (record->event.pressed) {
rgblight_step();
}
break;
case LIGHT_HUI:
if (record->event.pressed) {
rgblight_increase_hue();
}
break;
case LIGHT_HUD:
if (record->event.pressed) {
rgblight_decrease_hue();
}
break;
case LIGHT_SAI:
if (record->event.pressed) {
rgblight_increase_sat();
}
break;
case LIGHT_SAD:
if (record->event.pressed) {
rgblight_decrease_sat();
}
break;
case LIGHT_VAI:
if (record->event.pressed) {
rgblight_increase_val();
}
break;
case LIGHT_VAD:
if (record->event.pressed) {
rgblight_decrease_val();
}
break;
case LIGHT_SPI:
if (record->event.pressed) {
rgblight_increase_speed();
}
break;
case LIGHT_SPD:
if (record->event.pressed) {
rgblight_decrease_speed();
}
break;
#endif
#endif
}
return process_record_user(keycode, record);
}
// EEPROM is getting reset!
void eeconfig_init_kb(void) {
keyboard_config.raw = 0;
keyboard_config.led_level = 4;
keyboard_config.rgb_matrix_enable = true;
eeconfig_update_kb(keyboard_config.raw);
eeconfig_init_user();
}
#ifdef DYNAMIC_MACRO_ENABLE
static bool is_dynamic_recording = false;
static uint16_t dynamic_loop_timer;
void dynamic_macro_record_start_user(void) {
is_dynamic_recording = true;
dynamic_loop_timer = timer_read();
ergodox_right_led_1_on();
}
void dynamic_macro_record_end_user(int8_t direction) {
is_dynamic_recording = false;
layer_state_set_user(layer_state);
}
#endif
void matrix_scan_kb(void) {
#ifdef DYNAMIC_MACRO_ENABLE
if (is_dynamic_recording) {
ergodox_right_led_1_off();
// if (timer_elapsed(dynamic_loop_timer) > 5)
{
static uint8_t counter;
counter++;
if (counter > 100) ergodox_right_led_1_on();
dynamic_loop_timer = timer_read();
}
}
#endif
#ifdef CAPS_LOCK_STATUS
led_t led_state = host_keyboard_led_state();
if(led_state.caps_lock) {
ergodox_right_led_3_on();
}
else {
uint8_t layer = get_highest_layer(layer_state);
if(layer != 3) {
ergodox_right_led_3_off();
}
}
#endif
matrix_scan_user();
}

View File

@ -0,0 +1,307 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
Copyright 2015 ZSA Technology Labs Inc (@zsa)
Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna)
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "quantum.h"
#include <stdint.h>
#include <stdbool.h>
#include "i2c_master.h"
// I2C aliases and register addresses (see "mcp23018.md")
#define I2C_ADDR 0b0100000
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
#define IODIRA 0x00 // i/o direction register
#define IODIRB 0x01
#define GPPUA 0x0C // GPIO pull-up resistor register
#define GPPUB 0x0D
#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
#define GPIOB 0x13
#define OLATA 0x14 // output latch register
#define OLATB 0x15
extern i2c_status_t mcp23018_status;
#define ERGODOX_EZ_I2C_TIMEOUT 100
void init_ergodox(void);
void ergodox_blink_all_leds(void);
uint8_t init_mcp23018(void);
#ifndef LED_BRIGHTNESS_LO
#define LED_BRIGHTNESS_LO 15
#endif
#ifndef LED_BRIGHTNESS_HI
#define LED_BRIGHTNESS_HI 255
#endif
inline void ergodox_board_led_on(void) { DDRD |= (1<<6); PORTD |= (1<<6); }
inline void ergodox_right_led_1_on(void) { DDRB |= (1<<5); PORTB |= (1<<5); }
inline void ergodox_right_led_2_on(void) { DDRB |= (1<<6); PORTB |= (1<<6); }
inline void ergodox_right_led_3_on(void) { DDRB |= (1<<7); PORTB |= (1<<7); }
inline void ergodox_right_led_on(uint8_t led) { DDRB |= (1<<(led+4)); PORTB |= (1<<(led+4)); }
inline void ergodox_board_led_off(void) { DDRD &= ~(1<<6); PORTD &= ~(1<<6); }
inline void ergodox_right_led_1_off(void) { DDRB &= ~(1<<5); PORTB &= ~(1<<5); }
inline void ergodox_right_led_2_off(void) { DDRB &= ~(1<<6); PORTB &= ~(1<<6); }
inline void ergodox_right_led_3_off(void) { DDRB &= ~(1<<7); PORTB &= ~(1<<7); }
inline void ergodox_right_led_off(uint8_t led) { DDRB &= ~(1<<(led+4)); PORTB &= ~(1<<(led+4)); }
inline void ergodox_led_all_on(void) {
ergodox_board_led_on();
ergodox_right_led_1_on();
ergodox_right_led_2_on();
ergodox_right_led_3_on();
}
inline void ergodox_led_all_off(void) {
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
ergodox_right_led_3_off();
}
inline void ergodox_right_led_1_set(uint8_t n) { OCR1A = n; }
inline void ergodox_right_led_2_set(uint8_t n) { OCR1B = n; }
inline void ergodox_right_led_3_set(uint8_t n) { OCR1C = n; }
inline void ergodox_right_led_set(uint8_t led, uint8_t n) {
(led == 1) ? (OCR1A = n) :
(led == 2) ? (OCR1B = n) :
(OCR1C = n);
}
inline void ergodox_led_all_set(uint8_t n) {
ergodox_right_led_1_set(n);
ergodox_right_led_2_set(n);
ergodox_right_led_3_set(n);
}
enum ergodox_ez_keycodes {
LED_LEVEL = SAFE_RANGE,
TOGGLE_LAYER_COLOR,
// Custom RGBLIGHT macros
LIGHT_TOG, // Toggle backlight
LIGHT_HUI, // Increase backlight hue
LIGHT_HUD, // Decrease backlight hue
LIGHT_SAI, // Increase backlight sat
LIGHT_SAD, // Decrease backlight sat
LIGHT_VAI, // Increase backlight val
LIGHT_VAD, // Decrease backlight val
LIGHT_SPI, // Increase backlight speed
LIGHT_SPD, // Decrease backlight speed
LIGHT_MOD, // Change backlight animation mode
BETA_SAFE_RANGE
};
typedef union {
uint32_t raw;
struct {
uint8_t led_level :3;
bool disable_layer_led :1;
bool rgb_matrix_enable :1;
};
} keyboard_config_t;
extern keyboard_config_t keyboard_config;
// Turns {h, s, v} triples into a macro, so that
// the LEDS_ergodox macro can take them as inputs.
#define LC_HSV(h, s, v) {h, s, v}
// Rearrange a human-readable LED layout into the correct Ergodox order.
// LEDS_ergodox ONLY WORKS WITH MACROS.
// Don't input a standalone triple {h, s, v};
// Use LC_HSV if you need a single-instance color.
#define LEDS_ergodox( \
l01,l02,l03,l04,l05, \
l06,l07,l08,l09,l10, \
l11,l12,l13,l14,l15, \
l16,l17,l18,l19,l20, \
l21,l22,l23,l24, \
\
l25,l26,l27,l28,l29, \
l30,l31,l32,l33,l34, \
l35,l36,l37,l38,l39, \
l40,l41,l42,l43,l44, \
l45,l46,l47,l48 \
) \
{ \
l25,l26,l27,l28,l29, \
l30,l31,l32,l33,l34, \
l35,l36,l37,l38,l39, \
l40,l41,l42,l43,l44, \
l45,l46,l47,l48, \
\
l05,l04,l03,l02,l01, \
l10,l09,l08,l07,l06, \
l15,l14,l13,l12,l11, \
l20,l19,l18,l17,l16, \
l24,l23,l22,l21 \
}
/*
LEFT HAND: LINES 115-122
RIGHT HAND: LINES 124-131
*/
#define LAYOUT_ergodox( \
\
k00,k01,k02,k03,k04,k05,k06, \
k10,k11,k12,k13,k14,k15,k16, \
k20,k21,k22,k23,k24,k25, \
k30,k31,k32,k33,k34,k35,k36, \
k40,k41,k42,k43,k44, \
k55,k56, \
k54, \
k53,k52,k51, \
\
k07,k08,k09,k0A,k0B,k0C,k0D, \
k17,k18,k19,k1A,k1B,k1C,k1D, \
k28,k29,k2A,k2B,k2C,k2D, \
k37,k38,k39,k3A,k3B,k3C,k3D, \
k49,k4A,k4B,k4C,k4D, \
k57,k58, \
k59, \
k5C,k5B,k5A ) \
\
/* matrix positions */ \
{ \
{ k00, k10, k20, k30, k40, KC_NO }, \
{ k01, k11, k21, k31, k41, k51 }, \
{ k02, k12, k22, k32, k42, k52 }, \
{ k03, k13, k23, k33, k43, k53 }, \
{ k04, k14, k24, k34, k44, k54 }, \
{ k05, k15, k25, k35, KC_NO, k55 }, \
{ k06, k16, KC_NO, k36, KC_NO, k56 }, \
\
{ k07, k17, KC_NO, k37,KC_NO, k57 }, \
{ k08, k18, k28, k38,KC_NO, k58 }, \
{ k09, k19, k29, k39, k49, k59 }, \
{ k0A, k1A, k2A, k3A, k4A, k5A }, \
{ k0B, k1B, k2B, k3B, k4B, k5B }, \
{ k0C, k1C, k2C, k3C, k4C, k5C }, \
{ k0D, k1D, k2D, k3D, k4D, KC_NO } \
}
/*
LEFT HAND: LINES 158-165
RIGHT HAND: LINES 167-174
*/
#define LAYOUT_ergodox_80( \
\
k00,k01,k02,k03,k04,k05,k06, \
k10,k11,k12,k13,k14,k15,k16, \
k20,k21,k22,k23,k24,k25, \
k30,k31,k32,k33,k34,k35,k36, \
k40,k41,k42,k43,k44, \
k55,k56, \
k45,k46,k54, \
k53,k52,k51, \
\
k07,k08,k09,k0A,k0B,k0C,k0D, \
k17,k18,k19,k1A,k1B,k1C,k1D, \
k28,k29,k2A,k2B,k2C,k2D, \
k37,k38,k39,k3A,k3B,k3C,k3D, \
k49,k4A,k4B,k4C,k4D, \
k57,k58, \
k59,k47,k48, \
k5C,k5B,k5A ) \
\
/* matrix positions */ \
{ \
{ k00, k10, k20, k30, k40, KC_NO }, \
{ k01, k11, k21, k31, k41, k51 }, \
{ k02, k12, k22, k32, k42, k52 }, \
{ k03, k13, k23, k33, k43, k53 }, \
{ k04, k14, k24, k34, k44, k54 }, \
{ k05, k15, k25, k35, k45, k55 }, \
{ k06, k16, KC_NO, k36, k46, k56 }, \
\
{ k07, k17, KC_NO, k37, k47, k57 }, \
{ k08, k18, k28, k38, k48, k58 }, \
{ k09, k19, k29, k39, k49, k59 }, \
{ k0A, k1A, k2A, k3A, k4A, k5A }, \
{ k0B, k1B, k2B, k3B, k4B, k5B }, \
{ k0C, k1C, k2C, k3C, k4C, k5C }, \
{ k0D, k1D, k2D, k3D, k4D, KC_NO } \
}
/* ---------- LEFT HAND ----------- ---------- RIGHT HAND ---------- */
#define LAYOUT_ergodox_pretty( \
L00,L01,L02,L03,L04,L05,L06, R00,R01,R02,R03,R04,R05,R06, \
L10,L11,L12,L13,L14,L15,L16, R10,R11,R12,R13,R14,R15,R16, \
L20,L21,L22,L23,L24,L25, R21,R22,R23,R24,R25,R26, \
L30,L31,L32,L33,L34,L35,L36, R30,R31,R32,R33,R34,R35,R36, \
L40,L41,L42,L43,L44, R42,R43,R44,R45,R46, \
L55,L56, R50,R51, \
L54, R52, \
L53,L52,L51, R55,R54,R53 ) \
\
/* matrix positions */ \
{ \
{ L00, L10, L20, L30, L40, KC_NO }, \
{ L01, L11, L21, L31, L41, L51 }, \
{ L02, L12, L22, L32, L42, L52 }, \
{ L03, L13, L23, L33, L43, L53 }, \
{ L04, L14, L24, L34, L44, L54 }, \
{ L05, L15, L25, L35, KC_NO, L55 }, \
{ L06, L16, KC_NO, L36, KC_NO, L56 }, \
\
{ R00, R10, KC_NO, R30,KC_NO, R50 }, \
{ R01, R11, R21, R31,KC_NO, R51 }, \
{ R02, R12, R22, R32, R42, R52 }, \
{ R03, R13, R23, R33, R43, R53 }, \
{ R04, R14, R24, R34, R44, R54 }, \
{ R05, R15, R25, R35, R45, R55 }, \
{ R06, R16, R26, R36, R46, KC_NO } \
}
/* ---------- LEFT HAND ----------- ---------- RIGHT HAND ---------- */
#define LAYOUT_ergodox_pretty_80( \
L00,L01,L02,L03,L04,L05,L06, R00,R01,R02,R03,R04,R05,R06, \
L10,L11,L12,L13,L14,L15,L16, R10,R11,R12,R13,R14,R15,R16, \
L20,L21,L22,L23,L24,L25, R21,R22,R23,R24,R25,R26, \
L30,L31,L32,L33,L34,L35,L36, R30,R31,R32,R33,R34,R35,R36, \
L40,L41,L42,L43,L44, R42,R43,R44,R45,R46, \
L55,L56, R50,R51, \
L45,L46,L54, R52,R40,R41, \
L53,L52,L51, R55,R54,R53 ) \
\
/* matrix positions */ \
{ \
{ L00, L10, L20, L30, L40, KC_NO }, \
{ L01, L11, L21, L31, L41, L51 }, \
{ L02, L12, L22, L32, L42, L52 }, \
{ L03, L13, L23, L33, L43, L53 }, \
{ L04, L14, L24, L34, L44, L54 }, \
{ L05, L15, L25, L35, L45, L55 }, \
{ L06, L16, KC_NO, L36, L46, L56 }, \
\
{ R00, R10, KC_NO, R30, R40, R50 }, \
{ R01, R11, R21, R31, R41, R51 }, \
{ R02, R12, R22, R32, R42, R52 }, \
{ R03, R13, R23, R33, R43, R53 }, \
{ R04, R14, R24, R34, R44, R54 }, \
{ R05, R15, R25, R35, R45, R55 }, \
{ R06, R16, R26, R36, R46, KC_NO } \
}

View File

@ -0,0 +1,141 @@
#pragma once
#include "config_common.h"
// USB parameters
#define VENDOR_ID 0x3297 // ZSA Labs
#define PRODUCT_ID 0x4976 // Ergodox glow variant
#define DEVICE_VER 0x0002
#define MANUFACTURER Betalupi
#define PRODUCT Betalupi ErgoDox
#define WEBUSB_LANDING_PAGE_URL u8"betalupi.com"
#define USB_MAX_POWER_CONSUMPTION 500
#define USB_SUSPEND_WAKEUP_DELAY 0
// raw HID params
#define RAW_USAGE_PAGE 0xFF60
#define RAW_USAGE_ID 0x61
// Key matrix info
#define MATRIX_ROWS 14
#define MATRIX_ROWS_PER_SIDE (MATRIX_ROWS / 2)
#define MATRIX_COLS 6
#define COL_EXPANDED { true, true, true, true, true, true, true, false, false, false, false, false, false, false }
#define MATRIX_ONBOARD_ROW_PINS { 0, 0, 0, 0, 0, 0, 0, B0, B1, B2, B3, D2, D3, C6 }
#define MATRIX_ONBOARD_COL_PINS { F0, F1, F4, F5, F6, F7 }
#define DIODE_DIRECTION COL2ROW
#define EXPANDER_COL_REGISTER GPIOB
#define EXPANDER_ROW_REGISTER GPIOA
#define MATRIX_EXPANDER_COL_PINS { 5, 4, 3, 2, 1, 0 }
#define MATRIX_EXPANDER_ROW_PINS { 0, 1, 2, 3, 4, 5, 6 }
// The debounce filtering reports a key/switch change directly,
// without any extra delay. After that the debounce logic will filter
// all further changes, until the key/switch reports the same
// state for the given count of scans.
//
// A perfect switch will get a short debounce period and
// bad key will get a much longer debounce period.
//
// The result is an adaptive debouncing period for each switch.
// If you don't define it here, the matrix code will default to
// 5, which is now closer to 10ms, but still plenty according to
// manufacturer specs.
#define DEBOUNCE 30
// Feature parameters
#define TAPPING_TOGGLE 1
#define TAPPING_TERM 200
// This makes it possible to do rolling combos (zx)
// with keys that convert to other keys on hold
// (z becomes ctrl when you hold it, and when this option isn't
// enabled, z rapidly followed by x actually sends Ctrl-x)
#define IGNORE_MOD_TAP_INTERRUPT
#define MOUSEKEY_INTERVAL 20
#define MOUSEKEY_DELAY 0
#define MOUSEKEY_TIME_TO_MAX 100
#define MOUSEKEY_MAX_SPEED 5
#define MOUSEKEY_WHEEL_DELAY 400
#define MOUSEKEY_WHEEL_INTERVAL MOUSEKEY_INTERVAL
#define MOUSEKEY_WHEEL_MAX_SPEED MOUSEKEY_MAX_SPEED
#define MOUSEKEY_WHEEL_TIME_TO_MAX MOUSEKEY_TIME_TO_MAX
// Ergodox indicator LEDs
#define LED_BRIGHTNESS_LO 5
#define LED_BRIGHTNESS_HI 100
#define LED_BRIGHTNESS_DEFAULT (LED_BRIGHTNESS_LO)
// RGBLight (Underglow) config
#define RGBLED_NUM 8
#define RGB_DI_PIN D7
#define RGBLIGHT_HUE_STEP 10
#define RGBLIGHT_SAT_STEP 16
#define RGBLIGHT_VAL_STEP 10
// Max brightness
#define RGBLIGHT_LIMIT_VAL 200
//#define RGBLIGHT_OFF_AT_START
//#define RGBLIGHT_NO_EEPROM
// Prevents RGB keycodes from affecting underglow.
// This allows us to control RGBMatrix and RGBLight seperately
// with custom macros defined in betalupi_ergodox.c
#define RGBLIGHT_DISABLE_KEYCODES
// The underglow LEDs I used for the backlight mod aren't RGBW,
// undef this just to be sure.
#undef RGBW
#define RGBLIGHT_SLEEP
// RGBMatrix (Key light) config
#define DRIVER_ADDR_1 0b1110100
#define DRIVER_ADDR_2 0b1110111
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 24
#define DRIVER_2_LED_TOTAL 24
#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
#define RGB_MATRIX_HUE_STEP 10
#define RGB_MATRIX_SAT_STEP 16
#define RGB_MATRIX_VAL_STEP 16
#define RGB_MATRIX_STARTUP_SPD 60
// limits the number of LEDs to process in an animation per task run
// (increases keyboard responsiveness)
#define RGB_MATRIX_LED_PROCESS_LIMIT 5
// limits in milliseconds how frequently an animation will update the LEDs.
// 16 (16ms) is equivalent to limiting to 60fps
// (increases keyboard responsiveness)
#define RGB_MATRIX_LED_FLUSH_LIMIT 26
// turn off effects when suspended
#define RGB_DISABLE_WHEN_USB_SUSPENDED true
// Misc
/* key combination for command */
#define IS_COMMAND() ( \
get_mods() == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \
get_mods() == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
)
// Not sure what this does.
// ZSA says: "fixes space cadet rollover issue"
#define DISABLE_SPACE_CADET_ROLLOVER

View File

@ -0,0 +1,104 @@
{
"keyboard_name": "Betalupi ErgoDox",
"url": "betalupi.com",
"maintainer": "mark@betalupi",
"width": 17,
"height": 8,
"layouts": {
"LAYOUT_ergodox": {
"layout": [
{"x":0, "y":0.375, "w":1.5}, {"x":1.5, "y":0.375}, {"x":2.5, "y":0.125}, {"x":3.5, "y":0}, {"x":4.5, "y":0.125}, {"x":5.5, "y":0.25}, {"x":6.5, "y":0.25},
{"x":0, "y":1.375, "w":1.5}, {"x":1.5, "y":1.375}, {"x":2.5, "y":1.125}, {"x":3.5, "y":1}, {"x":4.5, "y":1.125}, {"x":5.5, "y":1.25}, {"x":6.5, "y":1.25, "h":1.5},
{"x":0, "y":2.375, "w":1.5}, {"x":1.5, "y":2.375}, {"x":2.5, "y":2.125}, {"x":3.5, "y":2}, {"x":4.5, "y":2.125}, {"x":5.5, "y":2.25},
{"x":0, "y":3.375, "w":1.5}, {"x":1.5, "y":3.375}, {"x":2.5, "y":3.125}, {"x":3.5, "y":3}, {"x":4.5, "y":3.125}, {"x":5.5, "y":3.25}, {"x":6.5, "y":2.75, "h":1.5},
{"x":0.5, "y":4.375}, {"x":1.5, "y":4.375}, {"x":2.5, "y":4.125}, {"x":3.5, "y":4}, {"x":4.5, "y":4.125},
{"x":6, "y":5}, {"x":7, "y":5},
{"x":7, "y":6},
{"x":5, "y":6, "h":2}, {"x":6, "y":6, "h":2}, {"x":7, "y":7},
{"x":9.5, "y":0.25}, {"x":10.5, "y":0.25}, {"x":11.5, "y":0.125}, {"x":12.5, "y":0}, {"x":13.5, "y":0.125}, {"x":14.5, "y":0.375}, {"x":15.5, "y":0.375, "w":1.5},
{"x":9.5, "y":1.25, "h":1.5}, {"x":10.5, "y":1.25}, {"x":11.5, "y":1.125}, {"x":12.5, "y":1}, {"x":13.5, "y":1.125}, {"x":14.5, "y":1.375}, {"x":15.5, "y":1.375, "w":1.5},
{"x":10.5, "y":2.25}, {"x":11.5, "y":2.125}, {"x":12.5, "y":2}, {"x":13.5, "y":2.125}, {"x":14.5, "y":2.375}, {"x":15.5, "y":2.375, "w":1.5},
{"x":9.5, "y":2.75, "h":1.5}, {"x":10.5, "y":3.25}, {"x":11.5, "y":3.125}, {"x":12.5, "y":3}, {"x":13.5, "y":3.125}, {"x":14.5, "y":3.375}, {"x":15.5, "y":3.375, "w":1.5},
{"x":11.5, "y":4.125}, {"x":12.5, "y":4}, {"x":13.5, "y":4.125}, {"x":14.5, "y":4.375}, {"x":15.5, "y":4.375},
{"x":9, "y":5}, {"x":10, "y":5},
{"x":9, "y":6},
{"x":9, "y":7}, {"x":10, "y":6, "h":2}, {"x":11, "y":6, "h":2}
]
},
"LAYOUT_ergodox_pretty": {
"layout": [
{"x":0, "y":0.375, "w":1.5}, {"x":1.5, "y":0.375}, {"x":2.5, "y":0.125}, {"x":3.5, "y":0}, {"x":4.5, "y":0.125}, {"x":5.5, "y":0.25}, {"x":6.5, "y":0.25},
{"x":9.5, "y":0.25}, {"x":10.5, "y":0.25}, {"x":11.5, "y":0.125}, {"x":12.5, "y":0}, {"x":13.5, "y":0.125}, {"x":14.5, "y":0.375}, {"x":15.5, "y":0.375, "w":1.5},
{"x":0, "y":1.375, "w":1.5}, {"x":1.5, "y":1.375}, {"x":2.5, "y":1.125}, {"x":3.5, "y":1}, {"x":4.5, "y":1.125}, {"x":5.5, "y":1.25}, {"x":6.5, "y":1.25, "h":1.5},
{"x":9.5, "y":1.25, "h":1.5}, {"x":10.5, "y":1.25}, {"x":11.5, "y":1.125}, {"x":12.5, "y":1}, {"x":13.5, "y":1.125}, {"x":14.5, "y":1.375}, {"x":15.5, "y":1.375, "w":1.5},
{"x":0, "y":2.375, "w":1.5}, {"x":1.5, "y":2.375}, {"x":2.5, "y":2.125}, {"x":3.5, "y":2}, {"x":4.5, "y":2.125}, {"x":5.5, "y":2.25},
{"x":10.5, "y":2.25}, {"x":11.5, "y":2.125}, {"x":12.5, "y":2}, {"x":13.5, "y":2.125}, {"x":14.5, "y":2.375}, {"x":15.5, "y":2.375, "w":1.5},
{"x":0, "y":3.375, "w":1.5}, {"x":1.5, "y":3.375}, {"x":2.5, "y":3.125}, {"x":3.5, "y":3}, {"x":4.5, "y":3.125}, {"x":5.5, "y":3.25}, {"x":6.5, "y":2.75, "h":1.5},
{"x":9.5, "y":2.75, "h":1.5}, {"x":10.5, "y":3.25}, {"x":11.5, "y":3.125}, {"x":12.5, "y":3}, {"x":13.5, "y":3.125}, {"x":14.5, "y":3.375}, {"x":15.5, "y":3.375, "w":1.5},
{"x":0.5, "y":4.375}, {"x":1.5, "y":4.375}, {"x":2.5, "y":4.125}, {"x":3.5, "y":4}, {"x":4.5, "y":4.125},
{"x":11.5, "y":4.125}, {"x":12.5, "y":4}, {"x":13.5, "y":4.125}, {"x":14.5, "y":4.375}, {"x":15.5, "y":4.375},
{"x":6, "y":5}, {"x":7, "y":5}, {"x":9, "y":5}, {"x":10, "y":5},
{"x":7, "y":6}, {"x":9, "y":6},
{"x":5, "y":6, "h":2}, {"x":6, "y":6, "h":2}, {"x":7, "y":7}, {"x":9, "y":7}, {"x":10, "y":6, "h":2}, {"x":11, "y":6, "h":2}
]
},
"LAYOUT_ergodox_80": {
"layout": [
{"x":0, "y":0.375, "w":1.5}, {"x":1.5, "y":0.375}, {"x":2.5, "y":0.125}, {"x":3.5, "y":0}, {"x":4.5, "y":0.125}, {"x":5.5, "y":0.25}, {"x":6.5, "y":0.25},
{"x":0, "y":1.375, "w":1.5}, {"x":1.5, "y":1.375}, {"x":2.5, "y":1.125}, {"x":3.5, "y":1}, {"x":4.5, "y":1.125}, {"x":5.5, "y":1.25}, {"x":6.5, "y":1.25, "h":1.5},
{"x":0, "y":2.375, "w":1.5}, {"x":1.5, "y":2.375}, {"x":2.5, "y":2.125}, {"x":3.5, "y":2}, {"x":4.5, "y":2.125}, {"x":5.5, "y":2.25},
{"x":0, "y":3.375, "w":1.5}, {"x":1.5, "y":3.375}, {"x":2.5, "y":3.125}, {"x":3.5, "y":3}, {"x":4.5, "y":3.125}, {"x":5.5, "y":3.25}, {"x":6.5, "y":2.75, "h":1.5},
{"x":0.5, "y":4.375}, {"x":1.5, "y":4.375}, {"x":2.5, "y":4.125}, {"x":3.5, "y":4}, {"x":4.5, "y":4.125},
{"x":6, "y":5}, {"x":7, "y":5},
{"x":5, "y":6}, {"x":6, "y":6}, {"x":7, "y":6},
{"x":5, "y":7}, {"x":6, "y":7}, {"x":7, "y":7},
{"x":9.5, "y":0.25}, {"x":10.5, "y":0.25}, {"x":11.5, "y":0.125}, {"x":12.5, "y":0}, {"x":13.5, "y":0.125}, {"x":14.5, "y":0.375}, {"x":15.5, "y":0.375, "w":1.5},
{"x":9.5, "y":1.25, "h":1.5}, {"x":10.5, "y":1.25}, {"x":11.5, "y":1.125}, {"x":12.5, "y":1}, {"x":13.5, "y":1.125}, {"x":14.5, "y":1.375}, {"x":15.5, "y":1.375, "w":1.5},
{"x":10.5, "y":2.25}, {"x":11.5, "y":2.125}, {"x":12.5, "y":2}, {"x":13.5, "y":2.125}, {"x":14.5, "y":2.375}, {"x":15.5, "y":2.375, "w":1.5},
{"x":9.5, "y":2.75, "h":1.5}, {"x":10.5, "y":3.25}, {"x":11.5, "y":3.125}, {"x":12.5, "y":3}, {"x":13.5, "y":3.125}, {"x":14.5, "y":3.375}, {"x":15.5, "y":3.375, "w":1.5},
{"x":11.5, "y":4.125}, {"x":12.5, "y":4}, {"x":13.5, "y":4.125}, {"x":14.5, "y":4.375}, {"x":15.5, "y":4.375},
{"x":9, "y":5}, {"x":10, "y":5},
{"x":9, "y":6}, {"x":10, "y":6}, {"x":11, "y":6},
{"x":9, "y":7}, {"x":10, "y":7}, {"x":11, "y":7}
]
},
"LAYOUT_ergodox_pretty_80": {
"layout": [
{"x":0, "y":0.375, "w":1.5}, {"x":1.5, "y":0.375}, {"x":2.5, "y":0.125}, {"x":3.5, "y":0}, {"x":4.5, "y":0.125}, {"x":5.5, "y":0.25}, {"x":6.5, "y":0.25},
{"x":9.5, "y":0.25}, {"x":10.5, "y":0.25}, {"x":11.5, "y":0.125}, {"x":12.5, "y":0}, {"x":13.5, "y":0.125}, {"x":14.5, "y":0.375}, {"x":15.5, "y":0.375, "w":1.5},
{"x":0, "y":1.375, "w":1.5}, {"x":1.5, "y":1.375}, {"x":2.5, "y":1.125}, {"x":3.5, "y":1}, {"x":4.5, "y":1.125}, {"x":5.5, "y":1.25}, {"x":6.5, "y":1.25, "h":1.5},
{"x":9.5, "y":1.25, "h":1.5}, {"x":10.5, "y":1.25}, {"x":11.5, "y":1.125}, {"x":12.5, "y":1}, {"x":13.5, "y":1.125}, {"x":14.5, "y":1.375}, {"x":15.5, "y":1.375, "w":1.5},
{"x":0, "y":2.375, "w":1.5}, {"x":1.5, "y":2.375}, {"x":2.5, "y":2.125}, {"x":3.5, "y":2}, {"x":4.5, "y":2.125}, {"x":5.5, "y":2.25},
{"x":10.5, "y":2.25}, {"x":11.5, "y":2.125}, {"x":12.5, "y":2}, {"x":13.5, "y":2.125}, {"x":14.5, "y":2.375}, {"x":15.5, "y":2.375, "w":1.5},
{"x":0, "y":3.375, "w":1.5}, {"x":1.5, "y":3.375}, {"x":2.5, "y":3.125}, {"x":3.5, "y":3}, {"x":4.5, "y":3.125}, {"x":5.5, "y":3.25}, {"x":6.5, "y":2.75, "h":1.5},
{"x":9.5, "y":2.75, "h":1.5}, {"x":10.5, "y":3.25}, {"x":11.5, "y":3.125}, {"x":12.5, "y":3}, {"x":13.5, "y":3.125}, {"x":14.5, "y":3.375}, {"x":15.5, "y":3.375, "w":1.5},
{"x":0.5, "y":4.375}, {"x":1.5, "y":4.375}, {"x":2.5, "y":4.125}, {"x":3.5, "y":4}, {"x":4.5, "y":4.125},
{"x":11.5, "y":4.125}, {"x":12.5, "y":4}, {"x":13.5, "y":4.125}, {"x":14.5, "y":4.375}, {"x":15.5, "y":4.375},
{"x":6, "y":5}, {"x":7, "y":5}, {"x":9, "y":5}, {"x":10, "y":5},
{"x":5, "y":6}, {"x":6, "y":6}, {"x":7, "y":6}, {"x":9, "y":6}, {"x":10, "y":6}, {"x":11, "y":6},
{"x":5, "y":7}, {"x":6, "y":7}, {"x":7, "y":7}, {"x":9, "y":7}, {"x":10, "y":7}, {"x":11, "y":7}
]
}
}
}

View File

@ -0,0 +1,73 @@
// RGBLight effects
// Static color is always enabled.
//#define RGBLIGHT_EFFECT_ALTERNATING
//#define RGBLIGHT_EFFECT_BREATHING
//#define RGBLIGHT_EFFECT_CHRISTMAS
//#define RGBLIGHT_EFFECT_KNIGHT
//#define RGBLIGHT_EFFECT_RAINBOW_MOOD
//#define RGBLIGHT_EFFECT_RAINBOW_SWIRL
//#define RGBLIGHT_EFFECT_RGB_TEST
//#define RGBLIGHT_EFFECT_SNAKE
//#define RGBLIGHT_EFFECT_STATIC_GRADIENT
//#define RGBLIGHT_EFFECT_TWINKLE
// Custom effects
#define RGB_MATRIX_DATAPOINTER_ENABLED
// Normal matrix effects
//#define DISABLE_RGB_MATRIX_SOLID_COLOR
#define DISABLE_RGB_MATRIX_ALPHAS_MODS // Static dual hue, speed is hue for secondary hue
//#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN // Static gradient top to bottom, speed controls how much gradient changes
#define DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT // Static gradient left to right, speed controls how much gradient changes
#define DISABLE_RGB_MATRIX_BREATHING // Single hue brightness cycling animation
#define DISABLE_RGB_MATRIX_BAND_SAT // Single hue band fading saturation scrolling left to right
#define DISABLE_RGB_MATRIX_BAND_VAL // Single hue band fading brightness scrolling left to right
#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT // Single hue 3 blade spinning pinwheel fades saturation
#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL // Single hue 3 blade spinning pinwheel fades brightness
#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT // Single hue spinning spiral fades saturation
#define DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL // Single hue spinning spiral fades brightness
#define DISABLE_RGB_MATRIX_CYCLE_ALL // Full keyboard solid hue cycling through full gradient
#define DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT // Full gradient scrolling left to right
#define DISABLE_RGB_MATRIX_CYCLE_UP_DOWN // Full gradient scrolling top to bottom
#define DISABLE_RGB_MATRIX_CYCLE_OUT_IN // Full gradient scrolling out to in
#define DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL // Full dual gradients scrolling out to in
#define DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON // Full gradent Chevron shapped scrolling left to right
#define DISABLE_RGB_MATRIX_CYCLE_PINWHEEL // Full gradient spinning pinwheel around center of keyboard
#define DISABLE_RGB_MATRIX_CYCLE_SPIRAL // Full gradient spinning spiral around center of keyboard
#define DISABLE_RGB_MATRIX_DUAL_BEACON // Full gradient spinning around center of keyboard
#define DISABLE_RGB_MATRIX_RAINBOW_BEACON // Full tighter gradient spinning around center of keyboard
#define DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS // Full dual gradients spinning two halfs of keyboard
#define DISABLE_RGB_MATRIX_RAINDROPS // Randomly changes a single key's hue
#define DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS // Randomly changes a single key's hue and saturation
#define DISABLE_RGB_MATRIX_HUE_BREATHING // Hue shifts up a slight ammount at the same time, then shifts back
#define DISABLE_RGB_MATRIX_HUE_PENDULUM // Hue shifts up a slight ammount in a wave to the right, then back to the left
#define DISABLE_RGB_MATRIX_HUE_WAVE // Hue shifts up a slight ammount and then back down in a wave to the right
#define DISABLE_RGB_MATRIX_PIXEL_FRACTAL // Single hue fractal filled keys pulsing horizontally out to edges
#define DISABLE_RGB_MATRIX_PIXEL_FLOW // Pulsing RGB flow along LED wiring with random hues
#define DISABLE_RGB_MATRIX_PIXEL_RAIN // Randomly light keys with random hues
// Framebuffer matrix effects
//#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS
#define DISABLE_RGB_MATRIX_TYPING_HEATMAP
#define DISABLE_RGB_MATRIX_DIGITAL_RAIN
#endif
// Keypress matrix effects
//#define RGB_MATRIX_KEYPRESSES
#ifdef RGB_MATRIX_KEYPRESSES
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE // Pulses keys hit to hue & value then fades value out
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE // Static single hue, pulses keys hit to shifted hue then fades to current hue
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE // Hue & value pulse near a single key hit then fades value out
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE // Hue & value pulse near multiple key hits then fades value out
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS // Hue & value pulse the same column and row of a single key hit then fades value out
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS // Hue & value pulse the same column and row of multiple key hits then fades value out
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS // Hue & value pulse away on the same column and row of a single key hit then fades value out
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS // Hue & value pulse away on the same column and row of multiple key hits then fades value out
#define DISABLE_RGB_MATRIX_SPLASH // Full gradient & value pulse away from a single key hit then fades value out
#define DISABLE_RGB_MATRIX_MULTISPLASH // Full gradient & value pulse away from multiple key hits then fades value out
#define DISABLE_RGB_MATRIX_SOLID_SPLASH // Hue & value pulse away from a single key hit then fades value out
#define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH // Hue & value pulse away from multiple key hits then fades value out
#endif

View File

@ -0,0 +1,262 @@
#include "keymap.h"
// Define custom keys
// (Must be done BEFORE keymaps)
enum custom_keycodes {
M_SHUTDOWN = BETA_SAFE_RANGE,
M_RESETWM,
RU_LAYER,
EN_LAYER,
M_RU_CTRL,
M_RU_ALT
};
enum tap_dance_codes {
TD_WMLAYOUT,
};
// Assemble key and LED maps
enum layer_indices {
LAYER_MAIN_IDX = 0,
LAYER_RUSSIAN_IDX,
LAYER_COLEMAK_IDX,
LAYER_NUMPAD_IDX,
LAYER_SYMBOLS_IDX,
LAYER_ARROWS_IDX,
LAYER_FKEYS_IDX,
LAYER_DESKTOP_IDX,
LAYER_KEYBOARD_IDX,
};
// Used to set system keymap
enum key_encodings {
LANG_NULL, // For layers that don't care about input lang
LANG_EN,
LANG_RU
};
enum led_indices {
// We have seperate indexes for LEDs because
// some layers may not need an led map.
// This saves memory by avoiding extra empty led maps.
LAYER_COLEMAK_LEDS_IDX = 0,
LAYER_RUSSIAN_LEDS_IDX,
LAYER_NUMPAD_LEDS_IDX,
LAYER_SYMBOLS_LEDS_IDX,
LAYER_ARROWS_LEDS_IDX,
LAYER_FKEYS_LEDS_IDX,
LAYER_DESKTOP_LEDS_IDX
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[LAYER_MAIN_IDX] = LAYER_MAIN,
[LAYER_RUSSIAN_IDX] = LAYER_RUSSIAN,
[LAYER_COLEMAK_IDX] = LAYER_COLEMAK,
[LAYER_NUMPAD_IDX] = LAYER_NUMPAD,
[LAYER_SYMBOLS_IDX] = LAYER_SYMBOLS,
[LAYER_ARROWS_IDX] = LAYER_ARROWS,
[LAYER_FKEYS_IDX] = LAYER_FKEYS,
[LAYER_DESKTOP_IDX] = LAYER_DESKTOP,
[LAYER_KEYBOARD_IDX] = LAYER_KEYBOARD
};
const uint8_t PROGMEM ledmap[][DRIVER_LED_TOTAL][3] = {
[LAYER_COLEMAK_LEDS_IDX] = LAYER_COLEMAK_LEDS,
[LAYER_RUSSIAN_LEDS_IDX] = LAYER_RUSSIAN_LEDS,
[LAYER_NUMPAD_LEDS_IDX] = LAYER_NUMPAD_LEDS,
[LAYER_SYMBOLS_LEDS_IDX] = LAYER_SYMBOLS_LEDS,
[LAYER_ARROWS_LEDS_IDX] = LAYER_ARROWS_LEDS,
[LAYER_FKEYS_LEDS_IDX] = LAYER_FKEYS_LEDS,
[LAYER_DESKTOP_LEDS_IDX] = LAYER_DESKTOP_LEDS
};
int current_lang = LANG_EN;
void keyboard_post_init_user(void) {}
void set_layer_color(int layer) {
for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
HSV hsv = {
.h = pgm_read_byte(&ledmap[layer][i][0]),
.s = pgm_read_byte(&ledmap[layer][i][1]),
.v = pgm_read_byte(&ledmap[layer][i][2]),
};
if (!hsv.h && !hsv.s && !hsv.v) {
rgb_matrix_set_color( i, 0, 0, 0 );
} else {
RGB rgb = hsv_to_rgb( hsv );
float f = (float)rgb_matrix_config.hsv.v / UINT8_MAX;
rgb_matrix_set_color( i, f * rgb.r, f * rgb.g, f * rgb.b );
}
}
}
void rgb_matrix_indicators_user(void) {
if (keyboard_config.disable_layer_led) {
return;
}
switch (biton32(layer_state)) {
case LAYER_COLEMAK_IDX:
set_layer_color(LAYER_COLEMAK_LEDS_IDX);
break;
case LAYER_RUSSIAN_IDX:
set_layer_color(LAYER_RUSSIAN_LEDS_IDX);
break;
case LAYER_NUMPAD_IDX:
set_layer_color(LAYER_NUMPAD_LEDS_IDX);
break;
case LAYER_SYMBOLS_IDX:
set_layer_color(LAYER_SYMBOLS_LEDS_IDX);
break;
case LAYER_ARROWS_IDX:
set_layer_color(LAYER_ARROWS_LEDS_IDX);
break;
case LAYER_FKEYS_IDX:
set_layer_color(LAYER_FKEYS_LEDS_IDX);
break;
case LAYER_DESKTOP_IDX:
set_layer_color(LAYER_DESKTOP_LEDS_IDX);
break;
default:
if (rgb_matrix_get_flags() == LED_FLAG_NONE) {
rgb_matrix_set_color_all(0, 0, 0);
}
break;
}
}
void set_lang(int lang) { set_lang_long(lang, false); }
void set_lang_long(int lang, bool force) {
if (current_lang != lang || force) {
switch (lang) {
case LANG_EN:
SEND_STRING(SS_LGUI(SS_LSFT(SS_LCTL(SS_TAP(X_0)))));
current_lang = lang;
break;
case LANG_RU:
SEND_STRING(SS_LGUI(SS_LSFT(SS_LCTL(SS_TAP(X_9)))));
current_lang = lang;
break;
case LANG_NULL:
break;
default:
break;
}
}
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case M_RESETWM:
if (record->event.pressed) {
SEND_STRING(SS_LCTL(SS_LGUI(SS_LSFT(SS_TAP(X_R)))));
}
break;
case M_SHUTDOWN:
if (record->event.pressed) {
SEND_STRING(SS_LGUI(SS_TAP(X_P)) SS_DELAY(100) SS_TAP(X_Y) SS_DELAY(100) SS_TAP(X_ENTER));
}
break;
case RU_LAYER:
if (record->event.pressed) {
set_lang(LANG_RU);
layer_move(LAYER_RUSSIAN_IDX);
}
break;
case EN_LAYER:
if (record->event.pressed) {
set_lang(LANG_EN);
layer_move(LAYER_MAIN_IDX);
}
break;
case M_RU_CTRL:
if (record->event.pressed) {
if (current_lang == LANG_RU) {
set_lang_long(LANG_EN, true);
layer_move(LAYER_MAIN_IDX);
current_lang = LANG_RU;
}
register_code16(KC_LCTRL);
} else {
unregister_code16(KC_LCTRL);
if (current_lang == LANG_RU) {
layer_move(LAYER_RUSSIAN_IDX);
set_lang_long(LANG_RU, true);
}
}
break;
}
return true;
}
uint32_t layer_state_set_user(uint32_t state) {
uint8_t layer = biton32(state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
ergodox_right_led_3_off();
switch (layer) {
case LAYER_MAIN_IDX:
set_lang(LANG_EN);
break;
case LAYER_RUSSIAN_IDX:
set_lang(LANG_RU);
ergodox_right_led_2_on();
break;
case LAYER_COLEMAK_IDX:
set_lang(LANG_EN);
ergodox_right_led_2_on();
break;
case LAYER_NUMPAD_IDX:
set_lang(LANG_EN);
ergodox_right_led_1_on();
break;
case LAYER_SYMBOLS_IDX:
set_lang(LANG_EN);
break;
case LAYER_ARROWS_IDX:
set_lang(LANG_EN);
break;
case LAYER_FKEYS_IDX:
set_lang(LANG_EN);
break;
case LAYER_DESKTOP_IDX:
set_lang(LANG_EN);
break;
case LAYER_KEYBOARD_IDX:
set_lang(LANG_NULL);
ergodox_right_led_1_on();
ergodox_right_led_2_on();
ergodox_right_led_3_on();
break;
default:
break;
}
return state;
};
qk_tap_dance_action_t tap_dance_actions[] = {
[TD_WMLAYOUT] = ACTION_TAP_DANCE_FN_ADVANCED(td_wmlayout_dance, td_wmlayout_finished, td_wmlayout_reset),
};

View File

@ -0,0 +1,84 @@
#pragma once
#include "betalupi_ergodox.h"
#include "version.h"
#include "keymap_russian.h"
#include "keymap_us_international.h"
#include "layers.h"
#include "tapdance.h"
#define KC_MAC_UNDO LGUI(KC_Z)
#define KC_MAC_CUT LGUI(KC_X)
#define KC_MAC_COPY LGUI(KC_C)
#define KC_MAC_PASTE LGUI(KC_V)
#define KC_PC_UNDO LCTL(KC_Z)
#define KC_PC_CUT LCTL(KC_X)
#define KC_PC_COPY LCTL(KC_C)
#define KC_PC_PASTE LCTL(KC_V)
#define ES_LESS_MAC KC_GRAVE
#define ES_GRTR_MAC LSFT(KC_GRAVE)
#define ES_BSLS_MAC ALGR(KC_6)
#define NO_PIPE_ALT KC_GRAVE
#define NO_BSLS_ALT KC_EQUAL
#define LSA_T(kc) MT(MOD_LSFT | MOD_LALT, kc)
#define BP_NDSH_MAC ALGR(KC_8)
/* Text keyboard
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | Del | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | BkSp | A | S | D | F | G |------| |------| H | J | K | L |; / L2|' / Cmd |
* |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
* | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | App | LGui | | Alt |Ctrl/Esc|
* ,------|------|------| |------+--------+------.
* | | | Home | | PgUp | | |
* | Space|Backsp|------| |------| Tab |Enter |
* | |ace | End | | PgDn | | |
* `--------------------' `----------------------'
*/
/* LED layout template
#define LAYER_COLEMAK_LEDS LEDS_ergodox(\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF \
)
*/
// LED colors, in HSV.
#define LC_OFF LC_HSV( 0, 0, 0)
#define LC_GREEN LC_HSV( 85, 203, 158)
#define LC_YELLOW LC_HSV( 32, 176, 255)
#define LC_PINK LC_HSV(243, 222, 234)
#define LC_CYAN LC_HSV(134, 255, 213)
#define LC_ORANGE LC_HSV( 14, 255, 255)
#define LC_RU_B LC_HSV( 0, 0, 165)
#define LC_RU_G LC_HSV(153, 255, 153)
#define LC_RU_K LC_HSV( 0, 255, 145)
extern int current_lang;
extern rgb_config_t rgb_matrix_config;
void set_lang(int lang);
void set_lang_long(int lang, bool force);

View File

@ -0,0 +1,11 @@
#pragma once
#include "layers/main.h"
#include "layers/colemak.h"
#include "layers/numpad.h"
#include "layers/symbols.h"
#include "layers/arrows.h"
#include "layers/fkeys.h"
#include "layers/desktop.h"
#include "layers/keyboard.h"
#include "layers/russian.h"

View File

@ -0,0 +1,39 @@
#pragma once
#include "keymap.h"
#define LAYER_ARROWS LAYOUT_ergodox(\
KC_TRANSPARENT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
KC_TRANSPARENT, KC_LEFT, KC_RIGHT, KC_UP, KC_NO, KC_NO, KC_TRANSPARENT,\
KC_TRANSPARENT, LALT(KC_LCTRL), KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO,\
KC_TRANSPARENT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
\
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
KC_TRANSPARENT, KC_NO, KC_PGUP, KC_NO, KC_NO, KC_NO, KC_TRANSPARENT,\
KC_NO, KC_PGDOWN, KC_NO, KC_NO, KC_NO, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT\
)
#define LAYER_ARROWS_LEDS LEDS_ergodox(\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_YELLOW, LC_YELLOW, LC_GREEN, LC_OFF, LC_OFF, \
LC_OFF, LC_GREEN, LC_GREEN, LC_GREEN, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_PINK, \
\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_GREEN, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_GREEN, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF \
)

View File

@ -0,0 +1,39 @@
#pragma once
#include "keymap.h"
#define LAYER_COLEMAK LAYOUT_ergodox(\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_Q, KC_W, KC_F, KC_P, KC_B, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_A, KC_R, KC_S, KC_T, KC_G,\
KC_TRANSPARENT, KC_Z, KC_X, KC_C, KC_D, KC_V, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_J, KC_L, KC_U, KC_O, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_M, KC_N, KC_E, KC_TRANSPARENT, KC_I, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_K, KC_H, KC_O, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT\
)
#define LAYER_COLEMAK_LEDS LEDS_ergodox(\
LC_PINK, LC_PINK, LC_PINK, LC_PINK, LC_PINK, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
\
LC_PINK, LC_PINK, LC_PINK, LC_PINK, LC_PINK, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF \
)

View File

@ -0,0 +1,39 @@
#pragma once
#include "keymap.h"
#define LAYER_DESKTOP LAYOUT_ergodox(\
KC_TRANSPARENT, LCTL(LGUI(LSFT(KC_1))), LCTL(LGUI(LSFT(KC_2))),LCTL(LGUI(LSFT(KC_3))), LCTL(LGUI(LSFT(KC_4))), KC_NO, M_RESETWM,\
KC_NO, KC_NO, KC_NO, KC_NO, LCTL(LGUI(KC_SPACE)), LGUI(KC_T), KC_NO,\
KC_NO, KC_NO, KC_NO, KC_NO, LGUI(KC_F), LGUI(KC_M),\
KC_NO, KC_NO, KC_NO, LGUI(LSFT(KC_C)), LGUI(KC_N), KC_NO, KC_NO,\
TO(LAYER_MAIN_IDX), KC_NO, KC_NO, KC_NO, KC_NO,\
\
KC_NO, KC_NO,\
KC_NO,\
LGUI(KC_ENTER), LGUI(KC_BSLASH), KC_NO,\
\
\
M_SHUTDOWN, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
KC_NO, KC_NO, KC_NO, LCTL(LGUI(KC_UP)), KC_NO, LGUI(KC_P), KC_NO,\
KC_NO, LCTL(LGUI(KC_LEFT)), LCTL(LGUI(KC_DOWN)), LCTL(LGUI(KC_RIGHT)), KC_NO, KC_NO,\
KC_NO, KC_NO, LGUI(KC_H), LGUI(KC_J), KC_NO, KC_NO, KC_NO,\
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
\
KC_MEDIA_PREV_TRACK, KC_MEDIA_NEXT_TRACK,\
KC_AUDIO_VOL_UP,\
KC_AUDIO_VOL_DOWN, KC_MEDIA_STOP, KC_MEDIA_PLAY_PAUSE\
)
#define LAYER_DESKTOP_LEDS LEDS_ergodox(\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_CYAN, LC_CYAN, \
LC_OFF, LC_OFF, LC_OFF, LC_CYAN, LC_CYAN, \
LC_OFF, LC_OFF, LC_OFF, LC_CYAN, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_GREEN, LC_OFF, LC_ORANGE, \
LC_OFF, LC_GREEN, LC_GREEN, LC_GREEN, LC_OFF, \
LC_OFF, LC_CYAN, LC_CYAN, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF \
)

View File

@ -0,0 +1,39 @@
#pragma once
#include "keymap.h"
#define LAYER_FKEYS LAYOUT_ergodox(\
KC_TRANSPARENT, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
\
KC_TRANSPARENT, KC_F6, KC_F7, KC_F9, KC_F9, KC_F10, KC_TRANSPARENT, \
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, \
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, \
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, \
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, \
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, \
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT \
)
#define LAYER_FKEYS_LEDS LEDS_ergodox(\
LC_CYAN, LC_CYAN, LC_CYAN, LC_CYAN, LC_CYAN, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
\
LC_CYAN, LC_CYAN, LC_CYAN, LC_CYAN, LC_CYAN, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF \
)

View File

@ -0,0 +1,25 @@
#pragma once
#include "keymap.h"
#define LAYER_KEYBOARD LAYOUT_ergodox(\
RGB_TOG, RGB_HUD, RGB_HUI, KC_NO, KC_NO, KC_NO, KC_NO,\
TOGGLE_LAYER_COLOR, RGB_SAD, RGB_SAI, KC_NO, KC_NO, KC_NO, RGB_HUI,\
KC_NO, RGB_VAD, RGB_VAI, KC_NO, KC_NO, KC_NO,\
KC_NO, RGB_SPD, RGB_SPI, KC_NO, KC_NO, KC_NO, RGB_HUD,\
KC_NO, KC_NO, KC_NO, KC_NO, RGB_MOD,\
\
KC_NO, KC_NO,\
KC_NO,\
KC_NO, KC_NO, KC_NO,\
\
\
KC_NO, LIGHT_HUD, LIGHT_HUI, KC_NO, KC_NO, KC_NO, LIGHT_TOG,\
KC_NO, LIGHT_SAD, LIGHT_SAI, KC_NO, KC_NO, KC_NO, KC_NO,\
LIGHT_VAD, LIGHT_VAI, KC_NO, KC_NO, KC_NO, KC_NO,\
KC_NO, LIGHT_SPD, LIGHT_SPI, KC_NO, KC_NO, KC_NO, KC_NO,\
LIGHT_MOD, KC_NO, KC_NO, TO(LAYER_MAIN_IDX), KC_NO,\
\
KC_NO, RGB_TOG,\
KC_NO,\
RESET, KC_NO, KC_NO\
)

View File

@ -0,0 +1,25 @@
#pragma once
#include "keymap.h"
#define LAYER_MAIN LAYOUT_ergodox(\
KC_ESCAPE, KC_1, KC_2, KC_3, KC_4, KC_5, TG(LAYER_NUMPAD_IDX),\
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LGUI,\
KC_DELETE, KC_A, KC_S, KC_D, KC_F, KC_G,\
M_RU_CTRL, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_TRANSPARENT,\
MO(LAYER_DESKTOP_IDX), MO(LAYER_FKEYS_IDX), KC_LALT, KC_LSHIFT, MO(LAYER_ARROWS_IDX),\
\
KC_PSCREEN, KC_NO,\
TD(TD_WMLAYOUT),\
KC_SPACE, KC_BSPACE, LCTL(KC_BSPACE),\
\
\
LCTL(KC_LALT), KC_6, KC_7, KC_8, KC_9, KC_0, LGUI(KC_TAB),\
KC_TRANSPARENT, KC_Y, KC_U, KC_I, KC_O, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_H, KC_J, KC_K, MO(LAYER_SYMBOLS_IDX), KC_L, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_N, KC_M, KC_P, KC_DOT, KC_COMMA, KC_TRANSPARENT,\
KC_RIGHT, KC_TRANSPARENT, KC_TRANSPARENT, TO(LAYER_KEYBOARD_IDX), KC_TRANSPARENT,\
\
LGUI(KC_SPACE), TO(LAYER_RUSSIAN_IDX),\
TG(LAYER_COLEMAK_IDX),\
KC_DELETE, KC_RSHIFT, KC_ENTER\
)

View File

@ -0,0 +1,39 @@
#pragma once
#include "keymap.h"
#define LAYER_NUMPAD LAYOUT_ergodox(\
KC_TRANSPARENT, KC_CIRC, KC_NO, KC_HASH, KC_DLR, KC_PERC, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_NO, KC_7, KC_8, KC_9, KC_ASTR, KC_SLASH,\
KC_TRANSPARENT, KC_PLUS, KC_4, KC_5, KC_6, KC_0,\
KC_TRANSPARENT, KC_MINUS, KC_1, KC_2, KC_3, KC_DOT, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_NO, KC_NO,\
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRANSPARENT,\
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT\
)
#define LAYER_NUMPAD_LEDS LEDS_ergodox(\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_GREEN, LC_GREEN, LC_GREEN, LC_YELLOW, \
LC_YELLOW, LC_GREEN, LC_GREEN, LC_GREEN, LC_GREEN, \
LC_YELLOW, LC_GREEN, LC_GREEN, LC_GREEN, LC_YELLOW, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF \
)

View File

@ -0,0 +1,39 @@
#pragma once
#include "keymap.h"
#define LAYER_RUSSIAN LAYOUT_ergodox(\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT, RU_CHE, RU_SHA, RU_IE, RU_ER, RU_TE, RU_YO,\
KC_TRANSPARENT, RU_A, RU_ES, RU_DE, RU_EF, RU_GHE,\
M_RU_CTRL, RU_ZE, RU_YA, RU_TSE, RU_VE, RU_BE, RU_E,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_LALT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
KC_TRANSPARENT, KC_TRANSPARENT,\
KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, RU_NUM, RU_RUBL, KC_TRANSPARENT,\
RU_SOFT, RU_U, RU_YU, RU_I, RU_O, RU_SHCH, KC_TRANSPARENT,\
RU_HA, RU_ZHE, RU_KA, KC_TRANSPARENT, RU_EL, KC_TRANSPARENT,\
RU_HARD, RU_EN, RU_EM, RU_PE, RU_YERU, RU_SHTI, KC_TRANSPARENT,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT,\
\
KC_NO, TO(LAYER_MAIN_IDX),\
KC_NO,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT\
)
#define LAYER_RUSSIAN_LEDS LEDS_ergodox(\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_RU_B, LC_RU_B, LC_RU_B, LC_RU_B, LC_RU_B, \
LC_RU_G, LC_RU_G, LC_RU_G, LC_RU_G, LC_RU_G, \
LC_RU_K, LC_RU_K, LC_RU_K, LC_RU_K, LC_RU_K, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_RU_B, LC_RU_B, LC_RU_B, LC_RU_B, LC_RU_B, \
LC_RU_G, LC_RU_G, LC_RU_G, LC_RU_G, LC_RU_G, \
LC_RU_K, LC_RU_K, LC_RU_K, LC_RU_K, LC_RU_K, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF \
)

View File

@ -0,0 +1,39 @@
#pragma once
#include "keymap.h"
#define LAYER_SYMBOLS LAYOUT_ergodox(\
KC_NO, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_NO,\
KC_NO, KC_GRAVE, KC_LPRN, KC_RPRN, KC_QUES, KC_LCBR, KC_NO,\
KC_NO, KC_TILD, KC_QUOTE, KC_COMMA, KC_DOT, KC_DQUO,\
KC_NO, KC_NO, KC_LBRACKET, KC_RBRACKET, KC_EXLM, KC_RCBR, KC_NO,\
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
\
KC_NO, KC_NO,\
KC_NO,\
KC_TRANSPARENT, KC_TRANSPARENT, KC_NO,\
\
\
KC_NO, KC_CIRC, KC_AMPR, KC_ASTR, KC_NO, KC_NO, KC_NO,\
KC_NO, KC_LABK, KC_RABK, KC_SLASH, KC_NO, KC_BSLASH, KC_NO,\
KC_UNDS, KC_MINUS, KC_COLN, KC_TRANSPARENT, KC_PIPE, KC_NO,\
KC_NO, KC_EQUAL, KC_PLUS, KC_SCOLON, KC_NO, KC_NO, KC_NO,\
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
\
KC_NO, KC_NO,\
KC_NO,\
KC_NO, KC_NO, KC_TRANSPARENT\
)
#define LAYER_SYMBOLS_LEDS LEDS_ergodox(\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_ORANGE, LC_CYAN, LC_CYAN, LC_PINK, LC_CYAN, \
LC_ORANGE, LC_PINK, LC_PINK, LC_PINK, LC_PINK, \
LC_OFF, LC_CYAN, LC_CYAN, LC_PINK, LC_CYAN, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
\
LC_OFF, LC_OFF, LC_OFF, LC_OFF, LC_OFF, \
LC_GREEN, LC_GREEN, LC_CYAN, LC_OFF, LC_CYAN, \
LC_CYAN, LC_GREEN, LC_PINK, LC_ORANGE, LC_CYAN, \
LC_GREEN, LC_GREEN, LC_PINK, LC_OFF, LC_OFF, \
LC_OFF, LC_OFF, LC_OFF, LC_OFF \
)

View File

@ -0,0 +1,7 @@
# rules.mk overrides
TAP_DANCE_ENABLE = yes
SRC += \
tapdance/wmlayout.c \
tapdance/tapdance.c

View File

@ -0,0 +1,18 @@
#pragma once
#include "keymap.h"
enum {
SINGLE_TAP = 1,
SINGLE_HOLD,
DOUBLE_TAP,
DOUBLE_HOLD,
DOUBLE_SINGLE_TAP,
MORE_TAPS
};
uint8_t dance_step(qk_tap_dance_state_t *state);
void td_wmlayout_dance(qk_tap_dance_state_t *state, void *user_data);
void td_wmlayout_finished(qk_tap_dance_state_t *state, void *user_data);
void td_wmlayout_reset(qk_tap_dance_state_t *state, void *user_data);

View File

@ -0,0 +1,21 @@
#include "keymap.h"
#include "tapdance.h"
uint8_t dance_step(qk_tap_dance_state_t *state) {
if (state->count == 1) {
if (state->interrupted || !state->pressed) {
return SINGLE_TAP;
} else {
return SINGLE_HOLD;
}
} else if (state->count == 2) {
if (state->interrupted) {
return DOUBLE_SINGLE_TAP;
} else if (state->pressed) {
return DOUBLE_HOLD;
} else {
return DOUBLE_TAP;
}
}
return MORE_TAPS;
}

View File

@ -0,0 +1,55 @@
#include "keymap.h"
#include "tapdance.h"
typedef struct {
bool is_press_action;
uint8_t step;
} tap;
static tap dance_state[1];
// Called on every tap
void td_wmlayout_dance(qk_tap_dance_state_t *state, void *user_data) {
if(state->count == 3) {
tap_code16(LGUI(KC_L));
tap_code16(LGUI(KC_L));
tap_code16(LGUI(KC_L));
}
if(state->count > 3) {
tap_code16(LGUI(KC_L));
}
}
// Called when action finishes
void td_wmlayout_finished(qk_tap_dance_state_t *state, void *user_data) {
dance_state[0].step = dance_step(state);
switch (dance_state[0].step) {
case SINGLE_TAP:
register_code16(LGUI(KC_L));
break;
case DOUBLE_TAP:
register_code16(LGUI(KC_K));
break;
case DOUBLE_SINGLE_TAP:
tap_code16(LGUI(KC_L));
register_code16(LGUI(KC_L));
break;
}
}
// Called when action resets
void td_wmlayout_reset(qk_tap_dance_state_t *state, void *user_data) {
wait_ms(10);
switch (dance_state[0].step) {
case SINGLE_TAP:
unregister_code16(LGUI(KC_L));
break;
case DOUBLE_TAP:
unregister_code16(LGUI(KC_K));
break;
case DOUBLE_SINGLE_TAP:
unregister_code16(LGUI(KC_L));
break;
}
dance_state[0].step = 0;
}

View File

@ -0,0 +1,57 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
Copyright 2015 ZSA Technology Labs Inc (@zsa)
Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna)
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 <http://www.gnu.org/licenses/>.
*/
/*
#ifdef RGBLIGHT_ENABLE
#include "betalupi_ergodox.h"
void rgblight_call_driver(LED_TYPE *led, uint8_t led_num) {
i2c_init();
i2c_start(0x84, ERGODOX_EZ_I2C_TIMEOUT);
int i = 0;
# if defined(ERGODOX_LED_30)
// prevent right-half code from trying to bitbang all 30
// so with 30 LEDs, we count from 29 to 15 here, and the
// other half does 0 to 14.
uint8_t half_led_num = RGBLED_NUM / 2;
for (i = half_led_num + half_led_num - 1; i >= half_led_num; --i)
# elif defined(ERGODOX_LED_15_MIRROR)
for (i = 0; i < led_num; ++i)
# else // ERGDOX_LED_15 non-mirrored
for (i = led_num - 1; i >= 0; --i)
# endif
{
uint8_t *data = (uint8_t *)(led + i);
i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT);
i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT);
i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT);
#ifdef RGBW
i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT);
#endif
}
i2c_stop();
ws2812_setleds(led, led_num);
}
#endif // RGBLIGHT_ENABLE
*/

View File

@ -0,0 +1,256 @@
/*
Note for ErgoDox EZ customizers: Here be dragons!
This is not a file you want to be messing with.
All of the interesting stuff for you is under keymaps/ :)
Love, Erez
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
Copyright 2015 ZSA Technology Labs Inc (@zsa)
Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna)
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 <http://www.gnu.org/licenses/>.
*/
/*
* scan matrix
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include "wait.h"
#include "action_layer.h"
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"
#include "debounce.h"
#include "betalupi_ergodox.h"
/*
* This constant define not debouncing time in msecs, assuming eager_pr.
*
* On Ergodox matrix scan rate is relatively low, because of slow I2C.
* Now it's only 317 scans/second, or about 3.15 msec/scan.
* According to Cherry specs, debouncing time is 5 msec.
*
* However, some switches seem to have higher debouncing requirements, or
* something else might be wrong. (Also, the scan speed has improved since
* that comment was written.)
*/
/* matrix state(1:on, 0:off) */
extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
static matrix_row_t read_cols(uint8_t row);
static void init_cols(void);
static void unselect_rows(void);
static void select_row(uint8_t row);
static uint8_t mcp23018_reset_loop;
void matrix_init_custom(void) {
// initialize row and col
mcp23018_status = init_mcp23018();
unselect_rows();
init_cols();
}
// Reads and stores a row, returning
// whether a change occurred.
static inline bool store_raw_matrix_row(uint8_t index) {
matrix_row_t temp = read_cols(index);
if (raw_matrix[index] != temp) {
raw_matrix[index] = temp;
return true;
}
return false;
}
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
if (mcp23018_status) { // if there was an error
if (++mcp23018_reset_loop == 0) {
print("trying to reset mcp23018\n");
mcp23018_status = init_mcp23018();
if (mcp23018_status) {
print("left side not responding\n");
} else {
print("left side attached\n");
ergodox_blink_all_leds();
#ifdef RGB_MATRIX_ENABLE
rgb_matrix_init(); // re-init driver on reconnect
#endif
}
}
}
bool changed = false;
for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
// select rows from left and right hands
uint8_t left_index = i;
uint8_t right_index = i + MATRIX_ROWS_PER_SIDE;
select_row(left_index);
select_row(right_index);
changed |= store_raw_matrix_row(left_index);
changed |= store_raw_matrix_row(right_index);
unselect_rows();
}
return changed;
}
/* Column pin configuration
*
* Teensy
* col: 0 1 2 3 4 5
* pin: F0 F1 F4 F5 F6 F7
*
* MCP23018
* col: 0 1 2 3 4 5
* pin: B5 B4 B3 B2 B1 B0
*/
static void init_cols(void) {
// init on mcp23018
// not needed, already done as part of init_mcp23018()
// init on teensy
setPinInputHigh(F0);
setPinInputHigh(F1);
setPinInputHigh(F4);
setPinInputHigh(F5);
setPinInputHigh(F6);
setPinInputHigh(F7);
}
static matrix_row_t read_cols(uint8_t row) {
if (row < 7) {
if (mcp23018_status) { // if there was an error
return 0;
} else {
uint8_t data = 0;
// reading GPIOB (column port) since in mcp23018's sequential mode
// it is addressed directly after writing to GPIOA in select_row()
mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
data = ~((uint8_t)mcp23018_status);
mcp23018_status = I2C_STATUS_SUCCESS;
out:
i2c_stop();
return data;
}
} else {
/* read from teensy
* bitmask is 0b11110011, but we want those all
* in the lower six bits.
* we'll return 1s for the top two, but that's harmless.
*/
return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2));
}
}
/* Row pin configuration
*
* Teensy
* row: 7 8 9 10 11 12 13
* pin: B0 B1 B2 B3 D2 D3 C6
*
* MCP23018
* row: 0 1 2 3 4 5 6
* pin: A0 A1 A2 A3 A4 A5 A6
*/
static void unselect_rows(void) {
// no need to unselect on mcp23018, because the select step sets all
// the other row bits high, and it's not changing to a different
// direction
// unselect on teensy
setPinInput(B0);
setPinInput(B1);
setPinInput(B2);
setPinInput(B3);
setPinInput(D2);
setPinInput(D3);
setPinInput(C6);
}
static void select_row(uint8_t row) {
if (row < 7) {
// select on mcp23018
if (!mcp23018_status) {
// set active row low : 0
// set other rows hi-Z : 1
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0xFF & ~(1 << row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
out:
i2c_stop();
}
} else {
// select on teensy
// Output low(DDR:1, PORT:0) to select
switch (row) {
case 7:
setPinOutput(B0);
writePinLow(B0);
break;
case 8:
setPinOutput(B1);
writePinLow(B1);
break;
case 9:
setPinOutput(B2);
writePinLow(B2);
break;
case 10:
setPinOutput(B3);
writePinLow(B3);
break;
case 11:
setPinOutput(D2);
writePinLow(D2);
break;
case 12:
setPinOutput(D3);
writePinLow(D3);
break;
case 13:
setPinOutput(C6);
writePinLow(C6);
break;
}
}
}
// DO NOT REMOVE
// Needed for proper wake/sleep
void matrix_power_up(void) {
mcp23018_status = init_mcp23018();
unselect_rows();
init_cols();
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
}
}

View File

@ -0,0 +1,42 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
Copyright 2015 ZSA Technology Labs Inc (@zsa)
Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna)
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
/*
#if !defined(ERGODOX_LED_15) && !defined(ERGODOX_LED_30)
// if no value is defined, assume previous behavior
// # define ERGODOX_LED_15
// # define ERGODOX_LED_30
# define ERGODOX_LED_15_MIRROR
#endif
#if (defined(ERGODOX_LED_30) + defined(ERGODOX_LED_15) + defined(ERGODOX_LED_15_MIRROR)) != 1
# error "You must only define one of the ERGODOX_LED options."
#endif
#ifdef ERGODOX_LED_30
// If using 30 LEDs, then define that many
# define RGBLED_NUM 30 // Number of LEDs
#else
// If not, then only define 15
# define RGBLED_NUM 15 // Number of LEDs
#endif
*/

View File

@ -0,0 +1,85 @@
#include "rawhid.h"
uint8_t hid_anim_data[32];
// See rawhid.h for prococol documentation
void raw_hid_receive(uint8_t *data, uint8_t length) {
uint8_t cmd = data[0];
switch (cmd) {
case CMD_HELLO:
ergodox_right_led_1_on();
_delay_ms(50);
ergodox_right_led_1_off();
hid_send_state();
break;
#ifdef RGB_MATRIX_DATAPOINTER_ENABLED
case CMD_ANIM_DATA:
cmd_animation(data, length);
break;
#endif
default:
break;
}
}
void hid_send_state() {
uint8_t packet[RAW_EPSIZE] = {
CMD_SEND_STATE
};
if (rgb_matrix_get_flags() != LED_FLAG_ALL) {
// RGB matrix is disabled
packet[1] = 0x00;
} else {
uint8_t mode = rgb_matrix_get_mode();
switch (mode) {
case RGB_MATRIX_CUSTOM_FFT_ANIM:
// FFT Animation is active
packet[1] = 0x02;
break;
default:
// Normal animation is active
packet[1] = 0x01;
break;
}
}
// Note that all sent packets MUST be
// RAW_EPSIZE long.
raw_hid_send(packet, RAW_EPSIZE);
}
#ifdef RGB_MATRIX_DATAPOINTER_ENABLED
void cmd_animation(uint8_t *data, uint8_t length) {
switch (data[1]) {
case CMD_ANIM_DATA_fft:
// Only read data if animation is in fft mode
if (rgb_matrix_get_mode() == RGB_MATRIX_CUSTOM_FFT_ANIM) {
// rgb_matrix_anim_data is set to NULL at animation init.
if (rgb_matrix_anim_data == NULL) { rgb_matrix_anim_data = hid_anim_data; }
// Copy data into rgb matrix array
memcpy(
hid_anim_data,
data + 2,
sizeof(uint8_t) + 10
);
} else {
// If not in fft mode and we receive fft data, send a state packet so host stops sending data.
hid_send_state();
}
break;
}
}
#endif

View File

@ -0,0 +1,68 @@
#pragma once
#include "betalupi_ergodox.h"
#include "raw_hid.h"
void raw_hid_receive(uint8_t *data, uint8_t length);
void hid_send_state(void);
#ifdef RGB_MATRIX_DATAPOINTER_ENABLED
void cmd_animation(uint8_t *data, uint8_t length);
// Animation data.
// Data received from host is saved here,
// and rgb_matrix_anim_data points to this array when necessary.
extern uint8_t hid_anim_data[32];
// Datapointer
extern void* rgb_matrix_anim_data;
#endif
// Sent by host when connection is initiated.
//
// Packet structure:
// Data: | cmd |
// # of Bytes: | 1 |
#define CMD_HELLO 0x00
// Sent periodically by host to test connection.
// Keyboard should ignore this command.
//
// Packet structure:
// Data: | cmd |
// # of Bytes: | 1 |
#define CMD_RUTHERE 0x01
// Send keyboard state to host.
//
// Packet structure:
// Data: | cmd | anim state |
// # of Bytes: | 1 | 1 |
//
// anim state:
// 0x00: RGBMatrix disabled
// 0x01: normal animation, no HID data.
// 0x02: FFT Animation
#define CMD_SEND_STATE 0x02
// Animation data. Sent by host.
//
// Packet structure:
// Data: | cmd | data type | data |
// # of Bytes: | 1 | 1 | ? |
//
// data type:
// Which animation this data is for. These are defined below.
//
// data:
// Animation data. Content depends on data type.
#define CMD_ANIM_DATA 0x03
// Data for FFT animation.
// Data segment consists of 10 bits, each representing the height of a column.
// Minimum height is 0, maximum is 250.
#define CMD_ANIM_DATA_fft 0x00

View File

@ -0,0 +1,77 @@
# Betalupi Ergodox
This is a modified version of the [ZSA ErgoDox firmware](https://git.betalupi.com/mirrors-QMK/zsa_firmware), based on the `ergodox_ex/glow` keyboard.
## TODO
- Layer switch cleanup
- Define indicator in keymap
- Define language in keymap
- Auto-switch all
--------------------------------------------------------------------------------
# Setup
Clone this repo into `keyboards/betalupi_ergodox` in your qmk directory.
Make example for this keyboard (after setting up your build environment):
make betalupi_ergodox:default:flash
If you get array-bounds errors on build, you may have a bad avr-gcc version. Read [this issue](https://github.com/qmk/qmk_firmware/issues/17064), and try
AVR_CFLAGS="-Wno-array-bounds"
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.
--------------------------------------------------------------------------------
# Notes
Custom keycodes (betalupi_keyboard.c)
```
// Custom RGBLIGHT macros
LIGHT_TOG, // Toggle backlight
LIGHT_HUI, // Increase backlight hue
LIGHT_HUD, // Decrease backlight hue
LIGHT_SAI, // Increase backlight sat
LIGHT_SAD, // Decrease backlight sat
LIGHT_VAI, // Increase backlight val
LIGHT_VAD, // Decrease backlight val
LIGHT_SPI, // Increase backlight speed
LIGHT_SPD, // Decrease backlight speed
LIGHT_MOD, // Change backlight animation mode
```
--------------------------------------------------------------------------------
# Notes from ZSA
### Indicator LEDs
You can use the `LED_LEVEL` keycode to cycle through the brightness levels for the LEDs on the top right of the keyboard. These settings are saved in eeprom (persistant memory).
Alternatively, you can set the brightness by calling the following functions:
```c
void ergodox_led_all_set(uint8_t level);
void ergodox_right_led_1_set(uint8_t level);
void ergodox_right_led_2_set(uint8_t level);
void ergodox_right_led_3_set(uint8_t level);
```
These settings are not persistent, so you'd need to reset it every time the board starts.
These are on a 0-255 scale
### RGB Matrix Features
If you're using the Smart LED (layer indication) feature from the Oryx Configurator, you want to make sure that you enable these options by adding `#define ORYX_CONFIGURATOR` to your keymap's `config.h`.
This changes the `RGB_TOG` keycode so that it will toggle the lights on and off, in a way that will allow the Smart LEDs to continue to work, even with the rest of the LEDs turned off.
Additionally, a new keycode has been added to toggle the Smart LEDs. Use `TOGGLE_LAYER_COLOR`, if you aren't already.

View File

@ -0,0 +1 @@
#include "animations/fft.h"

View File

@ -0,0 +1,60 @@
# MCU name
MCU = atmega32u4
# Enable raw HID for bi-directional communication
RAW_ENABLE = yes
# Bootloader selection
# Teensy halfkay
# Pro Micro caterina
# Atmel DFU atmel-dfu
# LUFA DFU lufa-dfu
# QMK DFU qmk-dfu
# ATmega32A bootloadHID
# ATmega328P USBasp
BOOTLOADER = halfkay
# Build Options
# comment out to disable the options.
#
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
MOUSEKEY_ENABLE = no # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
CUSTOM_MATRIX = lite # Custom matrix file for the ErgoDox EZ
NKRO_ENABLE = yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
UNICODE_ENABLE = no # Unicode
SWAP_HANDS_ENABLE= no # Allow swapping hands of keyboard
SLEEP_LED_ENABLE = no
API_SYSEX_ENABLE = no
# Disable some unused qmk features
# to save space
MAGIC_ENABLE = no
DEBOUNCE_TYPE = sym_eager_pr
SRC += \
matrix.c \
led_i2c.c \
rawhid.c
QUANTUM_LIB_SRC += i2c_master.c
LAYOUTS = ergodox
# Link-time optimization.
# Significantly reduces firmware size.
LTO_ENABLE = yes
# Enable keyboard-specific effects
RGB_MATRIX_CUSTOM_KB = yes
MOUSE_SHARED_EP = no
# FROM glow dir
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = IS31FL3731
RGBLIGHT_ENABLE = yes
RGBLIGHT_DRIVER = WS2812

View File

@ -0,0 +1,707 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Compiler for keymap.c files
This script will generate a keymap.c file from a simple
markdown file with a specific layout.
Usage:
python compile_keymap.py INPUT_PATH [OUTPUT_PATH]
"""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import io
import re
import sys
import json
import unicodedata
import collections
import itertools as it
PY2 = sys.version_info.major == 2
if PY2:
chr = unichr
KEYBOARD_LAYOUTS = {
# These map positions in the parsed layout to
# positions in the KEYMAP MATRIX
'ergodox_ez': [
[ 0, 1, 2, 3, 4, 5, 6], [38, 39, 40, 41, 42, 43, 44],
[ 7, 8, 9, 10, 11, 12, 13], [45, 46, 47, 48, 49, 50, 51],
[14, 15, 16, 17, 18, 19 ], [ 52, 53, 54, 55, 56, 57],
[20, 21, 22, 23, 24, 25, 26], [58, 59, 60, 61, 62, 63, 64],
[27, 28, 29, 30, 31 ], [ 65, 66, 67, 68, 69],
[ 32, 33], [70, 71 ],
[ 34], [72 ],
[ 35, 36, 37], [73, 74, 75 ],
]
}
ROW_INDENTS = {
'ergodox_ez': [0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 5, 0, 6, 0, 4, 0]
}
BLANK_LAYOUTS = [
# Compact Layout
"""
.------------------------------------.------------------------------------.
| | | | | | | | | | | | | | |
!-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
| | | | | | | | | | | | | | |
!-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
| | | | | | |-----!-----! | | | | | |
!-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
| | | | | | | | | | | | | | |
'-----+----+----+----+----+----------'----------+----+----+----+----+-----'
| | | | | | ! | | | | |
'------------------------' '------------------------'
.-----------. .-----------.
| | | ! | |
.-----+-----+-----! !-----+-----+-----.
! ! | | ! | ! !
! ! !-----! !-----! ! !
| | | | ! | | |
'-----------------' '-----------------'
""",
# Wide Layout
"""
.---------------------------------------------. .---------------------------------------------.
| | | | | | | | ! | | | | | | |
!-------+-----+-----+-----+-----+-------------! !-------+-----+-----+-----+-----+-----+-------!
| | | | | | | | ! | | | | | | |
!-------+-----+-----+-----x-----x-----! ! ! !-----x-----x-----+-----+-----+-------!
| | | | | | |-------! !-------! | | | | | |
!-------+-----+-----+-----x-----x-----! ! ! !-----x-----x-----+-----+-----+-------!
| | | | | | | | ! | | | | | | |
'-------+-----+-----+-----+-----+-------------' '-------------+-----+-----+-----+-----+-------'
| | | | | | ! | | | | |
'------------------------------' '------------------------------'
.---------------. .---------------.
| | | ! | |
.-------+-------+-------! !-------+-------+-------.
! ! | | ! | ! !
! ! !-------! !-------! ! !
| | | | ! | | |
'-----------------------' '-----------------------'
""",
]
DEFAULT_CONFIG = {
"keymaps_includes": [
"keymap_common.h",
],
'filler': "-+.'!:x",
'separator': "|",
'default_key_prefix': ["KC_"],
}
SECTIONS = [
'layout_config',
'layers',
]
# Markdown Parsing
ONELINE_COMMENT_RE = re.compile(r"""
^ # comment must be at the start of the line
\s* # arbitrary whitespace
// # start of the comment
(.*) # the comment
$ # until the end of line
""", re.MULTILINE | re.VERBOSE
)
INLINE_COMMENT_RE = re.compile(r"""
([\,\"\[\]\{\}\d]) # anythig that might end a expression
\s+ # comment must be preceded by whitespace
// # start of the comment
\s # and succeded by whitespace
(?:[^\"\]\}\{\[]*) # the comment (except things which might be json)
$ # until the end of line
""", re.MULTILINE | re.VERBOSE)
TRAILING_COMMA_RE = re.compile(r"""
, # the comma
(?:\s*) # arbitrary whitespace
$ # only works if the trailing comma is followed by newline
(\s*) # arbitrary whitespace
([\]\}]) # end of an array or object
""", re.MULTILINE | re.VERBOSE)
def loads(raw_data):
if isinstance(raw_data, bytes):
raw_data = raw_data.decode('utf-8')
raw_data = ONELINE_COMMENT_RE.sub(r"", raw_data)
raw_data = INLINE_COMMENT_RE.sub(r"\1", raw_data)
raw_data = TRAILING_COMMA_RE.sub(r"\1\2", raw_data)
return json.loads(raw_data)
def parse_config(path):
def reset_section():
section.update({
'name': section.get('name', ""),
'sub_name': "",
'start_line': -1,
'end_line': -1,
'code_lines': [],
})
def start_section(line_index, line):
end_section()
if line.startswith("# "):
name = line[2:]
elif line.startswith("## "):
name = line[3:]
else:
name = ""
name = name.strip().replace(" ", "_").lower()
if name in SECTIONS:
section['name'] = name
else:
section['sub_name'] = name
section['start_line'] = line_index
def end_section():
if section['start_line'] >= 0:
if section['name'] == 'layout_config':
config.update(loads("\n".join(
section['code_lines']
)))
elif section['sub_name'].startswith('layer'):
layer_name = section['sub_name']
config['layer_lines'][layer_name] = section['code_lines']
reset_section()
def amend_section(line_index, line):
section['end_line'] = line_index
section['code_lines'].append(line)
config = DEFAULT_CONFIG.copy()
config.update({
'layer_lines': collections.OrderedDict(),
'macro_ids': {'UM'},
'unicode_macros': {},
})
section = {}
reset_section()
with io.open(path, encoding="utf-8") as fh:
for i, line in enumerate(fh):
if line.startswith("#"):
start_section(i, line)
elif line.startswith(" "):
amend_section(i, line[4:])
else:
# TODO: maybe parse description
pass
end_section()
assert 'layout' in config
return config
# header file parsing
IF0_RE = re.compile(r"""
^
#if 0
$.*?
#endif
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
COMMENT_RE = re.compile(r"""
/\*
.*?
\*/"
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
def read_header_file(path):
with io.open(path, encoding="utf-8") as fh:
data = fh.read()
data, _ = COMMENT_RE.subn("", data)
data, _ = IF0_RE.subn("", data)
return data
def regex_partial(re_str_fmt, flags):
def partial(*args, **kwargs):
re_str = re_str_fmt.format(*args, **kwargs)
return re.compile(re_str, flags)
return partial
KEYDEF_REP = regex_partial(r"""
#define
\s
(
(?:{}) # the prefixes
(?:\w+) # the key name
) # capture group end
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
ENUM_RE = re.compile(r"""
(
enum
\s\w+\s
\{
.*? # the enum content
\}
;
) # capture group end
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
ENUM_KEY_REP = regex_partial(r"""
(
{} # the prefixes
\w+ # the key name
) # capture group end
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
def parse_keydefs(config, data):
prefix_options = "|".join(config['key_prefixes'])
keydef_re = KEYDEF_REP(prefix_options)
enum_key_re = ENUM_KEY_REP(prefix_options)
for match in keydef_re.finditer(data):
yield match.groups()[0]
for enum_match in ENUM_RE.finditer(data):
enum = enum_match.groups()[0]
for key_match in enum_key_re.finditer(enum):
yield key_match.groups()[0]
def parse_valid_keys(config, out_path):
basepath = os.path.abspath(os.path.join(os.path.dirname(out_path)))
dirpaths = []
subpaths = []
while len(subpaths) < 6:
path = os.path.join(basepath, *subpaths)
dirpaths.append(path)
dirpaths.append(os.path.join(path, "tmk_core", "common"))
dirpaths.append(os.path.join(path, "quantum"))
subpaths.append('..')
includes = set(config['keymaps_includes'])
includes.add("keycode.h")
valid_keycodes = set()
for dirpath, include in it.product(dirpaths, includes):
include_path = os.path.join(dirpath, include)
if os.path.exists(include_path):
header_data = read_header_file(include_path)
valid_keycodes.update(
parse_keydefs(config, header_data)
)
return valid_keycodes
# Keymap Parsing
def iter_raw_codes(layer_lines, filler, separator):
filler_re = re.compile("[" + filler + " ]")
for line in layer_lines:
line, _ = filler_re.subn("", line.strip())
if not line:
continue
codes = line.split(separator)
for code in codes[1:-1]:
yield code
def iter_indexed_codes(raw_codes, key_indexes):
key_rows = {}
key_indexes_flat = []
for row_index, key_indexes in enumerate(key_indexes):
for key_index in key_indexes:
key_rows[key_index] = row_index
key_indexes_flat.extend(key_indexes)
assert len(raw_codes) == len(key_indexes_flat)
for raw_code, key_index in zip(raw_codes, key_indexes_flat):
# we keep track of the row mostly for layout purposes
yield raw_code, key_index, key_rows[key_index]
LAYER_CHANGE_RE = re.compile(r"""
(DF|TG|MO)\(\d+\)
""", re.VERBOSE)
MACRO_RE = re.compile(r"""
M\(\w+\)
""", re.VERBOSE)
UNICODE_RE = re.compile(r"""
U[0-9A-F]{4}
""", re.VERBOSE)
NON_CODE = re.compile(r"""
^[^A-Z0-9_]$
""", re.VERBOSE)
def parse_uni_code(raw_code):
macro_id = "UC_" + (
unicodedata.name(raw_code)
.replace(" ", "_")
.replace("-", "_")
)
code = "M({})".format(macro_id)
uc_hex = "{:04X}".format(ord(raw_code))
return code, macro_id, uc_hex
def parse_key_code(raw_code, key_prefixes, valid_keycodes):
if raw_code in valid_keycodes:
return raw_code
for prefix in key_prefixes:
code = prefix + raw_code
if code in valid_keycodes:
return code
def parse_code(raw_code, key_prefixes, valid_keycodes):
if not raw_code:
return 'KC_TRNS', None, None
if LAYER_CHANGE_RE.match(raw_code):
return raw_code, None, None
if MACRO_RE.match(raw_code):
macro_id = raw_code[2:-1]
return raw_code, macro_id, None
if UNICODE_RE.match(raw_code):
hex_code = raw_code[1:]
return parse_uni_code(chr(int(hex_code, 16)))
if NON_CODE.match(raw_code):
return parse_uni_code(raw_code)
code = parse_key_code(raw_code, key_prefixes, valid_keycodes)
return code, None, None
def parse_keymap(config, key_indexes, layer_lines, valid_keycodes):
keymap = {}
raw_codes = list(iter_raw_codes(
layer_lines, config['filler'], config['separator']
))
indexed_codes = iter_indexed_codes(raw_codes, key_indexes)
key_prefixes = config['key_prefixes']
for raw_code, key_index, row_index in indexed_codes:
code, macro_id, uc_hex = parse_code(
raw_code, key_prefixes, valid_keycodes
)
# TODO: line numbers for invalid codes
err_msg = "Could not parse key '{}' on row {}".format(
raw_code, row_index
)
assert code is not None, err_msg
# print(repr(raw_code), repr(code), macro_id, uc_hex)
if macro_id:
config['macro_ids'].add(macro_id)
if uc_hex:
config['unicode_macros'][macro_id] = uc_hex
keymap[key_index] = (code, row_index)
return keymap
def parse_keymaps(config, valid_keycodes):
keymaps = collections.OrderedDict()
key_indexes = config.get(
'key_indexes', KEYBOARD_LAYOUTS[config['layout']]
)
# TODO: maybe validate key_indexes
for layer_name, layer_lines, in config['layer_lines'].items():
keymaps[layer_name] = parse_keymap(
config, key_indexes, layer_lines, valid_keycodes
)
return keymaps
# keymap.c output
USERCODE = """
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
uint8_t layer = biton32(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
ergodox_right_led_3_off();
switch (layer) {
case L1:
ergodox_right_led_1_on();
break;
case L2:
ergodox_right_led_2_on();
break;
case L3:
ergodox_right_led_3_on();
break;
case L4:
ergodox_right_led_1_on();
ergodox_right_led_2_on();
break;
case L5:
ergodox_right_led_1_on();
ergodox_right_led_3_on();
break;
// case L6:
// ergodox_right_led_2_on();
// ergodox_right_led_3_on();
// break;
// case L7:
// ergodox_right_led_1_on();
// ergodox_right_led_2_on();
// ergodox_right_led_3_on();
// break;
default:
ergodox_board_led_off();
break;
}
};
"""
MACROCODE = """
#define UC_MODE_WIN 0
#define UC_MODE_LINUX 1
#define UC_MODE_OSX 2
// TODO: allow default mode to be configured
static uint16_t unicode_mode = UC_MODE_WIN;
uint16_t hextokeycode(uint8_t hex) {{
if (hex == 0x0) {{
return KC_P0;
}}
if (hex < 0xA) {{
return KC_P1 + (hex - 0x1);
}}
return KC_A + (hex - 0xA);
}}
void unicode_action_function(uint16_t hi, uint16_t lo) {{
switch (unicode_mode) {{
case UC_MODE_WIN:
register_code(KC_LALT);
register_code(KC_PPLS);
unregister_code(KC_PPLS);
register_code(hextokeycode((hi & 0xF0) >> 4));
unregister_code(hextokeycode((hi & 0xF0) >> 4));
register_code(hextokeycode((hi & 0x0F)));
unregister_code(hextokeycode((hi & 0x0F)));
register_code(hextokeycode((lo & 0xF0) >> 4));
unregister_code(hextokeycode((lo & 0xF0) >> 4));
register_code(hextokeycode((lo & 0x0F)));
unregister_code(hextokeycode((lo & 0x0F)));
unregister_code(KC_LALT);
break;
case UC_MODE_LINUX:
register_code(KC_LCTL);
register_code(KC_LSFT);
register_code(KC_U);
unregister_code(KC_U);
register_code(hextokeycode((hi & 0xF0) >> 4));
unregister_code(hextokeycode((hi & 0xF0) >> 4));
register_code(hextokeycode((hi & 0x0F)));
unregister_code(hextokeycode((hi & 0x0F)));
register_code(hextokeycode((lo & 0xF0) >> 4));
unregister_code(hextokeycode((lo & 0xF0) >> 4));
register_code(hextokeycode((lo & 0x0F)));
unregister_code(hextokeycode((lo & 0x0F)));
unregister_code(KC_LCTL);
unregister_code(KC_LSFT);
break;
case UC_MODE_OSX:
break;
}}
}}
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {{
if (!record->event.pressed) {{
return MACRO_NONE;
}}
// MACRODOWN only works in this function
switch(id) {{
case UM:
unicode_mode = (unicode_mode + 1) % 2;
break;
{macro_cases}
{unicode_macro_cases}
default:
break;
}}
return MACRO_NONE;
}};
"""
UNICODE_MACRO_TEMPLATE = """
case {macro_id}:
unicode_action_function(0x{hi:02x}, 0x{lo:02x});
break;
""".strip()
def unicode_macro_cases(config):
for macro_id, uc_hex in config['unicode_macros'].items():
hi = int(uc_hex, 16) >> 8
lo = int(uc_hex, 16) & 0xFF
unimacro_keys = ", ".join(
"T({})".format(
"KP_" + digit if digit.isdigit() else digit
) for digit in uc_hex
)
yield UNICODE_MACRO_TEMPLATE.format(
macro_id=macro_id, hi=hi, lo=lo
)
def iter_keymap_lines(keymap, row_indents=None):
col_widths = {}
col = 0
# first pass, figure out the column widths
prev_row_index = None
for code, row_index in keymap.values():
if row_index != prev_row_index:
col = 0
if row_indents:
col = row_indents[row_index]
col_widths[col] = max(len(code), col_widths.get(col, 0))
prev_row_index = row_index
col += 1
# second pass, yield the cell values
col = 0
prev_row_index = None
for key_index in sorted(keymap):
code, row_index = keymap[key_index]
if row_index != prev_row_index:
col = 0
yield "\n"
if row_indents:
for indent_col in range(row_indents[row_index]):
pad = " " * (col_widths[indent_col] - 4)
yield (" /*-*/" + pad)
col = row_indents[row_index]
else:
yield pad
yield " {}".format(code)
if key_index < len(keymap) - 1:
yield ","
# This will be yielded on the next iteration when
# we know that we're not at the end of a line.
pad = " " * (col_widths[col] - len(code))
prev_row_index = row_index
col += 1
def iter_keymap_parts(config, keymaps):
# includes
for include_path in config['keymaps_includes']:
yield '#include "{}"\n'.format(include_path)
yield "\n"
# definitions
for i, macro_id in enumerate(sorted(config['macro_ids'])):
yield "#define {} {}\n".format(macro_id, i)
yield "\n"
for i, layer_name in enumerate(config['layer_lines']):
yield '#define L{0:<3} {0:<5} // {1}\n'.format(i, layer_name)
yield "\n"
# keymaps
yield "const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {\n"
for i, layer_name in enumerate(config['layer_lines']):
# comment
layer_lines = config['layer_lines'][layer_name]
prefixed_lines = " * " + " * ".join(layer_lines)
yield "/*\n{} */\n".format(prefixed_lines)
# keymap codes
keymap = keymaps[layer_name]
row_indents = ROW_INDENTS.get(config['layout'])
keymap_lines = "".join(iter_keymap_lines(keymap, row_indents))
yield "[L{0}] = KEYMAP({1}\n),\n".format(i, keymap_lines)
yield "};\n\n"
# macros
yield MACROCODE.format(
macro_cases="",
unicode_macro_cases="\n".join(unicode_macro_cases(config)),
)
# TODO: dynamically create blinking lights
yield USERCODE
def main(argv=sys.argv[1:]):
if not argv or '-h' in argv or '--help' in argv:
print(__doc__)
return 0
in_path = os.path.abspath(argv[0])
if not os.path.exists(in_path):
print("No such file '{}'".format(in_path))
return 1
if len(argv) > 1:
out_path = os.path.abspath(argv[1])
else:
dirname = os.path.dirname(in_path)
out_path = os.path.join(dirname, "keymap.c")
config = parse_config(in_path)
valid_keys = parse_valid_keys(config, out_path)
keymaps = parse_keymaps(config, valid_keys)
with io.open(out_path, mode="w", encoding="utf-8") as fh:
for part in iter_keymap_parts(config, keymaps):
fh.write(part)
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,3 @@
# ErgoDox EZ Utilities
The Python script in this directory, by [mbarkhau](https://github.com/mbarkhau) allows you to write out a basic ErgoDox EZ keymap using Markdown notation, and then transpile it to C, which you can then compile. It's experimental, but if you're not comfortable using C, it's a nice option.