diff options
Diffstat (limited to 'quantum')
39 files changed, 1886 insertions, 1000 deletions
diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c index 708022f68f..e57b31d103 100644 --- a/quantum/backlight/backlight.c +++ b/quantum/backlight/backlight.c @@ -21,6 +21,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. backlight_config_t backlight_config; +// TODO: migrate to backlight_config_t +static uint8_t breathing_period = BREATHING_PERIOD; + /** \brief Backlight initialization * * FIXME: needs doc @@ -191,3 +194,21 @@ void backlight_disable_breathing(void) { */ bool is_backlight_breathing(void) { return backlight_config.breathing; } #endif + +// following are marked as weak purely for backwards compatibility +__attribute__((weak)) void breathing_period_set(uint8_t value) { breathing_period = value ? value : 1; } + +__attribute__((weak)) uint8_t get_breathing_period(void) { return breathing_period; } + +__attribute__((weak)) void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); } + +__attribute__((weak)) void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); } + +__attribute__((weak)) void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); } + +// defaults for backlight api +__attribute__((weak)) void backlight_init_ports(void) {} + +__attribute__((weak)) void backlight_set(uint8_t level) {} + +__attribute__((weak)) void backlight_task(void) {} diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h index 1e581055db..9f0a5e81d7 100644 --- a/quantum/backlight/backlight.h +++ b/quantum/backlight/backlight.h @@ -41,22 +41,39 @@ typedef union { } backlight_config_t; void backlight_init(void); -void backlight_increase(void); -void backlight_decrease(void); void backlight_toggle(void); void backlight_enable(void); void backlight_disable(void); bool is_backlight_enabled(void); void backlight_step(void); -void backlight_set(uint8_t level); +void backlight_increase(void); +void backlight_decrease(void); void backlight_level(uint8_t level); uint8_t get_backlight_level(void); +// implementation specific +void backlight_init_ports(void); +void backlight_set(uint8_t level); +void backlight_task(void); + #ifdef BACKLIGHT_BREATHING + void backlight_toggle_breathing(void); void backlight_enable_breathing(void); void backlight_disable_breathing(void); bool is_backlight_breathing(void); + +void breathing_period_set(uint8_t value); +uint8_t get_breathing_period(void); +void breathing_period_default(void); +void breathing_period_inc(void); +void breathing_period_dec(void); + +// implementation specific void breathing_enable(void); void breathing_disable(void); +void breathing_toggle(void); +bool is_breathing(void); +void breathing_pulse(void); +void breathing_task(void); #endif diff --git a/quantum/backlight/backlight_arm.c b/quantum/backlight/backlight_arm.c index 3f94ccef8e..f7065906f8 100644 --- a/quantum/backlight/backlight_arm.c +++ b/quantum/backlight/backlight_arm.c @@ -10,10 +10,6 @@ # error "Backlight support for STMF072 is not available. Please disable." # endif -# if defined(STM32F1XX) || defined(STM32F1xx) -# define USE_GPIOV1 -# endif - // GPIOV2 && GPIOV3 # ifndef BACKLIGHT_PAL_MODE # define BACKLIGHT_PAL_MODE 2 @@ -110,7 +106,6 @@ void backlight_task(void) {} # define BREATHING_HALT_ON 2 # define BREATHING_STEPS 128 -static uint8_t breathing_period = BREATHING_PERIOD; static uint8_t breathing_halt = BREATHING_NO_HALT; static uint16_t breathing_counter = 0; @@ -118,7 +113,7 @@ bool is_breathing(void) { return BACKLIGHT_PWM_DRIVER.config == &pwmCFG_breathin static inline void breathing_min(void) { breathing_counter = 0; } -static inline void breathing_max(void) { breathing_counter = breathing_period * 256 / 2; } +static inline void breathing_max(void) { breathing_counter = get_breathing_period() * 256 / 2; } void breathing_interrupt_enable(void) { pwmStop(&BACKLIGHT_PWM_DRIVER); @@ -170,17 +165,6 @@ void breathing_toggle(void) { breathing_enable(); } -void breathing_period_set(uint8_t value) { - if (!value) value = 1; - breathing_period = value; -} - -void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); } - -void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); } - -void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); } - /* To generate breathing curve in python: * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)] */ @@ -191,7 +175,8 @@ static inline uint16_t scale_backlight(uint16_t v) { return v / BACKLIGHT_LEVELS static void breathing_callback(PWMDriver *pwmp) { (void)pwmp; - uint16_t interval = (uint16_t)breathing_period * 256 / BREATHING_STEPS; + uint8_t breathing_period = get_breathing_period(); + uint16_t interval = (uint16_t)breathing_period * 256 / BREATHING_STEPS; // resetting after one period to prevent ugly reset at overflow. breathing_counter = (breathing_counter + 1) % (breathing_period * 256); uint8_t index = breathing_counter / interval % BREATHING_STEPS; @@ -207,12 +192,4 @@ static void breathing_callback(PWMDriver *pwmp) { chSysUnlockFromISR(); } -#else - -__attribute__((weak)) void backlight_init_ports(void) {} - -__attribute__((weak)) void backlight_set(uint8_t level) {} - -__attribute__((weak)) void backlight_task(void) {} - #endif diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c index edda6ea0b6..7cf1e0fb30 100644 --- a/quantum/backlight/backlight_avr.c +++ b/quantum/backlight/backlight_avr.c @@ -206,7 +206,7 @@ static const pin_t backlight_pin = BACKLIGHT_PIN; # endif # ifdef NO_HARDWARE_PWM -__attribute__((weak)) void backlight_init_ports(void) { +void backlight_init_ports(void) { // Setup backlight pin as output and output to on state. FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);) @@ -217,8 +217,6 @@ __attribute__((weak)) void backlight_init_ports(void) { # endif } -__attribute__((weak)) void backlight_set(uint8_t level) {} - uint8_t backlight_tick = 0; # ifndef BACKLIGHT_CUSTOM_DRIVER @@ -303,7 +301,7 @@ static uint16_t cie_lightness(uint16_t v) { static inline void set_pwm(uint16_t val) { OCRxx = val; } # ifndef BACKLIGHT_CUSTOM_DRIVER -__attribute__((weak)) void backlight_set(uint8_t level) { +void backlight_set(uint8_t level) { if (level > BACKLIGHT_LEVELS) level = BACKLIGHT_LEVELS; if (level == 0) { @@ -342,7 +340,6 @@ void backlight_task(void) {} # define BREATHING_HALT_ON 2 # define BREATHING_STEPS 128 -static uint8_t breathing_period = BREATHING_PERIOD; static uint8_t breathing_halt = BREATHING_NO_HALT; static uint16_t breathing_counter = 0; @@ -377,9 +374,9 @@ bool is_breathing(void) { return !!(TIMSKx & _BV(TOIEx)); } do { \ breathing_counter = 0; \ } while (0) -# define breathing_max() \ - do { \ - breathing_counter = breathing_period * 244 / 2; \ +# define breathing_max() \ + do { \ + breathing_counter = get_breathing_period() * 244 / 2; \ } while (0) void breathing_enable(void) { @@ -417,17 +414,6 @@ void breathing_toggle(void) { breathing_enable(); } -void breathing_period_set(uint8_t value) { - if (!value) value = 1; - breathing_period = value; -} - -void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); } - -void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); } - -void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); } - /* To generate breathing curve in python: * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)] */ @@ -445,6 +431,7 @@ void breathing_task(void) ISR(TIMERx_OVF_vect) # endif { + uint8_t breathing_period = get_breathing_period(); uint16_t interval = (uint16_t)breathing_period * 244 / BREATHING_STEPS; // resetting after one period to prevent ugly reset at overflow. breathing_counter = (breathing_counter + 1) % (breathing_period * 244); @@ -459,7 +446,7 @@ ISR(TIMERx_OVF_vect) # endif // BACKLIGHT_BREATHING -__attribute__((weak)) void backlight_init_ports(void) { +void backlight_init_ports(void) { // Setup backlight pin as output and output to on state. FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);) @@ -500,10 +487,4 @@ __attribute__((weak)) void backlight_init_ports(void) { # endif // hardware backlight -#else // no backlight - -__attribute__((weak)) void backlight_init_ports(void) {} - -__attribute__((weak)) void backlight_set(uint8_t level) {} - -#endif // backlight
\ No newline at end of file +#endif // backlight diff --git a/quantum/backlight/backlight_soft.c b/quantum/backlight/backlight_soft.c index a6aba7782c..096b41d910 100644 --- a/quantum/backlight/backlight_soft.c +++ b/quantum/backlight/backlight_soft.c @@ -10,7 +10,7 @@ #endif #ifndef BACKLIGHT_ON_STATE -# define BACKLIGHT_ON_STATE 0 +# define BACKLIGHT_ON_STATE 1 #endif #ifdef BACKLIGHT_PINS @@ -20,6 +20,7 @@ { BACKLIGHT_PIN } #endif +static uint16_t s_duty_pattern = 0; static const pin_t backlight_pins[] = BACKLIGHT_PIN_INIT; #define BACKLIGHT_LED_COUNT (sizeof(backlight_pins) / sizeof(pin_t)) @@ -46,14 +47,38 @@ void backlight_off(pin_t backlight_pin) { } void backlight_init_ports(void) { - // Setup backlight pin as output and output to on state. - FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);) + // Setup backlight pin as output and output to off state. + FOR_EACH_LED(setPinOutput(backlight_pin); backlight_off(backlight_pin);) } +// clang-format off + +/** \brief PWM duty patterns + * + * We scale the current backlight level to an index within this array. This allows + * backlight_task to focus on just switching LEDs on/off, and we can predict the duty pattern + */ +static uint16_t backlight_duty_table[] = { + 0b0000000000000000, + 0b1000000000000000, + 0b1000000010000000, + 0b1000001000010000, + 0b1000100010001000, + 0b1001001001001000, + 0b1010101010101010, + 0b1110111011101110, + 0b1111111111111111, +}; +#define backlight_duty_table_size (sizeof(backlight_duty_table) / sizeof(backlight_duty_table[0])) + +// clang-format on + +static uint8_t scale_backlight(uint8_t v) { return v * (backlight_duty_table_size - 1) / BACKLIGHT_LEVELS; } + void backlight_task(void) { static uint8_t backlight_tick = 0; - if ((0xFFFF >> (get_backlight_level() * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) { + if (s_duty_pattern & ((uint16_t)1 << backlight_tick)) { FOR_EACH_LED(backlight_on(backlight_pin);) } else { FOR_EACH_LED(backlight_off(backlight_pin);) @@ -61,6 +86,4 @@ void backlight_task(void) { backlight_tick = (backlight_tick + 1) % 16; } -void backlight_set(uint8_t level) { - // noop as backlight_task uses get_backlight_level() -} +void backlight_set(uint8_t level) { s_duty_pattern = backlight_duty_table[scale_backlight(level)]; } diff --git a/quantum/color.c b/quantum/color.c index 1f398e2403..8bd52444fa 100644 --- a/quantum/color.c +++ b/quantum/color.c @@ -85,3 +85,17 @@ RGB hsv_to_rgb(HSV hsv) { return rgb; } + +#ifdef RGBW +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +void convert_rgb_to_rgbw(LED_TYPE *led) { + // Determine lowest value in all three colors, put that into + // the white channel and then shift all colors by that amount + led->w = MIN(led->r, MIN(led->g, led->b)); + led->r -= led->w; + led->g -= led->w; + led->b -= led->w; +} +#endif diff --git a/quantum/color.h b/quantum/color.h index 6781646628..58d4f0407f 100644 --- a/quantum/color.h +++ b/quantum/color.h @@ -64,5 +64,7 @@ typedef struct PACKED { #endif RGB hsv_to_rgb(HSV hsv); - +#ifdef RGBW +void convert_rgb_to_rgbw(LED_TYPE *led); +#endif #endif // COLOR_H diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index ca056f630e..11d28592d6 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -20,28 +20,37 @@ #include "progmem.h" // to read default from flash #include "quantum.h" // for send_string() #include "dynamic_keymap.h" - -#ifdef DYNAMIC_KEYMAP_ENABLE - -# ifndef DYNAMIC_KEYMAP_EEPROM_ADDR -# error DYNAMIC_KEYMAP_EEPROM_ADDR not defined -# endif - -# ifndef DYNAMIC_KEYMAP_LAYER_COUNT -# error DYNAMIC_KEYMAP_LAYER_COUNT not defined -# endif - -# ifndef DYNAMIC_KEYMAP_MACRO_COUNT -# error DYNAMIC_KEYMAP_MACRO_COUNT not defined -# endif - -# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR -# error DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR not defined -# endif - -# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE -# error DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE not defined -# endif +#include "via.h" // for default VIA_EEPROM_ADDR_END + +#ifndef DYNAMIC_KEYMAP_LAYER_COUNT +# define DYNAMIC_KEYMAP_LAYER_COUNT 4 +#endif + +#ifndef DYNAMIC_KEYMAP_MACRO_COUNT +# define DYNAMIC_KEYMAP_MACRO_COUNT 16 +#endif + +// If DYNAMIC_KEYMAP_EEPROM_ADDR not explicitly defined in config.h, +// default it start after VIA_EEPROM_CUSTOM_ADDR+VIA_EEPROM_CUSTOM_SIZE +#ifndef DYNAMIC_KEYMAP_EEPROM_ADDR +# ifdef VIA_EEPROM_CUSTOM_CONFIG_ADDR +# define DYNAMIC_KEYMAP_EEPROM_ADDR (VIA_EEPROM_CUSTOM_CONFIG_ADDR+VIA_EEPROM_CUSTOM_CONFIG_SIZE) +# else +# error DYNAMIC_KEYMAP_EEPROM_ADDR not defined +# endif +#endif + +// Dynamic macro starts after dynamic keymaps +#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR+(DYNAMIC_KEYMAP_LAYER_COUNT*MATRIX_ROWS*MATRIX_COLS*2)) +#endif + +// Dynamic macro uses up all remaining memory +// Assumes 1K EEPROM on ATMega32U4 +// Override for anything different +#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE +# define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE (1024-DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR) +#endif uint8_t dynamic_keymap_get_layer_count(void) { return DYNAMIC_KEYMAP_LAYER_COUNT; } @@ -208,5 +217,3 @@ void dynamic_keymap_macro_send(uint8_t id) { send_string(data); } } - -#endif // DYNAMIC_KEYMAP_ENABLE diff --git a/quantum/encoder.c b/quantum/encoder.c index 4aeb3d0cde..c41b89f495 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -37,8 +37,8 @@ static pin_t encoders_pad_b[] = ENCODERS_PAD_B; static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}; -static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0}; -static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0}; +static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0}; +static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0}; #ifdef SPLIT_KEYBOARD // right half encoders come over as second set of encoders @@ -79,27 +79,27 @@ void encoder_init(void) { } static void encoder_update(int8_t index, uint8_t state) { - encoder_pulses[index] += encoder_LUT[state & 0xF]; - if (encoder_pulses[index] >= ENCODER_RESOLUTION) { + uint8_t i = index; +#ifdef SPLIT_KEYBOARD + index += thisHand; +#endif + encoder_pulses[i] += encoder_LUT[state & 0xF]; + if (encoder_pulses[i] >= ENCODER_RESOLUTION) { encoder_value[index]++; encoder_update_kb(index, true); } - if (encoder_pulses[index] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise + if (encoder_pulses[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise encoder_value[index]--; encoder_update_kb(index, false); } - encoder_pulses[index] %= ENCODER_RESOLUTION; + encoder_pulses[i] %= ENCODER_RESOLUTION; } void encoder_read(void) { - for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { + for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { encoder_state[i] <<= 2; encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); -#if SPLIT_KEYBOARD - encoder_update(i + thisHand, encoder_state[i]); -#else encoder_update(i, encoder_state[i]); -#endif } } @@ -107,9 +107,9 @@ void encoder_read(void) { void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); } void encoder_update_raw(uint8_t* slave_state) { - for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { + for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { uint8_t index = i + thatHand; - int8_t delta = slave_state[i] - encoder_value[index]; + int8_t delta = slave_state[i] - encoder_value[index]; while (delta > 0) { delta--; encoder_value[index]++; diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 4fa45ac37b..c82c446399 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -48,13 +48,10 @@ action_t action_for_key(uint8_t layer, keypos_t key) { // keycode remapping keycode = keycode_config(keycode); - action_t action; + action_t action = {}; uint8_t action_layer, when, mod; switch (keycode) { - case KC_FN0 ... KC_FN31: - action.code = keymap_function_id_to_action(FN_INDEX(keycode)); - break; case KC_A ... KC_EXSEL: case KC_LCTRL ... KC_RGUI: action.code = ACTION_KEY(keycode); @@ -65,9 +62,11 @@ action_t action_for_key(uint8_t layer, keypos_t key) { case KC_AUDIO_MUTE ... KC_BRIGHTNESS_DOWN: action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode)); break; +#ifdef MOUSEKEY_ENABLE case KC_MS_UP ... KC_MS_ACCEL2: action.code = ACTION_MOUSEKEY(keycode); break; +#endif case KC_TRNS: action.code = ACTION_TRANSPARENT; break; @@ -76,17 +75,24 @@ action_t action_for_key(uint8_t layer, keypos_t key) { // Split it up action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key break; +#ifndef NO_ACTION_FUNCTION + case KC_FN0 ... KC_FN31: + action.code = keymap_function_id_to_action(FN_INDEX(keycode)); + break; case QK_FUNCTION ... QK_FUNCTION_MAX:; // Is a shortcut for function action_layer, pull last 12bits // This means we have 4,096 FN macros at our disposal action.code = keymap_function_id_to_action((int)keycode & 0xFFF); break; +#endif +#ifndef NO_ACTION_MACRO case QK_MACRO ... QK_MACRO_MAX: if (keycode & 0x800) // tap macros have upper bit set action.code = ACTION_MACRO_TAP(keycode & 0xFF); else action.code = ACTION_MACRO(keycode & 0xFF); break; +#endif case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF); break; diff --git a/quantum/matrix.c b/quantum/matrix.c index 907492a0f6..1675f2477b 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -17,34 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <stdint.h> #include <stdbool.h> #include "wait.h" -#include "print.h" -#include "debug.h" #include "util.h" #include "matrix.h" #include "debounce.h" #include "quantum.h" -#if (MATRIX_COLS <= 8) -# define print_matrix_header() print("\nr/c 01234567\n") -# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop(matrix[i]) -# define ROW_SHIFTER ((uint8_t)1) -#elif (MATRIX_COLS <= 16) -# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") -# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop16(matrix[i]) -# define ROW_SHIFTER ((uint16_t)1) -#elif (MATRIX_COLS <= 32) -# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") -# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop32(matrix[i]) -# define ROW_SHIFTER ((uint32_t)1) -#endif - -#ifdef MATRIX_MASKED -extern const matrix_row_t matrix_mask[]; -#endif - #ifdef DIRECT_PINS static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) @@ -53,61 +30,10 @@ static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; #endif /* matrix state(1:on, 0:off) */ -static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values -static matrix_row_t matrix[MATRIX_ROWS]; // debounced values - -__attribute__((weak)) void matrix_init_quantum(void) { matrix_init_kb(); } - -__attribute__((weak)) void matrix_scan_quantum(void) { matrix_scan_kb(); } - -__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } +extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values +extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values -__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } - -__attribute__((weak)) void matrix_init_user(void) {} - -__attribute__((weak)) void matrix_scan_user(void) {} - -inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } - -inline uint8_t matrix_cols(void) { return MATRIX_COLS; } - -// Deprecated. -bool matrix_is_modified(void) { - if (debounce_active()) return false; - return true; -} - -inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } - -inline matrix_row_t matrix_get_row(uint8_t row) { - // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a - // switch blocker installed and the switch is always pressed. -#ifdef MATRIX_MASKED - return matrix[row] & matrix_mask[row]; -#else - return matrix[row]; -#endif -} - -void matrix_print(void) { - print_matrix_header(); - - for (uint8_t row = 0; row < MATRIX_ROWS; row++) { - phex(row); - print(": "); - print_matrix_row(row); - print("\n"); - } -} - -uint8_t matrix_key_count(void) { - uint8_t count = 0; - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - count += matrix_bitpop(i); - } - return count; -} +// matrix code #ifdef DIRECT_PINS @@ -129,7 +55,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { pin_t pin = direct_pins[current_row][col_index]; if (pin != NO_PIN) { - current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index); + current_matrix[current_row] |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index); } } @@ -175,7 +101,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) uint8_t pin_state = readPin(col_pins[col_index]); // Populate the matrix row with the state of the col pin - current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); + current_matrix[current_row] |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); } // Unselect row @@ -221,10 +147,10 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) // Check row pin state if (readPin(row_pins[row_index]) == 0) { // Pin LO, set col bit - current_matrix[row_index] |= (ROW_SHIFTER << current_col); + current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col); } else { // Pin HI, clear col bit - current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); + current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col); } // Determine if the matrix changed state diff --git a/quantum/matrix_common.c b/quantum/matrix_common.c new file mode 100644 index 0000000000..c326e59ca3 --- /dev/null +++ b/quantum/matrix_common.c @@ -0,0 +1,107 @@ +#include "matrix.h" +#include "debounce.h" +#include "print.h" +#include "debug.h" + +/* matrix state(1:on, 0:off) */ +matrix_row_t raw_matrix[MATRIX_ROWS]; +matrix_row_t matrix[MATRIX_ROWS]; + +#ifdef MATRIX_MASKED +extern const matrix_row_t matrix_mask[]; +#endif + +// user-defined overridable functions + +__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } + +__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } + +__attribute__((weak)) void matrix_init_user(void) {} + +__attribute__((weak)) void matrix_scan_user(void) {} + +// helper functions + +inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } + +inline uint8_t matrix_cols(void) { return MATRIX_COLS; } + +inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } + +inline matrix_row_t matrix_get_row(uint8_t row) { + // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a + // switch blocker installed and the switch is always pressed. +#ifdef MATRIX_MASKED + return matrix[row] & matrix_mask[row]; +#else + return matrix[row]; +#endif +} + +// Deprecated. +bool matrix_is_modified(void) { + if (debounce_active()) return false; + return true; +} + +#if (MATRIX_COLS <= 8) +# define print_matrix_header() print("\nr/c 01234567\n") +# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) +# define matrix_bitpop(row) bitpop(matrix_get_row(row)) +#elif (MATRIX_COLS <= 16) +# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") +# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) +# define matrix_bitpop(row) bitpop16(matrix_get_row(row)) +#elif (MATRIX_COLS <= 32) +# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") +# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) +# define matrix_bitpop(row) bitpop32(matrix_get_row(row)) +#endif + +void matrix_print(void) { + print_matrix_header(); + + for (uint8_t row = 0; row < MATRIX_ROWS; row++) { + phex(row); + print(": "); + print_matrix_row(row); + print("\n"); + } +} + +uint8_t matrix_key_count(void) { + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += matrix_bitpop(i); + } + return count; +} + +// CUSTOM MATRIX 'LITE' +__attribute__((weak)) void matrix_init_custom(void) {} + +__attribute__((weak)) bool matrix_scan_custom(matrix_row_t current_matrix[]) { return true; } + +__attribute__((weak)) void matrix_init(void) { + matrix_init_custom(); + + // initialize matrix state: all keys off + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + raw_matrix[i] = 0; + matrix[i] = 0; + } + + debounce_init(MATRIX_ROWS); + + matrix_init_quantum(); +} + +__attribute__((weak)) uint8_t matrix_scan(void) { + bool changed = matrix_scan_custom(raw_matrix); + + debounce(raw_matrix, matrix, MATRIX_ROWS, changed); + + matrix_scan_quantum(); + return changed; +} diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index 6815a0d8a5..bddafa6a4c 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -1,9 +1,15 @@ ifneq ($(findstring STM32F303, $(MCU)),) + # Cortex version + MCU = cortex-m4 + + # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 + ARMV = 7 + ## chip/board settings # - the next two should match the directories in # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) - MCU_FAMILY ?= STM32 - MCU_SERIES ?= STM32F3xx + MCU_FAMILY = STM32 + MCU_SERIES = STM32F3xx # Linker script to use # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ @@ -18,22 +24,110 @@ ifneq ($(findstring STM32F303, $(MCU)),) # <keyboard_dir>/boards/, or drivers/boards/ BOARD ?= GENERIC_STM32_F303XC + USE_FPU ?= yes + + # Options to pass to dfu-util when flashing + DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave + DFU_SUFFIX_ARGS ?= -v 0483 -p df11 +endif + +ifneq ($(findstring STM32F072, $(MCU)),) # Cortex version - MCU = cortex-m4 + MCU = cortex-m0 # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 - ARMV ?= 7 + ARMV = 6 - USE_FPU = yes + ## chip/board settings + # - the next two should match the directories in + # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) + MCU_FAMILY = STM32 + MCU_SERIES = STM32F0xx - # Vector table for application - # 0x00000000-0x00001000 area is occupied by bootloader.*/ - # The CORTEX_VTOR... is needed only for MCHCK/Infinity KB - # OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000 + # Linker script to use + # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ + # or <keyboard_dir>/ld/ + MCU_LDSCRIPT ?= STM32F072xB + + # Startup code to use + # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ + MCU_STARTUP ?= stm32f0xx + + # Board: it should exist either in <chibios>/os/hal/boards/, + # <keyboard_dir>/boards/, or drivers/boards/ + BOARD ?= ST_STM32F072B_DISCOVERY + + USE_FPU ?= no # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave - DFU_SUFFIX_ARGS = -p DF11 -v 0483 + DFU_SUFFIX_ARGS ?= -v 0483 -p df11 +endif + +ifneq ($(findstring STM32F042, $(MCU)),) + # Cortex version + MCU = cortex-m0 + + # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 + ARMV = 6 + + ## chip/board settings + # - the next two should match the directories in + # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) + MCU_FAMILY = STM32 + MCU_SERIES = STM32F0xx + + # Linker script to use + # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ + # or <keyboard_dir>/ld/ + MCU_LDSCRIPT ?= STM32F042x6 + + # Startup code to use + # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ + MCU_STARTUP ?= stm32f0xx + + # Board: it should exist either in <chibios>/os/hal/boards/, + # <keyboard_dir>/boards/, or drivers/boards/ + BOARD ?= GENERIC_STM32_F042X6 + + USE_FPU ?= no + + # Options to pass to dfu-util when flashing + DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave + DFU_SUFFIX_ARGS ?= -v 0483 -p df11 +endif + +ifneq ($(findstring STM32F103, $(MCU)),) + # Cortex version + MCU = cortex-m3 + + # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 + ARMV = 7 + + ## chip/board settings + # - the next two should match the directories in + # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) + MCU_FAMILY = STM32 + MCU_SERIES = STM32F1xx + + # Linker script to use + # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ + # or <keyboard_dir>/ld/ + MCU_LDSCRIPT ?= STM32F103x8 + + # Startup code to use + # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ + MCU_STARTUP ?= stm32f1xx + + # Board: it should exist either in <chibios>/os/hal/boards/, + # <keyboard_dir>/boards/, or drivers/boards/ + BOARD ?= GENERIC_STM32_F103 + + USE_FPU ?= no + + # Options to pass to dfu-util when flashing + DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave + DFU_SUFFIX_ARGS ?= -v 0483 -p df11 endif ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb1286)) @@ -75,6 +169,9 @@ ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 a endif ifneq (,$(filter $(MCU),atmega32a)) + # MCU name for avrdude + AVRDUDE_MCU = m32 + PROTOCOL = VUSB # Processor frequency. @@ -87,12 +184,12 @@ ifneq (,$(filter $(MCU),atmega32a)) # unsupported features for now NO_UART ?= yes NO_SUSPEND_POWER_DOWN ?= yes - - # Programming options - PROGRAM_CMD ?= ./util/atmega32a_program.py $(TARGET).hex endif ifneq (,$(filter $(MCU),atmega328p)) + # MCU name for avrdude + AVRDUDE_MCU = m328p + PROTOCOL = VUSB # Processor frequency. diff --git a/quantum/process_keycode/process_magic.c b/quantum/process_keycode/process_magic.c new file mode 100644 index 0000000000..44dd5f0579 --- /dev/null +++ b/quantum/process_keycode/process_magic.c @@ -0,0 +1,178 @@ +/* Copyright 2019 Jack Humbert + * + * 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 "process_magic.h" + +#ifdef AUDIO_ENABLE +# ifndef AG_NORM_SONG +# define AG_NORM_SONG SONG(AG_NORM_SOUND) +# endif +# ifndef AG_SWAP_SONG +# define AG_SWAP_SONG SONG(AG_SWAP_SOUND) +# endif +# ifndef CG_NORM_SONG +# define CG_NORM_SONG SONG(AG_NORM_SOUND) +# endif +# ifndef CG_SWAP_SONG +# define CG_SWAP_SONG SONG(AG_SWAP_SOUND) +# endif +float ag_norm_song[][2] = AG_NORM_SONG; +float ag_swap_song[][2] = AG_SWAP_SONG; +float cg_norm_song[][2] = CG_NORM_SONG; +float cg_swap_song[][2] = CG_SWAP_SONG; +#endif + +/** + * MAGIC actions (BOOTMAGIC without the boot) + */ +bool process_magic(uint16_t keycode, keyrecord_t *record) { + // skip anything that isn't a keyup + if (record->event.pressed) { + switch (keycode) { + case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_ALT_GUI: + case MAGIC_SWAP_LCTL_LGUI ... MAGIC_EE_HANDS_RIGHT: + /* keymap config */ + keymap_config.raw = eeconfig_read_keymap(); + switch (keycode) { + case MAGIC_SWAP_CONTROL_CAPSLOCK: + keymap_config.swap_control_capslock = true; + break; + case MAGIC_CAPSLOCK_TO_CONTROL: + keymap_config.capslock_to_control = true; + break; + case MAGIC_SWAP_LALT_LGUI: + keymap_config.swap_lalt_lgui = true; + break; + case MAGIC_SWAP_RALT_RGUI: + keymap_config.swap_ralt_rgui = true; + break; + case MAGIC_SWAP_LCTL_LGUI: + keymap_config.swap_lctl_lgui = true; + break; + case MAGIC_SWAP_RCTL_RGUI: + keymap_config.swap_rctl_rgui = true; + break; + case MAGIC_NO_GUI: + keymap_config.no_gui = true; + break; + case MAGIC_SWAP_GRAVE_ESC: + keymap_config.swap_grave_esc = true; + break; + case MAGIC_SWAP_BACKSLASH_BACKSPACE: + keymap_config.swap_backslash_backspace = true; + break; + case MAGIC_HOST_NKRO: + clear_keyboard(); // clear first buffer to prevent stuck keys + keymap_config.nkro = true; + break; + case MAGIC_SWAP_ALT_GUI: + keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = true; +#ifdef AUDIO_ENABLE + PLAY_SONG(ag_swap_song); +#endif + break; + case MAGIC_SWAP_CTL_GUI: + keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = true; +#ifdef AUDIO_ENABLE + PLAY_SONG(cg_swap_song); +#endif + break; + case MAGIC_UNSWAP_CONTROL_CAPSLOCK: + keymap_config.swap_control_capslock = false; + break; + case MAGIC_UNCAPSLOCK_TO_CONTROL: + keymap_config.capslock_to_control = false; + break; + case MAGIC_UNSWAP_LALT_LGUI: + keymap_config.swap_lalt_lgui = false; + break; + case MAGIC_UNSWAP_RALT_RGUI: + keymap_config.swap_ralt_rgui = false; + break; + case MAGIC_UNSWAP_LCTL_LGUI: + keymap_config.swap_lctl_lgui = false; + break; + case MAGIC_UNSWAP_RCTL_RGUI: + keymap_config.swap_rctl_rgui = false; + break; + case MAGIC_UNNO_GUI: + keymap_config.no_gui = false; + break; + case MAGIC_UNSWAP_GRAVE_ESC: + keymap_config.swap_grave_esc = false; + break; + case MAGIC_UNSWAP_BACKSLASH_BACKSPACE: + keymap_config.swap_backslash_backspace = false; + break; + case MAGIC_UNHOST_NKRO: + clear_keyboard(); // clear first buffer to prevent stuck keys + keymap_config.nkro = false; + break; + case MAGIC_UNSWAP_ALT_GUI: + keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = false; +#ifdef AUDIO_ENABLE + PLAY_SONG(ag_norm_song); +#endif + break; + case MAGIC_UNSWAP_CTL_GUI: + keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = false; +#ifdef AUDIO_ENABLE + PLAY_SONG(cg_norm_song); +#endif + break; + case MAGIC_TOGGLE_ALT_GUI: + keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui; + keymap_config.swap_ralt_rgui = keymap_config.swap_lalt_lgui; +#ifdef AUDIO_ENABLE + if (keymap_config.swap_ralt_rgui) { + PLAY_SONG(ag_swap_song); + } else { + PLAY_SONG(ag_norm_song); + } +#endif + break; + case MAGIC_TOGGLE_CTL_GUI: + keymap_config.swap_lctl_lgui = !keymap_config.swap_lctl_lgui; + keymap_config.swap_rctl_rgui = keymap_config.swap_lctl_lgui; +#ifdef AUDIO_ENABLE + if (keymap_config.swap_rctl_rgui) { + PLAY_SONG(cg_swap_song); + } else { + PLAY_SONG(cg_norm_song); + } +#endif + break; + case MAGIC_TOGGLE_NKRO: + clear_keyboard(); // clear first buffer to prevent stuck keys + keymap_config.nkro = !keymap_config.nkro; + break; + case MAGIC_EE_HANDS_LEFT: + eeconfig_update_handedness(true); + break; + case MAGIC_EE_HANDS_RIGHT: + eeconfig_update_handedness(false); + break; + } + + eeconfig_update_keymap(keymap_config.raw); + clear_keyboard(); // clear to prevent stuck keys + + return false; + } + } + + // Not a magic keycode so continue processing + return true; +} diff --git a/quantum/process_keycode/process_magic.h b/quantum/process_keycode/process_magic.h new file mode 100644 index 0000000000..1eb39f1455 --- /dev/null +++ b/quantum/process_keycode/process_magic.h @@ -0,0 +1,20 @@ +/* Copyright 2019 + * + * 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" + +bool process_magic(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c new file mode 100644 index 0000000000..c76166342f --- /dev/null +++ b/quantum/process_keycode/process_rgb.c @@ -0,0 +1,141 @@ +/* Copyright 2019 + * + * 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 "process_rgb.h" +#include "rgb.h" + +typedef void (*rgb_func_pointer)(void); + +/** + * Wrapper for inc/dec rgb keycode + * + * noinline to optimise for firmware size not speed (not in hot path) + */ +static void __attribute__((noinline)) handleKeycodeRGB(const uint8_t is_shifted, const rgb_func_pointer inc_func, const rgb_func_pointer dec_func) { + if (is_shifted) { + dec_func(); + } else { + inc_func(); + } +} + +/** + * Wrapper for animation mode + * - if not in animation family -> jump to that animation + * - otherwise -> wrap round animation speed + * + * noinline to optimise for firmware size not speed (not in hot path) + */ +static void __attribute__((noinline,unused)) handleKeycodeRGBMode(const uint8_t start, const uint8_t end) { + if ((start <= rgblight_get_mode()) && (rgblight_get_mode() < end)) { + rgblight_step(); + } else { + rgblight_mode(start); + } +} + +/** + * Handle keycodes for both rgblight and rgbmatrix + */ +bool process_rgb(const uint16_t keycode, const keyrecord_t *record) { +#ifndef SPLIT_KEYBOARD + if (record->event.pressed) { +#else + // Split keyboards need to trigger on key-up for edge-case issue + if (!record->event.pressed) { +#endif + uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)); + switch (keycode) { + case RGB_TOG: + rgblight_toggle(); + return false; + case RGB_MODE_FORWARD: + handleKeycodeRGB(shifted, rgblight_step, rgblight_step_reverse); + return false; + case RGB_MODE_REVERSE: + handleKeycodeRGB(shifted, rgblight_step_reverse, rgblight_step); + return false; + case RGB_HUI: + handleKeycodeRGB(shifted, rgblight_increase_hue, rgblight_decrease_hue); + return false; + case RGB_HUD: + handleKeycodeRGB(shifted, rgblight_decrease_hue, rgblight_increase_hue); + return false; + case RGB_SAI: + handleKeycodeRGB(shifted, rgblight_increase_sat, rgblight_decrease_sat); + return false; + case RGB_SAD: + handleKeycodeRGB(shifted, rgblight_decrease_sat, rgblight_increase_sat); + return false; + case RGB_VAI: + handleKeycodeRGB(shifted, rgblight_increase_val, rgblight_decrease_val); + return false; + case RGB_VAD: + handleKeycodeRGB(shifted, rgblight_decrease_val, rgblight_increase_val); + return false; + case RGB_SPI: + handleKeycodeRGB(shifted, rgblight_increase_speed, rgblight_decrease_speed); + return false; + case RGB_SPD: + handleKeycodeRGB(shifted, rgblight_decrease_speed, rgblight_increase_speed); + return false; + case RGB_MODE_PLAIN: + rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT); + return false; + case RGB_MODE_BREATHE: +#ifdef RGBLIGHT_EFFECT_BREATHING + handleKeycodeRGBMode(RGBLIGHT_MODE_BREATHING, RGBLIGHT_MODE_BREATHING_end); +#endif + return false; + case RGB_MODE_RAINBOW: +#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD + handleKeycodeRGBMode(RGBLIGHT_MODE_RAINBOW_MOOD, RGBLIGHT_MODE_RAINBOW_MOOD_end); +#endif + return false; + case RGB_MODE_SWIRL: +#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL + handleKeycodeRGBMode(RGBLIGHT_MODE_RAINBOW_SWIRL, RGBLIGHT_MODE_RAINBOW_SWIRL_end); +#endif + return false; + case RGB_MODE_SNAKE: +#ifdef RGBLIGHT_EFFECT_SNAKE + handleKeycodeRGBMode(RGBLIGHT_MODE_SNAKE, RGBLIGHT_MODE_SNAKE_end); +#endif + return false; + case RGB_MODE_KNIGHT: +#ifdef RGBLIGHT_EFFECT_KNIGHT + handleKeycodeRGBMode(RGBLIGHT_MODE_KNIGHT, RGBLIGHT_MODE_KNIGHT_end); +#endif + return false; + case RGB_MODE_XMAS: +#ifdef RGBLIGHT_EFFECT_CHRISTMAS + rgblight_mode(RGBLIGHT_MODE_CHRISTMAS); +#endif + return false; + case RGB_MODE_GRADIENT: +#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT + handleKeycodeRGBMode(RGBLIGHT_MODE_STATIC_GRADIENT, RGBLIGHT_MODE_STATIC_GRADIENT_end); +#endif + return false; + case RGB_MODE_RGBTEST: +#ifdef RGBLIGHT_EFFECT_RGB_TEST + rgblight_mode(RGBLIGHT_MODE_RGB_TEST); +#endif + return false; + } + } + + return true; +} diff --git a/quantum/process_keycode/process_rgb.h b/quantum/process_keycode/process_rgb.h new file mode 100644 index 0000000000..26aca46896 --- /dev/null +++ b/quantum/process_keycode/process_rgb.h @@ -0,0 +1,20 @@ +/* Copyright 2019 + * + * 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" + +bool process_rgb(const uint16_t keycode, const keyrecord_t *record); diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c index e0b33ec861..57e279f211 100644 --- a/quantum/process_keycode/process_steno.c +++ b/quantum/process_keycode/process_steno.c @@ -73,7 +73,9 @@ static void steno_clear_state(void) { static void send_steno_state(uint8_t size, bool send_empty) { for (uint8_t i = 0; i < size; ++i) { if (chord[i] || send_empty) { +#ifdef VIRTSER_ENABLE virtser_send(chord[i]); +#endif } } } @@ -105,7 +107,9 @@ static void send_steno_chord(void) { switch (mode) { case STENO_MODE_BOLT: send_steno_state(BOLT_STATE_SIZE, false); +#ifdef VIRTSER_ENABLE virtser_send(0); // terminating byte +#endif break; case STENO_MODE_GEMINI: chord[0] |= 0x80; // Indicate start of packet diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h index 3675423728..ed049eb13f 100644 --- a/quantum/process_keycode/process_steno.h +++ b/quantum/process_keycode/process_steno.h @@ -18,10 +18,6 @@ #include "quantum.h" -#if defined(STENO_ENABLE) && !defined(VIRTSER_ENABLE) -# error "must have virtser enabled to use steno" -#endif - typedef enum { STENO_MODE_BOLT, STENO_MODE_GEMINI } steno_mode_t; bool process_steno(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c index f48f3d702d..7d1eefa9ed 100644 --- a/quantum/process_keycode/process_terminal.c +++ b/quantum/process_keycode/process_terminal.c @@ -61,7 +61,7 @@ void enable_terminal(void) { memset(cmd_buffer, 0, CMD_BUFF_SIZE * 80); for (int i = 0; i < 6; i++) strcpy(arguments[i], ""); // select all text to start over - // SEND_STRING(SS_LCTRL("a")); + // SEND_STRING(SS_LCTL("a")); send_string(terminal_prompt); } diff --git a/quantum/quantum.c b/quantum/quantum.c index 2e5e6376b7..9cd50b11d8 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -16,10 +16,6 @@ #include "quantum.h" -#if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE) -# include "rgb.h" -#endif - #ifdef PROTOCOL_LUFA # include "outputselect.h" #endif @@ -57,26 +53,13 @@ extern backlight_config_t backlight_config; # ifndef GOODBYE_SONG # define GOODBYE_SONG SONG(GOODBYE_SOUND) # endif -# ifndef AG_NORM_SONG -# define AG_NORM_SONG SONG(AG_NORM_SOUND) -# endif -# ifndef AG_SWAP_SONG -# define AG_SWAP_SONG SONG(AG_SWAP_SOUND) -# endif -# ifndef CG_NORM_SONG -# define CG_NORM_SONG SONG(AG_NORM_SOUND) -# endif -# ifndef CG_SWAP_SONG -# define CG_SWAP_SONG SONG(AG_SWAP_SOUND) -# endif float goodbye_song[][2] = GOODBYE_SONG; -float ag_norm_song[][2] = AG_NORM_SONG; -float ag_swap_song[][2] = AG_SWAP_SONG; -float cg_norm_song[][2] = CG_NORM_SONG; -float cg_swap_song[][2] = CG_SWAP_SONG; # ifdef DEFAULT_LAYER_SONGS float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS; # endif +# ifdef SENDSTRING_BELL +float bell_song[][2] = SONG(TERMINAL_SOUND); +# endif #endif static void do_code16(uint16_t code, void (*f)(uint8_t)) { @@ -164,11 +147,6 @@ void reset_keyboard(void) { bootloader_jump(); } -/* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise. - * Used to ensure that the correct keycode is released if the key is released. - */ -static bool grave_esc_was_shifted = false; - /* Convert record into usable keycode via the contained event. */ uint16_t get_record_keycode(keyrecord_t *record) { return get_event_keycode(record->event); } @@ -235,6 +213,9 @@ bool process_record_quantum(keyrecord_t *record) { #if defined(RGB_MATRIX_ENABLE) process_rgb_matrix(keycode, record) && #endif +#if defined(VIA_ENABLE) + process_record_via(keycode, record) && +#endif process_record_kb(keycode, record) && #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) process_midi(keycode, record) && @@ -272,402 +253,77 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef SPACE_CADET_ENABLE process_space_cadet(keycode, record) && #endif +#ifdef MAGIC_KEYCODE_ENABLE + process_magic(keycode, record) && +#endif +#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) + process_rgb(keycode, record) && +#endif true)) { return false; } - // Shift / paren setup - - switch (keycode) { - case RESET: - if (record->event.pressed) { + if (record->event.pressed) { + switch (keycode) { + case RESET: reset_keyboard(); - } - return false; - case DEBUG: - if (record->event.pressed) { + return false; +#ifndef NO_DEBUG + case DEBUG: debug_enable ^= 1; if (debug_enable) { print("DEBUG: enabled.\n"); } else { print("DEBUG: disabled.\n"); } - } - return false; - case EEPROM_RESET: - if (record->event.pressed) { +#endif + return false; + case EEPROM_RESET: eeconfig_init(); - } - return false; + return false; #ifdef FAUXCLICKY_ENABLE - case FC_TOG: - if (record->event.pressed) { + case FC_TOG: FAUXCLICKY_TOGGLE; - } - return false; - case FC_ON: - if (record->event.pressed) { + return false; + case FC_ON: FAUXCLICKY_ON; - } - return false; - case FC_OFF: - if (record->event.pressed) { + return false; + case FC_OFF: FAUXCLICKY_OFF; - } - return false; + return false; #endif -#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) - case RGB_TOG: -// Split keyboards need to trigger on key-up for edge-case issue -# ifndef SPLIT_KEYBOARD - if (record->event.pressed) { -# else - if (!record->event.pressed) { -# endif - rgblight_toggle(); - } - return false; - case RGB_MODE_FORWARD: - if (record->event.pressed) { - uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)); - if (shifted) { - rgblight_step_reverse(); - } else { - rgblight_step(); - } - } - return false; - case RGB_MODE_REVERSE: - if (record->event.pressed) { - uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)); - if (shifted) { - rgblight_step(); - } else { - rgblight_step_reverse(); - } - } - return false; - case RGB_HUI: -// Split keyboards need to trigger on key-up for edge-case issue -# ifndef SPLIT_KEYBOARD - if (record->event.pressed) { -# else - if (!record->event.pressed) { -# endif - rgblight_increase_hue(); - } - return false; - case RGB_HUD: -// Split keyboards need to trigger on key-up for edge-case issue -# ifndef SPLIT_KEYBOARD - if (record->event.pressed) { -# else - if (!record->event.pressed) { -# endif - rgblight_decrease_hue(); - } - return false; - case RGB_SAI: -// Split keyboards need to trigger on key-up for edge-case issue -# ifndef SPLIT_KEYBOARD - if (record->event.pressed) { -# else - if (!record->event.pressed) { -# endif - rgblight_increase_sat(); - } - return false; - case RGB_SAD: -// Split keyboards need to trigger on key-up for edge-case issue -# ifndef SPLIT_KEYBOARD - if (record->event.pressed) { -# else - if (!record->event.pressed) { -# endif - rgblight_decrease_sat(); - } - return false; - case RGB_VAI: -// Split keyboards need to trigger on key-up for edge-case issue -# ifndef SPLIT_KEYBOARD - if (record->event.pressed) { -# else - if (!record->event.pressed) { -# endif - rgblight_increase_val(); - } - return false; - case RGB_VAD: -// Split keyboards need to trigger on key-up for edge-case issue -# ifndef SPLIT_KEYBOARD - if (record->event.pressed) { -# else - if (!record->event.pressed) { -# endif - rgblight_decrease_val(); - } - return false; - case RGB_SPI: - if (record->event.pressed) { - rgblight_increase_speed(); - } - return false; - case RGB_SPD: - if (record->event.pressed) { - rgblight_decrease_speed(); - } - return false; - case RGB_MODE_PLAIN: - if (record->event.pressed) { - rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT); - } - return false; - case RGB_MODE_BREATHE: -# ifdef RGBLIGHT_EFFECT_BREATHING - if (record->event.pressed) { - if ((RGBLIGHT_MODE_BREATHING <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_BREATHING_end)) { - rgblight_step(); - } else { - rgblight_mode(RGBLIGHT_MODE_BREATHING); - } - } -# endif - return false; - case RGB_MODE_RAINBOW: -# ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD - if (record->event.pressed) { - if ((RGBLIGHT_MODE_RAINBOW_MOOD <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_MOOD_end)) { - rgblight_step(); - } else { - rgblight_mode(RGBLIGHT_MODE_RAINBOW_MOOD); - } - } -# endif - return false; - case RGB_MODE_SWIRL: -# ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL - if (record->event.pressed) { - if ((RGBLIGHT_MODE_RAINBOW_SWIRL <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_SWIRL_end)) { - rgblight_step(); - } else { - rgblight_mode(RGBLIGHT_MODE_RAINBOW_SWIRL); - } - } -# endif - return false; - case RGB_MODE_SNAKE: -# ifdef RGBLIGHT_EFFECT_SNAKE - if (record->event.pressed) { - if ((RGBLIGHT_MODE_SNAKE <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_SNAKE_end)) { - rgblight_step(); - } else { - rgblight_mode(RGBLIGHT_MODE_SNAKE); - } - } -# endif - return false; - case RGB_MODE_KNIGHT: -# ifdef RGBLIGHT_EFFECT_KNIGHT - if (record->event.pressed) { - if ((RGBLIGHT_MODE_KNIGHT <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_KNIGHT_end)) { - rgblight_step(); - } else { - rgblight_mode(RGBLIGHT_MODE_KNIGHT); - } - } -# endif - return false; - case RGB_MODE_XMAS: -# ifdef RGBLIGHT_EFFECT_CHRISTMAS - if (record->event.pressed) { - rgblight_mode(RGBLIGHT_MODE_CHRISTMAS); - } -# endif - return false; - case RGB_MODE_GRADIENT: -# ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT - if (record->event.pressed) { - if ((RGBLIGHT_MODE_STATIC_GRADIENT <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_STATIC_GRADIENT_end)) { - rgblight_step(); - } else { - rgblight_mode(RGBLIGHT_MODE_STATIC_GRADIENT); - } - } -# endif - return false; - case RGB_MODE_RGBTEST: -# ifdef RGBLIGHT_EFFECT_RGB_TEST - if (record->event.pressed) { - rgblight_mode(RGBLIGHT_MODE_RGB_TEST); - } -# endif - return false; -#endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) #ifdef VELOCIKEY_ENABLE - case VLK_TOG: - if (record->event.pressed) { + case VLK_TOG: velocikey_toggle(); - } - return false; + return false; #endif -#ifdef PROTOCOL_LUFA - case OUT_AUTO: - if (record->event.pressed) { +#ifdef BLUETOOTH_ENABLE + case OUT_AUTO: set_output(OUTPUT_AUTO); - } - return false; - case OUT_USB: - if (record->event.pressed) { + return false; + case OUT_USB: set_output(OUTPUT_USB); - } - return false; -# ifdef BLUETOOTH_ENABLE - case OUT_BT: - if (record->event.pressed) { + return false; + case OUT_BT: set_output(OUTPUT_BLUETOOTH); - } - return false; -# endif -#endif - case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_ALT_GUI: - case MAGIC_SWAP_LCTL_LGUI ... MAGIC_EE_HANDS_RIGHT: - if (record->event.pressed) { - // MAGIC actions (BOOTMAGIC without the boot) - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } - /* keymap config */ - keymap_config.raw = eeconfig_read_keymap(); - switch (keycode) { - case MAGIC_SWAP_CONTROL_CAPSLOCK: - keymap_config.swap_control_capslock = true; - break; - case MAGIC_CAPSLOCK_TO_CONTROL: - keymap_config.capslock_to_control = true; - break; - case MAGIC_SWAP_LALT_LGUI: - keymap_config.swap_lalt_lgui = true; - break; - case MAGIC_SWAP_RALT_RGUI: - keymap_config.swap_ralt_rgui = true; - break; - case MAGIC_SWAP_LCTL_LGUI: - keymap_config.swap_lctl_lgui = true; - break; - case MAGIC_SWAP_RCTL_RGUI: - keymap_config.swap_rctl_rgui = true; - break; - case MAGIC_NO_GUI: - keymap_config.no_gui = true; - break; - case MAGIC_SWAP_GRAVE_ESC: - keymap_config.swap_grave_esc = true; - break; - case MAGIC_SWAP_BACKSLASH_BACKSPACE: - keymap_config.swap_backslash_backspace = true; - break; - case MAGIC_HOST_NKRO: - clear_keyboard(); // clear first buffer to prevent stuck keys - keymap_config.nkro = true; - break; - case MAGIC_SWAP_ALT_GUI: - keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = true; -#ifdef AUDIO_ENABLE - PLAY_SONG(ag_swap_song); -#endif - break; - case MAGIC_SWAP_CTL_GUI: - keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = true; -#ifdef AUDIO_ENABLE - PLAY_SONG(cg_swap_song); -#endif - break; - case MAGIC_UNSWAP_CONTROL_CAPSLOCK: - keymap_config.swap_control_capslock = false; - break; - case MAGIC_UNCAPSLOCK_TO_CONTROL: - keymap_config.capslock_to_control = false; - break; - case MAGIC_UNSWAP_LALT_LGUI: - keymap_config.swap_lalt_lgui = false; - break; - case MAGIC_UNSWAP_RALT_RGUI: - keymap_config.swap_ralt_rgui = false; - break; - case MAGIC_UNSWAP_LCTL_LGUI: - keymap_config.swap_lctl_lgui = false; - break; - case MAGIC_UNSWAP_RCTL_RGUI: - keymap_config.swap_rctl_rgui = false; - break; - case MAGIC_UNNO_GUI: - keymap_config.no_gui = false; - break; - case MAGIC_UNSWAP_GRAVE_ESC: - keymap_config.swap_grave_esc = false; - break; - case MAGIC_UNSWAP_BACKSLASH_BACKSPACE: - keymap_config.swap_backslash_backspace = false; - break; - case MAGIC_UNHOST_NKRO: - clear_keyboard(); // clear first buffer to prevent stuck keys - keymap_config.nkro = false; - break; - case MAGIC_UNSWAP_ALT_GUI: - keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = false; -#ifdef AUDIO_ENABLE - PLAY_SONG(ag_norm_song); -#endif - break; - case MAGIC_UNSWAP_CTL_GUI: - keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = false; -#ifdef AUDIO_ENABLE - PLAY_SONG(cg_norm_song); + return false; #endif - break; - case MAGIC_TOGGLE_ALT_GUI: - keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui; - keymap_config.swap_ralt_rgui = keymap_config.swap_lalt_lgui; -#ifdef AUDIO_ENABLE - if (keymap_config.swap_ralt_rgui) { - PLAY_SONG(ag_swap_song); - } else { - PLAY_SONG(ag_norm_song); - } -#endif - break; - case MAGIC_TOGGLE_CTL_GUI: - keymap_config.swap_lctl_lgui = !keymap_config.swap_lctl_lgui; - keymap_config.swap_rctl_rgui = keymap_config.swap_lctl_lgui; -#ifdef AUDIO_ENABLE - if (keymap_config.swap_rctl_rgui) { - PLAY_SONG(cg_swap_song); - } else { - PLAY_SONG(cg_norm_song); - } -#endif - break; - case MAGIC_TOGGLE_NKRO: - clear_keyboard(); // clear first buffer to prevent stuck keys - keymap_config.nkro = !keymap_config.nkro; - break; - case MAGIC_EE_HANDS_LEFT: - eeconfig_update_handedness(true); - break; - case MAGIC_EE_HANDS_RIGHT: - eeconfig_update_handedness(false); - break; - default: - break; - } - eeconfig_update_keymap(keymap_config.raw); - clear_keyboard(); // clear to prevent stuck keys - +#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING) + case BL_BRTG: + backlight_toggle_breathing(); return false; - } - break; +#endif + } + } + // keycodes that depend on both pressed and non-pressed state + switch (keycode) { case GRAVE_ESC: { + /* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise. + * Used to ensure that the correct keycode is released if the key is released. + */ + static bool grave_esc_was_shifted = false; + uint8_t shifted = get_mods() & ((MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT) | MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))); #ifdef GRAVE_ESC_ALT_OVERRIDE @@ -710,15 +366,6 @@ bool process_record_quantum(keyrecord_t *record) { send_keyboard_report(); return false; } - -#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING) - case BL_BRTG: { - if (record->event.pressed) { - backlight_toggle_breathing(); - } - return false; - } -#endif } return process_action_kb(record); @@ -829,6 +476,13 @@ void send_string_with_delay_P(const char *str, uint8_t interval) { } void send_char(char ascii_code) { +#if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL) + if (ascii_code == '\a') { // BEL + PLAY_SONG(bell_song); + return; + } +#endif + uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]); bool is_shifted = pgm_read_byte(&ascii_to_shift_lut[(uint8_t)ascii_code]); bool is_altgred = pgm_read_byte(&ascii_to_altgr_lut[(uint8_t)ascii_code]); @@ -909,9 +563,7 @@ __attribute__((weak)) void bootmagic_lite(void) { // We need multiple scans because debouncing can't be turned off. matrix_scan(); -#if defined(DEBOUNCING_DELAY) && DEBOUNCING_DELAY > 0 - wait_ms(DEBOUNCING_DELAY * 2); -#elif defined(DEBOUNCE) && DEBOUNCE > 0 +#if defined(DEBOUNCE) && DEBOUNCE > 0 wait_ms(DEBOUNCE * 2); #else wait_ms(30); @@ -982,12 +634,8 @@ void matrix_scan_quantum() { matrix_scan_combo(); #endif -#if defined(BACKLIGHT_ENABLE) -# if defined(LED_MATRIX_ENABLE) +#ifdef LED_MATRIX_ENABLE led_matrix_task(); -# elif defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS) - backlight_task(); -# endif #endif #ifdef RGB_MATRIX_ENABLE diff --git a/quantum/quantum.h b/quantum/quantum.h index 6beab65a32..09550fec30 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -22,6 +22,7 @@ #endif #if defined(PROTOCOL_CHIBIOS) # include "hal.h" +# include "chibios_config.h" #endif #include "wait.h" @@ -133,6 +134,14 @@ extern layer_state_t layer_state; # include "process_space_cadet.h" #endif +#ifdef MAGIC_KEYCODE_ENABLE +# include "process_magic.h" +#endif + +#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) +# include "process_rgb.h" +#endif + #ifdef HD44780_ENABLE # include "hd44780.h" #endif @@ -153,6 +162,14 @@ extern layer_state_t layer_state; # include "process_dynamic_macro.h" #endif +#ifdef DYNAMIC_KEYMAP_ENABLE +# include "dynamic_keymap.h" +#endif + +#ifdef VIA_ENABLE +# include "via.h" +#endif + // Function substitutions to ease GPIO manipulation #if defined(__AVR__) typedef uint8_t pin_t; @@ -182,30 +199,8 @@ typedef ioline_t pin_t; # define readPin(pin) palReadLine(pin) #endif -// Send string macros -#define STRINGIZE(z) #z -#define ADD_SLASH_X(y) STRINGIZE(\x##y) -#define SYMBOL_STR(x) ADD_SLASH_X(x) - -#define SS_TAP_CODE 1 -#define SS_DOWN_CODE 2 -#define SS_UP_CODE 3 - -#define SS_TAP(keycode) "\1" SYMBOL_STR(keycode) -#define SS_DOWN(keycode) "\2" SYMBOL_STR(keycode) -#define SS_UP(keycode) "\3" SYMBOL_STR(keycode) - -// `string` arguments must not be parenthesized -#define SS_LCTRL(string) SS_DOWN(X_LCTRL) string SS_UP(X_LCTRL) -#define SS_LGUI(string) SS_DOWN(X_LGUI) string SS_UP(X_LGUI) -#define SS_LCMD(string) SS_LGUI(string) -#define SS_LWIN(string) SS_LGUI(string) -#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT) -#define SS_LSFT(string) SS_DOWN(X_LSHIFT) string SS_UP(X_LSHIFT) -#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT) -#define SS_ALGR(string) SS_RALT(string) - #define SEND_STRING(string) send_string_P(PSTR(string)) +#define SEND_STRING_DELAY(string, interval) send_string_with_delay_P(PSTR(string), interval) extern const bool ascii_to_shift_lut[128]; extern const bool ascii_to_altgr_lut[128]; @@ -256,30 +251,6 @@ void register_code16(uint16_t code); void unregister_code16(uint16_t code); void tap_code16(uint16_t code); -#ifdef BACKLIGHT_ENABLE -void backlight_init_ports(void); -void backlight_task(void); -void backlight_task_internal(void); -void backlight_on(pin_t backlight_pin); -void backlight_off(pin_t backlight_pin); - -# ifdef BACKLIGHT_BREATHING -void breathing_task(void); -void breathing_enable(void); -void breathing_pulse(void); -void breathing_disable(void); -void breathing_self_disable(void); -void breathing_toggle(void); -bool is_breathing(void); - -void breathing_intensity_default(void); -void breathing_period_default(void); -void breathing_period_set(uint8_t value); -void breathing_period_inc(void); -void breathing_period_dec(void); -# endif -#endif - void send_dword(uint32_t number); void send_word(uint16_t number); void send_byte(uint8_t number); diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 66a3c66e85..c8d0e354b0 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -655,13 +655,42 @@ enum quantum_keycodes { // L-ayer, T-ap - 256 keycode max, 16 layer max #define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF)) +#define CL_SWAP MAGIC_SWAP_CONTROL_CAPSLOCK +#define CL_NORM MAGIC_UNSWAP_CONTROL_CAPSLOCK +#define CL_CTRL MAGIC_CAPSLOCK_TO_CONTROL +#define CL_CAPS MAGIC_UNCAPSLOCK_TO_CONTROL + +#define LCG_SWP MAGIC_SWAP_LCTL_LGUI +#define LCG_NRM MAGIC_UNSWAP_LCTL_LGUI +#define RCG_SWP MAGIC_SWAP_RCTL_RGUI +#define RCG_NRM MAGIC_UNSWAP_RCTL_RGUI +#define CG_SWAP MAGIC_SWAP_CTL_GUI +#define CG_NORM MAGIC_UNSWAP_CTL_GUI +#define CG_TOGG MAGIC_TOGGLE_CTL_GUI + +#define LAG_SWP MAGIC_SWAP_LALT_LGUI +#define LAG_NRM MAGIC_UNSWAP_LALT_LGUI +#define RAG_SWP MAGIC_SWAP_RALT_RGUI +#define RAG_NRM MAGIC_UNSWAP_RALT_RGUI #define AG_SWAP MAGIC_SWAP_ALT_GUI #define AG_NORM MAGIC_UNSWAP_ALT_GUI #define AG_TOGG MAGIC_TOGGLE_ALT_GUI -#define CG_SWAP MAGIC_SWAP_CTL_GUI -#define CG_NORM MAGIC_UNSWAP_CTL_GUI -#define CG_TOGG MAGIC_TOGGLE_CTL_GUI +#define GUI_OFF MAGIC_NO_GUI +#define GUI_ON MAGIC_UNNO_GUI + +#define GE_SWAP MAGIC_SWAP_GRAVE_ESC +#define GE_NORM MAGIC_UNSWAP_GRAVE_ESC + +#define BS_SWAP MAGIC_SWAP_BACKSLASH_BACKSPACE +#define BS_NORM MAGIC_UNSWAP_BACKSLASH_BACKSPACE + +#define NK_ON MAGIC_HOST_NKRO +#define NK_OFF MAGIC_UNHOST_NKRO +#define NK_TOGG MAGIC_TOGGLE_NKRO + +#define EH_LEFT MAGIC_EE_HANDS_LEFT +#define EH_RGHT MAGIC_EE_HANDS_RIGHT // GOTO layer - 16 layers max // when: diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index 55a6f74be7..25ca44054d 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -95,6 +95,23 @@ const point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; # endif #endif +#if !defined(RGB_MATRIX_STARTUP_HUE) +# define RGB_MATRIX_STARTUP_HUE 0 +#endif + +#if !defined(RGB_MATRIX_STARTUP_SAT) +# define RGB_MATRIX_STARTUP_SAT UINT8_MAX +#endif + +#if !defined(RGB_MATRIX_STARTUP_VAL) +# define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS +#endif + +#if !defined(RGB_MATRIX_STARTUP_SPD) +# define RGB_MATRIX_STARTUP_SPD UINT8_MAX / 2 +#endif + + bool g_suspend_state = false; rgb_config_t rgb_matrix_config; @@ -119,8 +136,8 @@ void eeconfig_update_rgb_matrix_default(void) { dprintf("eeconfig_update_rgb_matrix_default\n"); rgb_matrix_config.enable = 1; rgb_matrix_config.mode = RGB_MATRIX_STARTUP_MODE; - rgb_matrix_config.hsv = (HSV){0, UINT8_MAX, RGB_MATRIX_MAXIMUM_BRIGHTNESS}; - rgb_matrix_config.speed = UINT8_MAX / 2; + rgb_matrix_config.hsv = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL}; + rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD; eeconfig_update_rgb_matrix(); } @@ -417,7 +434,12 @@ void rgb_matrix_init(void) { eeconfig_debug_rgb_matrix(); // display current eeprom values } -void rgb_matrix_set_suspend_state(bool state) { g_suspend_state = state; } +void rgb_matrix_set_suspend_state(bool state) { + if (RGB_DISABLE_WHEN_USB_SUSPENDED && state) { + rgb_matrix_set_color_all(0, 0, 0); // turn off all LEDs when suspending + } + g_suspend_state = state; +} void rgb_matrix_toggle(void) { rgb_matrix_config.enable ^= 1; diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h index 16ec96f036..96494836ee 100644 --- a/quantum/rgb_matrix.h +++ b/quantum/rgb_matrix.h @@ -128,26 +128,26 @@ void rgb_matrix_sethsv(uint16_t hue, uint8_t sat, uint8_t val); void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val); #ifndef RGBLIGHT_ENABLE -# define rgblight_toggle() rgb_matrix_toggle() -# define rgblight_enable() rgb_matrix_enable() -# define rgblight_enable_noeeprom() rgb_matrix_enable_noeeprom() -# define rgblight_disable() rgb_matrix_disable() -# define rgblight_disable_noeeprom() rgb_matrix_disable_noeeprom() -# define rgblight_step() rgb_matrix_step() -# define rgblight_sethsv(hue, sat, val) rgb_matrix_sethsv(hue, sat, val) -# define rgblight_sethsv_noeeprom(hue, sat, val) rgb_matrix_sethsv_noeeprom(hue, sat, val) -# define rgblight_step_reverse() rgb_matrix_step_reverse() -# define rgblight_increase_hue() rgb_matrix_increase_hue() -# define rgblight_decrease_hue() rgb_matrix_decrease_hue() -# define rgblight_increase_sat() rgb_matrix_increase_sat() -# define rgblight_decrease_sat() rgb_matrix_decrease_sat() -# define rgblight_increase_val() rgb_matrix_increase_val() -# define rgblight_decrease_val() rgb_matrix_decrease_val() -# define rgblight_increase_speed() rgb_matrix_increase_speed() -# define rgblight_decrease_speed() rgb_matrix_decrease_speed() -# define rgblight_mode(mode) rgb_matrix_mode(mode) -# define rgblight_mode_noeeprom(mode) rgb_matrix_mode_noeeprom(mode) -# define rgblight_get_mode() rgb_matrix_get_mode() +# define rgblight_toggle rgb_matrix_toggle +# define rgblight_enable rgb_matrix_enable +# define rgblight_enable_noeeprom rgb_matrix_enable_noeeprom +# define rgblight_disable rgb_matrix_disable +# define rgblight_disable_noeeprom rgb_matrix_disable_noeeprom +# define rgblight_step rgb_matrix_step +# define rgblight_sethsv rgb_matrix_sethsv +# define rgblight_sethsv_noeeprom rgb_matrix_sethsv_noeeprom +# define rgblight_step_reverse rgb_matrix_step_reverse +# define rgblight_increase_hue rgb_matrix_increase_hue +# define rgblight_decrease_hue rgb_matrix_decrease_hue +# define rgblight_increase_sat rgb_matrix_increase_sat +# define rgblight_decrease_sat rgb_matrix_decrease_sat +# define rgblight_increase_val rgb_matrix_increase_val +# define rgblight_decrease_val rgb_matrix_decrease_val +# define rgblight_increase_speed rgb_matrix_increase_speed +# define rgblight_decrease_speed rgb_matrix_decrease_speed +# define rgblight_mode rgb_matrix_mode +# define rgblight_mode_noeeprom rgb_matrix_mode_noeeprom +# define rgblight_get_mode rgb_matrix_get_mode #endif typedef struct { diff --git a/quantum/rgb_matrix_animations/gradient_left_right_anim.h b/quantum/rgb_matrix_animations/gradient_left_right_anim.h new file mode 100644 index 0000000000..2eab2eb759 --- /dev/null +++ b/quantum/rgb_matrix_animations/gradient_left_right_anim.h @@ -0,0 +1,22 @@ +#ifndef DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT +RGB_MATRIX_EFFECT(GRADIENT_LEFT_RIGHT) +# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +bool GRADIENT_LEFT_RIGHT(effect_params_t* params) { + RGB_MATRIX_USE_LIMITS(led_min, led_max); + + HSV hsv = rgb_matrix_config.hsv; + uint8_t scale = scale8(64, rgb_matrix_config.speed); + for (uint8_t i = led_min; i < led_max; i++) { + RGB_MATRIX_TEST_LED_FLAGS(); + // The x range will be 0..224, map this to 0..7 + // Relies on hue being 8-bit and wrapping + hsv.h = rgb_matrix_config.hsv.h + (scale * g_led_config.point[i].x >> 5); + RGB rgb = hsv_to_rgb(hsv); + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } + return led_max < DRIVER_LED_TOTAL; +} + +# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT diff --git a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc b/quantum/rgb_matrix_animations/rgb_matrix_effects.inc index 01332ed0dd..4c1723d933 100644 --- a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc +++ b/quantum/rgb_matrix_animations/rgb_matrix_effects.inc @@ -2,6 +2,7 @@ #include "rgb_matrix_animations/solid_color_anim.h" #include "rgb_matrix_animations/alpha_mods_anim.h" #include "rgb_matrix_animations/gradient_up_down_anim.h" +#include "rgb_matrix_animations/gradient_left_right_anim.h" #include "rgb_matrix_animations/breathing_anim.h" #include "rgb_matrix_animations/colorband_sat_anim.h" #include "rgb_matrix_animations/colorband_val_anim.h" diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix_drivers.c index 9729a3064e..ea41b0d396 100644 --- a/quantum/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix_drivers.c @@ -113,7 +113,7 @@ static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) { led[i].g = g; led[i].b = b; # ifdef RGBW - led[i].w = 0; + convert_rgb_to_rgbw(led[i]); # endif } diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 7949bb688e..141dc2e7bc 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -611,6 +611,7 @@ void rgblight_set(void) { # endif } } + # ifdef RGBLIGHT_LED_MAP LED_TYPE led0[RGBLED_NUM]; for (uint8_t i = 0; i < RGBLED_NUM; i++) { @@ -620,7 +621,13 @@ void rgblight_set(void) { # else start_led = led + clipping_start_pos; # endif - ws2812_setleds(start_led, num_leds); + +#ifdef RGBW + for (uint8_t i = 0; i < num_leds; i++) { + convert_rgb_to_rgbw(&start_led[i]); + } +#endif + ws2812_setleds(start_led, num_leds); } #endif diff --git a/quantum/send_string_keycodes.h b/quantum/send_string_keycodes.h index e71790a1dc..fc6467a741 100644 --- a/quantum/send_string_keycodes.h +++ b/quantum/send_string_keycodes.h @@ -1,207 +1,374 @@ -#ifndef SEND_STRING_KEYCODES -#define SEND_STRING_KEYCODES - -#define X_NO 00 -#define X_ROLL_OVER 01 -#define X_POST_FAIL 02 -#define X_UNDEFINED 03 -#define X_A 04 -#define X_B 05 -#define X_C 06 -#define X_D 07 -#define X_E 08 -#define X_F 09 -#define X_G 0a -#define X_H 0b -#define X_I 0c -#define X_J 0d -#define X_K 0e -#define X_L 0f -#define X_M 10 -#define X_N 11 -#define X_O 12 -#define X_P 13 -#define X_Q 14 -#define X_R 15 -#define X_S 16 -#define X_T 17 -#define X_U 18 -#define X_V 19 -#define X_W 1a -#define X_X 1b -#define X_Y 1c -#define X_Z 1d -#define X_1 1e -#define X_2 1f -#define X_3 20 -#define X_4 21 -#define X_5 22 -#define X_6 23 -#define X_7 24 -#define X_8 25 -#define X_9 26 -#define X_0 27 -#define X_ENTER 28 -#define X_ESCAPE 29 -#define X_BSPACE 2a -#define X_TAB 2b -#define X_SPACE 2c -#define X_MINUS 2d -#define X_EQUAL 2e -#define X_LBRACKET 2f -#define X_RBRACKET 30 -#define X_BSLASH 31 -#define X_NONUS_HASH 32 -#define X_SCOLON 33 -#define X_QUOTE 34 -#define X_GRAVE 35 -#define X_COMMA 36 -#define X_DOT 37 -#define X_SLASH 38 -#define X_CAPSLOCK 39 -#define X_F1 3a -#define X_F2 3b -#define X_F3 3c -#define X_F4 3d -#define X_F5 3e -#define X_F6 3f -#define X_F7 40 -#define X_F8 41 -#define X_F9 42 -#define X_F10 43 -#define X_F11 44 -#define X_F12 45 -#define X_PSCREEN 46 -#define X_SCROLLLOCK 47 -#define X_PAUSE 48 -#define X_INSERT 49 -#define X_HOME 4a -#define X_PGUP 4b -#define X_DELETE 4c -#define X_END 4d -#define X_PGDOWN 4e -#define X_RIGHT 4f -#define X_LEFT 50 -#define X_DOWN 51 -#define X_UP 52 -#define X_NUMLOCK 53 -#define X_KP_SLASH 54 -#define X_KP_ASTERISK 55 -#define X_KP_MINUS 56 -#define X_KP_PLUS 57 -#define X_KP_ENTER 58 -#define X_KP_1 59 -#define X_KP_2 5a -#define X_KP_3 5b -#define X_KP_4 5c -#define X_KP_5 5d -#define X_KP_6 5e -#define X_KP_7 5f -#define X_KP_8 60 -#define X_KP_9 61 -#define X_KP_0 62 -#define X_KP_DOT 63 -#define X_NONUS_BSLASH 64 -#define X_APPLICATION 65 -#define X_POWER 66 -#define X_KP_EQUAL 67 -#define X_F13 68 -#define X_F14 69 -#define X_F15 6a -#define X_F16 6b -#define X_F17 6c -#define X_F18 6d -#define X_F19 6e -#define X_F20 6f -#define X_F21 70 -#define X_F22 71 -#define X_F23 72 -#define X_F24 73 -#define X_EXECUTE 74 -#define X_HELP 75 -#define X_MENU 76 -#define X_SELECT 77 -#define X_STOP 78 -#define X_AGAIN 79 -#define X_UNDO 7a -#define X_CUT 7b -#define X_COPY 7c -#define X_PASTE 7d -#define X_FIND 7e -#define X__MUTE 7f -#define X__VOLUP 80 -#define X__VOLDOWN 81 -#define X_LOCKING_CAPS 82 -#define X_LOCKING_NUM 83 -#define X_LOCKING_SCROLL 84 -#define X_KP_COMMA 85 -#define X_KP_EQUAL_AS400 86 -#define X_INT1 87 -#define X_INT2 88 -#define X_INT3 89 -#define X_INT4 8a -#define X_INT5 8b -#define X_INT6 8c -#define X_INT7 8d -#define X_INT8 8e -#define X_INT9 8f -#define X_LANG1 90 -#define X_LANG2 91 -#define X_LANG3 92 -#define X_LANG4 93 -#define X_LANG5 94 -#define X_LANG6 95 -#define X_LANG7 96 -#define X_LANG8 97 -#define X_LANG9 98 -#define X_ALT_ERASE 99 -#define X_SYSREQ 9a -#define X_CANCEL 9b -#define X_CLEAR 9c -#define X_PRIOR 9d -#define X_RETURN 9e -#define X_SEPARATOR 9f -#define X_OUT a0 -#define X_OPER a1 -#define X_CLEAR_AGAIN a2 -#define X_CRSEL a3 -#define X_EXSEL a4 +/* Copyright 2019 + * + * 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 + +// clang-format off + +/* Punctuation */ +#define X_ENT X_ENTER +#define X_ESC X_ESCAPE +#define X_BSPC X_BSPACE +#define X_SPC X_SPACE +#define X_MINS X_MINUS +#define X_EQL X_EQUAL +#define X_LBRC X_LBRACKET +#define X_RBRC X_RBRACKET +#define X_BSLS X_BSLASH +#define X_NUHS X_NONUS_HASH +#define X_SCLN X_SCOLON +#define X_QUOT X_QUOTE +#define X_GRV X_GRAVE +#define X_COMM X_COMMA +#define X_SLSH X_SLASH +#define X_NUBS X_NONUS_BSLASH + +/* Lock Keys */ +#define X_CLCK X_CAPSLOCK +#define X_CAPS X_CAPSLOCK +#define X_SLCK X_SCROLLLOCK +#define X_NLCK X_NUMLOCK +#define X_LCAP X_LOCKING_CAPS +#define X_LNUM X_LOCKING_NUM +#define X_LSCR X_LOCKING_SCROLL + +/* Commands */ +#define X_PSCR X_PSCREEN +#define X_PAUS X_PAUSE +#define X_BRK X_PAUSE +#define X_INS X_INSERT +#define X_DEL X_DELETE +#define X_PGDN X_PGDOWN +#define X_RGHT X_RIGHT +#define X_APP X_APPLICATION +#define X_EXEC X_EXECUTE +#define X_SLCT X_SELECT +#define X_AGIN X_AGAIN +#define X_PSTE X_PASTE +#define X_ERAS X_ALT_ERASE +#define X_CLR X_CLEAR + +/* Keypad */ +#define X_PSLS X_KP_SLASH +#define X_PAST X_KP_ASTERISK +#define X_PMNS X_KP_MINUS +#define X_PPLS X_KP_PLUS +#define X_PENT X_KP_ENTER +#define X_P1 X_KP_1 +#define X_P2 X_KP_2 +#define X_P3 X_KP_3 +#define X_P4 X_KP_4 +#define X_P5 X_KP_5 +#define X_P6 X_KP_6 +#define X_P7 X_KP_7 +#define X_P8 X_KP_8 +#define X_P9 X_KP_9 +#define X_P0 X_KP_0 +#define X_PDOT X_KP_DOT +#define X_PEQL X_KP_EQUAL +#define X_PCMM X_KP_COMMA + +/* Japanese specific */ +#define X_ZKHK X_GRAVE +#define X_RO X_INT1 +#define X_KANA X_INT2 +#define X_JYEN X_INT3 +#define X_HENK X_INT4 +#define X_MHEN X_INT5 + +/* Korean specific */ +#define X_HAEN X_LANG1 +#define X_HANJ X_LANG2 + +/* Modifiers */ +#define X_LCTL X_LCTRL +#define X_LSFT X_LSHIFT +#define X_LCMD X_LGUI +#define X_LWIN X_LGUI +#define X_RCTL X_RCTRL +#define X_RSFT X_RSHIFT +#define X_ALGR X_RALT +#define X_RCMD X_RGUI +#define X_RWIN X_RGUI + +/* Generic Desktop Page (0x01) */ +#define X_PWR X_SYSTEM_POWER +#define X_SLEP X_SYSTEM_SLEEP +#define X_WAKE X_SYSTEM_WAKE + +/* Consumer Page (0x0C) */ +#define X_MUTE X_AUDIO_MUTE +#define X_VOLU X_AUDIO_VOL_UP +#define X_VOLD X_AUDIO_VOL_DOWN +#define X_MNXT X_MEDIA_NEXT_TRACK +#define X_MPRV X_MEDIA_PREV_TRACK +#define X_MSTP X_MEDIA_STOP +#define X_MPLY X_MEDIA_PLAY_PAUSE +#define X_MSEL X_MEDIA_SELECT +#define X_EJCT X_MEDIA_EJECT +#define X_CALC X_CALCULATOR +#define X_MYCM X_MY_COMPUTER +#define X_WSCH X_WWW_SEARCH +#define X_WHOM X_WWW_HOME +#define X_WBAK X_WWW_BACK +#define X_WFWD X_WWW_FORWARD +#define X_WSTP X_WWW_STOP +#define X_WREF X_WWW_REFRESH +#define X_WFAV X_WWW_FAVORITES +#define X_MFFD X_MEDIA_FAST_FORWARD +#define X_MRWD X_MEDIA_REWIND +#define X_BRIU X_BRIGHTNESS_UP +#define X_BRID X_BRIGHTNESS_DOWN + +/* System Specific */ +#define X_BRMU X_PAUSE +#define X_BRMD X_SCROLLLOCK + +/* Keyboard/Keypad Page (0x07) */ +#define X_A 04 +#define X_B 05 +#define X_C 06 +#define X_D 07 +#define X_E 08 +#define X_F 09 +#define X_G 0a +#define X_H 0b +#define X_I 0c +#define X_J 0d +#define X_K 0e +#define X_L 0f +#define X_M 10 +#define X_N 11 +#define X_O 12 +#define X_P 13 +#define X_Q 14 +#define X_R 15 +#define X_S 16 +#define X_T 17 +#define X_U 18 +#define X_V 19 +#define X_W 1a +#define X_X 1b +#define X_Y 1c +#define X_Z 1d +#define X_1 1e +#define X_2 1f +#define X_3 20 +#define X_4 21 +#define X_5 22 +#define X_6 23 +#define X_7 24 +#define X_8 25 +#define X_9 26 +#define X_0 27 +#define X_ENTER 28 +#define X_ESCAPE 29 +#define X_BSPACE 2a +#define X_TAB 2b +#define X_SPACE 2c +#define X_MINUS 2d +#define X_EQUAL 2e +#define X_LBRACKET 2f +#define X_RBRACKET 30 +#define X_BSLASH 31 +#define X_NONUS_HASH 32 +#define X_SCOLON 33 +#define X_QUOTE 34 +#define X_GRAVE 35 +#define X_COMMA 36 +#define X_DOT 37 +#define X_SLASH 38 +#define X_CAPSLOCK 39 +#define X_F1 3a +#define X_F2 3b +#define X_F3 3c +#define X_F4 3d +#define X_F5 3e +#define X_F6 3f +#define X_F7 40 +#define X_F8 41 +#define X_F9 42 +#define X_F10 43 +#define X_F11 44 +#define X_F12 45 +#define X_PSCREEN 46 +#define X_SCROLLLOCK 47 +#define X_PAUSE 48 +#define X_INSERT 49 +#define X_HOME 4a +#define X_PGUP 4b +#define X_DELETE 4c +#define X_END 4d +#define X_PGDOWN 4e +#define X_RIGHT 4f +#define X_LEFT 50 +#define X_DOWN 51 +#define X_UP 52 +#define X_NUMLOCK 53 +#define X_KP_SLASH 54 +#define X_KP_ASTERISK 55 +#define X_KP_MINUS 56 +#define X_KP_PLUS 57 +#define X_KP_ENTER 58 +#define X_KP_1 59 +#define X_KP_2 5a +#define X_KP_3 5b +#define X_KP_4 5c +#define X_KP_5 5d +#define X_KP_6 5e +#define X_KP_7 5f +#define X_KP_8 60 +#define X_KP_9 61 +#define X_KP_0 62 +#define X_KP_DOT 63 +#define X_NONUS_BSLASH 64 +#define X_APPLICATION 65 +#define X_POWER 66 +#define X_KP_EQUAL 67 +#define X_F13 68 +#define X_F14 69 +#define X_F15 6a +#define X_F16 6b +#define X_F17 6c +#define X_F18 6d +#define X_F19 6e +#define X_F20 6f +#define X_F21 70 +#define X_F22 71 +#define X_F23 72 +#define X_F24 73 +#define X_EXECUTE 74 +#define X_HELP 75 +#define X_MENU 76 +#define X_SELECT 77 +#define X_STOP 78 +#define X_AGAIN 79 +#define X_UNDO 7a +#define X_CUT 7b +#define X_COPY 7c +#define X_PASTE 7d +#define X_FIND 7e +#define X__MUTE 7f +#define X__VOLUP 80 +#define X__VOLDOWN 81 +#define X_LOCKING_CAPS 82 +#define X_LOCKING_NUM 83 +#define X_LOCKING_SCROLL 84 +#define X_KP_COMMA 85 +#define X_KP_EQUAL_AS400 86 +#define X_INT1 87 +#define X_INT2 88 +#define X_INT3 89 +#define X_INT4 8a +#define X_INT5 8b +#define X_INT6 8c +#define X_INT7 8d +#define X_INT8 8e +#define X_INT9 8f +#define X_LANG1 90 +#define X_LANG2 91 +#define X_LANG3 92 +#define X_LANG4 93 +#define X_LANG5 94 +#define X_LANG6 95 +#define X_LANG7 96 +#define X_LANG8 97 +#define X_LANG9 98 +#define X_ALT_ERASE 99 +#define X_SYSREQ 9a +#define X_CANCEL 9b +#define X_CLEAR 9c +#define X_PRIOR 9d +#define X_RETURN 9e +#define X_SEPARATOR 9f +#define X_OUT a0 +#define X_OPER a1 +#define X_CLEAR_AGAIN a2 +#define X_CRSEL a3 +#define X_EXSEL a4 /* Modifiers */ -#define X_LCTRL e0 -#define X_LSHIFT e1 -#define X_LALT e2 -#define X_LGUI e3 -#define X_RCTRL e4 -#define X_RSHIFT e5 -#define X_RALT e6 -#define X_RGUI e7 - -/* System Control */ -#define X_SYSTEM_POWER a5 -#define X_SYSTEM_SLEEP a6 -#define X_SYSTEM_WAKE a7 - -/* Media Control */ -#define X_AUDIO_MUTE a8 -#define X_AUDIO_VOL_UP a9 -#define X_AUDIO_VOL_DOWN aa -#define X_MEDIA_NEXT_TRACK ab -#define X_MEDIA_PREV_TRACK ac -#define X_MEDIA_STOP ad -#define X_MEDIA_PLAY_PAUSE ae -#define X_MEDIA_SELECT af -#define X_MEDIA_EJECT b0 -#define X_MAIL b1 -#define X_CALCULATOR b2 -#define X_MY_COMPUTER b3 -#define X_WWW_SEARCH b4 -#define X_WWW_HOME b5 -#define X_WWW_BACK b6 -#define X_WWW_FORWARD b7 -#define X_WWW_STOP b8 -#define X_WWW_REFRESH b9 -#define X_WWW_FAVORITES ba +#define X_LCTRL e0 +#define X_LSHIFT e1 +#define X_LALT e2 +#define X_LGUI e3 +#define X_RCTRL e4 +#define X_RSHIFT e5 +#define X_RALT e6 +#define X_RGUI e7 + +/* Media and Function keys */ +/* Generic Desktop Page (0x01) */ +#define X_SYSTEM_POWER a5 +#define X_SYSTEM_SLEEP a6 +#define X_SYSTEM_WAKE a7 + +/* Consumer Page (0x0C) */ +#define X_AUDIO_MUTE a8 +#define X_AUDIO_VOL_UP a9 +#define X_AUDIO_VOL_DOWN aa +#define X_MEDIA_NEXT_TRACK ab +#define X_MEDIA_PREV_TRACK ac +#define X_MEDIA_STOP ad +#define X_MEDIA_PLAY_PAUSE ae +#define X_MEDIA_SELECT af +#define X_MEDIA_EJECT b0 +#define X_MAIL b1 +#define X_CALCULATOR b2 +#define X_MY_COMPUTER b3 +#define X_WWW_SEARCH b4 +#define X_WWW_HOME b5 +#define X_WWW_BACK b6 +#define X_WWW_FORWARD b7 +#define X_WWW_STOP b8 +#define X_WWW_REFRESH b9 +#define X_WWW_FAVORITES ba #define X_MEDIA_FAST_FORWARD bb -#define X_MEDIA_REWIND bc -#endif +#define X_MEDIA_REWIND bc +#define X_BRIGHTNESS_UP bd +#define X_BRIGHTNESS_DOWN be + +// Send string macros +#define STRINGIZE(z) #z +#define ADD_SLASH_X(y) STRINGIZE(\x##y) +#define SYMBOL_STR(x) ADD_SLASH_X(x) + +#define SS_TAP_CODE 1 +#define SS_DOWN_CODE 2 +#define SS_UP_CODE 3 + +#define SS_TAP(keycode) "\1" SYMBOL_STR(keycode) +#define SS_DOWN(keycode) "\2" SYMBOL_STR(keycode) +#define SS_UP(keycode) "\3" SYMBOL_STR(keycode) + +// `string` arguments must not be parenthesized +#define SS_LCTL(string) SS_DOWN(X_LCTL) string SS_UP(X_LCTL) +#define SS_LSFT(string) SS_DOWN(X_LSFT) string SS_UP(X_LSFT) +#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT) +#define SS_LGUI(string) SS_DOWN(X_LGUI) string SS_UP(X_LGUI) +#define SS_LCMD(string) SS_LGUI(string) +#define SS_LWIN(string) SS_LGUI(string) + +#define SS_RCTL(string) SS_DOWN(X_RCTL) string SS_UP(X_RCTL) +#define SS_RSFT(string) SS_DOWN(X_RSFT) string SS_UP(X_RSFT) +#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT) +#define SS_RGUI(string) SS_DOWN(X_RGUI) string SS_UP(X_RGUI) +#define SS_ALGR(string) SS_RALT(string) +#define SS_RCMD(string) SS_RGUI(string) +#define SS_RWIN(string) SS_RGUI(string) + +// DEPRECATED +#define SS_LCTRL(string) SS_LCTL(string) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 7176d0cc4f..ed1ff5acf3 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -14,10 +14,6 @@ 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 "wait.h" @@ -33,23 +29,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # include "encoder.h" #endif -#if (MATRIX_COLS <= 8) -# define print_matrix_header() print("\nr/c 01234567\n") -# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop(matrix[i]) -# define ROW_SHIFTER ((uint8_t)1) -#elif (MATRIX_COLS <= 16) -# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") -# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop16(matrix[i]) -# define ROW_SHIFTER ((uint16_t)1) -#elif (MATRIX_COLS <= 32) -# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") -# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) -# define matrix_bitpop(i) bitpop32(matrix[i]) -# define ROW_SHIFTER ((uint32_t)1) -#endif - #define ERROR_DISCONNECT_COUNT 5 #define ROWS_PER_HAND (MATRIX_ROWS / 2) @@ -62,58 +41,15 @@ static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; #endif /* matrix state(1:on, 0:off) */ -static matrix_row_t matrix[MATRIX_ROWS]; -static matrix_row_t raw_matrix[ROWS_PER_HAND]; +extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values +extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values // row offsets for each hand uint8_t thisHand, thatHand; // user-defined overridable functions - -__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } - -__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } - -__attribute__((weak)) void matrix_init_user(void) {} - -__attribute__((weak)) void matrix_scan_user(void) {} - __attribute__((weak)) void matrix_slave_scan_user(void) {} -// helper functions - -inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } - -inline uint8_t matrix_cols(void) { return MATRIX_COLS; } - -bool matrix_is_modified(void) { - if (debounce_active()) return false; - return true; -} - -inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } - -inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } - -void matrix_print(void) { - print_matrix_header(); - - for (uint8_t row = 0; row < MATRIX_ROWS; row++) { - phex(row); - print(": "); - print_matrix_row(row); - print("\n"); - } -} - -uint8_t matrix_key_count(void) { - uint8_t count = 0; - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - count += matrix_bitpop(i); - } - return count; -} - // matrix code #ifdef DIRECT_PINS @@ -136,7 +72,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { pin_t pin = direct_pins[current_row][col_index]; if (pin != NO_PIN) { - current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index); + current_matrix[current_row] |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index); } } @@ -179,7 +115,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) // For each col... for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { // Populate the matrix row with the state of the col pin - current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index); + current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (MATRIX_ROW_SHIFTER << col_index); } // Unselect row @@ -225,10 +161,10 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) // Check row pin state if (readPin(row_pins[row_index])) { // Pin HI, clear col bit - current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); + current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col); } else { // Pin LO, set col bit - current_matrix[row_index] |= (ROW_SHIFTER << current_col); + current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col); } // Determine if the matrix changed state @@ -280,7 +216,8 @@ void matrix_init(void) { // initialize matrix state: all keys off for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - matrix[i] = 0; + raw_matrix[i] = 0; + matrix[i] = 0; } debounce_init(ROWS_PER_HAND); @@ -288,29 +225,7 @@ void matrix_init(void) { matrix_init_quantum(); } -uint8_t _matrix_scan(void) { - bool changed = false; - -#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) - // Set row, read cols - for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { - changed |= read_cols_on_row(raw_matrix, current_row); - } -#elif (DIODE_DIRECTION == ROW2COL) - // Set col, read rows - for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { - changed |= read_rows_on_col(raw_matrix, current_col); - } -#endif - - debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); - - return (uint8_t)changed; -} - -uint8_t matrix_scan(void) { - uint8_t ret = _matrix_scan(); - +void matrix_post_scan(void) { if (is_keyboard_master()) { static uint8_t error_count; @@ -335,6 +250,25 @@ uint8_t matrix_scan(void) { #endif matrix_slave_scan_user(); } +} + +uint8_t matrix_scan(void) { + bool changed = false; + +#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) + // Set row, read cols + for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { + changed |= read_cols_on_row(raw_matrix, current_row); + } +#elif (DIODE_DIRECTION == ROW2COL) + // Set col, read rows + for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { + changed |= read_rows_on_col(raw_matrix, current_col); + } +#endif + + debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); - return ret; + matrix_post_scan(); + return (uint8_t)changed; } diff --git a/quantum/split_common/matrix.h b/quantum/split_common/matrix.h deleted file mode 100644 index c2bdd3098c..0000000000 --- a/quantum/split_common/matrix.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include <common/matrix.h> diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h index 5c0b414fb3..4ae1d52732 100644 --- a/quantum/split_common/post_config.h +++ b/quantum/split_common/post_config.h @@ -1,4 +1,4 @@ -#if defined(USE_I2C) || defined(EH) +#if defined(USE_I2C) // When using I2C, using rgblight implicitly involves split support. # if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_SPLIT) # define RGBLIGHT_SPLIT diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 5c548de059..076f186649 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -33,9 +33,11 @@ bool waitForUsb(void) { wait_ms(100); } -#if defined(__AVR__) // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow +#if defined(__AVR__) (USBCON &= ~(_BV(USBE) | _BV(OTGPADE))); +#else + usbStop(&USBD1); #endif return false; @@ -76,7 +78,7 @@ __attribute__((weak)) bool is_keyboard_master(void) { } static void keyboard_master_setup(void) { -#if defined(USE_I2C) || defined(EH) +#if defined(USE_I2C) # ifdef SSD1306OLED matrix_master_OLED_init(); # endif diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 3c783dc568..ab421adc4a 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -21,7 +21,7 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A; # define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) #endif -#if defined(USE_I2C) || defined(EH) +#if defined(USE_I2C) # include "i2c_master.h" # include "i2c_slave.h" diff --git a/quantum/stm32/proton_c.mk b/quantum/stm32/proton_c.mk index ff28a4cb5d..b25b555045 100644 --- a/quantum/stm32/proton_c.mk +++ b/quantum/stm32/proton_c.mk @@ -5,9 +5,7 @@ AUDIO_ENABLE = yes WS2812_DRIVER = bitbang # Force task driven PWM until ARM can provide automatic configuration -ifneq ($(strip $(BACKLIGHT_ENABLE)), no) - BACKLIGHT_ENABLE = software -endif +BACKLIGHT_DRIVER = software # The rest of these settings shouldn't change diff --git a/quantum/template/base/keymaps/default/keymap.c b/quantum/template/base/keymaps/default/keymap.c index 3a68f5487c..af35ccec15 100644 --- a/quantum/template/base/keymaps/default/keymap.c +++ b/quantum/template/base/keymaps/default/keymap.c @@ -52,7 +52,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { case QMKURL: if (record->event.pressed) { // when keycode QMKURL is pressed - SEND_STRING("https://qmk.fm/" SS_TAP(X_ENTER)); + SEND_STRING("https://qmk.fm/\n"); } else { // when keycode QMKURL is released } diff --git a/quantum/via.c b/quantum/via.c new file mode 100644 index 0000000000..64b05324a1 --- /dev/null +++ b/quantum/via.c @@ -0,0 +1,400 @@ +/* Copyright 2019 Jason Williams (Wilba) + * + * 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/>. + */ + +#ifndef RAW_ENABLE +# error "RAW_ENABLE is not enabled" +#endif + +#ifndef DYNAMIC_KEYMAP_ENABLE +# error "DYNAMIC_KEYMAP_ENABLE is not enabled" +#endif + +#include "quantum.h" + +#include "via.h" +#include "raw_hid.h" +#include "dynamic_keymap.h" +#include "tmk_core/common/eeprom.h" +#include "version.h" // for QMK_BUILDDATE used in EEPROM magic + +// Can be called in an overriding via_init_kb() to test if keyboard level code usage of +// EEPROM is invalid and use/save defaults. +bool via_eeprom_is_valid(void) +{ + char *p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54" + uint8_t magic0 = ( ( p[2] & 0x0F ) << 4 ) | ( p[3] & 0x0F ); + uint8_t magic1 = ( ( p[5] & 0x0F ) << 4 ) | ( p[6] & 0x0F ); + uint8_t magic2 = ( ( p[8] & 0x0F ) << 4 ) | ( p[9] & 0x0F ); + + return (eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+0 ) == magic0 && + eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+1 ) == magic1 && + eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+2 ) == magic2 ); +} + +// Sets VIA/keyboard level usage of EEPROM to valid/invalid +// Keyboard level code (eg. via_init_kb()) should not call this +void via_eeprom_set_valid(bool valid) +{ + char *p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54" + uint8_t magic0 = ( ( p[2] & 0x0F ) << 4 ) | ( p[3] & 0x0F ); + uint8_t magic1 = ( ( p[5] & 0x0F ) << 4 ) | ( p[6] & 0x0F ); + uint8_t magic2 = ( ( p[8] & 0x0F ) << 4 ) | ( p[9] & 0x0F ); + + eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+0, valid ? magic0 : 0xFF); + eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+1, valid ? magic1 : 0xFF); + eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+2, valid ? magic2 : 0xFF); +} + +// Flag QMK and VIA/keyboard level EEPROM as invalid. +// Used in bootmagic_lite() and VIA command handler. +// Keyboard level code should not need to call this. +void via_eeprom_reset(void) +{ + // Set the VIA specific EEPROM state as invalid. + via_eeprom_set_valid(false); + // Set the TMK/QMK EEPROM state as invalid. + eeconfig_disable(); +} + +// Override bootmagic_lite() so it can flag EEPROM as invalid +// as well as jump to bootloader, thus performing a "factory reset" +// of dynamic keymaps and optionally backlight/other settings. +void bootmagic_lite(void) +{ + // The lite version of TMK's bootmagic based on Wilba. + // 100% less potential for accidentally making the + // keyboard do stupid things. + + // We need multiple scans because debouncing can't be turned off. + matrix_scan(); +#if defined(DEBOUNCE) && DEBOUNCE > 0 + wait_ms(DEBOUNCE * 2); +#else + wait_ms(30); +#endif + matrix_scan(); + + // If the Esc and space bar are held down on power up, + // reset the EEPROM valid state and jump to bootloader. + // Assumes Esc is at [0,0]. + // This isn't very generalized, but we need something that doesn't + // rely on user's keymaps in firmware or EEPROM. + if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) { + // This is the only difference from the default implementation. + via_eeprom_reset(); + // Jump to bootloader. + bootloader_jump(); + } +} + +// Override this at the keyboard code level to check +// VIA's EEPROM valid state and reset to defaults as needed. +// Used by keyboards that store their own state in EEPROM, +// for backlight, rotary encoders, etc. +// The override should not set via_eeprom_set_valid(true) as +// the caller also needs to check the valid state. +__attribute__((weak)) void via_init_kb(void) { +} + +// Called by QMK core to initialize dynamic keymaps etc. +void via_init(void) +{ + // Let keyboard level test EEPROM valid state, + // but not set it valid, it is done here. + via_init_kb(); + + // If the EEPROM has the magic, the data is good. + // OK to load from EEPROM. + if (via_eeprom_is_valid()) { + } else { + // This resets the layout options + via_set_layout_options(0); + // This resets the keymaps in EEPROM to what is in flash. + dynamic_keymap_reset(); + // This resets the macros in EEPROM to nothing. + dynamic_keymap_macro_reset(); + // Save the magic number last, in case saving was interrupted + via_eeprom_set_valid(true); + } +} + +// This is generalized so the layout options EEPROM usage can be +// variable, between 1 and 4 bytes. +uint32_t via_get_layout_options(void) +{ + uint32_t value = 0; + // Start at the most significant byte + void * source = (void *)(VIA_EEPROM_LAYOUT_OPTIONS_ADDR); + for ( uint8_t i = 0; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE; i++ ) { + value = value << 8; + value |= eeprom_read_byte(source); + source++; + } + return value; +} + +void via_set_layout_options(uint32_t value) +{ + // Start at the least significant byte + void * target = (void *)(VIA_EEPROM_LAYOUT_OPTIONS_ADDR+VIA_EEPROM_LAYOUT_OPTIONS_SIZE-1); + for ( uint8_t i = 0; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE; i++ ) { + eeprom_update_byte(target, value & 0xFF ); + value = value >> 8; + target--; + } +} + +// Called by QMK core to process VIA-specific keycodes. +bool process_record_via(uint16_t keycode, keyrecord_t *record) +{ + // Handle macros + if (record->event.pressed) { + if ( keycode >= MACRO00 && keycode <= MACRO15 ) + { + uint8_t id = keycode - MACRO00; + dynamic_keymap_macro_send(id); + return false; + } + } + + // TODO: ideally this would be generalized and refactored into + // QMK core as advanced keycodes, until then, the simple case + // can be available here to keyboards using VIA + switch(keycode) { + case FN_MO13: + if (record->event.pressed) { + layer_on(1); + update_tri_layer(1, 2, 3); + } else { + layer_off(1); + update_tri_layer(1, 2, 3); + } + return false; + break; + case FN_MO23: + if (record->event.pressed) { + layer_on(2); + update_tri_layer(1, 2, 3); + } else { + layer_off(2); + update_tri_layer(1, 2, 3); + } + return false; + break; + } + return true; +} + +// Keyboard level code can override this to handle custom messages from VIA. +// See raw_hid_receive() implementation. +// DO NOT call raw_hid_send() in the overide function. +__attribute__((weak)) void raw_hid_receive_kb(uint8_t *data, uint8_t length) { + uint8_t *command_id = &(data[0]); + *command_id = id_unhandled; +} + +// VIA handles received HID messages first, and will route to +// raw_hid_receive_kb() for command IDs that are not handled here. +// This gives the keyboard code level the ability to handle the command +// specifically. +// +// raw_hid_send() is called at the end, with the same buffer, which was +// possibly modified with returned values. +void raw_hid_receive( uint8_t *data, uint8_t length ) +{ + uint8_t *command_id = &(data[0]); + uint8_t *command_data = &(data[1]); + switch ( *command_id ) + { + case id_get_protocol_version: + { + command_data[0] = VIA_PROTOCOL_VERSION >> 8; + command_data[1] = VIA_PROTOCOL_VERSION & 0xFF; + break; + } + case id_get_keyboard_value: + { + switch ( command_data[0] ) + { + case id_uptime: + { + uint32_t value = timer_read32(); + command_data[1] = (value >> 24 ) & 0xFF; + command_data[2] = (value >> 16 ) & 0xFF; + command_data[3] = (value >> 8 ) & 0xFF; + command_data[4] = value & 0xFF; + break; + } + case id_layout_options: + { + uint32_t value = via_get_layout_options(); + command_data[1] = (value >> 24 ) & 0xFF; + command_data[2] = (value >> 16 ) & 0xFF; + command_data[3] = (value >> 8 ) & 0xFF; + command_data[4] = value & 0xFF; + break; + } + case id_switch_matrix_state: + { +#if ( (MATRIX_COLS/8+1)*MATRIX_ROWS <= 28 ) + uint8_t i = 1; + for ( uint8_t row=0; row<MATRIX_ROWS; row++ ) { + matrix_row_t value = matrix_get_row(row); +#if (MATRIX_COLS > 24) + command_data[i++] = (value >> 24 ) & 0xFF; +#endif +#if (MATRIX_COLS > 16) + command_data[i++] = (value >> 16 ) & 0xFF; +#endif +#if (MATRIX_COLS > 8) + command_data[i++] = (value >> 8 ) & 0xFF; +#endif + command_data[i++] = value & 0xFF; + } +#endif + break; + } + default: + { + raw_hid_receive_kb(data,length); + break; + } + } + break; + } + case id_set_keyboard_value: + { + switch ( command_data[0] ) + { + case id_layout_options: + { + uint32_t value = ( (uint32_t)command_data[1] << 24 ) | + ( (uint32_t)command_data[2] << 16 ) | + ( (uint32_t)command_data[3] << 8 ) | + (uint32_t)command_data[4]; + via_set_layout_options(value); + break; + } + default: + { + raw_hid_receive_kb(data,length); + break; + } + } + break; + } + case id_dynamic_keymap_get_keycode: + { + uint16_t keycode = dynamic_keymap_get_keycode( command_data[0], command_data[1], command_data[2] ); + command_data[3] = keycode >> 8; + command_data[4] = keycode & 0xFF; + break; + } + case id_dynamic_keymap_set_keycode: + { + dynamic_keymap_set_keycode( command_data[0], command_data[1], command_data[2], ( command_data[3] << 8 ) | command_data[4] ); + break; + } + case id_dynamic_keymap_reset: + { + dynamic_keymap_reset(); + break; + } + case id_backlight_config_set_value: + case id_backlight_config_get_value: + case id_backlight_config_save: + { + raw_hid_receive_kb(data, length); + break; + } + case id_dynamic_keymap_macro_get_count: + { + command_data[0] = dynamic_keymap_macro_get_count(); + break; + } + case id_dynamic_keymap_macro_get_buffer_size: + { + uint16_t size = dynamic_keymap_macro_get_buffer_size(); + command_data[0] = size >> 8; + command_data[1] = size & 0xFF; + break; + } + case id_dynamic_keymap_macro_get_buffer: + { + uint16_t offset = ( command_data[0] << 8 ) | command_data[1]; + uint16_t size = command_data[2]; // size <= 28 + dynamic_keymap_macro_get_buffer( offset, size, &command_data[3] ); + break; + } + case id_dynamic_keymap_macro_set_buffer: + { + uint16_t offset = ( command_data[0] << 8 ) | command_data[1]; + uint16_t size = command_data[2]; // size <= 28 + dynamic_keymap_macro_set_buffer( offset, size, &command_data[3] ); + break; + } + case id_dynamic_keymap_macro_reset: + { + dynamic_keymap_macro_reset(); + break; + } + case id_dynamic_keymap_get_layer_count: + { + command_data[0] = dynamic_keymap_get_layer_count(); + break; + } + case id_dynamic_keymap_get_buffer: + { + uint16_t offset = ( command_data[0] << 8 ) | command_data[1]; + uint16_t size = command_data[2]; // size <= 28 + dynamic_keymap_get_buffer( offset, size, &command_data[3] ); + break; + } + case id_dynamic_keymap_set_buffer: + { + uint16_t offset = ( command_data[0] << 8 ) | command_data[1]; + uint16_t size = command_data[2]; // size <= 28 + dynamic_keymap_set_buffer( offset, size, &command_data[3] ); + break; + } + case id_eeprom_reset: + { + via_eeprom_reset(); + break; + } + case id_bootloader_jump: + { + // Need to send data back before the jump + // Informs host that the command is handled + raw_hid_send( data, length ); + // Give host time to read it + wait_ms(100); + bootloader_jump(); + break; + } + default: + { + // The command ID is not known + // Return the unhandled state + *command_id = id_unhandled; + break; + } + } + + // Return the same buffer, optionally with values changed + // (i.e. returning state to the host, or the unhandled state). + raw_hid_send( data, length ); +} diff --git a/quantum/via.h b/quantum/via.h new file mode 100644 index 0000000000..f9a8017b24 --- /dev/null +++ b/quantum/via.h @@ -0,0 +1,151 @@ +/* Copyright 2019 Jason Williams (Wilba) + * + * 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 <tmk_core/common/eeconfig.h> // for EECONFIG_SIZE + +// Keyboard level code can change where VIA stores the magic. +// The magic is the build date YYMMDD encoded as BCD in 3 bytes, +// thus installing firmware built on a different date to the one +// already installed can be detected and the EEPROM data is reset. +// The only reason this is important is in case EEPROM usage changes +// and the EEPROM was not explicitly reset by bootmagic lite. +#ifndef VIA_EEPROM_MAGIC_ADDR +# define VIA_EEPROM_MAGIC_ADDR (EECONFIG_SIZE) +#endif + +#define VIA_EEPROM_LAYOUT_OPTIONS_ADDR (VIA_EEPROM_MAGIC_ADDR+3) + +// Changing the layout options size after release will invalidate EEPROM, +// but this is something that should be set correctly on initial implementation. +// 1 byte is enough for most uses (i.e. 8 binary states, or 6 binary + 1 ternary/quaternary ) +#ifndef VIA_EEPROM_LAYOUT_OPTIONS_SIZE +# define VIA_EEPROM_LAYOUT_OPTIONS_SIZE 1 +#endif + +// The end of the EEPROM memory used by VIA +// By default, dynamic keymaps will start at this if there is no +// custom config +#define VIA_EEPROM_CUSTOM_CONFIG_ADDR (VIA_EEPROM_LAYOUT_OPTIONS_ADDR+VIA_EEPROM_LAYOUT_OPTIONS_SIZE) + +#ifndef VIA_EEPROM_CUSTOM_CONFIG_SIZE +# define VIA_EEPROM_CUSTOM_CONFIG_SIZE 0 +#endif + +// This is changed only when the command IDs change, +// so VIA Configurator can detect compatible firmware. +#define VIA_PROTOCOL_VERSION 0x0009 + +enum via_command_id +{ + id_get_protocol_version = 0x01, // always 0x01 + id_get_keyboard_value, + id_set_keyboard_value, + id_dynamic_keymap_get_keycode, + id_dynamic_keymap_set_keycode, + id_dynamic_keymap_reset, + id_backlight_config_set_value, + id_backlight_config_get_value, + id_backlight_config_save, + id_eeprom_reset, + id_bootloader_jump, + id_dynamic_keymap_macro_get_count, + id_dynamic_keymap_macro_get_buffer_size, + id_dynamic_keymap_macro_get_buffer, + id_dynamic_keymap_macro_set_buffer, + id_dynamic_keymap_macro_reset, + id_dynamic_keymap_get_layer_count, + id_dynamic_keymap_get_buffer, + id_dynamic_keymap_set_buffer, + id_unhandled = 0xFF, +}; + +enum via_keyboard_value_id +{ + id_uptime = 0x01, + id_layout_options, + id_switch_matrix_state +}; + +// Can't use SAFE_RANGE here, it might change if someone adds +// new values to enum quantum_keycodes. +// Need to keep checking 0x5F10 is still in the safe range. +// TODO: merge this into quantum_keycodes +// Backlight keycodes are in range 0x5F00-0x5F0F +enum via_keycodes { + FN_MO13 = 0x5F10, + FN_MO23, + MACRO00, + MACRO01, + MACRO02, + MACRO03, + MACRO04, + MACRO05, + MACRO06, + MACRO07, + MACRO08, + MACRO09, + MACRO10, + MACRO11, + MACRO12, + MACRO13, + MACRO14, + MACRO15, +}; + +enum user_keycodes { + USER00 = 0x5F80, + USER01, + USER02, + USER03, + USER04, + USER05, + USER06, + USER07, + USER08, + USER09, + USER10, + USER11, + USER12, + USER13, + USER14, + USER15, +}; + +// Can be called in an overriding via_init_kb() to test if keyboard level code usage of +// EEPROM is invalid and use/save defaults. +bool via_eeprom_is_valid(void); + +// Sets VIA/keyboard level usage of EEPROM to valid/invalid +// Keyboard level code (eg. via_init_kb()) should not call this +void via_eeprom_set_valid(bool valid); + +// Flag QMK and VIA/keyboard level EEPROM as invalid. +// Used in bootmagic_lite() and VIA command handler. +// Keyboard level code should not need to call this. +void via_eeprom_reset(void); + +// Called by QMK core to initialize dynamic keymaps etc. +void via_init(void); + +// Used by VIA to store and retrieve the layout options. +uint32_t via_get_layout_options(void); +void via_set_layout_options(uint32_t value); + +// Called by QMK core to process VIA-specific keycodes. +bool process_record_via(uint16_t keycode, keyrecord_t *record); + |