diff options
Diffstat (limited to 'quantum')
192 files changed, 3281 insertions, 8150 deletions
diff --git a/quantum/action.c b/quantum/action.c index 208690f5e4..ceaaa551f5 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "keycode.h" #include "keyboard.h" #include "mousekey.h" +#include "programmable_button.h" #include "command.h" #include "led.h" #include "action_layer.h" @@ -26,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "action_util.h" #include "action.h" #include "wait.h" +#include "keycode_config.h" #ifdef BACKLIGHT_ENABLE # include "backlight.h" @@ -86,19 +88,21 @@ void action_exec(keyevent_t event) { keyrecord_t record = {.event = event}; #ifndef NO_ACTION_ONESHOT + if (!keymap_config.oneshot_disable) { # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - if (has_oneshot_layer_timed_out()) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } - if (has_oneshot_mods_timed_out()) { - clear_oneshot_mods(); - } + if (has_oneshot_layer_timed_out()) { + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + } + if (has_oneshot_mods_timed_out()) { + clear_oneshot_mods(); + } # ifdef SWAP_HANDS_ENABLE - if (has_oneshot_swaphands_timed_out()) { - clear_oneshot_swaphands(); - } + if (has_oneshot_swaphands_timed_out()) { + clear_oneshot_swaphands(); + } # endif # endif + } #endif #ifndef NO_ACTION_TAPPING @@ -194,7 +198,7 @@ void process_record(keyrecord_t *record) { if (!process_record_quantum(record)) { #ifndef NO_ACTION_ONESHOT - if (is_oneshot_layer_active() && record->event.pressed) { + if (is_oneshot_layer_active() && record->event.pressed && !keymap_config.oneshot_disable) { clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); } #endif @@ -259,7 +263,7 @@ void process_action(keyrecord_t *record, action_t action) { # ifdef SWAP_HANDS_ENABLE && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT) # endif - ) { + && !keymap_config.oneshot_disable) { clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); do_release_oneshot = !is_oneshot_layer_active(); } @@ -273,8 +277,8 @@ void process_action(keyrecord_t *record, action_t action) { if (event.pressed) { if (mods) { if (IS_MOD(action.key.code) || action.key.code == KC_NO) { - // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless. - // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT). + // e.g. LSFT(KC_LEFT_GUI): we don't want the LSFT to be weak as it would make it useless. + // This also makes LSFT(KC_LEFT_GUI) behave exactly the same as LGUI(KC_LEFT_SHIFT). // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO). add_mods(mods); } else { @@ -303,41 +307,68 @@ void process_action(keyrecord_t *record, action_t action) { # ifndef NO_ACTION_ONESHOT case MODS_ONESHOT: // Oneshot modifier - if (event.pressed) { - if (tap_count == 0) { - dprint("MODS_TAP: Oneshot: 0\n"); - register_mods(mods | get_oneshot_mods()); - } else if (tap_count == 1) { - dprint("MODS_TAP: Oneshot: start\n"); - set_oneshot_mods(mods | get_oneshot_mods()); -# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - } else if (tap_count == ONESHOT_TAP_TOGGLE) { - dprint("MODS_TAP: Toggling oneshot"); - clear_oneshot_mods(); - set_oneshot_locked_mods(mods); - register_mods(mods); -# endif + if (keymap_config.oneshot_disable) { + if (event.pressed) { + if (mods) { + if (IS_MOD(action.key.code) || action.key.code == KC_NO) { + // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless. + // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT). + // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO). + add_mods(mods); + } else { + add_weak_mods(mods); + } + send_keyboard_report(); + } + register_code(action.key.code); } else { - register_mods(mods | get_oneshot_mods()); + unregister_code(action.key.code); + if (mods) { + if (IS_MOD(action.key.code) || action.key.code == KC_NO) { + del_mods(mods); + } else { + del_weak_mods(mods); + } + send_keyboard_report(); + } } } else { - if (tap_count == 0) { - clear_oneshot_mods(); - unregister_mods(mods); - } else if (tap_count == 1) { - // Retain Oneshot mods + if (event.pressed) { + if (tap_count == 0) { + dprint("MODS_TAP: Oneshot: 0\n"); + register_mods(mods | get_oneshot_mods()); + } else if (tap_count == 1) { + dprint("MODS_TAP: Oneshot: start\n"); + set_oneshot_mods(mods | get_oneshot_mods()); # if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - if (mods & get_mods()) { - clear_oneshot_locked_mods(); + } else if (tap_count == ONESHOT_TAP_TOGGLE) { + dprint("MODS_TAP: Toggling oneshot"); clear_oneshot_mods(); - unregister_mods(mods); - } - } else if (tap_count == ONESHOT_TAP_TOGGLE) { - // Toggle Oneshot Layer + set_oneshot_locked_mods(mods); + register_mods(mods); # endif + } else { + register_mods(mods | get_oneshot_mods()); + } } else { - clear_oneshot_mods(); - unregister_mods(mods); + if (tap_count == 0) { + clear_oneshot_mods(); + unregister_mods(mods); + } else if (tap_count == 1) { + // Retain Oneshot mods +# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 + if (mods & get_mods()) { + clear_oneshot_locked_mods(); + clear_oneshot_mods(); + unregister_mods(mods); + } + } else if (tap_count == ONESHOT_TAP_TOGGLE) { + // Toggle Oneshot Layer +# endif + } else { + clear_oneshot_mods(); + unregister_mods(mods); + } } } break; @@ -379,7 +410,7 @@ void process_action(keyrecord_t *record, action_t action) { } else { if (tap_count > 0) { dprint("MODS_TAP: Tap: unregister_code\n"); - if (action.layer_tap.code == KC_CAPS) { + if (action.layer_tap.code == KC_CAPS_LOCK) { wait_ms(TAP_HOLD_CAPS_DELAY); } else { wait_ms(TAP_CODE_DELAY); @@ -522,39 +553,47 @@ void process_action(keyrecord_t *record, action_t action) { # ifndef NO_ACTION_ONESHOT case OP_ONESHOT: // Oneshot modifier -# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - do_release_oneshot = false; - if (event.pressed) { - del_mods(get_oneshot_locked_mods()); - if (get_oneshot_layer_state() == ONESHOT_TOGGLED) { - reset_oneshot_layer(); - layer_off(action.layer_tap.val); - break; - } else if (tap_count < ONESHOT_TAP_TOGGLE) { + if (keymap_config.oneshot_disable) { + if (event.pressed) { layer_on(action.layer_tap.val); - set_oneshot_layer(action.layer_tap.val, ONESHOT_START); + } else { + layer_off(action.layer_tap.val); } } else { - add_mods(get_oneshot_locked_mods()); - if (tap_count >= ONESHOT_TAP_TOGGLE) { - reset_oneshot_layer(); - clear_oneshot_locked_mods(); - set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED); +# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 + do_release_oneshot = false; + if (event.pressed) { + del_mods(get_oneshot_locked_mods()); + if (get_oneshot_layer_state() == ONESHOT_TOGGLED) { + reset_oneshot_layer(); + layer_off(action.layer_tap.val); + break; + } else if (tap_count < ONESHOT_TAP_TOGGLE) { + layer_on(action.layer_tap.val); + set_oneshot_layer(action.layer_tap.val, ONESHOT_START); + } } else { - clear_oneshot_layer_state(ONESHOT_PRESSED); + add_mods(get_oneshot_locked_mods()); + if (tap_count >= ONESHOT_TAP_TOGGLE) { + reset_oneshot_layer(); + clear_oneshot_locked_mods(); + set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED); + } else { + clear_oneshot_layer_state(ONESHOT_PRESSED); + } } - } # else - if (event.pressed) { - layer_on(action.layer_tap.val); - set_oneshot_layer(action.layer_tap.val, ONESHOT_START); - } else { - clear_oneshot_layer_state(ONESHOT_PRESSED); - if (tap_count > 1) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + if (event.pressed) { + layer_on(action.layer_tap.val); + set_oneshot_layer(action.layer_tap.val, ONESHOT_START); + } else { + clear_oneshot_layer_state(ONESHOT_PRESSED); + if (tap_count > 1) { + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + } } - } # endif + } break; # endif default: @@ -570,7 +609,7 @@ void process_action(keyrecord_t *record, action_t action) { } else { if (tap_count > 0) { dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n"); - if (action.layer_tap.code == KC_CAPS) { + if (action.layer_tap.code == KC_CAPS_LOCK) { wait_ms(TAP_HOLD_CAPS_DELAY); } else { wait_ms(TAP_CODE_DELAY); @@ -747,37 +786,37 @@ void register_code(uint8_t code) { return; } #ifdef LOCKING_SUPPORT_ENABLE - else if (KC_LOCKING_CAPS == code) { + else if (KC_LOCKING_CAPS_LOCK == code) { # ifdef LOCKING_RESYNC_ENABLE // Resync: ignore if caps lock already is on if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) return; # endif - add_key(KC_CAPSLOCK); + add_key(KC_CAPS_LOCK); send_keyboard_report(); wait_ms(100); - del_key(KC_CAPSLOCK); + del_key(KC_CAPS_LOCK); send_keyboard_report(); } - else if (KC_LOCKING_NUM == code) { + else if (KC_LOCKING_NUM_LOCK == code) { # ifdef LOCKING_RESYNC_ENABLE if (host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)) return; # endif - add_key(KC_NUMLOCK); + add_key(KC_NUM_LOCK); send_keyboard_report(); wait_ms(100); - del_key(KC_NUMLOCK); + del_key(KC_NUM_LOCK); send_keyboard_report(); } - else if (KC_LOCKING_SCROLL == code) { + else if (KC_LOCKING_SCROLL_LOCK == code) { # ifdef LOCKING_RESYNC_ENABLE if (host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK)) return; # endif - add_key(KC_SCROLLLOCK); + add_key(KC_SCROLL_LOCK); send_keyboard_report(); wait_ms(100); - del_key(KC_SCROLLLOCK); + del_key(KC_SCROLL_LOCK); send_keyboard_report(); } #endif @@ -843,34 +882,34 @@ void unregister_code(uint8_t code) { return; } #ifdef LOCKING_SUPPORT_ENABLE - else if (KC_LOCKING_CAPS == code) { + else if (KC_LOCKING_CAPS_LOCK == code) { # ifdef LOCKING_RESYNC_ENABLE // Resync: ignore if caps lock already is off if (!(host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK))) return; # endif - add_key(KC_CAPSLOCK); + add_key(KC_CAPS_LOCK); send_keyboard_report(); - del_key(KC_CAPSLOCK); + del_key(KC_CAPS_LOCK); send_keyboard_report(); } - else if (KC_LOCKING_NUM == code) { + else if (KC_LOCKING_NUM_LOCK == code) { # ifdef LOCKING_RESYNC_ENABLE if (!(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK))) return; # endif - add_key(KC_NUMLOCK); + add_key(KC_NUM_LOCK); send_keyboard_report(); - del_key(KC_NUMLOCK); + del_key(KC_NUM_LOCK); send_keyboard_report(); } - else if (KC_LOCKING_SCROLL == code) { + else if (KC_LOCKING_SCROLL_LOCK == code) { # ifdef LOCKING_RESYNC_ENABLE if (!(host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK))) return; # endif - add_key(KC_SCROLLLOCK); + add_key(KC_SCROLL_LOCK); send_keyboard_report(); - del_key(KC_SCROLLLOCK); + del_key(KC_SCROLL_LOCK); send_keyboard_report(); } #endif @@ -913,9 +952,9 @@ void tap_code_delay(uint8_t code, uint16_t delay) { /** \brief Tap a keycode with the default delay. * - * \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined. + * \param code The basic keycode to tap. If `code` is `KC_CAPS_LOCK`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined. */ -void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); } +void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS_LOCK ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); } /** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately. * @@ -995,6 +1034,10 @@ void clear_keyboard_but_mods_and_keys() { mousekey_clear(); mousekey_send(); #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE + programmable_button_clear(); + programmable_button_send(); +#endif } /** \brief Utilities for actions. (FIXME: Needs better description) @@ -1035,7 +1078,7 @@ bool is_tap_action(action_t action) { case ACT_LAYER_TAP: case ACT_LAYER_TAP_EXT: switch (action.layer_tap.code) { - case KC_NO ... KC_RGUI: + case KC_NO ... KC_RIGHT_GUI: case OP_TAP_TOGGLE: case OP_ONESHOT: return true; @@ -1043,7 +1086,7 @@ bool is_tap_action(action_t action) { return false; case ACT_SWAP_HANDS: switch (action.swap.code) { - case KC_NO ... KC_RGUI: + case KC_NO ... KC_RIGHT_GUI: case OP_SH_TAP_TOGGLE: return true; } diff --git a/quantum/action_util.c b/quantum/action_util.c index 9a85bd5040..78e02aec18 100644 --- a/quantum/action_util.c +++ b/quantum/action_util.c @@ -170,7 +170,7 @@ void reset_oneshot_layer(void) { void clear_oneshot_layer_state(oneshot_fullfillment_t state) { uint8_t start_state = oneshot_layer_data; oneshot_layer_data &= ~state; - if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) { + if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) && !keymap_config.oneshot_disable) { layer_off(get_oneshot_layer()); reset_oneshot_layer(); } @@ -189,6 +189,7 @@ void oneshot_set(bool active) { if (keymap_config.oneshot_disable != active) { keymap_config.oneshot_disable = active; eeconfig_update_keymap(keymap_config.raw); + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); dprintf("Oneshot: active: %d\n", active); } } diff --git a/quantum/api.c b/quantum/api.c deleted file mode 100644 index 1685744589..0000000000 --- a/quantum/api.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright 2016 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 "api.h" -#include "quantum.h" - -void dword_to_bytes(uint32_t dword, uint8_t* bytes) { - bytes[0] = (dword >> 24) & 0xFF; - bytes[1] = (dword >> 16) & 0xFF; - bytes[2] = (dword >> 8) & 0xFF; - bytes[3] = (dword >> 0) & 0xFF; -} - -uint32_t bytes_to_dword(uint8_t* bytes, uint8_t index) { return ((uint32_t)bytes[index + 0] << 24) | ((uint32_t)bytes[index + 1] << 16) | ((uint32_t)bytes[index + 2] << 8) | (uint32_t)bytes[index + 3]; } - -__attribute__((weak)) bool process_api_quantum(uint8_t length, uint8_t* data) { return process_api_keyboard(length, data); } - -__attribute__((weak)) bool process_api_keyboard(uint8_t length, uint8_t* data) { return process_api_user(length, data); } - -__attribute__((weak)) bool process_api_user(uint8_t length, uint8_t* data) { return true; } - -void process_api(uint16_t length, uint8_t* data) { - // SEND_STRING("\nRX: "); - // for (uint8_t i = 0; i < length; i++) { - // send_byte(data[i]); - // SEND_STRING(" "); - // } - if (!process_api_quantum(length, data)) return; - - switch (data[0]) { - case MT_SET_DATA: - switch (data[1]) { - case DT_DEFAULT_LAYER: { - eeconfig_update_default_layer(data[2]); - default_layer_set((uint32_t)(data[2])); - break; - } - case DT_KEYMAP_OPTIONS: { - eeconfig_update_keymap(data[2]); - break; - } - case DT_RGBLIGHT: { -#ifdef RGBLIGHT_ENABLE - uint32_t rgblight = bytes_to_dword(data, 2); - eeconfig_update_rgblight(rgblight); -#endif - break; - } - } - case MT_GET_DATA: - switch (data[1]) { - case DT_HANDSHAKE: { - MT_GET_DATA_ACK(DT_HANDSHAKE, NULL, 0); - break; - } - case DT_DEBUG: { - uint8_t debug_bytes[1] = {eeprom_read_byte(EECONFIG_DEBUG)}; - MT_GET_DATA_ACK(DT_DEBUG, debug_bytes, 1); - break; - } - case DT_DEFAULT_LAYER: { - uint8_t default_bytes[1] = {eeprom_read_byte(EECONFIG_DEFAULT_LAYER)}; - MT_GET_DATA_ACK(DT_DEFAULT_LAYER, default_bytes, 1); - break; - } - case DT_CURRENT_LAYER: { - uint8_t layer_state_bytes[4]; - dword_to_bytes(layer_state, layer_state_bytes); - MT_GET_DATA_ACK(DT_CURRENT_LAYER, layer_state_bytes, 4); - break; - } - case DT_AUDIO: { -#ifdef AUDIO_ENABLE - uint8_t audio_bytes[1] = {eeprom_read_byte(EECONFIG_AUDIO)}; - MT_GET_DATA_ACK(DT_AUDIO, audio_bytes, 1); -#else - MT_GET_DATA_ACK(DT_AUDIO, NULL, 0); -#endif - break; - } - case DT_BACKLIGHT: { -#ifdef BACKLIGHT_ENABLE - uint8_t backlight_bytes[1] = {eeprom_read_byte(EECONFIG_BACKLIGHT)}; - MT_GET_DATA_ACK(DT_BACKLIGHT, backlight_bytes, 1); -#else - MT_GET_DATA_ACK(DT_BACKLIGHT, NULL, 0); -#endif - break; - } - case DT_RGBLIGHT: { -#ifdef RGBLIGHT_ENABLE - uint8_t rgblight_bytes[4]; - dword_to_bytes(eeconfig_read_rgblight(), rgblight_bytes); - MT_GET_DATA_ACK(DT_RGBLIGHT, rgblight_bytes, 4); -#else - MT_GET_DATA_ACK(DT_RGBLIGHT, NULL, 0); -#endif - break; - } - case DT_KEYMAP_OPTIONS: { - uint8_t keymap_bytes[1] = {eeconfig_read_keymap()}; - MT_GET_DATA_ACK(DT_KEYMAP_OPTIONS, keymap_bytes, 1); - break; - } - case DT_KEYMAP_SIZE: { - uint8_t keymap_size[2] = {MATRIX_ROWS, MATRIX_COLS}; - MT_GET_DATA_ACK(DT_KEYMAP_SIZE, keymap_size, 2); - break; - } - // This may be too much - // case DT_KEYMAP: { - // uint8_t keymap_data[MATRIX_ROWS * MATRIX_COLS * 4 + 3]; - // keymap_data[0] = data[2]; - // keymap_data[1] = MATRIX_ROWS; - // keymap_data[2] = MATRIX_COLS; - // for (int i = 0; i < MATRIX_ROWS; i++) { - // for (int j = 0; j < MATRIX_COLS; j++) { - // keymap_data[3 + (i*MATRIX_COLS*2) + (j*2)] = pgm_read_word(&keymaps[data[2]][i][j]) >> 8; - // keymap_data[3 + (i*MATRIX_COLS*2) + (j*2) + 1] = pgm_read_word(&keymaps[data[2]][i][j]) & 0xFF; - // } - // } - // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, MATRIX_ROWS * MATRIX_COLS * 4 + 3); - // // uint8_t keymap_data[5]; - // // keymap_data[0] = data[2]; - // // keymap_data[1] = data[3]; - // // keymap_data[2] = data[4]; - // // keymap_data[3] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) >> 8; - // // keymap_data[4] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) & 0xFF; - - // // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, 5); - // break; - // } - default: - break; - } - break; - case MT_SET_DATA_ACK: - case MT_GET_DATA_ACK: - break; - case MT_SEND_DATA: - break; - case MT_SEND_DATA_ACK: - break; - case MT_EXE_ACTION: - break; - case MT_EXE_ACTION_ACK: - break; - case MT_TYPE_ERROR: - break; - default:; // command not recognised - SEND_BYTES(MT_TYPE_ERROR, DT_NONE, data, length); - break; - - // #ifdef RGBLIGHT_ENABLE - // case 0x27: ; // RGB LED functions - // switch (*data++) { - // case 0x00: ; // Update HSV - // rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]); - // break; - // case 0x01: ; // Update RGB - // break; - // case 0x02: ; // Update mode - // rgblight_mode(data[0]); - // break; - // } - // break; - // #endif - } -} diff --git a/quantum/api.h b/quantum/api.h deleted file mode 100644 index 0a30e9d6cc..0000000000 --- a/quantum/api.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2016 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/>. - */ - -#pragma once - -#ifdef __AVR__ -# include "lufa.h" -#endif - -enum MESSAGE_TYPE { - MT_GET_DATA = 0x10, // Get data from keyboard - MT_GET_DATA_ACK = 0x11, // returned data to process (ACK) - MT_SET_DATA = 0x20, // Set data on keyboard - MT_SET_DATA_ACK = 0x21, // returned data to confirm (ACK) - MT_SEND_DATA = 0x30, // Sending data/action from keyboard - MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK) - MT_EXE_ACTION = 0x40, // executing actions on keyboard - MT_EXE_ACTION_ACK = 0x41, // return confirmation/value (ACK) - MT_TYPE_ERROR = 0x80 // type not recognised (ACK) -}; - -enum DATA_TYPE { DT_NONE = 0x00, DT_HANDSHAKE, DT_DEFAULT_LAYER, DT_CURRENT_LAYER, DT_KEYMAP_OPTIONS, DT_BACKLIGHT, DT_RGBLIGHT, DT_UNICODE, DT_DEBUG, DT_AUDIO, DT_QUANTUM_ACTION, DT_KEYBOARD_ACTION, DT_USER_ACTION, DT_KEYMAP_SIZE, DT_KEYMAP }; - -void dword_to_bytes(uint32_t dword, uint8_t* bytes); -uint32_t bytes_to_dword(uint8_t* bytes, uint8_t index); - -#define MT_GET_DATA(data_type, data, length) SEND_BYTES(MT_GET_DATA, data_type, data, length) -#define MT_GET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_GET_DATA_ACK, data_type, data, length) -#define MT_SET_DATA(data_type, data, length) SEND_BYTES(MT_SET_DATA, data_type, data, length) -#define MT_SET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SET_DATA_ACK, data_type, data, length) -#define MT_SEND_DATA(data_type, data, length) SEND_BYTES(MT_SEND_DATA, data_type, data, length) -#define MT_SEND_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SEND_DATA_ACK, data_type, data, length) -#define MT_EXE_ACTION(data_type, data, length) SEND_BYTES(MT_EXE_ACTION, data_type, data, length) -#define MT_EXE_ACTION_ACK(data_type, data, length) SEND_BYTES(MT_EXE_ACTION_ACK, data_type, data, length) - -void process_api(uint16_t length, uint8_t* data); - -__attribute__((weak)) bool process_api_quantum(uint8_t length, uint8_t* data); - -__attribute__((weak)) bool process_api_keyboard(uint8_t length, uint8_t* data); - -__attribute__((weak)) bool process_api_user(uint8_t length, uint8_t* data); diff --git a/quantum/api/api_sysex.c b/quantum/api/api_sysex.c deleted file mode 100644 index 07c90cf804..0000000000 --- a/quantum/api/api_sysex.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright 2016 Jack Humbert, Fred Sundvik - * - * 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 "api_sysex.h" -#include "sysex_tools.h" -#include "print.h" -#include "qmk_midi.h" - -void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t* bytes, uint16_t length) { - // SEND_STRING("\nTX: "); - // for (uint8_t i = 0; i < length; i++) { - // send_byte(bytes[i]); - // SEND_STRING(" "); - // } - if (length > API_SYSEX_MAX_SIZE) { - xprintf("Sysex msg too big %d %d %d", message_type, data_type, length); - return; - } - - // The buffer size required is calculated as the following - // API_SYSEX_MAX_SIZE is the maximum length - // In addition to that we have a two byte message header consisting of the message_type and data_type - // This has to be encoded with an additional overhead of one byte for every starting 7 bytes - // We just add one extra byte in case it's not divisible by 7 - // Then we have an unencoded header consisting of 4 bytes - // Plus a one byte terminator - const unsigned message_header = 2; - const unsigned unencoded_message = API_SYSEX_MAX_SIZE + message_header; - const unsigned encoding_overhead = unencoded_message / 7 + 1; - const unsigned encoded_size = unencoded_message + encoding_overhead; - const unsigned unencoded_header = 4; - const unsigned terminator = 1; - const unsigned buffer_size = encoded_size + unencoded_header + terminator; - uint8_t buffer[encoded_size + unencoded_header + terminator]; - // The unencoded header - buffer[0] = 0xF0; - buffer[1] = 0x00; - buffer[2] = 0x00; - buffer[3] = 0x00; - - // We copy the message to the end of the array, this way we can do an inplace encoding, using the same - // buffer for both input and output - const unsigned message_size = length + message_header; - uint8_t* unencoded_start = buffer + buffer_size - message_size; - uint8_t* ptr = unencoded_start; - *(ptr++) = message_type; - *(ptr++) = data_type; - memcpy(ptr, bytes, length); - - unsigned encoded_length = sysex_encode(buffer + unencoded_header, unencoded_start, message_size); - unsigned final_size = unencoded_header + encoded_length + terminator; - buffer[final_size - 1] = 0xF7; - midi_send_array(&midi_device, final_size, buffer); - - // SEND_STRING("\nTD: "); - // for (uint8_t i = 0; i < encoded_length + 5; i++) { - // send_byte(buffer[i]); - // SEND_STRING(" "); - // } -} diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index 56b9158a1a..290d461f5a 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -26,17 +26,12 @@ #if defined(__AVR__) # include <avr/io.h> -# if defined(AUDIO_DRIVER_PWM) -# include "driver_avr_pwm.h" -# endif #endif -#if defined(PROTOCOL_CHIBIOS) -# if defined(AUDIO_DRIVER_PWM) -# include "driver_chibios_pwm.h" -# elif defined(AUDIO_DRIVER_DAC) -# include "driver_chibios_dac.h" -# endif +#if defined(AUDIO_DRIVER_PWM) +# include "audio_pwm.h" +#elif defined(AUDIO_DRIVER_DAC) +# include "audio_dac.h" #endif typedef union { diff --git a/quantum/audio/driver_avr_pwm.h b/quantum/audio/driver_avr_pwm.h deleted file mode 100644 index d6eb3571da..0000000000 --- a/quantum/audio/driver_avr_pwm.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 diff --git a/quantum/audio/driver_avr_pwm_hardware.c b/quantum/audio/driver_avr_pwm_hardware.c deleted file mode 100644 index df03a4558c..0000000000 --- a/quantum/audio/driver_avr_pwm_hardware.c +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright 2016 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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/>. - */ - -#if defined(__AVR__) -# include <avr/pgmspace.h> -# include <avr/interrupt.h> -# include <avr/io.h> -#endif - -#include "audio.h" - -extern bool playing_note; -extern bool playing_melody; -extern uint8_t note_timbre; - -#define CPU_PRESCALER 8 - -/* - Audio Driver: PWM - - drive up to two speakers through the AVR PWM hardware-peripheral, using timer1 and/or timer3 on Atmega32U4. - - the primary channel_1 can be connected to either pin PC4 PC5 or PC6 (the later being used by most AVR based keyboards) with a PMW signal generated by timer3 - and an optional secondary channel_2 on either pin PB5, PB6 or PB7, with a PWM signal from timer1 - - alternatively, the PWM pins on PORTB can be used as only/primary speaker -*/ - -#if defined(AUDIO_PIN) && (AUDIO_PIN != C4) && (AUDIO_PIN != C5) && (AUDIO_PIN != C6) && (AUDIO_PIN != B5) && (AUDIO_PIN != B6) && (AUDIO_PIN != B7) && (AUDIO_PIN != D5) -# error "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under the AVR settings for available options." -#endif - -#if (AUDIO_PIN == C4) || (AUDIO_PIN == C5) || (AUDIO_PIN == C6) -# define AUDIO1_PIN_SET -# define AUDIO1_TIMSKx TIMSK3 -# define AUDIO1_TCCRxA TCCR3A -# define AUDIO1_TCCRxB TCCR3B -# define AUDIO1_ICRx ICR3 -# define AUDIO1_WGMx0 WGM30 -# define AUDIO1_WGMx1 WGM31 -# define AUDIO1_WGMx2 WGM32 -# define AUDIO1_WGMx3 WGM33 -# define AUDIO1_CSx0 CS30 -# define AUDIO1_CSx1 CS31 -# define AUDIO1_CSx2 CS32 - -# if (AUDIO_PIN == C6) -# define AUDIO1_COMxy0 COM3A0 -# define AUDIO1_COMxy1 COM3A1 -# define AUDIO1_OCIExy OCIE3A -# define AUDIO1_OCRxy OCR3A -# define AUDIO1_PIN C6 -# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPA_vect -# elif (AUDIO_PIN == C5) -# define AUDIO1_COMxy0 COM3B0 -# define AUDIO1_COMxy1 COM3B1 -# define AUDIO1_OCIExy OCIE3B -# define AUDIO1_OCRxy OCR3B -# define AUDIO1_PIN C5 -# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPB_vect -# elif (AUDIO_PIN == C4) -# define AUDIO1_COMxy0 COM3C0 -# define AUDIO1_COMxy1 COM3C1 -# define AUDIO1_OCIExy OCIE3C -# define AUDIO1_OCRxy OCR3C -# define AUDIO1_PIN C4 -# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPC_vect -# endif -#endif - -#if defined(AUDIO_PIN) && defined(AUDIO_PIN_ALT) && (AUDIO_PIN == AUDIO_PIN_ALT) -# error "Audio feature: AUDIO_PIN and AUDIO_PIN_ALT on the same pin makes no sense." -#endif - -#if ((AUDIO_PIN == B5) && ((AUDIO_PIN_ALT == B6) || (AUDIO_PIN_ALT == B7))) || ((AUDIO_PIN == B6) && ((AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B7))) || ((AUDIO_PIN == B7) && ((AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B6))) -# error "Audio feature: PORTB as AUDIO_PIN and AUDIO_PIN_ALT at the same time is not supported." -#endif - -#if defined(AUDIO_PIN_ALT) && (AUDIO_PIN_ALT != B5) && (AUDIO_PIN_ALT != B6) && (AUDIO_PIN_ALT != B7) -# error "Audio feature: the pin selected as AUDIO_PIN_ALT is not supported." -#endif - -#if (AUDIO_PIN == B5) || (AUDIO_PIN == B6) || (AUDIO_PIN == B7) || (AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B6) || (AUDIO_PIN_ALT == B7) || (AUDIO_PIN == D5) -# define AUDIO2_PIN_SET -# define AUDIO2_TIMSKx TIMSK1 -# define AUDIO2_TCCRxA TCCR1A -# define AUDIO2_TCCRxB TCCR1B -# define AUDIO2_ICRx ICR1 -# define AUDIO2_WGMx0 WGM10 -# define AUDIO2_WGMx1 WGM11 -# define AUDIO2_WGMx2 WGM12 -# define AUDIO2_WGMx3 WGM13 -# define AUDIO2_CSx0 CS10 -# define AUDIO2_CSx1 CS11 -# define AUDIO2_CSx2 CS12 - -# if (AUDIO_PIN == B5) || (AUDIO_PIN_ALT == B5) -# define AUDIO2_COMxy0 COM1A0 -# define AUDIO2_COMxy1 COM1A1 -# define AUDIO2_OCIExy OCIE1A -# define AUDIO2_OCRxy OCR1A -# define AUDIO2_PIN B5 -# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPA_vect -# elif (AUDIO_PIN == B6) || (AUDIO_PIN_ALT == B6) -# define AUDIO2_COMxy0 COM1B0 -# define AUDIO2_COMxy1 COM1B1 -# define AUDIO2_OCIExy OCIE1B -# define AUDIO2_OCRxy OCR1B -# define AUDIO2_PIN B6 -# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPB_vect -# elif (AUDIO_PIN == B7) || (AUDIO_PIN_ALT == B7) -# define AUDIO2_COMxy0 COM1C0 -# define AUDIO2_COMxy1 COM1C1 -# define AUDIO2_OCIExy OCIE1C -# define AUDIO2_OCRxy OCR1C -# define AUDIO2_PIN B7 -# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPC_vect -# elif (AUDIO_PIN == D5) && defined(__AVR_ATmega32A__) -# pragma message "Audio support for ATmega32A is experimental and can cause crashes." -# undef AUDIO2_TIMSKx -# define AUDIO2_TIMSKx TIMSK -# define AUDIO2_COMxy0 COM1A0 -# define AUDIO2_COMxy1 COM1A1 -# define AUDIO2_OCIExy OCIE1A -# define AUDIO2_OCRxy OCR1A -# define AUDIO2_PIN D5 -# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPA_vect -# endif -#endif - -// C6 seems to be the assumed default by many existing keyboard - but sill warn the user -#if !defined(AUDIO1_PIN_SET) && !defined(AUDIO2_PIN_SET) -# pragma message "Audio feature enabled, but no suitable pin selected - see docs/feature_audio under the AVR settings for available options. Don't expect to hear anything... :-)" -// TODO: make this an error - go through the breaking-change-process and change all keyboards to the new define -#endif -// ----------------------------------------------------------------------------- - -#ifdef AUDIO1_PIN_SET -static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { - if (freq == 0.0f) // a pause/rest is a valid "note" with freq=0 - { - // disable the output, but keep the pwm-ISR going (with the previous - // frequency) so the audio-state keeps getting updated - // Note: setting the duty-cycle 0 is not possible on non-inverting PWM mode - see the AVR data-sheet - AUDIO1_TCCRxA &= ~(_BV(AUDIO1_COMxy1) | _BV(AUDIO1_COMxy0)); - return; - } else { - AUDIO1_TCCRxA |= _BV(AUDIO1_COMxy1); // enable output, PWM mode - } - - channel_1_frequency = freq; - - // set pwm period - AUDIO1_ICRx = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); - // and duty cycle - AUDIO1_OCRxy = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre / 100); -} - -void channel_1_start(void) { - // enable timer-counter ISR - AUDIO1_TIMSKx |= _BV(AUDIO1_OCIExy); - // enable timer-counter output - AUDIO1_TCCRxA |= _BV(AUDIO1_COMxy1); -} - -void channel_1_stop(void) { - // disable timer-counter ISR - AUDIO1_TIMSKx &= ~_BV(AUDIO1_OCIExy); - // disable timer-counter output - AUDIO1_TCCRxA &= ~(_BV(AUDIO1_COMxy1) | _BV(AUDIO1_COMxy0)); -} -#endif - -#ifdef AUDIO2_PIN_SET -static float channel_2_frequency = 0.0f; -void channel_2_set_frequency(float freq) { - if (freq == 0.0f) { - AUDIO2_TCCRxA &= ~(_BV(AUDIO2_COMxy1) | _BV(AUDIO2_COMxy0)); - return; - } else { - AUDIO2_TCCRxA |= _BV(AUDIO2_COMxy1); - } - - channel_2_frequency = freq; - - AUDIO2_ICRx = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); - AUDIO2_OCRxy = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre / 100); -} - -float channel_2_get_frequency(void) { return channel_2_frequency; } - -void channel_2_start(void) { - AUDIO2_TIMSKx |= _BV(AUDIO2_OCIExy); - AUDIO2_TCCRxA |= _BV(AUDIO2_COMxy1); -} - -void channel_2_stop(void) { - AUDIO2_TIMSKx &= ~_BV(AUDIO2_OCIExy); - AUDIO2_TCCRxA &= ~(_BV(AUDIO2_COMxy1) | _BV(AUDIO2_COMxy0)); -} -#endif - -void audio_driver_initialize() { -#ifdef AUDIO1_PIN_SET - channel_1_stop(); - setPinOutput(AUDIO1_PIN); -#endif - -#ifdef AUDIO2_PIN_SET - channel_2_stop(); - setPinOutput(AUDIO2_PIN); -#endif - - // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers TCCR3A/TCCR3B, TCCR1A/TCCR1B - // Compare Output Mode (COM3An and COM1An) = 0b00 = Normal port operation - // OC3A -- PC6 - // OC3B -- PC5 - // OC3C -- PC4 - // OC1A -- PB5 - // OC1B -- PB6 - // OC1C -- PB7 - - // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14. Period = ICR3, Duty Cycle OCR3A) - // OCR3A - PC6 - // OCR3B - PC5 - // OCR3C - PC4 - // OCR1A - PB5 - // OCR1B - PB6 - // OCR1C - PB7 - - // Clock Select (CS3n) = 0b010 = Clock / 8 -#ifdef AUDIO1_PIN_SET - // initialize timer-counter - AUDIO1_TCCRxA = (0 << AUDIO1_COMxy1) | (0 << AUDIO1_COMxy0) | (1 << AUDIO1_WGMx1) | (0 << AUDIO1_WGMx0); - AUDIO1_TCCRxB = (1 << AUDIO1_WGMx3) | (1 << AUDIO1_WGMx2) | (0 << AUDIO1_CSx2) | (1 << AUDIO1_CSx1) | (0 << AUDIO1_CSx0); -#endif - -#ifdef AUDIO2_PIN_SET - AUDIO2_TCCRxA = (0 << AUDIO2_COMxy1) | (0 << AUDIO2_COMxy0) | (1 << AUDIO2_WGMx1) | (0 << AUDIO2_WGMx0); - AUDIO2_TCCRxB = (1 << AUDIO2_WGMx3) | (1 << AUDIO2_WGMx2) | (0 << AUDIO2_CSx2) | (1 << AUDIO2_CSx1) | (0 << AUDIO2_CSx0); -#endif -} - -void audio_driver_stop() { -#ifdef AUDIO1_PIN_SET - channel_1_stop(); -#endif - -#ifdef AUDIO2_PIN_SET - channel_2_stop(); -#endif -} - -void audio_driver_start(void) { -#ifdef AUDIO1_PIN_SET - channel_1_start(); - if (playing_note) { - channel_1_set_frequency(audio_get_processed_frequency(0)); - } -#endif - -#if !defined(AUDIO1_PIN_SET) && defined(AUDIO2_PIN_SET) - channel_2_start(); - if (playing_note) { - channel_2_set_frequency(audio_get_processed_frequency(0)); - } -#endif -} - -static volatile uint32_t isr_counter = 0; -#ifdef AUDIO1_PIN_SET -ISR(AUDIO1_TIMERx_COMPy_vect) { - isr_counter++; - if (isr_counter < channel_1_frequency / (CPU_PRESCALER * 8)) return; - - isr_counter = 0; - bool state_changed = audio_update_state(); - - if (!playing_note && !playing_melody) { - channel_1_stop(); -# ifdef AUDIO2_PIN_SET - channel_2_stop(); -# endif - return; - } - - if (state_changed) { - channel_1_set_frequency(audio_get_processed_frequency(0)); -# ifdef AUDIO2_PIN_SET - if (audio_get_number_of_active_tones() > 1) { - channel_2_set_frequency(audio_get_processed_frequency(1)); - } else { - channel_2_stop(); - } -# endif - } -} -#endif - -#if !defined(AUDIO1_PIN_SET) && defined(AUDIO2_PIN_SET) -ISR(AUDIO2_TIMERx_COMPy_vect) { - isr_counter++; - if (isr_counter < channel_2_frequency / (CPU_PRESCALER * 8)) return; - - isr_counter = 0; - bool state_changed = audio_update_state(); - - if (!playing_note && !playing_melody) { - channel_2_stop(); - return; - } - - if (state_changed) { - channel_2_set_frequency(audio_get_processed_frequency(0)); - } -} -#endif diff --git a/quantum/audio/driver_chibios_dac.h b/quantum/audio/driver_chibios_dac.h deleted file mode 100644 index 07cd622ead..0000000000 --- a/quantum/audio/driver_chibios_dac.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright 2019 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 - -#ifndef A4 -# define A4 PAL_LINE(GPIOA, 4) -#endif -#ifndef A5 -# define A5 PAL_LINE(GPIOA, 5) -#endif - -/** - * Size of the dac_buffer arrays. All must be the same size. - */ -#define AUDIO_DAC_BUFFER_SIZE 256U - -/** - * Highest value allowed sample value. - - * since the DAC is limited to 12 bit, the absolute max is 0xfff = 4095U; - * lower values adjust the peak-voltage aka volume down. - * adjusting this value has only an effect on a sample-buffer whose values are - * are NOT pregenerated - see square-wave - */ -#ifndef AUDIO_DAC_SAMPLE_MAX -# define AUDIO_DAC_SAMPLE_MAX 4095U -#endif - -#if !defined(AUDIO_DAC_SAMPLE_RATE) && !defined(AUDIO_MAX_SIMULTANEOUS_TONES) && !defined(AUDIO_DAC_QUALITY_VERY_LOW) && !defined(AUDIO_DAC_QUALITY_LOW) && !defined(AUDIO_DAC_QUALITY_HIGH) && !defined(AUDIO_DAC_QUALITY_VERY_HIGH) -# define AUDIO_DAC_QUALITY_SANE_MINIMUM -#endif - -/** - * These presets allow you to quickly switch between quality settings for - * the DAC. The sample rate and maximum number of simultaneous tones roughly - * has an inverse relationship - slightly higher sample rates may be possible. - * - * NOTE: a high sample-rate results in a higher cpu-load, which might lead to - * (audible) discontinuities and/or starve other processes of cpu-time - * (like RGB-led back-lighting, ...) - */ -#ifdef AUDIO_DAC_QUALITY_VERY_LOW -# define AUDIO_DAC_SAMPLE_RATE 11025U -# define AUDIO_MAX_SIMULTANEOUS_TONES 8 -#endif - -#ifdef AUDIO_DAC_QUALITY_LOW -# define AUDIO_DAC_SAMPLE_RATE 22050U -# define AUDIO_MAX_SIMULTANEOUS_TONES 4 -#endif - -#ifdef AUDIO_DAC_QUALITY_HIGH -# define AUDIO_DAC_SAMPLE_RATE 44100U -# define AUDIO_MAX_SIMULTANEOUS_TONES 2 -#endif - -#ifdef AUDIO_DAC_QUALITY_VERY_HIGH -# define AUDIO_DAC_SAMPLE_RATE 88200U -# define AUDIO_MAX_SIMULTANEOUS_TONES 1 -#endif - -#ifdef AUDIO_DAC_QUALITY_SANE_MINIMUM -/* a sane-minimum config: with a trade-off between cpu-load and tone-range - * - * the (currently) highest defined note is NOTE_B8 with 7902Hz; if we now - * aim for an even even multiple of the buffer-size, we end up with: - * ( roundUptoPow2(highest note / AUDIO_DAC_BUFFER_SIZE) * nyquist-rate * AUDIO_DAC_BUFFER_SIZE) - * 7902/256 = 30.867 * 2 * 256 ~= 16384 - * which works out (but the 'scope shows some sampling artifacts with lower harmonics :-P) - */ -# define AUDIO_DAC_SAMPLE_RATE 16384U -# define AUDIO_MAX_SIMULTANEOUS_TONES 8 -#endif - -/** - * Effective bit-rate of the DAC. 44.1khz is the standard for most audio - any - * lower will sacrifice perceptible audio quality. Any higher will limit the - * number of simultaneous tones. In most situations, a tenth (1/10) of the - * sample rate is where notes become unbearable. - */ -#ifndef AUDIO_DAC_SAMPLE_RATE -# define AUDIO_DAC_SAMPLE_RATE 44100U -#endif - -/** - * The number of tones that can be played simultaneously. If too high a value - * is used here, the keyboard will freeze and glitch-out when that many tones - * are being played. - */ -#ifndef AUDIO_MAX_SIMULTANEOUS_TONES -# define AUDIO_MAX_SIMULTANEOUS_TONES 2 -#endif - -/** - * The default value of the DAC when not playing anything. Certain hardware - * setups may require a high (AUDIO_DAC_SAMPLE_MAX) or low (0) value here. - * Since multiple added sine waves tend to oscillate around the midpoint, - * and possibly never/rarely reach either 0 of MAX, 1/2 MAX can be a - * reasonable default value. - */ -#ifndef AUDIO_DAC_OFF_VALUE -# define AUDIO_DAC_OFF_VALUE AUDIO_DAC_SAMPLE_MAX / 2 -#endif - -#if AUDIO_DAC_OFF_VALUE > AUDIO_DAC_SAMPLE_MAX -# error "AUDIO_DAC: OFF_VALUE may not be larger than SAMPLE_MAX" -#endif - -/** - *user overridable sample generation/processing - */ -uint16_t dac_value_generate(void); diff --git a/quantum/audio/driver_chibios_dac_additive.c b/quantum/audio/driver_chibios_dac_additive.c deleted file mode 100644 index db304adb87..0000000000 --- a/quantum/audio/driver_chibios_dac_additive.c +++ /dev/null @@ -1,335 +0,0 @@ -/* Copyright 2016-2019 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 "audio.h" -#include <ch.h> -#include <hal.h> - -/* - Audio Driver: DAC - - which utilizes the dac unit many STM32 are equipped with, to output a modulated waveform from samples stored in the dac_buffer_* array who are passed to the hardware through DMA - - it is also possible to have a custom sample-LUT by implementing/overriding 'dac_value_generate' - - this driver allows for multiple simultaneous tones to be played through one single channel by doing additive wave-synthesis -*/ - -#if !defined(AUDIO_PIN) -# error "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under 'ARM (DAC additive)' for available options." -#endif -#if defined(AUDIO_PIN_ALT) && !defined(AUDIO_PIN_ALT_AS_NEGATIVE) -# pragma message "Audio feature: AUDIO_PIN_ALT set, but not AUDIO_PIN_ALT_AS_NEGATIVE - pin will be left unused; audio might still work though." -#endif - -#if !defined(AUDIO_PIN_ALT) -// no ALT pin defined is valid, but the c-ifs below need some value set -# define AUDIO_PIN_ALT PAL_NOLINE -#endif - -#if !defined(AUDIO_DAC_SAMPLE_WAVEFORM_SINE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID) -# define AUDIO_DAC_SAMPLE_WAVEFORM_SINE -#endif - -#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SINE -/* one full sine wave over [0,2*pi], but shifted up one amplitude and left pi/4; for the samples to start at 0 - */ -static const dacsample_t dac_buffer_sine[AUDIO_DAC_BUFFER_SIZE] = { - // 256 values, max 4095 - 0x0, 0x1, 0x2, 0x6, 0xa, 0xf, 0x16, 0x1e, 0x27, 0x32, 0x3d, 0x4a, 0x58, 0x67, 0x78, 0x89, 0x9c, 0xb0, 0xc5, 0xdb, 0xf2, 0x10a, 0x123, 0x13e, 0x159, 0x175, 0x193, 0x1b1, 0x1d1, 0x1f1, 0x212, 0x235, 0x258, 0x27c, 0x2a0, 0x2c6, 0x2ed, 0x314, 0x33c, 0x365, 0x38e, 0x3b8, 0x3e3, 0x40e, 0x43a, 0x467, 0x494, 0x4c2, 0x4f0, 0x51f, 0x54e, 0x57d, 0x5ad, 0x5dd, 0x60e, 0x63f, 0x670, 0x6a1, 0x6d3, 0x705, 0x737, 0x769, 0x79b, 0x7cd, 0x800, 0x832, 0x864, 0x896, 0x8c8, 0x8fa, 0x92c, 0x95e, 0x98f, 0x9c0, 0x9f1, 0xa22, 0xa52, 0xa82, 0xab1, 0xae0, 0xb0f, 0xb3d, 0xb6b, 0xb98, 0xbc5, 0xbf1, 0xc1c, 0xc47, 0xc71, 0xc9a, 0xcc3, 0xceb, 0xd12, 0xd39, 0xd5f, 0xd83, 0xda7, 0xdca, 0xded, 0xe0e, 0xe2e, 0xe4e, 0xe6c, 0xe8a, 0xea6, 0xec1, 0xedc, 0xef5, 0xf0d, 0xf24, 0xf3a, 0xf4f, 0xf63, 0xf76, 0xf87, 0xf98, 0xfa7, 0xfb5, 0xfc2, 0xfcd, 0xfd8, 0xfe1, 0xfe9, 0xff0, 0xff5, 0xff9, 0xffd, 0xffe, - 0xfff, 0xffe, 0xffd, 0xff9, 0xff5, 0xff0, 0xfe9, 0xfe1, 0xfd8, 0xfcd, 0xfc2, 0xfb5, 0xfa7, 0xf98, 0xf87, 0xf76, 0xf63, 0xf4f, 0xf3a, 0xf24, 0xf0d, 0xef5, 0xedc, 0xec1, 0xea6, 0xe8a, 0xe6c, 0xe4e, 0xe2e, 0xe0e, 0xded, 0xdca, 0xda7, 0xd83, 0xd5f, 0xd39, 0xd12, 0xceb, 0xcc3, 0xc9a, 0xc71, 0xc47, 0xc1c, 0xbf1, 0xbc5, 0xb98, 0xb6b, 0xb3d, 0xb0f, 0xae0, 0xab1, 0xa82, 0xa52, 0xa22, 0x9f1, 0x9c0, 0x98f, 0x95e, 0x92c, 0x8fa, 0x8c8, 0x896, 0x864, 0x832, 0x800, 0x7cd, 0x79b, 0x769, 0x737, 0x705, 0x6d3, 0x6a1, 0x670, 0x63f, 0x60e, 0x5dd, 0x5ad, 0x57d, 0x54e, 0x51f, 0x4f0, 0x4c2, 0x494, 0x467, 0x43a, 0x40e, 0x3e3, 0x3b8, 0x38e, 0x365, 0x33c, 0x314, 0x2ed, 0x2c6, 0x2a0, 0x27c, 0x258, 0x235, 0x212, 0x1f1, 0x1d1, 0x1b1, 0x193, 0x175, 0x159, 0x13e, 0x123, 0x10a, 0xf2, 0xdb, 0xc5, 0xb0, 0x9c, 0x89, 0x78, 0x67, 0x58, 0x4a, 0x3d, 0x32, 0x27, 0x1e, 0x16, 0xf, 0xa, 0x6, 0x2, 0x1}; -#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SINE -#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE -static const dacsample_t dac_buffer_triangle[AUDIO_DAC_BUFFER_SIZE] = { - // 256 values, max 4095 - 0x0, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4a0, 0x4c0, 0x4e0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5a0, 0x5c0, 0x5e0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6a0, 0x6c0, 0x6e0, 0x700, 0x720, 0x740, 0x760, 0x780, 0x7a0, 0x7c0, 0x7e0, 0x800, 0x81f, 0x83f, 0x85f, 0x87f, 0x89f, 0x8bf, 0x8df, 0x8ff, 0x91f, 0x93f, 0x95f, 0x97f, 0x99f, 0x9bf, 0x9df, 0x9ff, 0xa1f, 0xa3f, 0xa5f, 0xa7f, 0xa9f, 0xabf, 0xadf, 0xaff, 0xb1f, 0xb3f, 0xb5f, 0xb7f, 0xb9f, 0xbbf, 0xbdf, 0xbff, 0xc1f, 0xc3f, 0xc5f, 0xc7f, 0xc9f, 0xcbf, 0xcdf, 0xcff, 0xd1f, 0xd3f, 0xd5f, 0xd7f, 0xd9f, 0xdbf, 0xddf, 0xdff, 0xe1f, 0xe3f, 0xe5f, 0xe7f, 0xe9f, 0xebf, 0xedf, 0xeff, 0xf1f, 0xf3f, 0xf5f, 0xf7f, 0xf9f, 0xfbf, 0xfdf, - 0xfff, 0xfdf, 0xfbf, 0xf9f, 0xf7f, 0xf5f, 0xf3f, 0xf1f, 0xeff, 0xedf, 0xebf, 0xe9f, 0xe7f, 0xe5f, 0xe3f, 0xe1f, 0xdff, 0xddf, 0xdbf, 0xd9f, 0xd7f, 0xd5f, 0xd3f, 0xd1f, 0xcff, 0xcdf, 0xcbf, 0xc9f, 0xc7f, 0xc5f, 0xc3f, 0xc1f, 0xbff, 0xbdf, 0xbbf, 0xb9f, 0xb7f, 0xb5f, 0xb3f, 0xb1f, 0xaff, 0xadf, 0xabf, 0xa9f, 0xa7f, 0xa5f, 0xa3f, 0xa1f, 0x9ff, 0x9df, 0x9bf, 0x99f, 0x97f, 0x95f, 0x93f, 0x91f, 0x8ff, 0x8df, 0x8bf, 0x89f, 0x87f, 0x85f, 0x83f, 0x81f, 0x800, 0x7e0, 0x7c0, 0x7a0, 0x780, 0x760, 0x740, 0x720, 0x700, 0x6e0, 0x6c0, 0x6a0, 0x680, 0x660, 0x640, 0x620, 0x600, 0x5e0, 0x5c0, 0x5a0, 0x580, 0x560, 0x540, 0x520, 0x500, 0x4e0, 0x4c0, 0x4a0, 0x480, 0x460, 0x440, 0x420, 0x400, 0x3e0, 0x3c0, 0x3a0, 0x380, 0x360, 0x340, 0x320, 0x300, 0x2e0, 0x2c0, 0x2a0, 0x280, 0x260, 0x240, 0x220, 0x200, 0x1e0, 0x1c0, 0x1a0, 0x180, 0x160, 0x140, 0x120, 0x100, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20}; -#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE -#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE -static const dacsample_t dac_buffer_square[AUDIO_DAC_BUFFER_SIZE] = { - [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = 0, // first and - [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, // second half -}; -#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE -/* -// four steps: 0, 1/3, 2/3 and 1 -static const dacsample_t dac_buffer_staircase[AUDIO_DAC_BUFFER_SIZE] = { - [0 ... AUDIO_DAC_BUFFER_SIZE/3 -1 ] = 0, - [AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE / 2 -1 ] = AUDIO_DAC_SAMPLE_MAX / 3, - [AUDIO_DAC_BUFFER_SIZE / 2 ... 3 * AUDIO_DAC_BUFFER_SIZE / 4 -1 ] = 2 * AUDIO_DAC_SAMPLE_MAX / 3, - [3 * AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE -1 ] = AUDIO_DAC_SAMPLE_MAX, -} -*/ -#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID -static const dacsample_t dac_buffer_trapezoid[AUDIO_DAC_BUFFER_SIZE] = {0x0, 0x1f, 0x7f, 0xdf, 0x13f, 0x19f, 0x1ff, 0x25f, 0x2bf, 0x31f, 0x37f, 0x3df, 0x43f, 0x49f, 0x4ff, 0x55f, 0x5bf, 0x61f, 0x67f, 0x6df, 0x73f, 0x79f, 0x7ff, 0x85f, 0x8bf, 0x91f, 0x97f, 0x9df, 0xa3f, 0xa9f, 0xaff, 0xb5f, 0xbbf, 0xc1f, 0xc7f, 0xcdf, 0xd3f, 0xd9f, 0xdff, 0xe5f, 0xebf, 0xf1f, 0xf7f, 0xfdf, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, - 0xfff, 0xfdf, 0xf7f, 0xf1f, 0xebf, 0xe5f, 0xdff, 0xd9f, 0xd3f, 0xcdf, 0xc7f, 0xc1f, 0xbbf, 0xb5f, 0xaff, 0xa9f, 0xa3f, 0x9df, 0x97f, 0x91f, 0x8bf, 0x85f, 0x7ff, 0x79f, 0x73f, 0x6df, 0x67f, 0x61f, 0x5bf, 0x55f, 0x4ff, 0x49f, 0x43f, 0x3df, 0x37f, 0x31f, 0x2bf, 0x25f, 0x1ff, 0x19f, 0x13f, 0xdf, 0x7f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; -#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID - -static dacsample_t dac_buffer_empty[AUDIO_DAC_BUFFER_SIZE] = {AUDIO_DAC_OFF_VALUE}; - -/* keep track of the sample position for for each frequency */ -static float dac_if[AUDIO_MAX_SIMULTANEOUS_TONES] = {0.0}; - -static float active_tones_snapshot[AUDIO_MAX_SIMULTANEOUS_TONES] = {0, 0}; -static uint8_t active_tones_snapshot_length = 0; - -typedef enum { - OUTPUT_SHOULD_START, - OUTPUT_RUN_NORMALLY, - // path 1: wait for zero, then change/update active tones - OUTPUT_TONES_CHANGED, - OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE, - // path 2: hardware should stop, wait for zero then turn output off = stop the timer - OUTPUT_SHOULD_STOP, - OUTPUT_REACHED_ZERO_BEFORE_OFF, - OUTPUT_OFF, - OUTPUT_OFF_1, - OUTPUT_OFF_2, // trailing off: giving the DAC two more conversion cycles until the AUDIO_DAC_OFF_VALUE reaches the output, then turn the timer off, which leaves the output at that level - number_of_output_states -} output_states_t; -output_states_t state = OUTPUT_OFF_2; - -/** - * Generation of the waveform being passed to the callback. Declared weak so users - * can override it with their own wave-forms/noises. - */ -__attribute__((weak)) uint16_t dac_value_generate(void) { - // DAC is running/asking for values but snapshot length is zero -> must be playing a pause - if (active_tones_snapshot_length == 0) { - return AUDIO_DAC_OFF_VALUE; - } - - /* doing additive wave synthesis over all currently playing tones = adding up - * sine-wave-samples for each frequency, scaled by the number of active tones - */ - uint16_t value = 0; - float frequency = 0.0f; - - for (uint8_t i = 0; i < active_tones_snapshot_length; i++) { - /* Note: a user implementation does not have to rely on the active_tones_snapshot, but - * could directly query the active frequencies through audio_get_processed_frequency */ - frequency = active_tones_snapshot[i]; - - dac_if[i] = dac_if[i] + ((frequency * AUDIO_DAC_BUFFER_SIZE) / AUDIO_DAC_SAMPLE_RATE) * 2 / 3; - /*Note: the 2/3 are necessary to get the correct frequencies on the - * DAC output (as measured with an oscilloscope), since the gpt - * timer runs with 3*AUDIO_DAC_SAMPLE_RATE; and the DAC callback - * is called twice per conversion.*/ - - dac_if[i] = fmod(dac_if[i], AUDIO_DAC_BUFFER_SIZE); - - // Wavetable generation/lookup - uint16_t dac_i = (uint16_t)dac_if[i]; - -#if defined(AUDIO_DAC_SAMPLE_WAVEFORM_SINE) - value += dac_buffer_sine[dac_i] / active_tones_snapshot_length; -#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE) - value += dac_buffer_triangle[dac_i] / active_tones_snapshot_length; -#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID) - value += dac_buffer_trapezoid[dac_i] / active_tones_snapshot_length; -#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE) - value += dac_buffer_square[dac_i] / active_tones_snapshot_length; -#endif - /* - // SINE - value += dac_buffer_sine[dac_i] / active_tones_snapshot_length / 3; - // TRIANGLE - value += dac_buffer_triangle[dac_i] / active_tones_snapshot_length / 3; - // SQUARE - value += dac_buffer_square[dac_i] / active_tones_snapshot_length / 3; - //NOTE: combination of these three wave-forms is more exemplary - and doesn't sound particularly good :-P - */ - - // STAIRS (mostly usefully as test-pattern) - // value_avg = dac_buffer_staircase[dac_i] / active_tones_snapshot_length; - } - - return value; -} - -/** - * DAC streaming callback. Does all of the main computing for playing songs. - * - * Note: chibios calls this CB twice: during the 'half buffer event', and the 'full buffer event'. - */ -static void dac_end(DACDriver *dacp) { - dacsample_t *sample_p = (dacp)->samples; - - // work on the other half of the buffer - if (dacIsBufferComplete(dacp)) { - sample_p += AUDIO_DAC_BUFFER_SIZE / 2; // 'half_index' - } - - for (uint8_t s = 0; s < AUDIO_DAC_BUFFER_SIZE / 2; s++) { - if (OUTPUT_OFF <= state) { - sample_p[s] = AUDIO_DAC_OFF_VALUE; - continue; - } else { - sample_p[s] = dac_value_generate(); - } - - /* zero crossing (or approach, whereas zero == DAC_OFF_VALUE, which can be configured to anything from 0 to DAC_SAMPLE_MAX) - * ============================*=*========================== AUDIO_DAC_SAMPLE_MAX - * * * - * * * - * --------------------------------------------------------- - * * * } AUDIO_DAC_SAMPLE_MAX/100 - * --------------------------------------------------------- AUDIO_DAC_OFF_VALUE - * * * } AUDIO_DAC_SAMPLE_MAX/100 - * --------------------------------------------------------- - * * - * * * - * * * - * =====*=*================================================= 0x0 - */ - if (((sample_p[s] + (AUDIO_DAC_SAMPLE_MAX / 100)) > AUDIO_DAC_OFF_VALUE) && // value approaches from below - (sample_p[s] < (AUDIO_DAC_OFF_VALUE + (AUDIO_DAC_SAMPLE_MAX / 100))) // or above - ) { - if ((OUTPUT_SHOULD_START == state) && (active_tones_snapshot_length > 0)) { - state = OUTPUT_RUN_NORMALLY; - } else if (OUTPUT_TONES_CHANGED == state) { - state = OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE; - } else if (OUTPUT_SHOULD_STOP == state) { - state = OUTPUT_REACHED_ZERO_BEFORE_OFF; - } - } - - // still 'ramping up', reset the output to OFF_VALUE until the generated values reach that value, to do a smooth handover - if (OUTPUT_SHOULD_START == state) { - sample_p[s] = AUDIO_DAC_OFF_VALUE; - } - - if ((OUTPUT_SHOULD_START == state) || (OUTPUT_REACHED_ZERO_BEFORE_OFF == state) || (OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE == state)) { - uint8_t active_tones = MIN(AUDIO_MAX_SIMULTANEOUS_TONES, audio_get_number_of_active_tones()); - active_tones_snapshot_length = 0; - // update the snapshot - once, and only on occasion that something changed; - // -> saves cpu cycles (?) - for (uint8_t i = 0; i < active_tones; i++) { - float freq = audio_get_processed_frequency(i); - if (freq > 0) { // disregard 'rest' notes, with valid frequency 0.0f; which would only lower the resulting waveform volume during the additive synthesis step - active_tones_snapshot[active_tones_snapshot_length++] = freq; - } - } - - if ((0 == active_tones_snapshot_length) && (OUTPUT_REACHED_ZERO_BEFORE_OFF == state)) { - state = OUTPUT_OFF; - } - if (OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE == state) { - state = OUTPUT_RUN_NORMALLY; - } - } - } - - // update audio internal state (note position, current_note, ...) - if (audio_update_state()) { - if (OUTPUT_SHOULD_STOP != state) { - state = OUTPUT_TONES_CHANGED; - } - } - - if (OUTPUT_OFF <= state) { - if (OUTPUT_OFF_2 == state) { - // stopping timer6 = stopping the DAC at whatever value it is currently pushing to the output = AUDIO_DAC_OFF_VALUE - gptStopTimer(&GPTD6); - } else { - state++; - } - } -} - -static void dac_error(DACDriver *dacp, dacerror_t err) { - (void)dacp; - (void)err; - - chSysHalt("DAC failure. halp"); -} - -static const GPTConfig gpt6cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE * 3, - .callback = NULL, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0U}; - -static const DACConfig dac_conf = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT}; - -/** - * @note The DAC_TRG(0) here selects the Timer 6 TRGO event, which is triggered - * on the rising edge after 3 APB1 clock cycles, causing our gpt6cfg1.frequency - * to be a third of what we expect. - * - * Here are all the values for DAC_TRG (TSEL in the ref manual) - * TIM15_TRGO 0b011 - * TIM2_TRGO 0b100 - * TIM3_TRGO 0b001 - * TIM6_TRGO 0b000 - * TIM7_TRGO 0b010 - * EXTI9 0b110 - * SWTRIG 0b111 - */ -static const DACConversionGroup dac_conv_cfg = {.num_channels = 1U, .end_cb = dac_end, .error_cb = dac_error, .trigger = DAC_TRG(0b000)}; - -void audio_driver_initialize() { - if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { - palSetLineMode(A4, PAL_MODE_INPUT_ANALOG); - dacStart(&DACD1, &dac_conf); - } - if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) { - palSetLineMode(A5, PAL_MODE_INPUT_ANALOG); - dacStart(&DACD2, &dac_conf); - } - - /* enable the output buffer, to directly drive external loads with no additional circuitry - * - * see: AN4566 Application note: Extending the DAC performance of STM32 microcontrollers - * Note: Buffer-Off bit -> has to be set 0 to enable the output buffer - * Note: enabling the output buffer imparts an additional dc-offset of a couple mV - * - * this is done here, reaching directly into the stm32 registers since chibios has not implemented BOFF handling yet - * (see: chibios/os/hal/ports/STM32/todo.txt '- BOFF handling in DACv1.' - */ - DACD1.params->dac->CR &= ~DAC_CR_BOFF1; - DACD2.params->dac->CR &= ~DAC_CR_BOFF2; - - if (AUDIO_PIN == A4) { - dacStartConversion(&DACD1, &dac_conv_cfg, dac_buffer_empty, AUDIO_DAC_BUFFER_SIZE); - } else if (AUDIO_PIN == A5) { - dacStartConversion(&DACD2, &dac_conv_cfg, dac_buffer_empty, AUDIO_DAC_BUFFER_SIZE); - } - - // no inverted/out-of-phase waveform (yet?), only pulling AUDIO_PIN_ALT to AUDIO_DAC_OFF_VALUE -#if defined(AUDIO_PIN_ALT_AS_NEGATIVE) - if (AUDIO_PIN_ALT == A4) { - dacPutChannelX(&DACD1, 0, AUDIO_DAC_OFF_VALUE); - } else if (AUDIO_PIN_ALT == A5) { - dacPutChannelX(&DACD2, 0, AUDIO_DAC_OFF_VALUE); - } -#endif - - gptStart(&GPTD6, &gpt6cfg1); -} - -void audio_driver_stop(void) { state = OUTPUT_SHOULD_STOP; } - -void audio_driver_start(void) { - gptStartContinuous(&GPTD6, 2U); - - for (uint8_t i = 0; i < AUDIO_MAX_SIMULTANEOUS_TONES; i++) { - dac_if[i] = 0.0f; - active_tones_snapshot[i] = 0.0f; - } - active_tones_snapshot_length = 0; - state = OUTPUT_SHOULD_START; -} diff --git a/quantum/audio/driver_chibios_dac_basic.c b/quantum/audio/driver_chibios_dac_basic.c deleted file mode 100644 index fac6513506..0000000000 --- a/quantum/audio/driver_chibios_dac_basic.c +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright 2016-2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 "audio.h" -#include "ch.h" -#include "hal.h" - -/* - Audio Driver: DAC - - which utilizes both channels of the DAC unit many STM32 are equipped with to output a modulated square-wave, from precomputed samples stored in a buffer, which is passed to the hardware through DMA - - this driver can either be used to drive to separate speakers, wired to A4+Gnd and A5+Gnd, which allows two tones to be played simultaneously - OR - one speaker wired to A4+A5 with the AUDIO_PIN_ALT_AS_NEGATIVE define set - see docs/feature_audio - -*/ - -#if !defined(AUDIO_PIN) -# pragma message "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under 'ARM (DAC basic)' for available options." -// TODO: make this an 'error' instead; go through a breaking change, and add AUDIO_PIN A5 to all keyboards currently using AUDIO on STM32 based boards? - for now: set the define here -# define AUDIO_PIN A5 -#endif -// check configuration for ONE speaker, connected to both DAC pins -#if defined(AUDIO_PIN_ALT_AS_NEGATIVE) && !defined(AUDIO_PIN_ALT) -# error "Audio feature: AUDIO_PIN_ALT_AS_NEGATIVE set, but no pin configured as AUDIO_PIN_ALT" -#endif - -#ifndef AUDIO_PIN_ALT -// no ALT pin defined is valid, but the c-ifs below need some value set -# define AUDIO_PIN_ALT -1 -#endif - -#if !defined(AUDIO_STATE_TIMER) -# define AUDIO_STATE_TIMER GPTD8 -#endif - -// square-wave -static const dacsample_t dac_buffer_1[AUDIO_DAC_BUFFER_SIZE] = { - // First half is max, second half is 0 - [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = AUDIO_DAC_SAMPLE_MAX, - [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = 0, -}; - -// square-wave -static const dacsample_t dac_buffer_2[AUDIO_DAC_BUFFER_SIZE] = { - // opposite of dac_buffer above - [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = 0, - [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, -}; - -GPTConfig gpt6cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE, - .callback = NULL, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0U}; -GPTConfig gpt7cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE, - .callback = NULL, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0U}; - -static void gpt_audio_state_cb(GPTDriver *gptp); -GPTConfig gptStateUpdateCfg = {.frequency = 10, - .callback = gpt_audio_state_cb, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0U}; - -static const DACConfig dac_conf_ch1 = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT}; -static const DACConfig dac_conf_ch2 = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT}; - -/** - * @note The DAC_TRG(0) here selects the Timer 6 TRGO event, which is triggered - * on the rising edge after 3 APB1 clock cycles, causing our gpt6cfg1.frequency - * to be a third of what we expect. - * - * Here are all the values for DAC_TRG (TSEL in the ref manual) - * TIM15_TRGO 0b011 - * TIM2_TRGO 0b100 - * TIM3_TRGO 0b001 - * TIM6_TRGO 0b000 - * TIM7_TRGO 0b010 - * EXTI9 0b110 - * SWTRIG 0b111 - */ -static const DACConversionGroup dac_conv_grp_ch1 = {.num_channels = 1U, .trigger = DAC_TRG(0b000)}; -static const DACConversionGroup dac_conv_grp_ch2 = {.num_channels = 1U, .trigger = DAC_TRG(0b010)}; - -void channel_1_start(void) { - gptStart(&GPTD6, &gpt6cfg1); - gptStartContinuous(&GPTD6, 2U); - palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); -} - -void channel_1_stop(void) { - gptStopTimer(&GPTD6); - palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL); - palSetPad(GPIOA, 4); -} - -static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { - channel_1_frequency = freq; - - channel_1_stop(); - if (freq <= 0.0) // a pause/rest has freq=0 - return; - - gpt6cfg1.frequency = 2 * freq * AUDIO_DAC_BUFFER_SIZE; - channel_1_start(); -} -float channel_1_get_frequency(void) { return channel_1_frequency; } - -void channel_2_start(void) { - gptStart(&GPTD7, &gpt7cfg1); - gptStartContinuous(&GPTD7, 2U); - palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); -} - -void channel_2_stop(void) { - gptStopTimer(&GPTD7); - palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); - palSetPad(GPIOA, 5); -} - -static float channel_2_frequency = 0.0f; -void channel_2_set_frequency(float freq) { - channel_2_frequency = freq; - - channel_2_stop(); - if (freq <= 0.0) // a pause/rest has freq=0 - return; - - gpt7cfg1.frequency = 2 * freq * AUDIO_DAC_BUFFER_SIZE; - channel_2_start(); -} -float channel_2_get_frequency(void) { return channel_2_frequency; } - -static void gpt_audio_state_cb(GPTDriver *gptp) { - if (audio_update_state()) { -#if defined(AUDIO_PIN_ALT_AS_NEGATIVE) - // one piezo/speaker connected to both audio pins, the generated square-waves are inverted - channel_1_set_frequency(audio_get_processed_frequency(0)); - channel_2_set_frequency(audio_get_processed_frequency(0)); - -#else // two separate audio outputs/speakers - // primary speaker on A4, optional secondary on A5 - if (AUDIO_PIN == A4) { - channel_1_set_frequency(audio_get_processed_frequency(0)); - if (AUDIO_PIN_ALT == A5) { - if (audio_get_number_of_active_tones() > 1) { - channel_2_set_frequency(audio_get_processed_frequency(1)); - } else { - channel_2_stop(); - } - } - } - - // primary speaker on A5, optional secondary on A4 - if (AUDIO_PIN == A5) { - channel_2_set_frequency(audio_get_processed_frequency(0)); - if (AUDIO_PIN_ALT == A4) { - if (audio_get_number_of_active_tones() > 1) { - channel_1_set_frequency(audio_get_processed_frequency(1)); - } else { - channel_1_stop(); - } - } - } -#endif - } -} - -void audio_driver_initialize() { - if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { - palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); - dacStart(&DACD1, &dac_conf_ch1); - - // initial setup of the dac-triggering timer is still required, even - // though it gets reconfigured and restarted later on - gptStart(&GPTD6, &gpt6cfg1); - } - - if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) { - palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); - dacStart(&DACD2, &dac_conf_ch2); - - gptStart(&GPTD7, &gpt7cfg1); - } - - /* enable the output buffer, to directly drive external loads with no additional circuitry - * - * see: AN4566 Application note: Extending the DAC performance of STM32 microcontrollers - * Note: Buffer-Off bit -> has to be set 0 to enable the output buffer - * Note: enabling the output buffer imparts an additional dc-offset of a couple mV - * - * this is done here, reaching directly into the stm32 registers since chibios has not implemented BOFF handling yet - * (see: chibios/os/hal/ports/STM32/todo.txt '- BOFF handling in DACv1.' - */ - DACD1.params->dac->CR &= ~DAC_CR_BOFF1; - DACD2.params->dac->CR &= ~DAC_CR_BOFF2; - - // start state-updater - gptStart(&AUDIO_STATE_TIMER, &gptStateUpdateCfg); -} - -void audio_driver_stop(void) { - if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { - gptStopTimer(&GPTD6); - - // stop the ongoing conversion and put the output in a known state - dacStopConversion(&DACD1); - dacPutChannelX(&DACD1, 0, AUDIO_DAC_OFF_VALUE); - } - - if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) { - gptStopTimer(&GPTD7); - - dacStopConversion(&DACD2); - dacPutChannelX(&DACD2, 0, AUDIO_DAC_OFF_VALUE); - } - gptStopTimer(&AUDIO_STATE_TIMER); -} - -void audio_driver_start(void) { - if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { - dacStartConversion(&DACD1, &dac_conv_grp_ch1, (dacsample_t *)dac_buffer_1, AUDIO_DAC_BUFFER_SIZE); - } - if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) { - dacStartConversion(&DACD2, &dac_conv_grp_ch2, (dacsample_t *)dac_buffer_2, AUDIO_DAC_BUFFER_SIZE); - } - gptStartContinuous(&AUDIO_STATE_TIMER, 2U); -} diff --git a/quantum/audio/driver_chibios_pwm.h b/quantum/audio/driver_chibios_pwm.h deleted file mode 100644 index 86cab916e1..0000000000 --- a/quantum/audio/driver_chibios_pwm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#pragma once - -#if !defined(AUDIO_PWM_DRIVER) -// NOTE: Timer2 seems to be used otherwise in QMK, otherwise we could default to A5 (= TIM2_CH1, with PWMD2 and alternate-function(1)) -# define AUDIO_PWM_DRIVER PWMD1 -#endif - -#if !defined(AUDIO_PWM_CHANNEL) -// NOTE: sticking to the STM data-sheet numbering: TIMxCH1 to TIMxCH4 -// default: STM32F303CC PA8+TIM1_CH1 -> 1 -# define AUDIO_PWM_CHANNEL 1 -#endif - -#if !defined(AUDIO_PWM_PAL_MODE) -// pin-alternate function: see the data-sheet for which pin needs what AF to connect to TIMx_CHy -// default: STM32F303CC PA8+TIM1_CH1 -> 6 -# define AUDIO_PWM_PAL_MODE 6 -#endif - -#if !defined(AUDIO_STATE_TIMER) -// timer used to trigger updates in the audio-system, configured/enabled in chibios mcuconf. -// Tim6 is the default for "larger" STMs, smaller ones might not have this one (enabled) and need to switch to a different one (e.g.: STM32F103 has only Tim1-Tim4) -# define AUDIO_STATE_TIMER GPTD6 -#endif diff --git a/quantum/audio/driver_chibios_pwm_hardware.c b/quantum/audio/driver_chibios_pwm_hardware.c deleted file mode 100644 index 3c7d89b290..0000000000 --- a/quantum/audio/driver_chibios_pwm_hardware.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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/>. - */ - -/* -Audio Driver: PWM - -the duty-cycle is always kept at 50%, and the pwm-period is adjusted to match the frequency of a note to be played back. - -this driver uses the chibios-PWM system to produce a square-wave on specific output pins that are connected to the PWM hardware. -The hardware directly toggles the pin via its alternate function. see your MCUs data-sheet for which pin can be driven by what timer - looking for TIMx_CHy and the corresponding alternate function. - - */ - -#include "audio.h" -#include "ch.h" -#include "hal.h" - -#if !defined(AUDIO_PIN) -# error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings" -#endif - -extern bool playing_note; -extern bool playing_melody; -extern uint8_t note_timbre; - -static PWMConfig pwmCFG = { - .frequency = 100000, /* PWM clock frequency */ - // CHIBIOS-BUG? can't set the initial period to <2, or the pwm (hard or software) takes ~130ms with .frequency=500000 for a pwmChangePeriod to take effect; with no output=silence in the meantime - .period = 2, /* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ - .callback = NULL, /* no callback, the hardware directly toggles the pin */ - .channels = - { -#if AUDIO_PWM_CHANNEL == 4 - {PWM_OUTPUT_DISABLED, NULL}, /* channel 0 -> TIMx_CH1 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 1 -> TIMx_CH2 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 2 -> TIMx_CH3 */ - {PWM_OUTPUT_ACTIVE_HIGH, NULL} /* channel 3 -> TIMx_CH4 */ -#elif AUDIO_PWM_CHANNEL == 3 - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH3 */ - {PWM_OUTPUT_DISABLED, NULL} -#elif AUDIO_PWM_CHANNEL == 2 - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH2 */ - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL} -#else /*fallback to CH1 */ - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH1 */ - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL} -#endif - }, -}; - -static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { - channel_1_frequency = freq; - - if (freq <= 0.0) // a pause/rest has freq=0 - return; - - pwmcnt_t period = (pwmCFG.frequency / freq); - pwmChangePeriod(&AUDIO_PWM_DRIVER, period); - pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1, - // adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH - PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100)); -} - -float channel_1_get_frequency(void) { return channel_1_frequency; } - -void channel_1_start(void) { - pwmStop(&AUDIO_PWM_DRIVER); - pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); -} - -void channel_1_stop(void) { pwmStop(&AUDIO_PWM_DRIVER); } - -static void gpt_callback(GPTDriver *gptp); -GPTConfig gptCFG = { - /* a whole note is one beat, which is - per definition in musical_notes.h - set to 64 - the longest note is BREAVE_DOT=128+64=192, the shortest SIXTEENTH=4 - the tempo (which might vary!) is in bpm (beats per minute) - therefore: if the timer ticks away at .frequency = (60*64)Hz, - and the .interval counts from 64 downwards - audio_update_state is - called just often enough to not miss any notes - */ - .frequency = 60 * 64, - .callback = gpt_callback, -}; - -void audio_driver_initialize(void) { - pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); - - // connect the AUDIO_PIN to the PWM hardware -#if defined(USE_GPIOV1) // STM32F103C8 - palSetLineMode(AUDIO_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL); -#else // GPIOv2 (or GPIOv3 for f4xx, which is the same/compatible at this command) - palSetLineMode(AUDIO_PIN, PAL_STM32_MODE_ALTERNATE | PAL_STM32_ALTERNATE(AUDIO_PWM_PAL_MODE)); -#endif - - gptStart(&AUDIO_STATE_TIMER, &gptCFG); -} - -void audio_driver_start(void) { - channel_1_stop(); - channel_1_start(); - - if (playing_note || playing_melody) { - gptStartContinuous(&AUDIO_STATE_TIMER, 64); - } -} - -void audio_driver_stop(void) { - channel_1_stop(); - gptStopTimer(&AUDIO_STATE_TIMER); -} - -/* a regular timer task, that checks the note to be currently played - * and updates the pwm to output that frequency - */ -static void gpt_callback(GPTDriver *gptp) { - float freq; // TODO: freq_alt - - if (audio_update_state()) { - freq = audio_get_processed_frequency(0); // freq_alt would be index=1 - channel_1_set_frequency(freq); - } -} diff --git a/quantum/audio/driver_chibios_pwm_software.c b/quantum/audio/driver_chibios_pwm_software.c deleted file mode 100644 index 15c3e98b6a..0000000000 --- a/quantum/audio/driver_chibios_pwm_software.c +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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/>. - */ - -/* -Audio Driver: PWM - -the duty-cycle is always kept at 50%, and the pwm-period is adjusted to match the frequency of a note to be played back. - -this driver uses the chibios-PWM system to produce a square-wave on any given output pin in software -- a pwm callback is used to set/clear the configured pin. - - */ -#include "audio.h" -#include "ch.h" -#include "hal.h" - -#if !defined(AUDIO_PIN) -# error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings" -#endif -extern bool playing_note; -extern bool playing_melody; -extern uint8_t note_timbre; - -static void pwm_audio_period_callback(PWMDriver *pwmp); -static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp); - -static PWMConfig pwmCFG = { - .frequency = 100000, /* PWM clock frequency */ - // CHIBIOS-BUG? can't set the initial period to <2, or the pwm (hard or software) takes ~130ms with .frequency=500000 for a pwmChangePeriod to take effect; with no output=silence in the meantime - .period = 2, /* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ - .callback = pwm_audio_period_callback, - .channels = - { - // software-PWM just needs another callback on any channel - {PWM_OUTPUT_ACTIVE_HIGH, pwm_audio_channel_interrupt_callback}, /* channel 0 -> TIMx_CH1 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 1 -> TIMx_CH2 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 2 -> TIMx_CH3 */ - {PWM_OUTPUT_DISABLED, NULL} /* channel 3 -> TIMx_CH4 */ - }, -}; - -static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { - channel_1_frequency = freq; - - if (freq <= 0.0) // a pause/rest has freq=0 - return; - - pwmcnt_t period = (pwmCFG.frequency / freq); - pwmChangePeriod(&AUDIO_PWM_DRIVER, period); - - pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1, - // adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH - PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100)); -} - -float channel_1_get_frequency(void) { return channel_1_frequency; } - -void channel_1_start(void) { - pwmStop(&AUDIO_PWM_DRIVER); - pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); - - pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER); - pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1); -} - -void channel_1_stop(void) { - pwmStop(&AUDIO_PWM_DRIVER); - - palClearLine(AUDIO_PIN); // leave the line low, after last note was played - -#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE) - palClearLine(AUDIO_PIN_ALT); // leave the line low, after last note was played -#endif -} - -// generate a PWM signal on any pin, not necessarily the one connected to the timer -static void pwm_audio_period_callback(PWMDriver *pwmp) { - (void)pwmp; - palClearLine(AUDIO_PIN); - -#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE) - palSetLine(AUDIO_PIN_ALT); -#endif -} -static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp) { - (void)pwmp; - if (channel_1_frequency > 0) { - palSetLine(AUDIO_PIN); // generate a PWM signal on any pin, not necessarily the one connected to the timer -#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE) - palClearLine(AUDIO_PIN_ALT); -#endif - } -} - -static void gpt_callback(GPTDriver *gptp); -GPTConfig gptCFG = { - /* a whole note is one beat, which is - per definition in musical_notes.h - set to 64 - the longest note is BREAVE_DOT=128+64=192, the shortest SIXTEENTH=4 - the tempo (which might vary!) is in bpm (beats per minute) - therefore: if the timer ticks away at .frequency = (60*64)Hz, - and the .interval counts from 64 downwards - audio_update_state is - called just often enough to not miss anything - */ - .frequency = 60 * 64, - .callback = gpt_callback, -}; - -void audio_driver_initialize(void) { - pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); - - palSetLineMode(AUDIO_PIN, PAL_MODE_OUTPUT_PUSHPULL); - palClearLine(AUDIO_PIN); - -#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE) - palSetLineMode(AUDIO_PIN_ALT, PAL_MODE_OUTPUT_PUSHPULL); - palClearLine(AUDIO_PIN_ALT); -#endif - - pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER); // enable pwm callbacks - pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1); - - gptStart(&AUDIO_STATE_TIMER, &gptCFG); -} - -void audio_driver_start(void) { - channel_1_stop(); - channel_1_start(); - - if (playing_note || playing_melody) { - gptStartContinuous(&AUDIO_STATE_TIMER, 64); - } -} - -void audio_driver_stop(void) { - channel_1_stop(); - gptStopTimer(&AUDIO_STATE_TIMER); -} - -/* a regular timer task, that checks the note to be currently played - * and updates the pwm to output that frequency - */ -static void gpt_callback(GPTDriver *gptp) { - float freq; // TODO: freq_alt - - if (audio_update_state()) { - freq = audio_get_processed_frequency(0); // freq_alt would be index=1 - channel_1_set_frequency(freq); - } -} diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h index b54b397e1c..8e80a016aa 100644 --- a/quantum/audio/song_list.h +++ b/quantum/audio/song_list.h @@ -20,11 +20,9 @@ #include "musical_notes.h" -#if __GNUC__ > 5 // don't use for older gcc compilers since check isn't supported. -# if __has_include("user_song_list.h") -# include "user_song_list.h" -# endif // if file exists -#endif // __GNUC__ +#if __has_include("user_song_list.h") +# include "user_song_list.h" +#endif // if file exists #define NO_SOUND diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c index e47192de34..67b551dc3c 100644 --- a/quantum/backlight/backlight_avr.c +++ b/quantum/backlight/backlight_avr.c @@ -199,13 +199,14 @@ static inline void disable_pwm(void) { // reaches the backlight level, where we turn off the LEDs, // but also an overflow interrupt when the counter rolls back to 0, // in which we're going to turn on the LEDs. -// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz. +// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz, +// or F_CPU/BACKLIGHT_CUSTOM_RESOLUTION if used. // Triggered when the counter reaches the OCRx value ISR(TIMERx_COMPA_vect) { backlight_pins_off(); } // Triggered when the counter reaches the TOP value -// this one triggers at F_CPU/65536 =~ 244 Hz +// this one triggers at F_CPU/ICRx = 16MHz/65536 =~ 244 Hz ISR(TIMERx_OVF_vect) { # ifdef BACKLIGHT_BREATHING if (is_breathing()) { @@ -220,7 +221,7 @@ ISR(TIMERx_OVF_vect) { // artifacts (especially while breathing, because breathing_task // takes many computation cycles). // so better not turn them on while the counter TOP is very low. - if (OCRxx > 256) { + if (OCRxx > ICRx / 250 + 5) { backlight_pins_on(); } } @@ -231,24 +232,26 @@ ISR(TIMERx_OVF_vect) { // See http://jared.geek.nz/2013/feb/linear-led-pwm static uint16_t cie_lightness(uint16_t v) { - if (v <= 5243) // if below 8% of max - return v / 9; // same as dividing by 900% - else { - uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare - // to get a useful result with integer division, we shift left in the expression above - // and revert what we've done again after squaring. - y = y * y * y >> 8; - if (y > 0xFFFFUL) // prevent overflow - return 0xFFFFU; - else - return (uint16_t)y; + if (v <= ICRx / 12) // If the value is less than or equal to ~8% of max + { + return v / 9; // Same as dividing by 900% + } else { + // In the next two lines values are bit-shifted. This is to avoid loosing decimals in integer math. + uint32_t y = (((uint32_t)v + ICRx / 6) << 5) / (ICRx / 6 + ICRx); // If above 8%, add ~16% of max, and normalize with (max + ~16% max) + uint32_t out = (y * y * y * ICRx) >> 15; // Cube it and undo the bit-shifting. (which is now three times as much due to the cubing) + + if (out > ICRx) // Avoid overflows + { + out = ICRx; + } + return out; } } -// rescale the supplied backlight value to be in terms of the value limit +// rescale the supplied backlight value to be in terms of the value limit // range for val is [0..ICRx]. PWM pin is high while the timer count is below val. static uint32_t rescale_limit_val(uint32_t val) { return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256; } -// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val. +// range for val is [0..ICRx]. PWM pin is high while the timer count is below val. static inline void set_pwm(uint16_t val) { OCRxx = val; } void backlight_set(uint8_t level) { @@ -277,7 +280,7 @@ void backlight_set(uint8_t level) { #endif } // Set the brightness - set_pwm(cie_lightness(rescale_limit_val(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS))); + set_pwm(cie_lightness(rescale_limit_val(ICRx * (uint32_t)level / BACKLIGHT_LEVELS))); } void backlight_task(void) {} @@ -292,6 +295,11 @@ void backlight_task(void) {} static uint8_t breathing_halt = BREATHING_NO_HALT; static uint16_t breathing_counter = 0; +static uint8_t breath_scale_counter = 1; +/* Run the breathing loop at ~120Hz*/ +const uint8_t breathing_ISR_frequency = 120; +static uint16_t breathing_freq_scale_factor = 2; + # ifdef BACKLIGHT_PWM_TIMER static bool breathing = false; @@ -323,9 +331,9 @@ bool is_breathing(void) { return !!(TIMSKx & _BV(TOIEx)); } do { \ breathing_counter = 0; \ } while (0) -# define breathing_max() \ - do { \ - breathing_counter = get_breathing_period() * 244 / 2; \ +# define breathing_max() \ + do { \ + breathing_counter = get_breathing_period() * breathing_ISR_frequency / 2; \ } while (0) void breathing_enable(void) { @@ -369,21 +377,30 @@ void breathing_task(void) # else /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run * about 244 times per second. + * + * The following ISR runs at F_CPU/ISRx. With a 16MHz clock and default pwm resolution, that means 244Hz */ ISR(TIMERx_OVF_vect) # endif { - uint8_t breathing_period = get_breathing_period(); - uint16_t interval = (uint16_t)breathing_period * 244 / BREATHING_STEPS; + + // Only run this ISR at ~120 Hz + if (breath_scale_counter++ == breathing_freq_scale_factor) { + breath_scale_counter = 1; + } else { + return; + } + uint16_t interval = (uint16_t)get_breathing_period() * breathing_ISR_frequency / BREATHING_STEPS; // resetting after one period to prevent ugly reset at overflow. - breathing_counter = (breathing_counter + 1) % (breathing_period * 244); + breathing_counter = (breathing_counter + 1) % (get_breathing_period() * breathing_ISR_frequency); uint8_t index = breathing_counter / interval % BREATHING_STEPS; if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) { breathing_interrupt_disable(); } - set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * 0x0101U)))); + // Set PWM to a brightnessvalue scaled to the configured resolution + set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * ICRx / 255)))); } #endif // BACKLIGHT_BREATHING @@ -413,16 +430,23 @@ void backlight_init_ports(void) { "In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]." "In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)." */ -# if BACKLIGHT_ON_STATE == 1 - TCCRxA = _BV(COMxx1) | _BV(WGM11); -# else - TCCRxA = _BV(COMxx1) | _BV(COMxx0) | _BV(WGM11); -# endif - - TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); + TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010; + TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; #endif - // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0. + +#ifdef BACKLIGHT_CUSTOM_RESOLUTION +# if (BACKLIGHT_CUSTOM_RESOLUTION > 0xFFFF || BACKLIGHT_CUSTOM_RESOLUTION < 1) +# error "This out of range of the timer capabilities" +# elif (BACKLIGHT_CUSTOM_RESOLUTION < 0xFF) +# warning "Resolution lower than 0xFF isn't recommended" +# endif +# ifdef BACKLIGHT_BREATHING + breathing_freq_scale_factor = F_CPU / BACKLIGHT_CUSTOM_RESOLUTION / 120; +# endif + ICRx = BACKLIGHT_CUSTOM_RESOLUTION; +#else ICRx = TIMER_TOP; +#endif backlight_init(); #ifdef BACKLIGHT_BREATHING diff --git a/quantum/backlight/backlight_chibios.c b/quantum/backlight/backlight_chibios.c index 4d5a69e14e..7c6edd10d6 100644 --- a/quantum/backlight/backlight_chibios.c +++ b/quantum/backlight/backlight_chibios.c @@ -8,9 +8,13 @@ # define BACKLIGHT_LIMIT_VAL 255 #endif -// GPIOV2 && GPIOV3 #ifndef BACKLIGHT_PAL_MODE -# define BACKLIGHT_PAL_MODE 2 +# if defined(USE_GPIOV1) +# define BACKLIGHT_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL +# else +// GPIOV2 && GPIOV3 +# define BACKLIGHT_PAL_MODE 5 +# endif #endif // GENERIC @@ -70,7 +74,7 @@ static uint32_t rescale_limit_val(uint32_t val) { void backlight_init_ports(void) { #ifdef USE_GPIOV1 - palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); + palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), BACKLIGHT_PAL_MODE); #else palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_ALTERNATE(BACKLIGHT_PAL_MODE)); #endif diff --git a/quantum/config_common.h b/quantum/config_common.h index 661609ef2a..d93477b27e 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -24,7 +24,4 @@ #define COL2ROW 0 #define ROW2COL 1 -// Deprecated alias - avoid using -#define KEYMAP LAYOUT - #include "song_list.h" diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk index 66928d7eb6..e908dd6f67 100644 --- a/quantum/debounce/tests/rules.mk +++ b/quantum/debounce/tests/rules.mk @@ -16,7 +16,7 @@ DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5 DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \ - $(TMK_PATH)/common/test/timer.c + $(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS) debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \ diff --git a/quantum/deferred_exec.c b/quantum/deferred_exec.c new file mode 100644 index 0000000000..5b0a5b1425 --- /dev/null +++ b/quantum/deferred_exec.c @@ -0,0 +1,152 @@ +// Copyright 2021 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <stddef.h> +#include <timer.h> +#include <deferred_exec.h> + +#ifndef MAX_DEFERRED_EXECUTORS +# define MAX_DEFERRED_EXECUTORS 8 +#endif + +typedef struct deferred_executor_t { + deferred_token token; + uint32_t trigger_time; + deferred_exec_callback callback; + void * cb_arg; +} deferred_executor_t; + +static deferred_token current_token = 0; +static uint32_t last_deferred_exec_check = 0; +static deferred_executor_t executors[MAX_DEFERRED_EXECUTORS] = {0}; + +static inline bool token_can_be_used(deferred_token token) { + if (token == INVALID_DEFERRED_TOKEN) { + return false; + } + for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { + if (executors[i].token == token) { + return false; + } + } + return true; +} + +static inline deferred_token allocate_token(void) { + deferred_token first = ++current_token; + while (!token_can_be_used(current_token)) { + ++current_token; + if (current_token == first) { + // If we've looped back around to the first, everything is already allocated (yikes!). Need to exit with a failure. + return INVALID_DEFERRED_TOKEN; + } + } + return current_token; +} + +deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) { + // Ignore queueing if it's a zero-time delay, or invalid callback + if (delay_ms == 0 || !callback) { + return INVALID_DEFERRED_TOKEN; + } + + // Find an unused slot and claim it + for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { + deferred_executor_t *entry = &executors[i]; + if (entry->token == INVALID_DEFERRED_TOKEN) { + // Work out the new token value, dropping out if none were available + deferred_token token = allocate_token(); + if (token == INVALID_DEFERRED_TOKEN) { + return false; + } + + // Set up the executor table entry + entry->token = current_token; + entry->trigger_time = timer_read32() + delay_ms; + entry->callback = callback; + entry->cb_arg = cb_arg; + return current_token; + } + } + + // None available + return INVALID_DEFERRED_TOKEN; +} + +bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) { + // Ignore queueing if it's a zero-time delay, or the token is not valid + if (delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) { + return false; + } + + // Find the entry corresponding to the token + for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { + deferred_executor_t *entry = &executors[i]; + if (entry->token == token) { + // Found it, extend the delay + entry->trigger_time = timer_read32() + delay_ms; + return true; + } + } + + // Not found + return false; +} + +bool cancel_deferred_exec(deferred_token token) { + // Ignore request if the token is not valid + if (token == INVALID_DEFERRED_TOKEN) { + return false; + } + + // Find the entry corresponding to the token + for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { + deferred_executor_t *entry = &executors[i]; + if (entry->token == token) { + // Found it, cancel and clear the table entry + entry->token = INVALID_DEFERRED_TOKEN; + entry->trigger_time = 0; + entry->callback = NULL; + entry->cb_arg = NULL; + return true; + } + } + + // Not found + return false; +} + +void deferred_exec_task(void) { + uint32_t now = timer_read32(); + + // Throttle only once per millisecond + if (((int32_t)TIMER_DIFF_32(now, last_deferred_exec_check)) > 0) { + last_deferred_exec_check = now; + + // Run through each of the executors + for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { + deferred_executor_t *entry = &executors[i]; + + // Check if we're supposed to execute this entry + if (entry->token != INVALID_DEFERRED_TOKEN && ((int32_t)TIMER_DIFF_32(entry->trigger_time, now)) <= 0) { + // Invoke the callback and work work out if we should be requeued + uint32_t delay_ms = entry->callback(entry->trigger_time, entry->cb_arg); + + // Update the trigger time if we have to repeat, otherwise clear it out + if (delay_ms > 0) { + // Intentionally add just the delay to the existing trigger time -- this ensures the next + // invocation is with respect to the previous trigger, rather than when it got to execution. Under + // normal circumstances this won't cause issue, but if another executor is invoked that takes a + // considerable length of time, then this ensures best-effort timing between invocations. + entry->trigger_time += delay_ms; + } else { + // If it was zero, then the callback is cancelling repeated execution. Free up the slot. + entry->token = INVALID_DEFERRED_TOKEN; + entry->trigger_time = 0; + entry->callback = NULL; + entry->cb_arg = NULL; + } + } + } + } +} diff --git a/quantum/deferred_exec.h b/quantum/deferred_exec.h new file mode 100644 index 0000000000..f80d353169 --- /dev/null +++ b/quantum/deferred_exec.h @@ -0,0 +1,38 @@ +// Copyright 2021 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +// A token that can be used to cancel an existing deferred execution. +typedef uint8_t deferred_token; +#define INVALID_DEFERRED_TOKEN 0 + +// Callback to execute. +// -- Parameter trigger_time: the intended trigger time to execute the callback -- equivalent time-space as timer_read32() +// cb_arg: the callback argument specified when enqueueing the deferred executor +// -- Return value: Non-zero re-queues the callback to execute after the returned number of milliseconds. Zero cancels repeated execution. +typedef uint32_t (*deferred_exec_callback)(uint32_t trigger_time, void *cb_arg); + +// Configures the supplied deferred executor to be executed after the required number of milliseconds. +// -- Parameter delay_ms: the number of milliseconds before executing the callback +// -- callback: the executor to invoke +// -- cb_arg: the argument to pass to the executor, may be NULL if unused by the executor +// -- Return value: a token usable for cancellation, or INVALID_DEFERRED_TOKEN if an error occurred +deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg); + +// Allows for extending the timeframe before an existing deferred execution is invoked. +// -- Parameter token: the returned value from defer_exec for the deferred execution you wish to extend. +// -- delay_ms: the new delay (with respect to the current time) +// -- Return value: if the token was found, and the delay was extended +bool extend_deferred_exec(deferred_token token, uint32_t delay_ms); + +// Allows for cancellation of an existing deferred execution. +// -- Parameter token: the returned value from defer_exec for the deferred execution you wish to cancel. +// -- Return value: if the token was found, and the executor was cancelled +bool cancel_deferred_exec(deferred_token token); + +// Forward declaration for the main loop in order to execute any deferred executors. Should not be invoked by keyboard/user code. +void deferred_exec_task(void); diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index b7a9f2662c..f5525576d8 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -16,7 +16,7 @@ #include "config.h" #include "keymap.h" // to get keymaps[][][] -#include "tmk_core/common/eeprom.h" +#include "eeprom.h" #include "progmem.h" // to read default from flash #include "quantum.h" // for send_string() #include "dynamic_keymap.h" diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c index 92f0ac4439..4c2ad2490c 100644 --- a/quantum/eeconfig.c +++ b/quantum/eeconfig.c @@ -4,11 +4,6 @@ #include "eeconfig.h" #include "action_layer.h" -#ifdef STM32_EEPROM_ENABLE -# include <hal.h> -# include "eeprom_stm32.h" -#endif - #if defined(EEPROM_DRIVER) # include "eeprom_driver.h" #endif @@ -43,9 +38,6 @@ __attribute__((weak)) void eeconfig_init_kb(void) { * FIXME: needs doc */ void eeconfig_init_quantum(void) { -#ifdef STM32_EEPROM_ENABLE - EEPROM_Erase(); -#endif #if defined(EEPROM_DRIVER) eeprom_driver_erase(); #endif @@ -111,9 +103,6 @@ void eeconfig_enable(void) { eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_N * FIXME: needs doc */ void eeconfig_disable(void) { -#ifdef STM32_EEPROM_ENABLE - EEPROM_Erase(); -#endif #if defined(EEPROM_DRIVER) eeprom_driver_erase(); #endif diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h index bd39971b2c..22d874273c 100644 --- a/quantum/eeconfig.h +++ b/quantum/eeconfig.h @@ -111,3 +111,29 @@ void eeconfig_update_haptic(uint32_t val); bool eeconfig_read_handedness(void); void eeconfig_update_handedness(bool val); + +#define EECONFIG_DEBOUNCE_HELPER(name, offset, config) \ + static uint8_t dirty_##name = false; \ + \ + static inline void eeconfig_init_##name(void) { \ + eeprom_read_block(&config, offset, sizeof(config)); \ + dirty_##name = false; \ + } \ + static inline void eeconfig_flush_##name(bool force) { \ + if (force || dirty_##name) { \ + eeprom_update_block(&config, offset, sizeof(config)); \ + dirty_##name = false; \ + } \ + } \ + static inline void eeconfig_flush_##name##_task(uint16_t timeout) { \ + static uint16_t flush_timer = 0; \ + if (timer_elapsed(flush_timer) > timeout) { \ + eeconfig_flush_##name(false); \ + flush_timer = timer_read(); \ + } \ + } \ + static inline void eeconfig_flag_##name(bool v) { dirty_##name |= v; } \ + static inline void eeconfig_write_##name(typeof(config) conf) { \ + memcpy(&config, &conf, sizeof(config)); \ + eeconfig_flag_##name(true); \ + } diff --git a/quantum/encoder.c b/quantum/encoder.c index 8fb87281c2..7d4e978981 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -16,8 +16,17 @@ */ #include "encoder.h" -#ifdef SPLIT_KEYBOARD -# include "split_util.h" + +// this is for unit testing +#if defined(ENCODER_MOCK_SINGLE) +# include "encoder/tests/mock.h" +#elif defined(ENCODER_MOCK_SPLIT) +# include "encoder/tests/mock_split.h" +#else +# include <gpio.h> +# ifdef SPLIT_KEYBOARD +# include "split_util.h" +# endif #endif // for memcpy @@ -27,17 +36,41 @@ # define ENCODER_RESOLUTION 4 #endif -#if !defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B) -# error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B" +#if (!defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B)) && (!defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B)) +# error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B or ENCODERS_PAD_A_RIGHT and ENCODERS_PAD_B_RIGHT" #endif -#define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t)) +// on split keyboards, these are the pads and resolutions for the left half static pin_t encoders_pad_a[] = ENCODERS_PAD_A; static pin_t encoders_pad_b[] = ENCODERS_PAD_B; #ifdef ENCODER_RESOLUTIONS static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS; #endif +#ifndef SPLIT_KEYBOARD +# define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t)) +#else +// if no pads for right half are defined, we assume the keyboard is symmetric (i.e. same pads) +# ifndef ENCODERS_PAD_A_RIGHT +# define ENCODERS_PAD_A_RIGHT ENCODERS_PAD_A +# endif +# ifndef ENCODERS_PAD_B_RIGHT +# define ENCODERS_PAD_B_RIGHT ENCODERS_PAD_B +# endif +# if defined(ENCODER_RESOLUTIONS) && !defined(ENCODER_RESOLUTIONS_RIGHT) +# define ENCODER_RESOLUTIONS_RIGHT ENCODER_RESOLUTIONS +# endif + +# define NUMBER_OF_ENCODERS ((sizeof(encoders_pad_a) + sizeof(encoders_pad_a_right)) / sizeof(pin_t)) +# define NUMBER_OF_ENCODERS_LEFT (sizeof(encoders_pad_a) / sizeof(pin_t)) +# define NUMBER_OF_ENCODERS_RIGHT (sizeof(encoders_pad_a_right) / sizeof(pin_t)) +static pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT; +static pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT; +# ifdef ENCODER_RESOLUTIONS_RIGHT +static uint8_t encoder_resolutions_right[] = ENCODER_RESOLUTIONS_RIGHT; +# endif +#endif + #ifndef ENCODER_DIRECTION_FLIP # define ENCODER_CLOCKWISE true # define ENCODER_COUNTER_CLOCKWISE false @@ -50,78 +83,81 @@ static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 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 -static uint8_t encoder_value[NUMBER_OF_ENCODERS * 2] = {0}; -// row offsets for each hand -static uint8_t thisHand, thatHand; -#else static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0}; -#endif __attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; } __attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); } +// number of encoders connected to this controller +static uint8_t numEncodersHere; +// index of the first encoder connected to this controller (only for right halves, this will be nonzero) +static uint8_t firstEncoderHere; +#ifdef SPLIT_KEYBOARD +// index of the first encoder connected to the other half +static uint8_t firstEncoderThere; +#endif +// the pads for this controller +static pin_t* pad_a; +static pin_t* pad_b; + void encoder_init(void) { -#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) - if (!isLeftHand) { - const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT; - const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT; -# if defined(ENCODER_RESOLUTIONS_RIGHT) - const uint8_t encoder_resolutions_right[] = ENCODER_RESOLUTIONS_RIGHT; -# endif - for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { - encoders_pad_a[i] = encoders_pad_a_right[i]; - encoders_pad_b[i] = encoders_pad_b_right[i]; -# if defined(ENCODER_RESOLUTIONS_RIGHT) - encoder_resolutions[i] = encoder_resolutions_right[i]; -# endif - } +#ifndef SPLIT_KEYBOARD + numEncodersHere = NUMBER_OF_ENCODERS; + pad_a = encoders_pad_a; + pad_b = encoders_pad_b; + firstEncoderHere = 0; +#else + if (isLeftHand) { + numEncodersHere = NUMBER_OF_ENCODERS_LEFT; + pad_a = encoders_pad_a; + pad_b = encoders_pad_b; + firstEncoderHere = 0; + firstEncoderThere = NUMBER_OF_ENCODERS_LEFT; + } else { + numEncodersHere = NUMBER_OF_ENCODERS_RIGHT; + pad_a = encoders_pad_a_right; + pad_b = encoders_pad_b_right; + firstEncoderHere = NUMBER_OF_ENCODERS_LEFT; + firstEncoderThere = 0; } #endif - for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { - setPinInputHigh(encoders_pad_a[i]); - setPinInputHigh(encoders_pad_b[i]); + for (int i = 0; i < numEncodersHere; i++) { + setPinInputHigh(pad_a[i]); + setPinInputHigh(pad_b[i]); - encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); + encoder_state[firstEncoderHere + i] = (readPin(pad_a[i]) << 0) | (readPin(pad_b[i]) << 1); } - -#ifdef SPLIT_KEYBOARD - thisHand = isLeftHand ? 0 : NUMBER_OF_ENCODERS; - thatHand = NUMBER_OF_ENCODERS - thisHand; -#endif } -static bool encoder_update(uint8_t index, uint8_t state) { - bool changed = false; - uint8_t i = index; +static bool encoder_update(int8_t index, uint8_t state) { + bool changed = false; #ifdef ENCODER_RESOLUTIONS - uint8_t resolution = encoder_resolutions[i]; +# ifndef SPLIT_KEYBOARD + int8_t resolution = encoder_resolutions[index]; +# else + int8_t resolution = isLeftHand ? encoder_resolutions[index] : encoder_resolutions_right[index - NUMBER_OF_ENCODERS_LEFT]; +# endif #else uint8_t resolution = ENCODER_RESOLUTION; #endif - -#ifdef SPLIT_KEYBOARD - index += thisHand; -#endif - encoder_pulses[i] += encoder_LUT[state & 0xF]; - if (encoder_pulses[i] >= resolution) { + encoder_pulses[index] += encoder_LUT[state & 0xF]; + if (encoder_pulses[index] >= resolution) { encoder_value[index]++; changed = true; encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE); } - if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise + if (encoder_pulses[index] <= -resolution) { // direction is arbitrary here, but this clockwise encoder_value[index]--; changed = true; encoder_update_kb(index, ENCODER_CLOCKWISE); } - encoder_pulses[i] %= resolution; + encoder_pulses[index] %= resolution; #ifdef ENCODER_DEFAULT_POS if ((state & 0x3) == ENCODER_DEFAULT_POS) { - encoder_pulses[i] = 0; + encoder_pulses[index] = 0; } #endif return changed; @@ -129,10 +165,10 @@ static bool encoder_update(uint8_t index, uint8_t state) { bool encoder_read(void) { bool changed = false; - 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); - changed |= encoder_update(i, encoder_state[i]); + for (uint8_t i = 0; i < numEncodersHere; i++) { + encoder_state[firstEncoderHere + i] <<= 2; + encoder_state[firstEncoderHere + i] |= (readPin(pad_a[i]) << 0) | (readPin(pad_b[i]) << 1); + changed |= encoder_update(firstEncoderHere + i, encoder_state[firstEncoderHere + i]); } return changed; } @@ -140,12 +176,12 @@ bool encoder_read(void) { #ifdef SPLIT_KEYBOARD void last_encoder_activity_trigger(void); -void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); } +void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[firstEncoderHere], sizeof(uint8_t) * numEncodersHere); } void encoder_update_raw(uint8_t* slave_state) { bool changed = false; - for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { - uint8_t index = i + thatHand; + for (uint8_t i = 0; i < NUMBER_OF_ENCODERS - numEncodersHere; i++) { + uint8_t index = firstEncoderThere + i; int8_t delta = slave_state[i] - encoder_value[index]; while (delta > 0) { delta--; diff --git a/quantum/encoder.h b/quantum/encoder.h index 25dc77721d..67f71ec0f0 100644 --- a/quantum/encoder.h +++ b/quantum/encoder.h @@ -17,7 +17,8 @@ #pragma once -#include "quantum.h" +#include <stdbool.h> +#include <stdint.h> void encoder_init(void); bool encoder_read(void); diff --git a/quantum/encoder/tests/encoder_tests.cpp b/quantum/encoder/tests/encoder_tests.cpp new file mode 100644 index 0000000000..1888fdab8d --- /dev/null +++ b/quantum/encoder/tests/encoder_tests.cpp @@ -0,0 +1,144 @@ +/* Copyright 2021 Balz Guenat + * + * 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 "gtest/gtest.h" +#include "gmock/gmock.h" +#include <vector> +#include <algorithm> +#include <stdio.h> + +extern "C" { +#include "encoder.h" +#include "encoder/tests/mock.h" +} + +struct update { + int8_t index; + bool clockwise; +}; + +uint8_t uidx = 0; +update updates[32]; + +bool encoder_update_kb(uint8_t index, bool clockwise) { + updates[uidx % 32] = {index, clockwise}; + uidx++; + return true; +} + +bool setAndRead(pin_t pin, bool val) { + setPin(pin, val); + return encoder_read(); +} + +class EncoderTest : public ::testing::Test {}; + +TEST_F(EncoderTest, TestInit) { + uidx = 0; + encoder_init(); + EXPECT_EQ(pinIsInputHigh[0], true); + EXPECT_EQ(pinIsInputHigh[1], true); + EXPECT_EQ(uidx, 0); +} + +TEST_F(EncoderTest, TestOneClockwise) { + uidx = 0; + encoder_init(); + // send 4 pulses. with resolution 4, that's one step and we should get 1 update. + setAndRead(0, false); + setAndRead(1, false); + setAndRead(0, true); + setAndRead(1, true); + + EXPECT_EQ(uidx, 1); + EXPECT_EQ(updates[0].index, 0); + EXPECT_EQ(updates[0].clockwise, true); +} + +TEST_F(EncoderTest, TestOneCounterClockwise) { + uidx = 0; + encoder_init(); + setAndRead(1, false); + setAndRead(0, false); + setAndRead(1, true); + setAndRead(0, true); + + EXPECT_EQ(uidx, 1); + EXPECT_EQ(updates[0].index, 0); + EXPECT_EQ(updates[0].clockwise, false); +} + +TEST_F(EncoderTest, TestTwoClockwiseOneCC) { + uidx = 0; + encoder_init(); + setAndRead(0, false); + setAndRead(1, false); + setAndRead(0, true); + setAndRead(1, true); + setAndRead(0, false); + setAndRead(1, false); + setAndRead(0, true); + setAndRead(1, true); + setAndRead(1, false); + setAndRead(0, false); + setAndRead(1, true); + setAndRead(0, true); + + EXPECT_EQ(uidx, 3); + EXPECT_EQ(updates[0].index, 0); + EXPECT_EQ(updates[0].clockwise, true); + EXPECT_EQ(updates[1].index, 0); + EXPECT_EQ(updates[1].clockwise, true); + EXPECT_EQ(updates[2].index, 0); + EXPECT_EQ(updates[2].clockwise, false); +} + +TEST_F(EncoderTest, TestNoEarly) { + uidx = 0; + encoder_init(); + // send 3 pulses. with resolution 4, that's not enough for a step. + setAndRead(0, false); + setAndRead(1, false); + setAndRead(0, true); + EXPECT_EQ(uidx, 0); + // now send last pulse + setAndRead(1, true); + EXPECT_EQ(uidx, 1); + EXPECT_EQ(updates[0].index, 0); + EXPECT_EQ(updates[0].clockwise, true); +} + +TEST_F(EncoderTest, TestHalfway) { + uidx = 0; + encoder_init(); + // go halfway + setAndRead(0, false); + setAndRead(1, false); + EXPECT_EQ(uidx, 0); + // back off + setAndRead(1, true); + setAndRead(0, true); + EXPECT_EQ(uidx, 0); + // go all the way + setAndRead(0, false); + setAndRead(1, false); + setAndRead(0, true); + setAndRead(1, true); + // should result in 1 update + EXPECT_EQ(uidx, 1); + EXPECT_EQ(updates[0].index, 0); + EXPECT_EQ(updates[0].clockwise, true); +} diff --git a/quantum/encoder/tests/encoder_tests_split.cpp b/quantum/encoder/tests/encoder_tests_split.cpp new file mode 100644 index 0000000000..25e52c83f9 --- /dev/null +++ b/quantum/encoder/tests/encoder_tests_split.cpp @@ -0,0 +1,143 @@ +/* Copyright 2021 Balz Guenat + * + * 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 "gtest/gtest.h" +#include "gmock/gmock.h" +#include <vector> +#include <algorithm> +#include <stdio.h> + +extern "C" { +#include "encoder.h" +#include "encoder/tests/mock_split.h" +} + +struct update { + int8_t index; + bool clockwise; +}; + +uint8_t uidx = 0; +update updates[32]; + +bool isLeftHand; + +bool encoder_update_kb(uint8_t index, bool clockwise) { + if (!isLeftHand) { + // this method has no effect on slave half + printf("ignoring update on right hand (%d,%s)\n", index, clockwise ? "CW" : "CC"); + return true; + } + updates[uidx % 32] = {index, clockwise}; + uidx++; + return true; +} + +bool setAndRead(pin_t pin, bool val) { + setPin(pin, val); + return encoder_read(); +} + +class EncoderTest : public ::testing::Test { + protected: + void SetUp() override { + uidx = 0; + for (int i = 0; i < 32; i++) { + pinIsInputHigh[i] = 0; + pins[i] = 0; + } + } +}; + +TEST_F(EncoderTest, TestInitLeft) { + isLeftHand = true; + encoder_init(); + EXPECT_EQ(pinIsInputHigh[0], true); + EXPECT_EQ(pinIsInputHigh[1], true); + EXPECT_EQ(pinIsInputHigh[2], false); + EXPECT_EQ(pinIsInputHigh[3], false); + EXPECT_EQ(uidx, 0); +} + +TEST_F(EncoderTest, TestInitRight) { + isLeftHand = false; + encoder_init(); + EXPECT_EQ(pinIsInputHigh[0], false); + EXPECT_EQ(pinIsInputHigh[1], false); + EXPECT_EQ(pinIsInputHigh[2], true); + EXPECT_EQ(pinIsInputHigh[3], true); + EXPECT_EQ(uidx, 0); +} + +TEST_F(EncoderTest, TestOneClockwiseLeft) { + isLeftHand = true; + encoder_init(); + // send 4 pulses. with resolution 4, that's one step and we should get 1 update. + setAndRead(0, false); + setAndRead(1, false); + setAndRead(0, true); + setAndRead(1, true); + + EXPECT_EQ(uidx, 1); + EXPECT_EQ(updates[0].index, 0); + EXPECT_EQ(updates[0].clockwise, true); +} + +TEST_F(EncoderTest, TestOneClockwiseRightSent) { + isLeftHand = false; + encoder_init(); + // send 4 pulses. with resolution 4, that's one step and we should get 1 update. + setAndRead(2, false); + setAndRead(3, false); + setAndRead(2, true); + setAndRead(3, true); + + uint8_t slave_state[2] = {0}; + encoder_state_raw(slave_state); + + EXPECT_EQ((int8_t)slave_state[0], -1); +} + +/* this test will not work after the previous test. + * this is due to encoder_value[1] already being set to -1 when simulating the right half. + * When we now receive this update acting as the left half, there is no change. + * This is hard to mock, as the static values inside encoder.c normally exist twice, once on each half, + * but here, they only exist once. + */ + +// TEST_F(EncoderTest, TestOneClockwiseRightReceived) { +// isLeftHand = true; +// encoder_init(); + +// uint8_t slave_state[2] = {255, 0}; +// encoder_update_raw(slave_state); + +// EXPECT_EQ(uidx, 1); +// EXPECT_EQ(updates[0].index, 1); +// EXPECT_EQ(updates[0].clockwise, true); +// } + +TEST_F(EncoderTest, TestOneCounterClockwiseRightReceived) { + isLeftHand = true; + encoder_init(); + + uint8_t slave_state[2] = {0, 0}; + encoder_update_raw(slave_state); + + EXPECT_EQ(uidx, 1); + EXPECT_EQ(updates[0].index, 1); + EXPECT_EQ(updates[0].clockwise, false); +} diff --git a/quantum/api/api_sysex.h b/quantum/encoder/tests/mock.c index eb0a18848d..d0506a938f 100644 --- a/quantum/api/api_sysex.h +++ b/quantum/encoder/tests/mock.c @@ -1,4 +1,4 @@ -/* Copyright 2016 Jack Humbert +/* Copyright 2021 Balz Guenat * * 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 @@ -14,12 +14,21 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#pragma once +#include "mock.h" -#include "api.h" +bool pins[32] = {0}; +bool pinIsInputHigh[32] = {0}; -#define API_SYSEX_MAX_SIZE 32 +uint8_t mockSetPinInputHigh(pin_t pin) { + // dprintf("Setting pin %d input high.", pin); + pins[pin] = true; + pinIsInputHigh[pin] = true; + return 0; +} -void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t* bytes, uint16_t length); +bool mockReadPin(pin_t pin) { return pins[pin]; } -#define SEND_BYTES(mt, dt, b, l) send_bytes_sysex(mt, dt, b, l) +bool setPin(pin_t pin, bool val) { + pins[pin] = val; + return val; +} diff --git a/quantum/visualizer/resources/resources.h b/quantum/encoder/tests/mock.h index 5178fbe55a..dbc25a0846 100644 --- a/quantum/visualizer/resources/resources.h +++ b/quantum/encoder/tests/mock.h @@ -1,4 +1,4 @@ -/* Copyright 2017 Fred Sundvik +/* Copyright 2021 Balz Guenat * * 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 @@ -17,7 +17,24 @@ #pragma once #include <stdint.h> +#include <stdbool.h> -#ifdef LCD_ENABLE -extern const uint8_t resource_lcd_logo[]; -#endif +/* Here, "pins" from 0 to 31 are allowed. */ +#define ENCODERS_PAD_A \ + { 0 } +#define ENCODERS_PAD_B \ + { 1 } + +typedef uint8_t pin_t; + +extern bool pins[]; +extern bool pinIsInputHigh[]; + +#define setPinInputHigh(pin) (mockSetPinInputHigh(pin)) +#define readPin(pin) (mockReadPin(pin)) + +uint8_t mockSetPinInputHigh(pin_t pin); + +bool mockReadPin(pin_t pin); + +bool setPin(pin_t pin, bool val); diff --git a/quantum/visualizer/visualizer_keyframes.c b/quantum/encoder/tests/mock_split.c index 8f6a7e15a4..68bf3af599 100644 --- a/quantum/visualizer/visualizer_keyframes.c +++ b/quantum/encoder/tests/mock_split.c @@ -1,4 +1,4 @@ -/* Copyright 2017 Fred Sundvik +/* Copyright 2021 Balz Guenat * * 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 @@ -14,10 +14,23 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "visualizer_keyframes.h" +#include "mock_split.h" -bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - return false; +bool pins[32] = {0}; +bool pinIsInputHigh[32] = {0}; + +uint8_t mockSetPinInputHigh(pin_t pin) { + // dprintf("Setting pin %d input high.", pin); + pins[pin] = true; + pinIsInputHigh[pin] = true; + return 0; } + +bool mockReadPin(pin_t pin) { return pins[pin]; } + +bool setPin(pin_t pin, bool val) { + pins[pin] = val; + return val; +} + +void last_encoder_activity_trigger(void) {} diff --git a/quantum/encoder/tests/mock_split.h b/quantum/encoder/tests/mock_split.h new file mode 100644 index 0000000000..0ae62652f9 --- /dev/null +++ b/quantum/encoder/tests/mock_split.h @@ -0,0 +1,48 @@ +/* Copyright 2021 Balz Guenat + * + * 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 <stdint.h> +#include <stdbool.h> + +#define SPLIT_KEYBOARD +/* Here, "pins" from 0 to 31 are allowed. */ +#define ENCODERS_PAD_A \ + { 0 } +#define ENCODERS_PAD_B \ + { 1 } +#define ENCODERS_PAD_A_RIGHT \ + { 2 } +#define ENCODERS_PAD_B_RIGHT \ + { 3 } + +typedef uint8_t pin_t; +extern bool isLeftHand; +void encoder_state_raw(uint8_t* slave_state); +void encoder_update_raw(uint8_t* slave_state); + +extern bool pins[]; +extern bool pinIsInputHigh[]; + +#define setPinInputHigh(pin) (mockSetPinInputHigh(pin)) +#define readPin(pin) (mockReadPin(pin)) + +uint8_t mockSetPinInputHigh(pin_t pin); + +bool mockReadPin(pin_t pin); + +bool setPin(pin_t pin, bool val); diff --git a/quantum/encoder/tests/rules.mk b/quantum/encoder/tests/rules.mk new file mode 100644 index 0000000000..b826ce3aed --- /dev/null +++ b/quantum/encoder/tests/rules.mk @@ -0,0 +1,13 @@ +encoder_DEFS := -DENCODER_MOCK_SINGLE + +encoder_SRC := \ + $(QUANTUM_PATH)/encoder/tests/mock.c \ + $(QUANTUM_PATH)/encoder/tests/encoder_tests.cpp \ + $(QUANTUM_PATH)/encoder.c + +encoder_split_DEFS := -DENCODER_MOCK_SPLIT + +encoder_split_SRC := \ + $(QUANTUM_PATH)/encoder/tests/mock_split.c \ + $(QUANTUM_PATH)/encoder/tests/encoder_tests_split.cpp \ + $(QUANTUM_PATH)/encoder.c diff --git a/quantum/encoder/tests/testlist.mk b/quantum/encoder/tests/testlist.mk new file mode 100644 index 0000000000..1be9f4a054 --- /dev/null +++ b/quantum/encoder/tests/testlist.mk @@ -0,0 +1,3 @@ +TEST_LIST += \ + encoder \ + encoder_split diff --git a/quantum/haptic.c b/quantum/haptic.c index 65abcc15fa..f915acf946 100644 --- a/quantum/haptic.c +++ b/quantum/haptic.c @@ -17,6 +17,8 @@ #include "haptic.h" #include "eeconfig.h" #include "debug.h" +#include "usb_device_state.h" +#include "gpio.h" #ifdef DRV2605L # include "DRV2605L.h" #endif @@ -26,6 +28,29 @@ haptic_config_t haptic_config; +static void update_haptic_enable_gpios(void) { + if (haptic_config.enable && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) { +#if defined(HAPTIC_ENABLE_PIN) + HAPTIC_ENABLE_PIN_WRITE_ACTIVE(); +#endif +#if defined(HAPTIC_ENABLE_STATUS_LED) + HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE(); +#endif + } else { +#if defined(HAPTIC_ENABLE_PIN) + HAPTIC_ENABLE_PIN_WRITE_INACTIVE(); +#endif +#if defined(HAPTIC_ENABLE_STATUS_LED) + HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE(); +#endif + } +} + +static void set_haptic_config_enable(bool enabled) { + haptic_config.enable = enabled; + update_haptic_enable_gpios(); +} + void haptic_init(void) { if (!eeconfig_is_enabled()) { eeconfig_init(); @@ -44,6 +69,10 @@ void haptic_init(void) { // or the previous firmware didn't have solenoid enabled, // and the current one has solenoid enabled. haptic_reset(); + } else { + // Haptic configuration has been loaded through the "raw" union item. + // This is to execute any side effects of the configuration. + set_haptic_config_enable(haptic_config.enable); } #ifdef SOLENOID_ENABLE solenoid_setup(); @@ -54,6 +83,12 @@ void haptic_init(void) { dprintf("DRV2605 driver initialized\n"); #endif eeconfig_debug_haptic(); +#ifdef HAPTIC_ENABLE_PIN + setPinOutput(HAPTIC_ENABLE_PIN); +#endif +#ifdef HAPTIC_ENABLE_STATUS_LED + setPinOutput(HAPTIC_ENABLE_STATUS_LED); +#endif } void haptic_task(void) { @@ -69,13 +104,13 @@ void eeconfig_debug_haptic(void) { } void haptic_enable(void) { - haptic_config.enable = 1; + set_haptic_config_enable(true); xprintf("haptic_config.enable = %u\n", haptic_config.enable); eeconfig_update_haptic(haptic_config.raw); } void haptic_disable(void) { - haptic_config.enable = 0; + set_haptic_config_enable(false); xprintf("haptic_config.enable = %u\n", haptic_config.enable); eeconfig_update_haptic(haptic_config.raw); } @@ -157,7 +192,7 @@ void haptic_dwell_decrease(void) { } void haptic_reset(void) { - haptic_config.enable = true; + set_haptic_config_enable(true); uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT; haptic_config.feedback = feedback; #ifdef DRV2605L @@ -293,3 +328,13 @@ void haptic_shutdown(void) { solenoid_shutdown(); #endif } + +void haptic_notify_usb_device_state_change(void) { + update_haptic_enable_gpios(); +#if defined(HAPTIC_ENABLE_PIN) + setPinOutput(HAPTIC_ENABLE_PIN); +#endif +#if defined(HAPTIC_ENABLE_STATUS_LED) + setPinOutput(HAPTIC_ENABLE_STATUS_LED); +#endif +} diff --git a/quantum/haptic.h b/quantum/haptic.h index fc7ca2f3e6..7d70a01333 100644 --- a/quantum/haptic.h +++ b/quantum/haptic.h @@ -75,3 +75,30 @@ void haptic_cont_decrease(void); void haptic_play(void); void haptic_shutdown(void); +void haptic_notify_usb_device_state_change(void); + +#ifdef HAPTIC_ENABLE_PIN_ACTIVE_LOW +# ifndef HAPTIC_ENABLE_PIN +# error HAPTIC_ENABLE_PIN not defined +# endif +# define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_PIN) +# define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_PIN) +#else +# define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_PIN) +# define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_PIN) +#endif + +#ifdef HAPTIC_ENABLE_STATUS_LED_ACTIVE_LOW +# ifndef HAPTIC_ENABLE_STATUS_LED +# error HAPTIC_ENABLE_STATUS_LED not defined +# endif +# define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED) +# define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED) +#else +# define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED) +# define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED) +#endif + +#ifndef HAPTIC_OFF_IN_LOW_POWER +# define HAPTIC_OFF_IN_LOW_POWER 0 +#endif diff --git a/quantum/keyboard.c b/quantum/keyboard.c index b98fc64e45..3bca05aab7 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -40,12 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef PS2_MOUSE_ENABLE # include "ps2_mouse.h" #endif -#ifdef SERIAL_MOUSE_ENABLE -# include "serial_mouse.h" -#endif -#ifdef ADB_MOUSE_ENABLE -# include "adb.h" -#endif #ifdef RGBLIGHT_ENABLE # include "rgblight.h" #endif @@ -61,12 +55,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef STENO_ENABLE # include "process_steno.h" #endif -#ifdef SERIAL_LINK_ENABLE -# include "serial_link/system/serial_link.h" -#endif -#ifdef VISUALIZER_ENABLE -# include "visualizer/visualizer.h" -#endif #ifdef POINTING_DEVICE_ENABLE # include "pointing_device.h" #endif @@ -76,12 +64,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef JOYSTICK_ENABLE # include "process_joystick.h" #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE +# include "programmable_button.h" +#endif #ifdef HD44780_ENABLE # include "hd44780.h" #endif -#ifdef QWIIC_ENABLE -# include "qwiic.h" -#endif #ifdef OLED_ENABLE # include "oled_driver.h" #endif @@ -97,9 +85,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef DIP_SWITCH_ENABLE # include "dip_switch.h" #endif -#ifdef STM32_EEPROM_ENABLE -# include "eeprom_stm32.h" -#endif #ifdef EEPROM_DRIVER # include "eeprom_driver.h" #endif @@ -109,6 +94,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef DIGITIZER_ENABLE # include "digitizer.h" #endif +#ifdef VIRTSER_ENABLE +# include "virtser.h" +#endif +#ifdef SLEEP_LED_ENABLE +# include "sleep_led.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { return last_input_modification_time; } @@ -246,9 +237,6 @@ void keyboard_setup(void) { disable_jtag(); #endif print_set_sendchar(sendchar); -#ifdef STM32_EEPROM_ENABLE - EEPROM_Init(); -#endif #ifdef EEPROM_DRIVER eeprom_driver_init(); #endif @@ -316,9 +304,6 @@ void keyboard_init(void) { #if defined(CRC_ENABLE) crc_init(); #endif -#ifdef QWIIC_ENABLE - qwiic_init(); -#endif #ifdef OLED_ENABLE oled_init(OLED_ROTATION_0); #endif @@ -328,12 +313,6 @@ void keyboard_init(void) { #ifdef PS2_MOUSE_ENABLE ps2_mouse_init(); #endif -#ifdef SERIAL_MOUSE_ENABLE - serial_mouse_init(); -#endif -#ifdef ADB_MOUSE_ENABLE - adb_mouse_init(); -#endif #ifdef BACKLIGHT_ENABLE backlight_init(); #endif @@ -356,6 +335,12 @@ void keyboard_init(void) { #ifdef DIP_SWITCH_ENABLE dip_switch_init(); #endif +#ifdef SLEEP_LED_ENABLE + sleep_led_init(); +#endif +#ifdef VIRTSER_ENABLE + virtser_init(); +#endif #if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE) debug_enable = true; @@ -384,7 +369,6 @@ void switch_events(uint8_t row, uint8_t col, bool pressed) { * * * scan matrix * * handle mouse movements - * * run visualizer code * * handle midi commands * * light LEDs * @@ -473,10 +457,6 @@ MATRIX_LOOP_END: if (encoders_changed) last_encoder_activity_trigger(); #endif -#ifdef QWIIC_ENABLE - qwiic_task(); -#endif - #ifdef OLED_ENABLE oled_task(); # if OLED_TIMEOUT > 0 @@ -510,22 +490,6 @@ MATRIX_LOOP_END: ps2_mouse_task(); #endif -#ifdef SERIAL_MOUSE_ENABLE - serial_mouse_task(); -#endif - -#ifdef ADB_MOUSE_ENABLE - adb_mouse_task(); -#endif - -#ifdef SERIAL_LINK_ENABLE - serial_link_update(); -#endif - -#ifdef VISUALIZER_ENABLE - visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds()); -#endif - #ifdef POINTING_DEVICE_ENABLE pointing_device_task(); #endif @@ -548,6 +512,10 @@ MATRIX_LOOP_END: digitizer_task(); #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE + programmable_button_send(); +#endif + // update LED if (led_status != host_keyboard_leds()) { led_status = host_keyboard_leds(); diff --git a/quantum/keycode.h b/quantum/keycode.h index 8facabd818..38a29b439b 100644 --- a/quantum/keycode.h +++ b/quantum/keycode.h @@ -29,7 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED) #define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF) #define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL) -#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI) +#define IS_MOD(code) (KC_LEFT_CTRL <= (code) && (code) <= KC_RIGHT_GUI) #define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF)) #define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE) @@ -46,10 +46,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define MOD_BIT(code) (1 << MOD_INDEX(code)) #define MOD_INDEX(code) ((code)&0x07) -#define MOD_MASK_CTRL (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL)) -#define MOD_MASK_SHIFT (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) -#define MOD_MASK_ALT (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) -#define MOD_MASK_GUI (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI)) +#define MOD_MASK_CTRL (MOD_BIT(KC_LEFT_CTRL) | MOD_BIT(KC_RIGHT_CTRL)) +#define MOD_MASK_SHIFT (MOD_BIT(KC_LEFT_SHIFT) | MOD_BIT(KC_RIGHT_SHIFT)) +#define MOD_MASK_ALT (MOD_BIT(KC_LEFT_ALT) | MOD_BIT(KC_RIGHT_ALT)) +#define MOD_MASK_GUI (MOD_BIT(KC_LEFT_GUI) | MOD_BIT(KC_RIGHT_GUI)) #define MOD_MASK_CS (MOD_MASK_CTRL | MOD_MASK_SHIFT) #define MOD_MASK_CA (MOD_MASK_CTRL | MOD_MASK_ALT) #define MOD_MASK_CG (MOD_MASK_CTRL | MOD_MASK_GUI) @@ -67,6 +67,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define FN_MIN KC_FN0 #define FN_MAX KC_FN31 +// clang-format off + /* * Short names for ease of definition of keymap */ @@ -75,47 +77,55 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define KC_TRNS KC_TRANSPARENT /* Punctuation */ -#define KC_ENT KC_ENTER -#define KC_ESC KC_ESCAPE -#define KC_BSPC KC_BSPACE -#define KC_SPC KC_SPACE +#define KC_ENT KC_ENTER +#define KC_ESC KC_ESCAPE +#define KC_BSPC KC_BACKSPACE +#define KC_SPC KC_SPACE #define KC_MINS KC_MINUS -#define KC_EQL KC_EQUAL -#define KC_LBRC KC_LBRACKET -#define KC_RBRC KC_RBRACKET -#define KC_BSLS KC_BSLASH +#define KC_EQL KC_EQUAL +#define KC_LBRC KC_LEFT_BRACKET +#define KC_RBRC KC_RIGHT_BRACKET +#define KC_BSLS KC_BACKSLASH #define KC_NUHS KC_NONUS_HASH -#define KC_SCLN KC_SCOLON +#define KC_SCLN KC_SEMICOLON #define KC_QUOT KC_QUOTE -#define KC_GRV KC_GRAVE +#define KC_GRV KC_GRAVE #define KC_COMM KC_COMMA #define KC_SLSH KC_SLASH -#define KC_NUBS KC_NONUS_BSLASH +#define KC_NUBS KC_NONUS_BACKSLASH /* Lock Keys */ -#define KC_CLCK KC_CAPSLOCK -#define KC_CAPS KC_CAPSLOCK -#define KC_SLCK KC_SCROLLLOCK -#define KC_NLCK KC_NUMLOCK -#define KC_LCAP KC_LOCKING_CAPS -#define KC_LNUM KC_LOCKING_NUM -#define KC_LSCR KC_LOCKING_SCROLL +#define KC_CAPS KC_CAPS_LOCK +#define KC_SCRL KC_SCROLL_LOCK +#define KC_NUM KC_NUM_LOCK +#define KC_LCAP KC_LOCKING_CAPS_LOCK +#define KC_LNUM KC_LOCKING_NUM_LOCK +#define KC_LSCR KC_LOCKING_SCROLL_LOCK /* Commands */ -#define KC_PSCR KC_PSCREEN +#define KC_PSCR KC_PRINT_SCREEN #define KC_PAUS KC_PAUSE -#define KC_BRK KC_PAUSE -#define KC_INS KC_INSERT -#define KC_DEL KC_DELETE -#define KC_PGDN KC_PGDOWN +#define KC_BRK KC_PAUSE +#define KC_INS KC_INSERT +#define KC_PGUP KC_PAGE_UP +#define KC_DEL KC_DELETE +#define KC_PGDN KC_PAGE_DOWN #define KC_RGHT KC_RIGHT -#define KC_APP KC_APPLICATION +#define KC_APP KC_APPLICATION #define KC_EXEC KC_EXECUTE #define KC_SLCT KC_SELECT #define KC_AGIN KC_AGAIN #define KC_PSTE KC_PASTE -#define KC_ERAS KC_ALT_ERASE -#define KC_CLR KC_CLEAR +#define KC_ERAS KC_ALTERNATE_ERASE +#define KC_SYRQ KC_SYSTEM_REQUEST +#define KC_CNCL KC_CANCEL +#define KC_CLR KC_CLEAR +#define KC_PRIR KC_PRIOR +#define KC_RETN KC_RETURN +#define KC_SEPR KC_SEPARATOR +#define KC_CLAG KC_CLEAR_AGAIN +#define KC_CRSL KC_CRSEL +#define KC_EXSL KC_EXSEL /* Keypad */ #define KC_PSLS KC_KP_SLASH @@ -123,47 +133,59 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define KC_PMNS KC_KP_MINUS #define KC_PPLS KC_KP_PLUS #define KC_PENT KC_KP_ENTER -#define KC_P1 KC_KP_1 -#define KC_P2 KC_KP_2 -#define KC_P3 KC_KP_3 -#define KC_P4 KC_KP_4 -#define KC_P5 KC_KP_5 -#define KC_P6 KC_KP_6 -#define KC_P7 KC_KP_7 -#define KC_P8 KC_KP_8 -#define KC_P9 KC_KP_9 -#define KC_P0 KC_KP_0 +#define KC_P1 KC_KP_1 +#define KC_P2 KC_KP_2 +#define KC_P3 KC_KP_3 +#define KC_P4 KC_KP_4 +#define KC_P5 KC_KP_5 +#define KC_P6 KC_KP_6 +#define KC_P7 KC_KP_7 +#define KC_P8 KC_KP_8 +#define KC_P9 KC_KP_9 +#define KC_P0 KC_KP_0 #define KC_PDOT KC_KP_DOT #define KC_PEQL KC_KP_EQUAL #define KC_PCMM KC_KP_COMMA -/* Japanese specific */ -#define KC_ZKHK KC_GRAVE -#define KC_RO KC_INT1 -#define KC_KANA KC_INT2 -#define KC_JYEN KC_INT3 -#define KC_HENK KC_INT4 -#define KC_MHEN KC_INT5 - -/* Korean specific */ -#define KC_HAEN KC_LANG1 -#define KC_HANJ KC_LANG2 +/* Language Specific */ +#define KC_INT1 KC_INTERNATIONAL_1 +#define KC_INT2 KC_INTERNATIONAL_2 +#define KC_INT3 KC_INTERNATIONAL_3 +#define KC_INT4 KC_INTERNATIONAL_4 +#define KC_INT5 KC_INTERNATIONAL_5 +#define KC_INT6 KC_INTERNATIONAL_6 +#define KC_INT7 KC_INTERNATIONAL_7 +#define KC_INT8 KC_INTERNATIONAL_8 +#define KC_INT9 KC_INTERNATIONAL_9 +#define KC_LNG1 KC_LANGUAGE_1 +#define KC_LNG2 KC_LANGUAGE_2 +#define KC_LNG3 KC_LANGUAGE_3 +#define KC_LNG4 KC_LANGUAGE_4 +#define KC_LNG5 KC_LANGUAGE_5 +#define KC_LNG6 KC_LANGUAGE_6 +#define KC_LNG7 KC_LANGUAGE_7 +#define KC_LNG8 KC_LANGUAGE_8 +#define KC_LNG9 KC_LANGUAGE_9 /* Modifiers */ -#define KC_LCTL KC_LCTRL -#define KC_LSFT KC_LSHIFT -#define KC_LOPT KC_LALT -#define KC_LCMD KC_LGUI -#define KC_LWIN KC_LGUI -#define KC_RCTL KC_RCTRL -#define KC_RSFT KC_RSHIFT -#define KC_ALGR KC_RALT -#define KC_ROPT KC_RALT -#define KC_RCMD KC_RGUI -#define KC_RWIN KC_RGUI +#define KC_LCTL KC_LEFT_CTRL +#define KC_LSFT KC_LEFT_SHIFT +#define KC_LALT KC_LEFT_ALT +#define KC_LOPT KC_LEFT_ALT +#define KC_LGUI KC_LEFT_GUI +#define KC_LCMD KC_LEFT_GUI +#define KC_LWIN KC_LEFT_GUI +#define KC_RCTL KC_RIGHT_CTRL +#define KC_RSFT KC_RIGHT_SHIFT +#define KC_RALT KC_RIGHT_ALT +#define KC_ALGR KC_RIGHT_ALT +#define KC_ROPT KC_RIGHT_ALT +#define KC_RGUI KC_RIGHT_GUI +#define KC_RCMD KC_RIGHT_GUI +#define KC_RWIN KC_RIGHT_GUI /* Generic Desktop Page (0x01) */ -#define KC_PWR KC_SYSTEM_POWER +#define KC_PWR KC_SYSTEM_POWER #define KC_SLEP KC_SYSTEM_SLEEP #define KC_WAKE KC_SYSTEM_WAKE @@ -193,7 +215,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /* System Specific */ #define KC_BRMU KC_PAUSE -#define KC_BRMD KC_SCROLLLOCK +#define KC_BRMD KC_SCROLL_LOCK /* Mouse Keys */ #define KC_MS_U KC_MS_UP @@ -216,6 +238,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define KC_ACL1 KC_MS_ACCEL1 #define KC_ACL2 KC_MS_ACCEL2 +// clang-format on + /* Keyboard/Keypad Page (0x07) */ enum hid_keyboard_keypad_usage { KC_NO = 0x00, @@ -260,22 +284,22 @@ enum hid_keyboard_keypad_usage { KC_0, KC_ENTER, KC_ESCAPE, - KC_BSPACE, + KC_BACKSPACE, KC_TAB, KC_SPACE, KC_MINUS, KC_EQUAL, - KC_LBRACKET, - KC_RBRACKET, // 0x30 - KC_BSLASH, + KC_LEFT_BRACKET, + KC_RIGHT_BRACKET, // 0x30 + KC_BACKSLASH, KC_NONUS_HASH, - KC_SCOLON, + KC_SEMICOLON, KC_QUOTE, KC_GRAVE, KC_COMMA, KC_DOT, KC_SLASH, - KC_CAPSLOCK, + KC_CAPS_LOCK, KC_F1, KC_F2, KC_F3, @@ -288,20 +312,20 @@ enum hid_keyboard_keypad_usage { KC_F10, KC_F11, KC_F12, - KC_PSCREEN, - KC_SCROLLLOCK, + KC_PRINT_SCREEN, + KC_SCROLL_LOCK, KC_PAUSE, KC_INSERT, KC_HOME, - KC_PGUP, + KC_PAGE_UP, KC_DELETE, KC_END, - KC_PGDOWN, + KC_PAGE_DOWN, KC_RIGHT, KC_LEFT, // 0x50 KC_DOWN, KC_UP, - KC_NUMLOCK, + KC_NUM_LOCK, KC_KP_SLASH, KC_KP_ASTERISK, KC_KP_MINUS, @@ -318,9 +342,9 @@ enum hid_keyboard_keypad_usage { KC_KP_9, KC_KP_0, KC_KP_DOT, - KC_NONUS_BSLASH, + KC_NONUS_BACKSLASH, KC_APPLICATION, - KC_POWER, + KC_KB_POWER, KC_KP_EQUAL, KC_F13, KC_F14, @@ -345,34 +369,34 @@ enum hid_keyboard_keypad_usage { KC_COPY, KC_PASTE, KC_FIND, - KC__MUTE, - KC__VOLUP, // 0x80 - KC__VOLDOWN, - KC_LOCKING_CAPS, - KC_LOCKING_NUM, - KC_LOCKING_SCROLL, + KC_KB_MUTE, + KC_KB_VOLUME_UP, // 0x80 + KC_KB_VOLUME_DOWN, + KC_LOCKING_CAPS_LOCK, + KC_LOCKING_NUM_LOCK, + KC_LOCKING_SCROLL_LOCK, KC_KP_COMMA, KC_KP_EQUAL_AS400, - KC_INT1, - KC_INT2, - KC_INT3, - KC_INT4, - KC_INT5, - KC_INT6, - KC_INT7, - KC_INT8, - KC_INT9, - KC_LANG1, // 0x90 - KC_LANG2, - KC_LANG3, - KC_LANG4, - KC_LANG5, - KC_LANG6, - KC_LANG7, - KC_LANG8, - KC_LANG9, - KC_ALT_ERASE, - KC_SYSREQ, + KC_INTERNATIONAL_1, + KC_INTERNATIONAL_2, + KC_INTERNATIONAL_3, + KC_INTERNATIONAL_4, + KC_INTERNATIONAL_5, + KC_INTERNATIONAL_6, + KC_INTERNATIONAL_7, + KC_INTERNATIONAL_8, + KC_INTERNATIONAL_9, + KC_LANGUAGE_1, // 0x90 + KC_LANGUAGE_2, + KC_LANGUAGE_3, + KC_LANGUAGE_4, + KC_LANGUAGE_5, + KC_LANGUAGE_6, + KC_LANGUAGE_7, + KC_LANGUAGE_8, + KC_LANGUAGE_9, + KC_ALTERNATE_ERASE, + KC_SYSTEM_REQUEST, KC_CANCEL, KC_CLEAR, KC_PRIOR, @@ -397,12 +421,12 @@ enum hid_keyboard_keypad_usage { KC_DECIMAL_SEPARATOR, KC_CURRENCY_UNIT, KC_CURRENCY_SUB_UNIT, - KC_KP_LPAREN, - KC_KP_RPAREN, - KC_KP_LCBRACKET, - KC_KP_RCBRACKET, + KC_KP_LEFT_PARENTHESIS, + KC_KP_RIGHT_PARENTHESIS, + KC_KP_LEFT_BRACE, + KC_KP_RIGHT_BRACE, KC_KP_TAB, - KC_KP_BSPACE, + KC_KP_BACKSPACE, KC_KP_A, KC_KP_B, KC_KP_C, @@ -411,17 +435,17 @@ enum hid_keyboard_keypad_usage { KC_KP_F, KC_KP_XOR, KC_KP_HAT, - KC_KP_PERC, - KC_KP_LT, - KC_KP_GT, + KC_KP_PERCENT, + KC_KP_LESS_THAN, + KC_KP_GREATER_THAN, KC_KP_AND, - KC_KP_LAZYAND, + KC_KP_LAZY_AND, KC_KP_OR, - KC_KP_LAZYOR, + KC_KP_LAZY_OR, KC_KP_COLON, KC_KP_HASH, KC_KP_SPACE, - KC_KP_ATMARK, + KC_KP_AT, KC_KP_EXCLAMATION, KC_KP_MEM_STORE, //0xD0 KC_KP_MEM_RECALL, @@ -440,14 +464,14 @@ enum hid_keyboard_keypad_usage { #endif /* Modifiers */ - KC_LCTRL = 0xE0, - KC_LSHIFT, - KC_LALT, - KC_LGUI, - KC_RCTRL, - KC_RSHIFT, - KC_RALT, - KC_RGUI + KC_LEFT_CTRL = 0xE0, + KC_LEFT_SHIFT, + KC_LEFT_ALT, + KC_LEFT_GUI, + KC_RIGHT_CTRL, + KC_RIGHT_SHIFT, + KC_RIGHT_ALT, + KC_RIGHT_GUI // ********************************************** // * 0xF0-0xFF are unallocated in the HID spec. * @@ -558,3 +582,5 @@ enum mouse_keys { KC_MS_ACCEL1, KC_MS_ACCEL2 // 0xFF }; + +#include "keycode_legacy.h" diff --git a/quantum/keycode_config.c b/quantum/keycode_config.c index f340905eab..dd2a17e242 100644 --- a/quantum/keycode_config.c +++ b/quantum/keycode_config.c @@ -25,89 +25,89 @@ extern keymap_config_t keymap_config; */ uint16_t keycode_config(uint16_t keycode) { switch (keycode) { - case KC_CAPSLOCK: - case KC_LOCKING_CAPS: + case KC_CAPS_LOCK: + case KC_LOCKING_CAPS_LOCK: if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) { - return KC_LCTL; + return KC_LEFT_CTRL; } return keycode; - case KC_LCTL: + case KC_LEFT_CTRL: if (keymap_config.swap_control_capslock) { - return KC_CAPSLOCK; + return KC_CAPS_LOCK; } if (keymap_config.swap_lctl_lgui) { if (keymap_config.no_gui) { return KC_NO; } - return KC_LGUI; + return KC_LEFT_GUI; } - return KC_LCTL; - case KC_LALT: + return KC_LEFT_CTRL; + case KC_LEFT_ALT: if (keymap_config.swap_lalt_lgui) { if (keymap_config.no_gui) { return KC_NO; } - return KC_LGUI; + return KC_LEFT_GUI; } - return KC_LALT; - case KC_LGUI: + return KC_LEFT_ALT; + case KC_LEFT_GUI: if (keymap_config.swap_lalt_lgui) { - return KC_LALT; + return KC_LEFT_ALT; } if (keymap_config.swap_lctl_lgui) { - return KC_LCTRL; + return KC_LEFT_CTRL; } if (keymap_config.no_gui) { return KC_NO; } - return KC_LGUI; - case KC_RCTL: + return KC_LEFT_GUI; + case KC_RIGHT_CTRL: if (keymap_config.swap_rctl_rgui) { if (keymap_config.no_gui) { return KC_NO; } - return KC_RGUI; + return KC_RIGHT_GUI; } - return KC_RCTL; - case KC_RALT: + return KC_RIGHT_CTRL; + case KC_RIGHT_ALT: if (keymap_config.swap_ralt_rgui) { if (keymap_config.no_gui) { return KC_NO; } - return KC_RGUI; + return KC_RIGHT_GUI; } - return KC_RALT; - case KC_RGUI: + return KC_RIGHT_ALT; + case KC_RIGHT_GUI: if (keymap_config.swap_ralt_rgui) { - return KC_RALT; + return KC_RIGHT_ALT; } if (keymap_config.swap_rctl_rgui) { - return KC_RCTL; + return KC_RIGHT_CTRL; } if (keymap_config.no_gui) { return KC_NO; } - return KC_RGUI; + return KC_RIGHT_GUI; case KC_GRAVE: if (keymap_config.swap_grave_esc) { - return KC_ESC; + return KC_ESCAPE; } return KC_GRAVE; - case KC_ESC: + case KC_ESCAPE: if (keymap_config.swap_grave_esc) { return KC_GRAVE; } - return KC_ESC; - case KC_BSLASH: + return KC_ESCAPE; + case KC_BACKSLASH: if (keymap_config.swap_backslash_backspace) { - return KC_BSPACE; + return KC_BACKSPACE; } - return KC_BSLASH; - case KC_BSPACE: + return KC_BACKSLASH; + case KC_BACKSPACE: if (keymap_config.swap_backslash_backspace) { - return KC_BSLASH; + return KC_BACKSLASH; } - return KC_BSPACE; + return KC_BACKSPACE; default: return keycode; } diff --git a/quantum/keycode_legacy.h b/quantum/keycode_legacy.h new file mode 100644 index 0000000000..0317a05534 --- /dev/null +++ b/quantum/keycode_legacy.h @@ -0,0 +1,53 @@ +#pragma once + +// clang-format off + +// These keycode names have been deprecated + +#define KC_BSPACE KC_BACKSPACE +#define KC_LBRACKET KC_LEFT_BRACKET +#define KC_RBRACKET KC_RIGHT_BRACKET +#define KC_BSLASH KC_BACKSLASH +#define KC_SCOLON KC_SEMICOLON +#define KC_CAPSLOCK KC_CAPS_LOCK +#define KC_PSCREEN KC_PRINT_SCREEN +#define KC_SCROLLLOCK KC_SCROLL_LOCK +#define KC_PGDOWN KC_PAGE_DOWN +#define KC_NUMLOCK KC_NUM_LOCK +#define KC_NONUS_BSLASH KC_NONUS_BACKSLASH +#define KC_POWER KC_KB_POWER +#define KC__MUTE KC_KB_MUTE +#define KC__VOLUP KC_KB_VOLUME_UP +#define KC__VOLDOWN KC_KB_VOLUME_DOWN +#define KC_LOCKING_CAPS KC_LOCKING_CAPS_LOCK +#define KC_LOCKING_NUM KC_LOCKING_NUM_LOCK +#define KC_LOCKING_SCROLL KC_LOCKING_SCROLL_LOCK +#define KC_LANG1 KC_LANGUAGE_1 +#define KC_LANG2 KC_LANGUAGE_2 +#define KC_LANG3 KC_LANGUAGE_3 +#define KC_LANG4 KC_LANGUAGE_4 +#define KC_LANG5 KC_LANGUAGE_5 +#define KC_LANG6 KC_LANGUAGE_6 +#define KC_LANG7 KC_LANGUAGE_7 +#define KC_LANG8 KC_LANGUAGE_8 +#define KC_LANG9 KC_LANGUAGE_9 +#define KC_ALT_ERASE KC_ALTERNATE_ERASE +#define KC_SYSREQ KC_SYSTEM_REQUEST + +#define KC_LCTRL KC_LEFT_CTRL +#define KC_LSHIFT KC_LEFT_SHIFT +#define KC_RCTRL KC_RIGHT_CTRL +#define KC_RSHIFT KC_RIGHT_SHIFT + +#define KC_ZKHK KC_GRAVE +#define KC_RO KC_INTERNATIONAL_1 +#define KC_KANA KC_INTERNATIONAL_2 +#define KC_JYEN KC_INTERNATIONAL_3 +#define KC_HENK KC_INTERNATIONAL_4 +#define KC_MHEN KC_INTERNATIONAL_5 +#define KC_HAEN KC_LANGUAGE_1 +#define KC_HANJ KC_LANGUAGE_2 + +#define KC_CLCK KC_CAPS_LOCK +#define KC_SLCK KC_SCROLL_LOCK +#define KC_NLCK KC_NUM_LOCK diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 780c71ab9b..5007f15f11 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -56,7 +56,7 @@ action_t action_for_keycode(uint16_t keycode) { switch (keycode) { case KC_A ... KC_EXSEL: - case KC_LCTRL ... KC_RGUI: + case KC_LEFT_CTRL ... KC_RIGHT_GUI: action.code = ACTION_KEY(keycode); break; #ifdef EXTRAKEY_ENABLE @@ -72,7 +72,7 @@ action_t action_for_keycode(uint16_t keycode) { action.code = ACTION_MOUSEKEY(keycode); break; #endif - case KC_TRNS: + case KC_TRANSPARENT: action.code = ACTION_TRANSPARENT; break; case QK_MODS ... QK_MODS_MAX:; diff --git a/quantum/keymap_extras/keymap_korean.h b/quantum/keymap_extras/keymap_korean.h index 23d235ef09..74be122dad 100644 --- a/quantum/keymap_extras/keymap_korean.h +++ b/quantum/keymap_extras/keymap_korean.h @@ -85,8 +85,8 @@ #define KR_DOT KC_DOT // . #define KR_SLSH KC_SLSH // / // Row 5 -#define KR_HANJ KC_LANG2 // Hanja (한자) -#define KR_HAEN KC_LANG1 // Han ↔ Yeong (한 ↔ 영) +#define KR_HANJ KC_LNG2 // Hanja (한자) +#define KR_HAEN KC_LNG1 // Han ↔ Yeong (한 ↔ 영) /* Shifted symbols * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ diff --git a/quantum/keymap_extras/keymap_turkish_f.h b/quantum/keymap_extras/keymap_turkish_f.h index 226f8cbeb0..f86ef21546 100644 --- a/quantum/keymap_extras/keymap_turkish_f.h +++ b/quantum/keymap_extras/keymap_turkish_f.h @@ -111,7 +111,7 @@ #define TR_LPRN S(TR_8) // ( #define TR_RPRN S(TR_9) // ) #define TR_EQL S(TR_0) // = -#define TR_QUES S(TR_ASTR) // ? +#define TR_QUES S(TR_SLSH) // ? #define TR_UNDS S(TR_MINS) // _ // Row 4 #define TR_RABK S(TR_LABK) // > diff --git a/quantum/led_matrix/animations/alpha_mods_anim.h b/quantum/led_matrix/animations/alpha_mods_anim.h index 14038cd082..4d017894a1 100644 --- a/quantum/led_matrix/animations/alpha_mods_anim.h +++ b/quantum/led_matrix/animations/alpha_mods_anim.h @@ -17,8 +17,8 @@ bool ALPHAS_MODS(effect_params_t* params) { led_matrix_set_value(i, val1); } } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_ALPHAS_MODS +#endif // ENABLE_LED_MATRIX_ALPHAS_MODS diff --git a/quantum/led_matrix/animations/band_anim.h b/quantum/led_matrix/animations/band_anim.h index 5548787b88..293be4f67a 100644 --- a/quantum/led_matrix/animations/band_anim.h +++ b/quantum/led_matrix/animations/band_anim.h @@ -10,4 +10,4 @@ static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) { bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_BAND +#endif // ENABLE_LED_MATRIX_BAND diff --git a/quantum/led_matrix/animations/band_pinwheel_anim.h b/quantum/led_matrix/animations/band_pinwheel_anim.h index 89651582d5..f47a3869ce 100644 --- a/quantum/led_matrix/animations/band_pinwheel_anim.h +++ b/quantum/led_matrix/animations/band_pinwheel_anim.h @@ -7,4 +7,4 @@ static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t t bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL +#endif // ENABLE_LED_MATRIX_BAND_PINWHEEL diff --git a/quantum/led_matrix/animations/band_spiral_anim.h b/quantum/led_matrix/animations/band_spiral_anim.h index 70b0ffaea9..a4bd382181 100644 --- a/quantum/led_matrix/animations/band_spiral_anim.h +++ b/quantum/led_matrix/animations/band_spiral_anim.h @@ -7,4 +7,4 @@ static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dis bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_BAND_SPIRAL +#endif // ENABLE_LED_MATRIX_BAND_SPIRAL diff --git a/quantum/led_matrix/animations/breathing_anim.h b/quantum/led_matrix/animations/breathing_anim.h index e3f600c45c..899925f516 100644 --- a/quantum/led_matrix/animations/breathing_anim.h +++ b/quantum/led_matrix/animations/breathing_anim.h @@ -12,8 +12,8 @@ bool BREATHING(effect_params_t* params) { LED_MATRIX_TEST_LED_FLAGS(); led_matrix_set_value(i, val); } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_BREATHING +#endif // ENABLE_LED_MATRIX_BREATHING diff --git a/quantum/led_matrix/animations/cycle_left_right_anim.h b/quantum/led_matrix/animations/cycle_left_right_anim.h index 769e6d7942..1a8999b831 100644 --- a/quantum/led_matrix/animations/cycle_left_right_anim.h +++ b/quantum/led_matrix/animations/cycle_left_right_anim.h @@ -7,4 +7,4 @@ static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { ret bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT +#endif // ENABLE_LED_MATRIX_CYCLE_LEFT_RIGHT diff --git a/quantum/led_matrix/animations/cycle_out_in_anim.h b/quantum/led_matrix/animations/cycle_out_in_anim.h index 6adf9c25ff..77d3a14b6f 100644 --- a/quantum/led_matrix/animations/cycle_out_in_anim.h +++ b/quantum/led_matrix/animations/cycle_out_in_anim.h @@ -7,4 +7,4 @@ static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t di bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN +#endif // ENABLE_LED_MATRIX_CYCLE_OUT_IN diff --git a/quantum/led_matrix/animations/cycle_up_down_anim.h b/quantum/led_matrix/animations/cycle_up_down_anim.h index 7a5868ac26..b25947199c 100644 --- a/quantum/led_matrix/animations/cycle_up_down_anim.h +++ b/quantum/led_matrix/animations/cycle_up_down_anim.h @@ -7,4 +7,4 @@ static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN +#endif // ENABLE_LED_MATRIX_CYCLE_UP_DOWN diff --git a/quantum/led_matrix/animations/dual_beacon_anim.h b/quantum/led_matrix/animations/dual_beacon_anim.h index 3552c9fc39..81735e323c 100644 --- a/quantum/led_matrix/animations/dual_beacon_anim.h +++ b/quantum/led_matrix/animations/dual_beacon_anim.h @@ -7,4 +7,4 @@ static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_DUAL_BEACON +#endif // ENABLE_LED_MATRIX_DUAL_BEACON diff --git a/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h index ef97631b90..fa9b7dbbfa 100644 --- a/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h +++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h @@ -12,5 +12,5 @@ bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) { int16_t dy = g_led_config.point[i].y - k_led_matrix_center.y; led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, time)); } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } diff --git a/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h index 5ef5938be0..061a5f07fe 100644 --- a/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h +++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h @@ -13,5 +13,5 @@ bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func) uint8_t dist = sqrt16(dx * dx + dy * dy); led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, dist, time)); } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } diff --git a/quantum/led_matrix/animations/runners/effect_runner_i.h b/quantum/led_matrix/animations/runners/effect_runner_i.h index b3015759be..f6f8c0dee0 100644 --- a/quantum/led_matrix/animations/runners/effect_runner_i.h +++ b/quantum/led_matrix/animations/runners/effect_runner_i.h @@ -10,5 +10,5 @@ bool effect_runner_i(effect_params_t* params, i_f effect_func) { LED_MATRIX_TEST_LED_FLAGS(); led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, i, time)); } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } diff --git a/quantum/led_matrix/animations/runners/effect_runner_reactive.h b/quantum/led_matrix/animations/runners/effect_runner_reactive.h index 4369ea8c49..be3090aa53 100644 --- a/quantum/led_matrix/animations/runners/effect_runner_reactive.h +++ b/quantum/led_matrix/animations/runners/effect_runner_reactive.h @@ -22,7 +22,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) { uint16_t offset = scale16by8(tick, led_matrix_eeconfig.speed); led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, offset)); } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } #endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h index d6eb9731ee..f6ffc825a1 100644 --- a/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h +++ b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h @@ -20,7 +20,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react } led_matrix_set_value(i, scale8(val, led_matrix_eeconfig.val)); } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } #endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h index 4a5219abd1..3145e27139 100644 --- a/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h +++ b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h @@ -12,5 +12,5 @@ bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) { LED_MATRIX_TEST_LED_FLAGS(); led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, cos_value, sin_value, i, time)); } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } diff --git a/quantum/led_matrix/animations/solid_anim.h b/quantum/led_matrix/animations/solid_anim.h index 4c9e43c581..c728dbcc98 100644 --- a/quantum/led_matrix/animations/solid_anim.h +++ b/quantum/led_matrix/animations/solid_anim.h @@ -9,7 +9,7 @@ bool SOLID(effect_params_t* params) { LED_MATRIX_TEST_LED_FLAGS(); led_matrix_set_value(i, val); } - return led_max < DRIVER_LED_TOTAL; + return led_matrix_check_finished_leds(led_max); } #endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/quantum/led_matrix/animations/solid_reactive_cross.h b/quantum/led_matrix/animations/solid_reactive_cross.h index 3a3c46be13..a149e9a929 100644 --- a/quantum/led_matrix/animations/solid_reactive_cross.h +++ b/quantum/led_matrix/animations/solid_reactive_cross.h @@ -1,5 +1,5 @@ #ifdef LED_MATRIX_KEYREACTIVE_ENABLED -# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) +# if defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) # ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS LED_MATRIX_EFFECT(SOLID_REACTIVE_CROSS) @@ -31,5 +31,5 @@ bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_r # endif # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) +# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) #endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix/animations/solid_reactive_nexus.h b/quantum/led_matrix/animations/solid_reactive_nexus.h index 2520b8e1df..5a86e48c6c 100644 --- a/quantum/led_matrix/animations/solid_reactive_nexus.h +++ b/quantum/led_matrix/animations/solid_reactive_nexus.h @@ -28,5 +28,5 @@ bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_r # endif # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) +# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) #endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix/animations/solid_reactive_simple_anim.h b/quantum/led_matrix/animations/solid_reactive_simple_anim.h index 43f6ad9ab4..14f5e90730 100644 --- a/quantum/led_matrix/animations/solid_reactive_simple_anim.h +++ b/quantum/led_matrix/animations/solid_reactive_simple_anim.h @@ -8,5 +8,5 @@ static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE +# endif // ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE #endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix/animations/solid_reactive_wide.h b/quantum/led_matrix/animations/solid_reactive_wide.h index d683b02510..3aa88063a7 100644 --- a/quantum/led_matrix/animations/solid_reactive_wide.h +++ b/quantum/led_matrix/animations/solid_reactive_wide.h @@ -1,5 +1,5 @@ #ifdef LED_MATRIX_KEYREACTIVE_ENABLED -# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) +# if !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) # ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE LED_MATRIX_EFFECT(SOLID_REACTIVE_WIDE) @@ -26,5 +26,5 @@ bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_re # endif # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) +# endif // !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) #endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix/animations/solid_splash_anim.h b/quantum/led_matrix/animations/solid_splash_anim.h index cf599c8fe6..17b692a09a 100644 --- a/quantum/led_matrix/animations/solid_splash_anim.h +++ b/quantum/led_matrix/animations/solid_splash_anim.h @@ -1,5 +1,5 @@ #ifdef LED_MATRIX_KEYREACTIVE_ENABLED -# if !defined(DISABLE_LED_MATRIX_SOLID_SPLASH) || !defined(DISABLE_LED_MATRIX_SOLID_MULTISPLASH) +# if defined(ENABLE_LED_MATRIX_SOLID_SPLASH) || defined(ENABLE_LED_MATRIX_SOLID_MULTISPLASH) # ifdef ENABLE_LED_MATRIX_SOLID_SPLASH LED_MATRIX_EFFECT(SOLID_SPLASH) @@ -26,5 +26,5 @@ bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_ # endif # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) +# endif // defined(ENABLE_LED_MATRIX_SPLASH) || defined(ENABLE_LED_MATRIX_MULTISPLASH) #endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix/animations/wave_left_right_anim.h b/quantum/led_matrix/animations/wave_left_right_anim.h index c062cf968e..76487f8515 100644 --- a/quantum/led_matrix/animations/wave_left_right_anim.h +++ b/quantum/led_matrix/animations/wave_left_right_anim.h @@ -7,4 +7,4 @@ static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { retu bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT +#endif // ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT diff --git a/quantum/led_matrix/animations/wave_up_down_anim.h b/quantum/led_matrix/animations/wave_up_down_anim.h index 5e612f6b6d..94710f5c6e 100644 --- a/quantum/led_matrix/animations/wave_up_down_anim.h +++ b/quantum/led_matrix/animations/wave_up_down_anim.h @@ -7,4 +7,4 @@ static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN +#endif // ENABLE_LED_MATRIX_WAVE_UP_DOWN diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c index 50510e49aa..be1494e884 100644 --- a/quantum/led_matrix/led_matrix.c +++ b/quantum/led_matrix/led_matrix.c @@ -33,14 +33,6 @@ const led_point_t k_led_matrix_center = {112, 32}; const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; #endif -// clang-format off -#ifndef LED_MATRIX_IMMEDIATE_EEPROM -# define led_eeconfig_update(v) led_update_eeprom |= v -#else -# define led_eeconfig_update(v) if (v) eeconfig_update_led_matrix() -#endif -// clang-format on - // Generic effect runners #include "led_matrix_runners.inc" @@ -107,7 +99,6 @@ last_hit_t g_last_hit_tracker; // internals static bool suspend_state = false; -static bool led_update_eeprom = false; static uint8_t led_last_enable = UINT8_MAX; static uint8_t led_last_effect = UINT8_MAX; static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; @@ -127,9 +118,9 @@ static last_hit_t last_hit_buffer; const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; #endif -void eeconfig_read_led_matrix(void) { eeprom_read_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); } +EECONFIG_DEBOUNCE_HELPER(led_matrix, EECONFIG_LED_MATRIX, led_matrix_eeconfig); -void eeconfig_update_led_matrix(void) { eeprom_update_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); } +void eeconfig_update_led_matrix(void) { eeconfig_flush_led_matrix(true); } void eeconfig_update_led_matrix_default(void) { dprintf("eeconfig_update_led_matrix_default\n"); @@ -138,7 +129,7 @@ void eeconfig_update_led_matrix_default(void) { led_matrix_eeconfig.val = LED_MATRIX_STARTUP_VAL; led_matrix_eeconfig.speed = LED_MATRIX_STARTUP_SPD; led_matrix_eeconfig.flags = LED_FLAG_ALL; - eeconfig_update_led_matrix(); + eeconfig_flush_led_matrix(true); } void eeconfig_debug_led_matrix(void) { @@ -165,20 +156,10 @@ uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l void led_matrix_update_pwm_buffers(void) { led_matrix_driver.flush(); } void led_matrix_set_value(int index, uint8_t value) { -#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) - if (!is_keyboard_left() && index >= k_led_matrix_split[0]) -# ifdef USE_CIE1931_CURVE - led_matrix_driver.set_value(index - k_led_matrix_split[0], pgm_read_byte(&CIE1931_CURVE[value])); -# else - led_matrix_driver.set_value(index - k_led_matrix_split[0], value); -# endif - else if (is_keyboard_left() && index < k_led_matrix_split[0]) -#endif #ifdef USE_CIE1931_CURVE - led_matrix_driver.set_value(index, pgm_read_byte(&CIE1931_CURVE[value])); -#else - led_matrix_driver.set_value(index, value); + value = pgm_read_byte(&CIE1931_CURVE[value]); #endif + led_matrix_driver.set_value(index, value); } void led_matrix_set_value_all(uint8_t value) { @@ -232,11 +213,11 @@ void process_led_matrix(uint8_t row, uint8_t col, bool pressed) { } #endif // LED_MATRIX_KEYREACTIVE_ENABLED -#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP) +#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP) if (led_matrix_eeconfig.mode == LED_MATRIX_TYPING_HEATMAP) { process_led_matrix_typing_heatmap(row, col); } -#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP) +#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP) } static bool led_matrix_none(effect_params_t *params) { @@ -279,9 +260,8 @@ static void led_task_timers(void) { } static void led_task_sync(void) { + eeconfig_flush_led_matrix(false); // next task - if (led_update_eeprom) eeconfig_update_led_matrix(); - led_update_eeprom = false; if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING; } @@ -449,7 +429,7 @@ void led_matrix_init(void) { eeconfig_update_led_matrix_default(); } - eeconfig_read_led_matrix(); + eeconfig_init_led_matrix(); if (!led_matrix_eeconfig.mode) { dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n"); eeconfig_update_led_matrix_default(); @@ -472,7 +452,7 @@ bool led_matrix_get_suspend_state(void) { return suspend_state; } void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { led_matrix_eeconfig.enable ^= 1; led_task_state = STARTING; - led_eeconfig_update(write_to_eeprom); + eeconfig_flag_led_matrix(write_to_eeprom); dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable); } void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); } @@ -480,7 +460,7 @@ void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); } void led_matrix_enable(void) { led_matrix_enable_noeeprom(); - led_eeconfig_update(true); + eeconfig_flag_led_matrix(true); } void led_matrix_enable_noeeprom(void) { @@ -490,7 +470,7 @@ void led_matrix_enable_noeeprom(void) { void led_matrix_disable(void) { led_matrix_disable_noeeprom(); - led_eeconfig_update(true); + eeconfig_flag_led_matrix(true); } void led_matrix_disable_noeeprom(void) { @@ -512,7 +492,7 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { led_matrix_eeconfig.mode = mode; } led_task_state = STARTING; - led_eeconfig_update(write_to_eeprom); + eeconfig_flag_led_matrix(write_to_eeprom); dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode); } void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); } @@ -539,7 +519,7 @@ void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) { return; } led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; - led_eeconfig_update(write_to_eeprom); + eeconfig_flag_led_matrix(write_to_eeprom); dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val); } void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); } @@ -557,7 +537,7 @@ void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); } void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { led_matrix_eeconfig.speed = speed; - led_eeconfig_update(write_to_eeprom); + eeconfig_flag_led_matrix(write_to_eeprom); dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed); } void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); } diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h index a7a1c983f7..e42be64661 100644 --- a/quantum/led_matrix/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h @@ -23,7 +23,6 @@ #include <stdbool.h> #include "led_matrix_types.h" #include "quantum.h" -#include "led_matrix_legacy_enables.h" #ifdef IS31FL3731 # include "is31fl3731-simple.h" @@ -38,14 +37,33 @@ #endif #if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL -# define LED_MATRIX_USE_LIMITS(min, max) \ - uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \ - uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \ - if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; +# if defined(LED_MATRIX_SPLIT) +# define LED_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \ + uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \ + if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; \ + uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; \ + if (is_keyboard_left() && (max > k_led_matrix_split[0])) max = k_led_matrix_split[0]; \ + if (!(is_keyboard_left()) && (min < k_led_matrix_split[0])) min = k_led_matrix_split[0]; +# else +# define LED_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \ + uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \ + if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; +# endif #else -# define LED_MATRIX_USE_LIMITS(min, max) \ - uint8_t min = 0; \ - uint8_t max = DRIVER_LED_TOTAL; +# if defined(LED_MATRIX_SPLIT) +# define LED_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = 0; \ + uint8_t max = DRIVER_LED_TOTAL; \ + const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; \ + if (is_keyboard_left() && (max > k_led_matrix_split[0])) max = k_led_matrix_split[0]; \ + if (!(is_keyboard_left()) && (min < k_led_matrix_split[0])) min = k_led_matrix_split[0]; +# else +# define LED_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = 0; \ + uint8_t max = DRIVER_LED_TOTAL; +# endif #endif #define LED_MATRIX_TEST_LED_FLAGS() \ @@ -147,6 +165,18 @@ typedef struct { void (*flush)(void); } led_matrix_driver_t; +static inline bool led_matrix_check_finished_leds(uint8_t led_idx) { +#if defined(LED_MATRIX_SPLIT) + if (is_keyboard_left()) { + uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; + return led_idx < k_led_matrix_split[0]; + } else + return led_idx < DRIVER_LED_TOTAL; +#else + return led_idx < DRIVER_LED_TOTAL; +#endif +} + extern const led_matrix_driver_t led_matrix_driver; extern led_eeconfig_t led_matrix_eeconfig; diff --git a/quantum/led_matrix/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c index 1d46b2c506..2157619a0b 100644 --- a/quantum/led_matrix/led_matrix_drivers.c +++ b/quantum/led_matrix/led_matrix_drivers.c @@ -26,128 +26,123 @@ */ #if defined(IS31FL3731) || defined(IS31FL3733) - # include "i2c_master.h" static void init(void) { i2c_init(); -# ifdef IS31FL3731 -# ifdef LED_DRIVER_ADDR_1 + +# if defined(IS31FL3731) IS31FL3731_init(LED_DRIVER_ADDR_1); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3731_init(LED_DRIVER_ADDR_2); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3731_init(LED_DRIVER_ADDR_3); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3731_init(LED_DRIVER_ADDR_4); -# endif -# else -# ifdef LED_DRIVER_ADDR_1 -# ifndef LED_DRIVER_SYNC_1 -# define LED_DRIVER_SYNC_1 0 +# endif # endif - IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1); # endif -# ifdef LED_DRIVER_ADDR_2 -# ifndef LED_DRIVER_SYNC_2 + +# elif defined(IS31FL3733) +# if !defined(LED_DRIVER_SYNC_1) +# define LED_DRIVER_SYNC_1 0 +# endif + IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1); +# if defined(LED_DRIVER_ADDR_2) +# if !defined(LED_DRIVER_SYNC_2) # define LED_DRIVER_SYNC_2 0 # endif IS31FL3733_init(LED_DRIVER_ADDR_2, LED_DRIVER_SYNC_2); -# endif -# ifdef LED_DRIVER_ADDR_3 -# ifndef LED_DRIVER_SYNC_3 -# define LED_DRIVER_SYNC_3 0 -# endif +# if defined(LED_DRIVER_ADDR_3) +# if !defined(LED_DRIVER_SYNC_3) +# define LED_DRIVER_SYNC_3 0 +# endif IS31FL3733_init(LED_DRIVER_ADDR_3, LED_DRIVER_SYNC_3); -# endif -# ifdef LED_DRIVER_ADDR_4 -# ifndef LED_DRIVER_SYNC_4 -# define LED_DRIVER_SYNC_4 0 -# endif +# if defined(LED_DRIVER_ADDR_4) +# if !defined(LED_DRIVER_SYNC_4) +# define LED_DRIVER_SYNC_4 0 +# endif IS31FL3733_init(LED_DRIVER_ADDR_4, LED_DRIVER_SYNC_4); +# endif +# endif # endif # endif for (int index = 0; index < DRIVER_LED_TOTAL; index++) { -# ifdef IS31FL3731 +# if defined(IS31FL3731) IS31FL3731_set_led_control_register(index, true); -# else +# elif defined(IS31FL3733) IS31FL3733_set_led_control_register(index, true); # endif } + // This actually updates the LED drivers -# ifdef IS31FL3731 -# ifdef LED_DRIVER_ADDR_1 +# if defined(IS31FL3731) IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_1, 0); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_2, 1); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_3, 2); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_4, 3); +# endif +# endif # endif -# else -# ifdef LED_DRIVER_ADDR_1 + +# elif defined(IS31FL3733) IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_1, 0); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_2, 1); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_3, 2); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_4, 3); +# endif +# endif # endif # endif } +# if defined(IS31FL3731) static void flush(void) { -# ifdef IS31FL3731 -# ifdef LED_DRIVER_ADDR_1 IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_1, 0); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_2, 1); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_3, 2); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_4, 3); +# endif +# endif # endif -# else -# ifdef LED_DRIVER_ADDR_1 +} + +const led_matrix_driver_t led_matrix_driver = { + .init = init, + .flush = flush, + .set_value = IS31FL3731_set_value, + .set_value_all = IS31FL3731_set_value_all, +}; + +# elif defined(IS31FL3733) +static void flush(void) { IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_1, 0); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_2, 1); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_3, 2); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_4, 3); +# endif +# endif # endif -# endif } const led_matrix_driver_t led_matrix_driver = { - .init = init, + .init = init, .flush = flush, -# ifdef IS31FL3731 - .set_value = IS31FL3731_set_value, - .set_value_all = IS31FL3731_set_value_all, -# else .set_value = IS31FL3733_set_value, .set_value_all = IS31FL3733_set_value_all, -# endif }; - +# endif #endif diff --git a/quantum/led_matrix/led_matrix_legacy_enables.h b/quantum/led_matrix/led_matrix_legacy_enables.h deleted file mode 100644 index 7738d2f34e..0000000000 --- a/quantum/led_matrix/led_matrix_legacy_enables.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright 2021 QMK - * - * 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/>. - */ - -// to-do: remove this - -#pragma once - -#ifndef DISABLE_LED_MATRIX_ALPHAS_MODS -# define ENABLE_LED_MATRIX_ALPHAS_MODS -#endif -#ifndef DISABLE_LED_MATRIX_BREATHING -# define ENABLE_LED_MATRIX_BREATHING -#endif -#ifndef DISABLE_LED_MATRIX_BAND -# define ENABLE_LED_MATRIX_BAND -#endif -#ifndef DISABLE_LED_MATRIX_BAND_PINWHEEL -# define ENABLE_LED_MATRIX_BAND_PINWHEEL -#endif -#ifndef DISABLE_LED_MATRIX_BAND_SPIRAL -# define ENABLE_LED_MATRIX_BAND_SPIRAL -#endif -#ifndef DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT -# define ENABLE_LED_MATRIX_CYCLE_LEFT_RIGHT -#endif -#ifndef DISABLE_LED_MATRIX_CYCLE_UP_DOWN -# define ENABLE_LED_MATRIX_CYCLE_UP_DOWN -#endif -#ifndef DISABLE_LED_MATRIX_CYCLE_OUT_IN -# define ENABLE_LED_MATRIX_CYCLE_OUT_IN -#endif -#ifndef DISABLE_LED_MATRIX_DUAL_BEACON -# define ENABLE_LED_MATRIX_DUAL_BEACON -#endif -#if defined(LED_MATRIX_KEYREACTIVE_ENABLED) -# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE -# define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE -# endif -# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE -# define ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE -# endif -# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE -# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE -# endif -# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS -# define ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS -# endif -# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS -# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS -# endif -# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS -# define ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS -# endif -# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS -# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS -# endif -# ifndef DISABLE_LED_MATRIX_SPLASH -# define ENABLE_LED_MATRIX_SPLASH -# endif -# ifndef DISABLE_LED_MATRIX_MULTISPLASH -# define ENABLE_LED_MATRIX_MULTISPLASH -# endif -#endif -#ifndef DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT -# define ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT -#endif -#ifndef DISABLE_LED_MATRIX_WAVE_UP_DOWN -# define ENABLE_LED_MATRIX_WAVE_UP_DOWN -#endif diff --git a/quantum/main.c b/quantum/main.c index 2cbcd73d8f..6ed6b95741 100644 --- a/quantum/main.c +++ b/quantum/main.c @@ -19,8 +19,33 @@ void platform_setup(void); void protocol_setup(void); -void protocol_init(void); -void protocol_task(void); +void protocol_pre_init(void); +void protocol_post_init(void); +void protocol_pre_task(void); +void protocol_post_task(void); + +// Bodge as refactoring this area sucks.... +void protocol_init(void) __attribute__((weak)); +void protocol_init(void) { + protocol_pre_init(); + + keyboard_init(); + + protocol_post_init(); +} + +void protocol_task(void) __attribute__((weak)); +void protocol_task(void) { + protocol_pre_task(); + + keyboard_task(); + + protocol_post_task(); +} + +#ifdef DEFERRED_EXEC_ENABLE +void deferred_exec_task(void); +#endif // DEFERRED_EXEC_ENABLE /** \brief Main * @@ -30,12 +55,19 @@ int main(void) __attribute__((weak)); int main(void) { platform_setup(); protocol_setup(); + keyboard_setup(); protocol_init(); /* Main loop */ while (true) { protocol_task(); + +#ifdef DEFERRED_EXEC_ENABLE + // Run deferred executions + deferred_exec_task(); +#endif // DEFERRED_EXEC_ENABLE + housekeeping_task(); } } diff --git a/quantum/matrix.c b/quantum/matrix.c index 33586c431b..483d518ecc 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -69,7 +69,7 @@ uint8_t thisHand, thatHand; // user-defined overridable functions __attribute__((weak)) void matrix_init_pins(void); __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); -__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); +__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter); #ifdef SPLIT_KEYBOARD __attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); } __attribute__((weak)) void matrix_slave_scan_user(void) {} @@ -113,10 +113,11 @@ __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[] // Start with a clear matrix row matrix_row_t current_row_value = 0; - for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { + matrix_row_t row_shifter = MATRIX_ROW_SHIFTER; + for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) { pin_t pin = direct_pins[current_row][col_index]; if (pin != NO_PIN) { - current_row_value |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index); + current_row_value |= readPin(pin) ? 0 : row_shifter; } } @@ -169,11 +170,12 @@ __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[] matrix_output_select_delay(); // For each col... - for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { + matrix_row_t row_shifter = MATRIX_ROW_SHIFTER; + for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) { uint8_t pin_state = readMatrixPin(col_pins[col_index]); // Populate the matrix row with the state of the col pin - current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); + current_row_value |= pin_state ? 0 : row_shifter; } // Unselect row @@ -217,7 +219,7 @@ __attribute__((weak)) void matrix_init_pins(void) { } } -__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { +__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter) { bool key_pressed = false; // Select col @@ -231,11 +233,11 @@ __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[] // Check row pin state if (readMatrixPin(row_pins[row_index]) == 0) { // Pin LO, set col bit - current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col); + current_matrix[row_index] |= row_shifter; key_pressed = true; } else { // Pin HI, clear col bit - current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col); + current_matrix[row_index] &= ~row_shifter; } } @@ -288,10 +290,8 @@ void matrix_init(void) { matrix_init_pins(); // initialize matrix state: all keys off - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - raw_matrix[i] = 0; - matrix[i] = 0; - } + memset(matrix, 0, sizeof(matrix)); + memset(raw_matrix, 0, sizeof(raw_matrix)); debounce_init(ROWS_PER_HAND); @@ -312,24 +312,22 @@ __attribute__((weak)) bool transport_master_if_connected(matrix_row_t master_mat bool matrix_post_scan(void) { bool changed = false; if (is_keyboard_master()) { + static bool last_connected = false; matrix_row_t slave_matrix[ROWS_PER_HAND] = {0}; if (transport_master_if_connected(matrix + thisHand, slave_matrix)) { - for (int i = 0; i < ROWS_PER_HAND; ++i) { - if (matrix[thatHand + i] != slave_matrix[i]) { - matrix[thatHand + i] = slave_matrix[i]; - changed = true; - } - } - } else { - // reset other half if disconnected - for (int i = 0; i < ROWS_PER_HAND; ++i) { - matrix[thatHand + i] = 0; - slave_matrix[i] = 0; - } + changed = memcmp(matrix + thatHand, slave_matrix, sizeof(slave_matrix)) != 0; + last_connected = true; + } else if (last_connected) { + // reset other half when disconnected + memset(slave_matrix, 0, sizeof(slave_matrix)); changed = true; + + last_connected = false; } + if (changed) memcpy(matrix + thatHand, slave_matrix, sizeof(slave_matrix)); + matrix_scan_quantum(); } else { transport_slave(matrix + thatHand, matrix + thisHand); @@ -351,8 +349,9 @@ uint8_t matrix_scan(void) { } #elif (DIODE_DIRECTION == ROW2COL) // Set col, read rows - for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { - matrix_read_rows_on_col(curr_matrix, current_col); + matrix_row_t row_shifter = MATRIX_ROW_SHIFTER; + for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++, row_shifter <<= 1) { + matrix_read_rows_on_col(curr_matrix, current_col, row_shifter); } #endif diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk deleted file mode 100644 index 3b86433a86..0000000000 --- a/quantum/mcu_selection.mk +++ /dev/null @@ -1,600 +0,0 @@ -MCU_ORIG := $(MCU) - -ifneq ($(findstring MKL26Z64, $(MCU)),) - # Cortex version - MCU = cortex-m0plus - - # 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 = KINETIS - MCU_SERIES = KL2x - - # Linker script to use - # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= MKL26Z64 - - # Startup code to use - # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= kl2x - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= PJRC_TEENSY_LC -endif - -ifneq ($(findstring MK20DX128, $(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 = KINETIS - MCU_SERIES = K20x - - # Linker script to use - # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= MK20DX128 - - # Startup code to use - # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= k20x5 - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= PJRC_TEENSY_3 -endif - -ifneq ($(findstring MK20DX256, $(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 = KINETIS - MCU_SERIES = K20x - - # Linker script to use - # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= MK20DX256 - - # Startup code to use - # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= k20x7 - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= PJRC_TEENSY_3_1 -endif - -ifneq ($(findstring MK66F18, $(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 = KINETIS - MCU_SERIES = MK66F18 - - # Linker script to use - # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= MK66FX1M0 - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= MK66F18 - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= PJRC_TEENSY_3_6 -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/startup/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 - - # UF2 settings - UF2_FAMILY ?= STM32F0 -endif - -ifneq ($(findstring STM32F072, $(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/startup/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 ?= GENERIC_STM32_F072XB - - USE_FPU ?= no - - # UF2 settings - UF2_FAMILY ?= STM32F0 -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/startup/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 - - # UF2 settings - UF2_FAMILY ?= STM32F1 -endif - -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 - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= STM32F303xC - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32f3xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= GENERIC_STM32_F303XC - - USE_FPU ?= yes - - # UF2 settings - UF2_FAMILY ?= STM32F3 -endif - -ifneq ($(findstring STM32F401, $(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 = STM32F4xx - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - ifeq ($(strip $(BOOTLOADER)), tinyuf2) - MCU_LDSCRIPT ?= STM32F401xC_tinyuf2 - FIRMWARE_FORMAT ?= uf2 - else - MCU_LDSCRIPT ?= STM32F401xC - endif - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32f4xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= BLACKPILL_STM32_F401 - - USE_FPU ?= yes - - # UF2 settings - UF2_FAMILY ?= STM32F4 -endif - -ifneq ($(findstring STM32F407, $(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 = STM32F4xx - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= STM32F407xE - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32f4xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= GENERIC_STM32_F407XE - - USE_FPU ?= yes - - # UF2 settings - UF2_FAMILY ?= STM32F4 -endif - -ifneq ($(findstring STM32F411, $(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 = STM32F4xx - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - ifeq ($(strip $(BOOTLOADER)), tinyuf2) - MCU_LDSCRIPT ?= STM32F411xE_tinyuf2 - FIRMWARE_FORMAT ?= uf2 - else - MCU_LDSCRIPT ?= STM32F411xE - endif - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32f4xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= BLACKPILL_STM32_F411 - - USE_FPU ?= yes - - # UF2 settings - UF2_FAMILY ?= STM32F4 -endif - -ifneq ($(findstring STM32F446, $(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 = STM32F4xx - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= STM32F446xE - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32f4xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= GENERIC_STM32_F446XE - - USE_FPU ?= yes -endif - -ifneq ($(findstring STM32G431, $(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 = STM32G4xx - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= STM32G431xB - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32g4xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= GENERIC_STM32_G431XB - - USE_FPU ?= yes - - # UF2 settings - UF2_FAMILY ?= STM32G4 -endif - -ifneq ($(findstring STM32G474, $(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 = STM32G4xx - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= STM32G474xE - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32g4xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= GENERIC_STM32_G474XE - - USE_FPU ?= yes - - # UF2 settings - UF2_FAMILY ?= STM32G4 -endif - -ifneq (,$(filter $(MCU),STM32L433 STM32L443)) - # 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 = STM32L4xx - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= STM32L432xC - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32l4xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= GENERIC_STM32_L433XC - - PLATFORM_NAME ?= platform_l432 - - USE_FPU ?= yes - - # UF2 settings - UF2_FAMILY ?= STM32L4 -endif - -ifneq (,$(filter $(MCU),STM32L412 STM32L422)) - # 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 = STM32L4xx - - # Linker script to use - # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ - # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= STM32L412xB - - # Startup code to use - # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP ?= stm32l4xx - - # Board: it should exist either in <chibios>/os/hal/boards/, - # <keyboard_dir>/boards/, or drivers/boards/ - BOARD ?= GENERIC_STM32_L412XB - - PLATFORM_NAME ?= platform_l432 - - USE_FPU ?= yes - - # UF2 settings - UF2_FAMILY ?= STM32L4 -endif - -ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287)) - PROTOCOL = LUFA - - # Processor frequency. - # This will define a symbol, F_CPU, in all source code files equal to the - # processor frequency in Hz. You can then use this symbol in your source code to - # calculate timings. Do NOT tack on a 'UL' at the end, this will be done - # automatically to create a 32-bit value in your source code. - # - # This will be an integer division of F_USB below, as it is sourced by - # F_USB after it has run through any CPU prescalers. Note that this value - # does not *change* the processor frequency - it should merely be updated to - # reflect the processor speed set externally so that the code can use accurate - # software delays. - F_CPU ?= 16000000 - - # LUFA specific - # - # Target architecture (see library "Board Types" documentation). - ARCH = AVR8 - - # Input clock frequency. - # This will define a symbol, F_USB, in all source code files equal to the - # input clock frequency (before any prescaling is performed) in Hz. This value may - # differ from F_CPU if prescaling is used on the latter, and is required as the - # raw input clock is fed directly to the PLL sections of the AVR for high speed - # clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' - # at the end, this will be done automatically to create a 32-bit value in your - # source code. - # - # If no clock division is performed on the input clock inside the AVR (via the - # CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. - F_USB ?= $(F_CPU) - - # Interrupt driven control endpoint task - ifeq (,$(filter $(NO_INTERRUPT_CONTROL_ENDPOINT),yes)) - OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT - endif - ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2)) - NO_I2C = yes - endif -endif - -ifneq (,$(filter $(MCU),atmega32a)) - # MCU name for avrdude - AVRDUDE_MCU = m32 - - PROTOCOL = VUSB - - # Processor frequency. - # This will define a symbol, F_CPU, in all source code files equal to the - # processor frequency in Hz. You can then use this symbol in your source code to - # calculate timings. Do NOT tack on a 'UL' at the end, this will be done - # automatically to create a 32-bit value in your source code. - F_CPU ?= 12000000 -endif - -ifneq (,$(filter $(MCU),atmega328p)) - # MCU name for avrdude - AVRDUDE_MCU = m328p - - PROTOCOL = VUSB - - # Processor frequency. - # This will define a symbol, F_CPU, in all source code files equal to the - # processor frequency in Hz. You can then use this symbol in your source code to - # calculate timings. Do NOT tack on a 'UL' at the end, this will be done - # automatically to create a 32-bit value in your source code. - F_CPU ?= 16000000 -endif - -ifneq (,$(filter $(MCU),atmega328)) - # MCU name for avrdude - AVRDUDE_MCU = m328 - - PROTOCOL = VUSB - - # Processor frequency. - # This will define a symbol, F_CPU, in all source code files equal to the - # processor frequency in Hz. You can then use this symbol in your source code to - # calculate timings. Do NOT tack on a 'UL' at the end, this will be done - # automatically to create a 32-bit value in your source code. - F_CPU ?= 16000000 -endif - -ifneq (,$(filter $(MCU),attiny85)) - PROTOCOL = VUSB - - # Processor frequency. - # This will define a symbol, F_CPU, in all source code files equal to the - # processor frequency in Hz. You can then use this symbol in your source code to - # calculate timings. Do NOT tack on a 'UL' at the end, this will be done - # automatically to create a 32-bit value in your source code. - F_CPU ?= 16500000 -endif diff --git a/quantum/pointing_device.c b/quantum/pointing_device.c index 09d889f697..2fefdb67b6 100644 --- a/quantum/pointing_device.c +++ b/quantum/pointing_device.c @@ -1,34 +1,57 @@ -/* -Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com> - -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 <stdint.h> -#include "report.h" -#include "host.h" -#include "timer.h" -#include "print.h" -#include "debug.h" +/* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com> + * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> + * Copyright 2021 Dasky (@daskygit) + * + * 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 "pointing_device.h" +#include <string.h> +#ifdef MOUSEKEY_ENABLE +# include "mousekey.h" +#endif +#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1 +# error More than one rotation selected. This is not supported. +#endif static report_mouse_t mouseReport = {}; -__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return (new.buttons != old.buttons) || (new.x&& new.x != old.x) || (new.y&& new.y != old.y) || (new.h&& new.h != old.h) || (new.v&& new.v != old.v); } +extern const pointing_device_driver_t pointing_device_driver; + +__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return memcmp(&new, &old, sizeof(new)); } + +__attribute__((weak)) void pointing_device_init_kb(void) {} +__attribute__((weak)) void pointing_device_init_user(void) {} +__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { return pointing_device_task_user(mouse_report); } +__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return mouse_report; } + +__attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) { + if (pressed) { + buttons |= 1 << (button); + } else { + buttons &= ~(1 << (button)); + } + return buttons; +} __attribute__((weak)) void pointing_device_init(void) { - // initialize device, if that needs to be done. + pointing_device_driver.init(); +#ifdef POINTING_DEVICE_MOTION_PIN + setPinInputHigh(POINTING_DEVICE_MOTION_PIN); +#endif + pointing_device_init_kb(); + pointing_device_init_user(); } __attribute__((weak)) void pointing_device_send(void) { @@ -43,20 +66,55 @@ __attribute__((weak)) void pointing_device_send(void) { mouseReport.y = 0; mouseReport.v = 0; mouseReport.h = 0; - old_report = mouseReport; + + memcpy(&old_report, &mouseReport, sizeof(mouseReport)); } __attribute__((weak)) void pointing_device_task(void) { - // gather info and put it in: - // mouseReport.x = 127 max -127 min - // mouseReport.y = 127 max -127 min - // mouseReport.v = 127 max -127 min (scroll vertical) - // mouseReport.h = 127 max -127 min (scroll horizontal) - // mouseReport.buttons = 0x1F (decimal 31, binary 00011111) max (bitmask for mouse buttons 1-5, 1 is rightmost, 5 is leftmost) 0x00 min - // send the report + // Gather report info +#ifdef POINTING_DEVICE_MOTION_PIN + if (!readPin(POINTING_DEVICE_MOTION_PIN)) +#endif + mouseReport = pointing_device_driver.get_report(mouseReport); + + // Support rotation of the sensor data +#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270) + int8_t x = mouseReport.x, y = mouseReport.y; +# if defined(POINTING_DEVICE_ROTATION_90) + mouseReport.x = y; + mouseReport.y = -x; +# elif defined(POINTING_DEVICE_ROTATION_180) + mouseReport.x = -x; + mouseReport.y = -y; +# elif defined(POINTING_DEVICE_ROTATION_270) + mouseReport.x = -y; + mouseReport.y = x; +# else +# error "How the heck did you get here?!" +# endif +#endif + // Support Inverting the X and Y Axises +#if defined(POINTING_DEVICE_INVERT_X) + mouseReport.x = -mouseReport.x; +#endif +#if defined(POINTING_DEVICE_INVERT_Y) + mouseReport.y = -mouseReport.y; +#endif + + // allow kb to intercept and modify report + mouseReport = pointing_device_task_kb(mouseReport); + // combine with mouse report to ensure that the combined is sent correctly +#ifdef MOUSEKEY_ENABLE + report_mouse_t mousekey_report = mousekey_get_report(); + mouseReport.buttons = mouseReport.buttons | mousekey_report.buttons; +#endif pointing_device_send(); } report_mouse_t pointing_device_get_report(void) { return mouseReport; } void pointing_device_set_report(report_mouse_t newMouseReport) { mouseReport = newMouseReport; } + +uint16_t pointing_device_get_cpi(void) { return pointing_device_driver.get_cpi(); } + +void pointing_device_set_cpi(uint16_t cpi) { pointing_device_driver.set_cpi(cpi); } diff --git a/quantum/pointing_device.h b/quantum/pointing_device.h index 56a542d545..5106c26660 100644 --- a/quantum/pointing_device.h +++ b/quantum/pointing_device.h @@ -21,9 +21,68 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "host.h" #include "report.h" +#if defined(POINTING_DEVICE_DRIVER_adns5050) +# include "drivers/sensors/adns5050.h" +#elif defined(POINTING_DEVICE_DRIVER_adns9800) +# include "spi_master.h" +# include "drivers/sensors/adns9800.h" +#elif defined(POINTING_DEVICE_DRIVER_analog_joystick) +# include "analog.h" +# include "drivers/sensors/analog_joystick.h" +#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi) +# include "drivers/sensors/cirque_pinnacle.h" +#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball) +# include "i2c_master.h" +# include "drivers/sensors/pimoroni_trackball.h" +// support for legacy pimoroni defines +# ifdef PIMORONI_TRACKBALL_INVERT_X +# define POINTING_DEVICE_INVERT_X +# endif +# ifdef PIMORONI_TRACKBALL_INVERT_Y +# define POINTING_DEVICE_INVERT_Y +# endif +# ifdef PIMORONI_TRACKBALL_ROTATE +# define POINTING_DEVICE_ROTATION_90 +# endif +#elif defined(POINTING_DEVICE_DRIVER_pmw3360) +# include "spi_master.h" +# include "drivers/sensors/pmw3360.h" +#else +void pointing_device_driver_init(void); +report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report); +uint16_t pointing_device_driver_get_cpi(void); +void pointing_device_driver_set_cpi(uint16_t cpi); +#endif + +typedef struct { + void (*init)(void); + report_mouse_t (*get_report)(report_mouse_t mouse_report); + void (*set_cpi)(uint16_t); + uint16_t (*get_cpi)(void); +} pointing_device_driver_t; + +typedef enum { + POINTING_DEVICE_BUTTON1, + POINTING_DEVICE_BUTTON2, + POINTING_DEVICE_BUTTON3, + POINTING_DEVICE_BUTTON4, + POINTING_DEVICE_BUTTON5, + POINTING_DEVICE_BUTTON6, + POINTING_DEVICE_BUTTON7, + POINTING_DEVICE_BUTTON8, +} pointing_device_buttons_t; + void pointing_device_init(void); void pointing_device_task(void); void pointing_device_send(void); report_mouse_t pointing_device_get_report(void); void pointing_device_set_report(report_mouse_t newMouseReport); bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old); +uint16_t pointing_device_get_cpi(void); +void pointing_device_set_cpi(uint16_t cpi); + +void pointing_device_init_kb(void); +void pointing_device_init_user(void); +report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report); +report_mouse_t pointing_device_task_user(report_mouse_t mouse_report); +uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button); diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c new file mode 100644 index 0000000000..9ad5e76ba6 --- /dev/null +++ b/quantum/pointing_device_drivers.c @@ -0,0 +1,262 @@ +/* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com> + * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> + * Copyright 2021 Dasky (@daskygit) + * + * 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 "pointing_device.h" +#include "debug.h" +#include "wait.h" +#include "timer.h" +#include <stddef.h> + +// hid mouse reports cannot exceed -127 to 127, so constrain to that value +#define constrain_hid(amt) ((amt) < -127 ? -127 : ((amt) > 127 ? 127 : (amt))) + +// get_report functions should probably be moved to their respective drivers. +#if defined(POINTING_DEVICE_DRIVER_adns5050) +report_mouse_t adns5050_get_report(report_mouse_t mouse_report) { + report_adns5050_t data = adns5050_read_burst(); + + if (data.dx != 0 || data.dy != 0) { +# ifdef CONSOLE_ENABLE + if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy); +# endif + + mouse_report.x = data.dx; + mouse_report.y = data.dy; + } + + return mouse_report; +} + +// clang-format off +const pointing_device_driver_t pointing_device_driver = { + .init = adns5050_init, + .get_report = adns5050_get_report, + .set_cpi = adns5050_set_cpi, + .get_cpi = adns5050_get_cpi, +}; +// clang-format on +#elif defined(POINTING_DEVICE_DRIVER_adns9800) + +report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) { + report_adns9800_t sensor_report = adns9800_get_report(); + + int8_t clamped_x = constrain_hid(sensor_report.x); + int8_t clamped_y = constrain_hid(sensor_report.y); + + mouse_report.x = clamped_x; + mouse_report.y = clamped_y; + + return mouse_report; +} + +// clang-format off +const pointing_device_driver_t pointing_device_driver = { + .init = adns9800_init, + .get_report = adns9800_get_report_driver, + .set_cpi = adns9800_set_cpi, + .get_cpi = adns9800_get_cpi +}; +// clang-format on +#elif defined(POINTING_DEVICE_DRIVER_analog_joystick) +report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) { + report_analog_joystick_t data = analog_joystick_read(); + +# ifdef CONSOLE_ENABLE + if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y); +# endif + + mouse_report.x = data.x; + mouse_report.y = data.y; + + mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, data.button, POINTING_DEVICE_BUTTON1); + + return mouse_report; +} + +// clang-format off +const pointing_device_driver_t pointing_device_driver = { + .init = analog_joystick_init, + .get_report = analog_joystick_get_report, + .set_cpi = NULL, + .get_cpi = NULL +}; +// clang-format on +#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi) +# ifndef CIRQUE_PINNACLE_TAPPING_TERM +# ifdef TAPPING_TERM_PER_KEY +# include "action.h" +# include "action_tapping.h" +# define CIRQUE_PINNACLE_TAPPING_TERM get_tapping_term(KC_BTN1, NULL) +# else +# ifdef TAPPING_TERM +# define CIRQUE_PINNACLE_TAPPING_TERM TAPPING_TERM +# else +# define CIRQUE_PINNACLE_TAPPING_TERM 200 +# endif +# endif +# endif +# ifndef CIRQUE_PINNACLE_TOUCH_DEBOUNCE +# define CIRQUE_PINNACLE_TOUCH_DEBOUNCE (CIRQUE_PINNACLE_TAPPING_TERM * 8) +# endif + +report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { + pinnacle_data_t touchData = cirque_pinnacle_read_data(); + static uint16_t x = 0, y = 0, mouse_timer = 0; + int8_t report_x = 0, report_y = 0; + static bool is_z_down = false; + + cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); // Scale coordinates to arbitrary X, Y resolution + + if (x && y && touchData.xValue && touchData.yValue) { + report_x = (int8_t)(touchData.xValue - x); + report_y = (int8_t)(touchData.yValue - y); + } + x = touchData.xValue; + y = touchData.yValue; + + if ((bool)touchData.zValue != is_z_down) { + is_z_down = (bool)touchData.zValue; + if (!touchData.zValue) { + if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) { + mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1); + pointing_device_set_report(mouse_report); + pointing_device_send(); +# if TAP_CODE_DELAY > 0 + wait_ms(TAP_CODE_DELAY); +# endif + mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1); + pointing_device_set_report(mouse_report); + pointing_device_send(); + } + } + mouse_timer = timer_read(); + } + if (timer_elapsed(mouse_timer) > (CIRQUE_PINNACLE_TOUCH_DEBOUNCE)) { + mouse_timer = 0; + } + mouse_report.x = report_x; + mouse_report.y = report_y; + + return mouse_report; +} + +// clang-format off +const pointing_device_driver_t pointing_device_driver = { + .init = cirque_pinnacle_init, + .get_report = cirque_pinnacle_get_report, + .set_cpi = cirque_pinnacle_set_scale, + .get_cpi = cirque_pinnacle_get_scale +}; +// clang-format on + +#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball) +report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) { + static fast_timer_t throttle = 0; + static uint16_t debounce = 0; + static uint8_t error_count = 0; + pimoroni_data_t pimoroni_data = {0}; + static int16_t x_offset = 0, y_offset = 0; + + if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) { + i2c_status_t status = read_pimoroni_trackball(&pimoroni_data); + + if (status == I2C_STATUS_SUCCESS) { + error_count = 0; + + if (!(pimoroni_data.click & 128)) { + mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1); + if (!debounce) { + x_offset += pimoroni_trackball_get_offsets(pimoroni_data.right, pimoroni_data.left, PIMORONI_TRACKBALL_SCALE); + y_offset += pimoroni_trackball_get_offsets(pimoroni_data.down, pimoroni_data.up, PIMORONI_TRACKBALL_SCALE); + pimoroni_trackball_adapt_values(&mouse_report.x, &x_offset); + pimoroni_trackball_adapt_values(&mouse_report.y, &y_offset); + } else { + debounce--; + } + } else { + mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1); + debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES; + } + } else { + error_count++; + } + throttle = timer_read_fast(); + } + return mouse_report; +} + +// clang-format off +const pointing_device_driver_t pointing_device_driver = { + .init = pimironi_trackball_device_init, + .get_report = pimorono_trackball_get_report, + .set_cpi = NULL, + .get_cpi = NULL +}; +// clang-format on +#elif defined(POINTING_DEVICE_DRIVER_pmw3360) + +static void init(void) { pmw3360_init(); } + +report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) { + report_pmw3360_t data = pmw3360_read_burst(); + static uint16_t MotionStart = 0; // Timer for accel, 0 is resting state + + if (data.isOnSurface && data.isMotion) { + // Reset timer if stopped moving + if (!data.isMotion) { + if (MotionStart != 0) MotionStart = 0; + return mouse_report; + } + + // Set timer if new motion + if ((MotionStart == 0) && data.isMotion) { +# ifdef CONSOLE_ENABLE + if (debug_mouse) dprintf("Starting motion.\n"); +# endif + MotionStart = timer_read(); + } + mouse_report.x = constrain_hid(data.dx); + mouse_report.y = constrain_hid(data.dy); + } + + return mouse_report; +} + +// clang-format off +const pointing_device_driver_t pointing_device_driver = { + .init = init, + .get_report = pmw3360_get_report, + .set_cpi = pmw3360_set_cpi, + .get_cpi = pmw3360_get_cpi +}; +// clang-format on +#else +__attribute__((weak)) void pointing_device_driver_init(void) {} +__attribute__((weak)) report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { return mouse_report; } +__attribute__((weak)) uint16_t pointing_device_driver_get_cpi(void) { return 0; } +__attribute__((weak)) void pointing_device_driver_set_cpi(uint16_t cpi) {} + +// clang-format off +const pointing_device_driver_t pointing_device_driver = { + .init = pointing_device_driver_init, + .get_report = pointing_device_driver_get_report, + .get_cpi = pointing_device_driver_get_cpi, + .set_cpi = pointing_device_driver_set_cpi +}; +// clang-format on +#endif diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c index 51b0efdb47..4d928edb57 100644 --- a/quantum/process_keycode/process_auto_shift.c +++ b/quantum/process_keycode/process_auto_shift.c @@ -21,6 +21,12 @@ # include "process_auto_shift.h" +# ifndef AUTO_SHIFT_DISABLED_AT_STARTUP +# define AUTO_SHIFT_STARTUP_STATE true /* enabled */ +# else +# define AUTO_SHIFT_STARTUP_STATE false /* disabled */ +# endif + static uint16_t autoshift_time = 0; static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; static uint16_t autoshift_lastkey = KC_NO; @@ -34,7 +40,7 @@ static struct { bool in_progress : 1; // Whether the auto-shifted keypress has been registered. bool holding_shift : 1; -} autoshift_flags = {true, false, false, false}; +} autoshift_flags = {AUTO_SHIFT_STARTUP_STATE, false, false, false}; /** \brief Record the press of an autoshiftable key * @@ -61,7 +67,7 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) register_code(autoshift_lastkey); } else { // Simulate pressing the shift key. - add_weak_mods(MOD_BIT(KC_LSFT)); + add_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); register_code(autoshift_lastkey); } return false; @@ -102,7 +108,7 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) { autoshift_flags.lastshifted = false; } else { // Simulate pressing the shift key. - add_weak_mods(MOD_BIT(KC_LSFT)); + add_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); register_code(autoshift_lastkey); autoshift_flags.lastshifted = true; # if defined(AUTO_SHIFT_REPEAT) && !defined(AUTO_SHIFT_NO_AUTO_REPEAT) @@ -117,7 +123,7 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) { wait_ms(TAP_CODE_DELAY); # endif unregister_code(autoshift_lastkey); - del_weak_mods(MOD_BIT(KC_LSFT)); + del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); } else { // Release after keyrepeat. unregister_code(keycode); @@ -125,7 +131,7 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) { // This will only fire when the key was the last auto-shiftable // pressed. That prevents aaaaBBBB then releasing a from unshifting // later Bs (if B wasn't auto-shiftable). - del_weak_mods(MOD_BIT(KC_LSFT)); + del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); } } send_keyboard_report(); // del_weak_mods doesn't send one. @@ -151,14 +157,14 @@ void autoshift_matrix_scan(void) { void autoshift_toggle(void) { autoshift_flags.enabled = !autoshift_flags.enabled; - del_weak_mods(MOD_BIT(KC_LSFT)); + del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); } void autoshift_enable(void) { autoshift_flags.enabled = true; } void autoshift_disable(void) { autoshift_flags.enabled = false; - del_weak_mods(MOD_BIT(KC_LSFT)); + del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); } # ifndef AUTO_SHIFT_NO_SETUP @@ -189,7 +195,7 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { autoshift_end(KC_NO, now, false); } // For pressing another key while keyrepeating shifted autoshift. - del_weak_mods(MOD_BIT(KC_LSFT)); + del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); switch (keycode) { case KC_ASTG: @@ -238,7 +244,7 @@ __attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *r # ifndef NO_AUTO_SHIFT_SPECIAL case KC_TAB: case KC_MINUS ... KC_SLASH: - case KC_NONUS_BSLASH: + case KC_NONUS_BACKSLASH: # endif return true; } diff --git a/quantum/process_keycode/process_haptic.c b/quantum/process_keycode/process_haptic.c index 64d455d009..85b2ffcddd 100644 --- a/quantum/process_keycode/process_haptic.c +++ b/quantum/process_keycode/process_haptic.c @@ -17,6 +17,7 @@ #include "process_haptic.h" #include "quantum_keycodes.h" #include "action_tapping.h" +#include "usb_device_state.h" __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) { switch (keycode) { @@ -30,8 +31,9 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: if (record->tap.count == 0) return false; break; - case KC_LCTRL ... KC_RGUI: + case KC_LEFT_CTRL ... KC_RIGHT_GUI: case QK_MOMENTARY ... QK_MOMENTARY_MAX: + case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: #endif #ifdef NO_HAPTIC_FN case KC_FN0 ... KC_FN31: @@ -42,34 +44,34 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t #ifdef NO_HAPTIC_PUNCTUATION case KC_ENTER: case KC_ESCAPE: - case KC_BSPACE: + case KC_BACKSPACE: case KC_SPACE: case KC_MINUS: case KC_EQUAL: - case KC_LBRACKET: - case KC_RBRACKET: - case KC_BSLASH: + case KC_LEFT_BRACKET: + case KC_RIGHT_BRACKET: + case KC_BACKSLASH: case KC_NONUS_HASH: - case KC_SCOLON: + case KC_SEMICOLON: case KC_QUOTE: case KC_GRAVE: case KC_COMMA: case KC_SLASH: case KC_DOT: - case KC_NONUS_BSLASH: + case KC_NONUS_BACKSLASH: #endif #ifdef NO_HAPTIC_LOCKKEYS - case KC_CAPSLOCK: - case KC_SCROLLLOCK: - case KC_NUMLOCK: + case KC_CAPS_LOCK: + case KC_SCROLL_LOCK: + case KC_NUM_LOCK: #endif #ifdef NO_HAPTIC_NAV - case KC_PSCREEN: + case KC_PRINT_SCREEN: case KC_PAUSE: case KC_INSERT: case KC_DELETE: - case KC_PGDOWN: - case KC_PGUP: + case KC_PAGE_DOWN: + case KC_PAGE_UP: case KC_LEFT: case KC_UP: case KC_RIGHT: @@ -130,7 +132,7 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) { } } - if (haptic_get_enable()) { + if (haptic_get_enable() && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) { if (record->event.pressed) { // keypress if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) { diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 2beccbd8f9..6822c5e289 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -146,7 +146,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { if (music_activated || midi_activated) { if (record->event.pressed) { - if (keycode == KC_LCTL) { // Start recording + if (keycode == KC_LEFT_CTRL) { // Start recording music_all_notes_off(); music_sequence_recording = true; music_sequence_recorded = false; @@ -155,7 +155,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { return false; } - if (keycode == KC_LALT) { // Stop recording/playing + if (keycode == KC_LEFT_ALT) { // Stop recording/playing music_all_notes_off(); if (music_sequence_recording) { // was recording music_sequence_recorded = true; @@ -165,7 +165,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { return false; } - if (keycode == KC_LGUI && music_sequence_recorded) { // Start playing + if (keycode == KC_LEFT_GUI && music_sequence_recorded) { // Start playing music_all_notes_off(); music_sequence_recording = false; music_sequence_playing = true; diff --git a/quantum/process_keycode/process_printer.c b/quantum/process_keycode/process_printer.c index 7c5e4169a6..82528cc680 100644 --- a/quantum/process_keycode/process_printer.c +++ b/quantum/process_keycode/process_printer.c @@ -31,7 +31,7 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0 // uint8_t keycode_to_ascii[0xFF][2]; -// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F}; +// keycode_to_ascii[KC_MINUS] = {0x2D, 0x5F}; void print_char(char c) { USB_Disable(); @@ -90,8 +90,8 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { case KC_PIPE: case KC_TILD: keycode &= 0xFF; - case KC_LSFT: - case KC_RSFT: + case KC_LEFT_SHIFT: + case KC_RIGHT_SHIFT: if (record->event.pressed) { character_shift++; } else { @@ -107,13 +107,13 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { print_box_string("This is a line of text!"); } return false; - case KC_ESC: + case KC_ESCAPE: if (record->event.pressed) { print_char(0x1B); } return false; break; - case KC_SPC: + case KC_SPACE: if (record->event.pressed) { print_char(0x20); } @@ -139,7 +139,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_ENT: + case KC_ENTER: if (record->event.pressed) { if (character_shift) { print_char(0x0C); @@ -149,7 +149,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_BSPC: + case KC_BACKSPACE: if (record->event.pressed) { if (character_shift) { print_char(0x18); @@ -169,7 +169,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_COMM: + case KC_COMMA: if (record->event.pressed) { if (character_shift) { print_char(0x3C); @@ -179,7 +179,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_SLSH: + case KC_SLASH: if (record->event.pressed) { if (character_shift) { print_char(0x3F); @@ -189,7 +189,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_QUOT: + case KC_QUOTE: if (record->event.pressed) { if (character_shift) { print_char(0x22); @@ -199,7 +199,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_GRV: + case KC_GRAVE: if (record->event.pressed) { if (character_shift) { print_char(0x7E); @@ -209,7 +209,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_MINS: + case KC_MINUS: if (record->event.pressed) { if (character_shift) { print_char(0x5F); @@ -219,7 +219,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_EQL: + case KC_EQUAL: if (record->event.pressed) { if (character_shift) { print_char(0x2B); @@ -229,7 +229,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_LBRC: + case KC_LEFT_BRACKET: if (record->event.pressed) { if (character_shift) { print_char(0x7B); @@ -239,7 +239,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_RBRC: + case KC_RIGHT_BRACKET: if (record->event.pressed) { if (character_shift) { print_char(0x7D); @@ -249,7 +249,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_BSLS: + case KC_BACKSLASH: if (record->event.pressed) { if (character_shift) { print_char(0x7C); diff --git a/quantum/process_keycode/process_printer_bb.c b/quantum/process_keycode/process_printer_bb.c index e482d82591..6c91bd27ef 100644 --- a/quantum/process_keycode/process_printer_bb.c +++ b/quantum/process_keycode/process_printer_bb.c @@ -45,7 +45,7 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0 // uint8_t keycode_to_ascii[0xFF][2]; -// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F}; +// keycode_to_ascii[KC_MINUS] = {0x2D, 0x5F}; void print_char(char c) { uint8_t b = 8; @@ -84,8 +84,8 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { case KC_PIPE: case KC_TILD: keycode &= 0xFF; - case KC_LSFT: - case KC_RSFT: + case KC_LEFT_SHIFT: + case KC_RIGHT_SHIFT: if (record->event.pressed) { character_shift++; } else { @@ -101,13 +101,13 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { print_string("This is a line of text!\n\n\n"); } return false; - case KC_ESC: + case KC_ESCAPE: if (record->event.pressed) { print_char(0x1B); } return false; break; - case KC_SPC: + case KC_SPACE: if (record->event.pressed) { print_char(0x20); } @@ -133,7 +133,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_ENT: + case KC_ENTER: if (record->event.pressed) { if (character_shift) { print_char(0x0C); @@ -143,7 +143,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_BSPC: + case KC_BACKSPACE: if (record->event.pressed) { if (character_shift) { print_char(0x18); @@ -163,7 +163,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_COMM: + case KC_COMMA: if (record->event.pressed) { if (character_shift) { print_char(0x3C); @@ -173,7 +173,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_SLSH: + case KC_SLASH: if (record->event.pressed) { if (character_shift) { print_char(0x3F); @@ -183,7 +183,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_QUOT: + case KC_QUOTE: if (record->event.pressed) { if (character_shift) { print_char(0x22); @@ -193,7 +193,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_GRV: + case KC_GRAVE: if (record->event.pressed) { if (character_shift) { print_char(0x7E); @@ -203,7 +203,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_MINS: + case KC_MINUS: if (record->event.pressed) { if (character_shift) { print_char(0x5F); @@ -213,7 +213,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_EQL: + case KC_EQUAL: if (record->event.pressed) { if (character_shift) { print_char(0x2B); @@ -223,7 +223,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_LBRC: + case KC_LEFT_BRACKET: if (record->event.pressed) { if (character_shift) { print_char(0x7B); @@ -233,7 +233,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_RBRC: + case KC_RIGHT_BRACKET: if (record->event.pressed) { if (character_shift) { print_char(0x7D); @@ -243,7 +243,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_BSLS: + case KC_BACKSLASH: if (record->event.pressed) { if (character_shift) { print_char(0x7C); diff --git a/quantum/process_keycode/process_programmable_button.c b/quantum/process_keycode/process_programmable_button.c new file mode 100644 index 0000000000..c6e77faacc --- /dev/null +++ b/quantum/process_keycode/process_programmable_button.c @@ -0,0 +1,31 @@ +/* +Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de> + +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_programmable_button.h" +#include "programmable_button.h" + +bool process_programmable_button(uint16_t keycode, keyrecord_t *record) { + if (keycode >= PROGRAMMABLE_BUTTON_MIN && keycode <= PROGRAMMABLE_BUTTON_MAX) { + uint8_t button = keycode - PROGRAMMABLE_BUTTON_MIN + 1; + if (record->event.pressed) { + programmable_button_on(button); + } else { + programmable_button_off(button); + } + } + return true; +} diff --git a/quantum/process_keycode/process_programmable_button.h b/quantum/process_keycode/process_programmable_button.h new file mode 100644 index 0000000000..47c6ce5614 --- /dev/null +++ b/quantum/process_keycode/process_programmable_button.h @@ -0,0 +1,23 @@ +/* +Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de> + +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 <stdint.h> +#include "quantum.h" + +bool process_programmable_button(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_space_cadet.c b/quantum/process_keycode/process_space_cadet.c index f99db2a87b..46b2648c35 100644 --- a/quantum/process_keycode/process_space_cadet.c +++ b/quantum/process_keycode/process_space_cadet.c @@ -27,53 +27,53 @@ // Shift / Enter setup #ifndef SFTENT_KEY -# define SFTENT_KEY KC_ENT +# define SFTENT_KEY KC_ENTER #endif #ifdef DISABLE_SPACE_CADET_MODIFIER # ifndef LSPO_MOD -# define LSPO_MOD KC_TRNS +# define LSPO_MOD KC_TRANSPARENT # endif # ifndef RSPC_MOD -# define RSPC_MOD KC_TRNS +# define RSPC_MOD KC_TRANSPARENT # endif #else # ifndef LSPO_MOD -# define LSPO_MOD KC_LSFT +# define LSPO_MOD KC_LEFT_SHIFT # endif # ifndef RSPC_MOD -# define RSPC_MOD KC_RSFT +# define RSPC_MOD KC_RIGHT_SHIFT # endif #endif // ********************************************************** // Shift / paren setup #ifndef LSPO_KEYS -# define LSPO_KEYS KC_LSFT, LSPO_MOD, LSPO_KEY +# define LSPO_KEYS KC_LEFT_SHIFT, LSPO_MOD, LSPO_KEY #endif #ifndef RSPC_KEYS -# define RSPC_KEYS KC_RSFT, RSPC_MOD, RSPC_KEY +# define RSPC_KEYS KC_RIGHT_SHIFT, RSPC_MOD, RSPC_KEY #endif // Control / paren setup #ifndef LCPO_KEYS -# define LCPO_KEYS KC_LCTL, KC_LSFT, KC_9 +# define LCPO_KEYS KC_LEFT_CTRL, KC_LEFT_SHIFT, KC_9 #endif #ifndef RCPC_KEYS -# define RCPC_KEYS KC_RCTL, KC_RSFT, KC_0 +# define RCPC_KEYS KC_RIGHT_CTRL, KC_RIGHT_SHIFT, KC_0 #endif // Alt / paren setup #ifndef LAPO_KEYS -# define LAPO_KEYS KC_LALT, KC_LSFT, KC_9 +# define LAPO_KEYS KC_LEFT_ALT, KC_LEFT_SHIFT, KC_9 #endif #ifndef RAPC_KEYS -# define RAPC_KEYS KC_RALT, KC_RSFT, KC_0 +# define RAPC_KEYS KC_RIGHT_ALT, KC_RIGHT_SHIFT, KC_0 #endif // Shift / Enter setup #ifndef SFTENT_KEYS -# define SFTENT_KEYS KC_RSFT, KC_TRNS, SFTENT_KEY +# define SFTENT_KEYS KC_RIGHT_SHIFT, KC_TRANSPARENT, SFTENT_KEY #endif static uint8_t sc_last = 0; diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c index 7d1eefa9ed..a059f3a521 100644 --- a/quantum/process_keycode/process_terminal.c +++ b/quantum/process_keycode/process_terminal.c @@ -257,12 +257,12 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) { process_terminal_command(); return false; break; - case KC_ESC: + case KC_ESCAPE: SEND_STRING("\n"); enable_terminal(); return false; break; - case KC_BSPC: + case KC_BACKSPACE: str_len = strlen(buffer); if (str_len > 0) { buffer[str_len - 1] = 0; @@ -284,7 +284,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) { str_len = strlen(buffer); for (int i = 0; i < str_len; ++i) { send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already - // process_terminal(KC_BSPC,record); + // process_terminal(KC_BACKSPACE,record); } strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 80); @@ -299,7 +299,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) { str_len = strlen(buffer); for (int i = 0; i < str_len; ++i) { send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already - // process_terminal(KC_BSPC,record); + // process_terminal(KC_BACKSPACE,record); } strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 79); @@ -311,7 +311,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) { default: if (keycode <= 58) { char_to_add = 0; - if (get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { + if (get_mods() & (MOD_BIT(KC_LEFT_SHIFT) | MOD_BIT(KC_RIGHT_SHIFT))) { char_to_add = shifted_keycode_to_ascii_lut[keycode]; } else if (get_mods() == 0) { char_to_add = keycode_to_ascii_lut[keycode]; diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c index 12b0aba9bf..d084d2b66c 100644 --- a/quantum/process_keycode/process_ucis.c +++ b/quantum/process_keycode/process_ucis.c @@ -46,7 +46,7 @@ static bool is_uni_seq(char *seq) { return false; } } - return qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC; + return qk_ucis_state.codes[i] == KC_ENTER || qk_ucis_state.codes[i] == KC_SPACE; } __attribute__((weak)) void qk_ucis_symbol_fallback(void) { @@ -72,7 +72,7 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) { return true; } - bool special = keycode == KC_SPC || keycode == KC_ENT || keycode == KC_ESC || keycode == KC_BSPC; + bool special = keycode == KC_SPACE || keycode == KC_ENTER || keycode == KC_ESCAPE || keycode == KC_BACKSPACE; if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) { return false; } @@ -81,7 +81,7 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) { qk_ucis_state.count++; switch (keycode) { - case KC_BSPC: + case KC_BACKSPACE: if (qk_ucis_state.count >= 2) { qk_ucis_state.count -= 2; return true; @@ -90,16 +90,16 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) { return false; } - case KC_SPC: - case KC_ENT: - case KC_ESC: + case KC_SPACE: + case KC_ENTER: + case KC_ESCAPE: for (uint8_t i = 0; i < qk_ucis_state.count; i++) { - register_code(KC_BSPC); - unregister_code(KC_BSPC); + register_code(KC_BACKSPACE); + unregister_code(KC_BACKSPACE); wait_ms(UNICODE_TYPE_DELAY); } - if (keycode == KC_ESC) { + if (keycode == KC_ESCAPE) { qk_ucis_state.in_progress = false; qk_ucis_cancel(); return false; diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c index 889c768a85..7685bb1c99 100644 --- a/quantum/process_keycode/process_unicode_common.c +++ b/quantum/process_keycode/process_unicode_common.c @@ -22,6 +22,7 @@ unicode_config_t unicode_config; uint8_t unicode_saved_mods; bool unicode_saved_caps_lock; +bool unicode_saved_num_lock; #if UNICODE_SELECTED_MODES != -1 static uint8_t selected[] = {UNICODE_SELECTED_MODES}; @@ -79,13 +80,14 @@ void persist_unicode_input_mode(void) { eeprom_update_byte(EECONFIG_UNICODEMODE, __attribute__((weak)) void unicode_input_start(void) { unicode_saved_caps_lock = host_keyboard_led_state().caps_lock; + unicode_saved_num_lock = host_keyboard_led_state().num_lock; // Note the order matters here! // Need to do this before we mess around with the mods, or else // UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work // correctly in the shifted case. if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) { - tap_code(KC_CAPS); + tap_code(KC_CAPS_LOCK); } unicode_saved_mods = get_mods(); // Save current mods @@ -99,9 +101,13 @@ __attribute__((weak)) void unicode_input_start(void) { tap_code16(UNICODE_KEY_LNX); break; case UC_WIN: - register_code(KC_LALT); + // For increased reliability, use numpad keys for inputting digits + if (!unicode_saved_num_lock) { + tap_code(KC_NUM_LOCK); + } + register_code(KC_LEFT_ALT); wait_ms(UNICODE_TYPE_DELAY); - tap_code(KC_PPLS); + tap_code(KC_KP_PLUS); break; case UC_WINC: tap_code(UNICODE_KEY_WINC); @@ -118,13 +124,16 @@ __attribute__((weak)) void unicode_input_finish(void) { unregister_code(UNICODE_KEY_MAC); break; case UC_LNX: - tap_code(KC_SPC); + tap_code(KC_SPACE); if (unicode_saved_caps_lock) { - tap_code(KC_CAPS); + tap_code(KC_CAPS_LOCK); } break; case UC_WIN: - unregister_code(KC_LALT); + unregister_code(KC_LEFT_ALT); + if (!unicode_saved_num_lock) { + tap_code(KC_NUM_LOCK); + } break; case UC_WINC: tap_code(KC_ENTER); @@ -140,26 +149,44 @@ __attribute__((weak)) void unicode_input_cancel(void) { unregister_code(UNICODE_KEY_MAC); break; case UC_LNX: - tap_code(KC_ESC); + tap_code(KC_ESCAPE); if (unicode_saved_caps_lock) { - tap_code(KC_CAPS); + tap_code(KC_CAPS_LOCK); } break; case UC_WINC: - tap_code(KC_ESC); + tap_code(KC_ESCAPE); break; case UC_WIN: - unregister_code(KC_LALT); + unregister_code(KC_LEFT_ALT); + if (!unicode_saved_num_lock) { + tap_code(KC_NUM_LOCK); + } break; } set_mods(unicode_saved_mods); // Reregister previously set mods } +// clang-format off + +static void send_nibble_wrapper(uint8_t digit) { + if (unicode_config.input_mode == UC_WIN) { + uint8_t kc = digit < 10 + ? KC_KP_1 + (10 + digit - 1) % 10 + : KC_A + (digit - 10); + tap_code(kc); + return; + } + send_nibble(digit); +} + +// clang-format on + void register_hex(uint16_t hex) { for (int i = 3; i >= 0; i--) { uint8_t digit = ((hex >> (i * 4)) & 0xF); - send_nibble(digit); + send_nibble_wrapper(digit); } } @@ -172,10 +199,10 @@ void register_hex32(uint32_t hex) { uint8_t digit = ((hex >> (i * 4)) & 0xF); if (digit == 0) { if (!onzerostart) { - send_nibble(digit); + send_nibble_wrapper(digit); } } else { - send_nibble(digit); + send_nibble_wrapper(digit); onzerostart = false; } } diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h index c10e171ec3..72defb445e 100644 --- a/quantum/process_keycode/process_unicode_common.h +++ b/quantum/process_keycode/process_unicode_common.h @@ -24,13 +24,13 @@ // Keycodes used for starting Unicode input on different platforms #ifndef UNICODE_KEY_MAC -# define UNICODE_KEY_MAC KC_LALT +# define UNICODE_KEY_MAC KC_LEFT_ALT #endif #ifndef UNICODE_KEY_LNX # define UNICODE_KEY_LNX LCTL(LSFT(KC_U)) #endif #ifndef UNICODE_KEY_WINC -# define UNICODE_KEY_WINC KC_RALT +# define UNICODE_KEY_WINC KC_RIGHT_ALT #endif // Comma-delimited, ordered list of input modes selected for use (e.g. in cycle) diff --git a/quantum/programmable_button.c b/quantum/programmable_button.c new file mode 100644 index 0000000000..be828fd17c --- /dev/null +++ b/quantum/programmable_button.c @@ -0,0 +1,37 @@ +/* +Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de> + +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 "programmable_button.h" +#include "host.h" + +#define REPORT_BIT(index) (((uint32_t)1) << (index - 1)) + +static uint32_t programmable_button_report = 0; + +void programmable_button_clear(void) { programmable_button_report = 0; } + +void programmable_button_send(void) { host_programmable_button_send(programmable_button_report); } + +void programmable_button_on(uint8_t index) { programmable_button_report |= REPORT_BIT(index); } + +void programmable_button_off(uint8_t index) { programmable_button_report &= ~REPORT_BIT(index); } + +bool programmable_button_is_on(uint8_t index) { return !!(programmable_button_report & REPORT_BIT(index)); }; + +uint32_t programmable_button_get_report(void) { return programmable_button_report; }; + +void programmable_button_set_report(uint32_t report) { programmable_button_report = report; } diff --git a/quantum/programmable_button.h b/quantum/programmable_button.h new file mode 100644 index 0000000000..e89b8b9fd6 --- /dev/null +++ b/quantum/programmable_button.h @@ -0,0 +1,30 @@ +/* +Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de> + +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 <stdint.h> +#include <stdbool.h> +#include "report.h" + +void programmable_button_clear(void); +void programmable_button_send(void); +void programmable_button_on(uint8_t index); +void programmable_button_off(uint8_t index); +bool programmable_button_is_on(uint8_t index); +uint32_t programmable_button_get_report(void); +void programmable_button_set_report(uint32_t report); diff --git a/quantum/quantum.c b/quantum/quantum.c index 0ae12b5834..c7a3bb1970 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -25,10 +25,6 @@ # include "backlight.h" #endif -#ifdef API_ENABLE -# include "api.h" -#endif - #ifdef MIDI_ENABLE # include "process_midi.h" #endif @@ -66,15 +62,15 @@ uint8_t extract_mod_bits(uint16_t code) { uint8_t mods_to_send = 0; if (code & QK_RMODS_MIN) { // Right mod flag is set - if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RCTL); - if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RSFT); - if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RALT); - if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RGUI); + if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RIGHT_CTRL); + if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RIGHT_SHIFT); + if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RIGHT_ALT); + if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RIGHT_GUI); } else { - if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LCTL); - if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LSFT); - if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LALT); - if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LGUI); + if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LEFT_CTRL); + if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LEFT_SHIFT); + if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LEFT_ALT); + if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LEFT_GUI); } return mods_to_send; @@ -297,6 +293,9 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef JOYSTICK_ENABLE process_joystick(keycode, record) && #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE + process_programmable_button(keycode, record) && +#endif true)) { return false; } @@ -466,14 +465,6 @@ void matrix_scan_quantum() { # include "hd44780.h" #endif -void api_send_unicode(uint32_t unicode) { -#ifdef API_ENABLE - uint8_t chunk[4]; - dword_to_bytes(unicode, chunk); - MT_SEND_DATA(DT_UNICODE, chunk, 5); -#endif -} - //------------------------------------------------------------------------------ // Override these functions in your keymap file to play different tunes on // different events such as startup and bootloader jump @@ -481,3 +472,103 @@ void api_send_unicode(uint32_t unicode) { __attribute__((weak)) void startup_user() {} __attribute__((weak)) void shutdown_user() {} + +/** \brief Run keyboard level Power down + * + * FIXME: needs doc + */ +__attribute__((weak)) void suspend_power_down_user(void) {} +/** \brief Run keyboard level Power down + * + * FIXME: needs doc + */ +__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); } + +void suspend_power_down_quantum(void) { +#ifndef NO_SUSPEND_POWER_DOWN +// Turn off backlight +# ifdef BACKLIGHT_ENABLE + backlight_set(0); +# endif + +# ifdef LED_MATRIX_ENABLE + led_matrix_task(); +# endif +# ifdef RGB_MATRIX_ENABLE + rgb_matrix_task(); +# endif + + // Turn off LED indicators + uint8_t leds_off = 0; +# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) + if (is_backlight_enabled()) { + // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off + leds_off |= (1 << USB_LED_CAPS_LOCK); + } +# endif + led_set(leds_off); + +// Turn off audio +# ifdef AUDIO_ENABLE + stop_all_notes(); +# endif + +// Turn off underglow +# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) + rgblight_suspend(); +# endif + +# if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(true); +# endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(true); +# endif + +# ifdef OLED_ENABLE + oled_off(); +# endif +# ifdef ST7565_ENABLE + st7565_off(); +# endif +# if defined(POINTING_DEVICE_ENABLE) + // run to ensure scanning occurs while suspended + pointing_device_task(); +# endif +#endif +} + +/** \brief run user level code immediately after wakeup + * + * FIXME: needs doc + */ +__attribute__((weak)) void suspend_wakeup_init_user(void) {} + +/** \brief run keyboard level code immediately after wakeup + * + * FIXME: needs doc + */ +__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); } + +__attribute__((weak)) void suspend_wakeup_init_quantum(void) { +// Turn on backlight +#ifdef BACKLIGHT_ENABLE + backlight_init(); +#endif + + // Restore LED indicators + led_set(host_keyboard_leds()); + +// Wake up underglow +#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) + rgblight_wakeup(); +#endif + +#if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(false); +#endif +#if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(false); +#endif + suspend_wakeup_init_kb(); +} diff --git a/quantum/quantum.h b/quantum/quantum.h index 86b717e445..b34ff6ec51 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -54,6 +54,10 @@ #include <stddef.h> #include <stdlib.h> +#ifdef DEFERRED_EXEC_ENABLE +# include "deferred_exec.h" +#endif + extern layer_state_t default_layer_state; #ifndef NO_ACTION_LAYER @@ -147,6 +151,10 @@ extern layer_state_t layer_state; # include "process_joystick.h" #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE +# include "process_programmable_button.h" +#endif + #ifdef GRAVE_ESC_ENABLE # include "process_grave_esc.h" #endif @@ -200,6 +208,10 @@ extern layer_state_t layer_state; # include "encoder.h" #endif +#ifdef POINTING_DEVICE_ENABLE +# include "pointing_device.h" +#endif + // For tri-layer void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3); layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3); @@ -233,5 +245,3 @@ void led_set_user(uint8_t usb_led); void led_set_kb(uint8_t usb_led); bool led_update_user(led_t led_state); bool led_update_kb(led_t led_state); - -void api_send_unicode(uint32_t unicode); diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 99eade0e03..cde97074d3 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -19,7 +19,7 @@ #include "sequencer.h" // Fillers to make layering more clear -#define _______ KC_TRNS +#define _______ KC_TRANSPARENT #define XXXXXXX KC_NO enum quantum_keycodes { @@ -524,6 +524,40 @@ enum quantum_keycodes { // Additional magic key MAGIC_TOGGLE_GUI, + // Programmable Button + PROGRAMMABLE_BUTTON_1, + PROGRAMMABLE_BUTTON_2, + PROGRAMMABLE_BUTTON_3, + PROGRAMMABLE_BUTTON_4, + PROGRAMMABLE_BUTTON_5, + PROGRAMMABLE_BUTTON_6, + PROGRAMMABLE_BUTTON_7, + PROGRAMMABLE_BUTTON_8, + PROGRAMMABLE_BUTTON_9, + PROGRAMMABLE_BUTTON_10, + PROGRAMMABLE_BUTTON_11, + PROGRAMMABLE_BUTTON_12, + PROGRAMMABLE_BUTTON_13, + PROGRAMMABLE_BUTTON_14, + PROGRAMMABLE_BUTTON_15, + PROGRAMMABLE_BUTTON_16, + PROGRAMMABLE_BUTTON_17, + PROGRAMMABLE_BUTTON_18, + PROGRAMMABLE_BUTTON_19, + PROGRAMMABLE_BUTTON_20, + PROGRAMMABLE_BUTTON_21, + PROGRAMMABLE_BUTTON_22, + PROGRAMMABLE_BUTTON_23, + PROGRAMMABLE_BUTTON_24, + PROGRAMMABLE_BUTTON_25, + PROGRAMMABLE_BUTTON_26, + PROGRAMMABLE_BUTTON_27, + PROGRAMMABLE_BUTTON_28, + PROGRAMMABLE_BUTTON_29, + PROGRAMMABLE_BUTTON_30, + PROGRAMMABLE_BUTTON_31, + PROGRAMMABLE_BUTTON_32, + // Start of custom keycode range for keyboards and keymaps - always leave at the end SAFE_RANGE }; @@ -565,69 +599,67 @@ enum quantum_keycodes { #define MOD_MEH 0x7 // US ANSI shifted keycode aliases -#define KC_TILD LSFT(KC_GRV) // ~ -#define KC_TILDE KC_TILD +#define KC_TILDE LSFT(KC_GRAVE) // ~ +#define KC_TILD KC_TILDE -#define KC_EXLM LSFT(KC_1) // ! -#define KC_EXCLAIM KC_EXLM +#define KC_EXCLAIM LSFT(KC_1) // ! +#define KC_EXLM KC_EXCLAIM #define KC_AT LSFT(KC_2) // @ #define KC_HASH LSFT(KC_3) // # -#define KC_DLR LSFT(KC_4) // $ -#define KC_DOLLAR KC_DLR - -#define KC_PERC LSFT(KC_5) // % -#define KC_PERCENT KC_PERC +#define KC_DOLLAR LSFT(KC_4) // $ +#define KC_DLR KC_DOLLAR -#define KC_CIRC LSFT(KC_6) // ^ -#define KC_CIRCUMFLEX KC_CIRC +#define KC_PERCENT LSFT(KC_5) // % +#define KC_PERC KC_PERCENT -#define KC_AMPR LSFT(KC_7) // & -#define KC_AMPERSAND KC_AMPR +#define KC_CIRCUMFLEX LSFT(KC_6) // ^ +#define KC_CIRC KC_CIRCUMFLEX -#define KC_ASTR LSFT(KC_8) // * -#define KC_ASTERISK KC_ASTR +#define KC_AMPERSAND LSFT(KC_7) // & +#define KC_AMPR KC_AMPERSAND -#define KC_LPRN LSFT(KC_9) // ( -#define KC_LEFT_PAREN KC_LPRN +#define KC_ASTERISK LSFT(KC_8) // * +#define KC_ASTR KC_ASTERISK -#define KC_RPRN LSFT(KC_0) // ) -#define KC_RIGHT_PAREN KC_RPRN +#define KC_LEFT_PAREN LSFT(KC_9) // ( +#define KC_LPRN KC_LEFT_PAREN -#define KC_UNDS LSFT(KC_MINS) // _ -#define KC_UNDERSCORE KC_UNDS +#define KC_RIGHT_PAREN LSFT(KC_0) // ) +#define KC_RPRN KC_RIGHT_PAREN -#define KC_PLUS LSFT(KC_EQL) // + +#define KC_UNDERSCORE LSFT(KC_MINUS) // _ +#define KC_UNDS KC_UNDERSCORE -#define KC_LCBR LSFT(KC_LBRC) // { -#define KC_LEFT_CURLY_BRACE KC_LCBR +#define KC_PLUS LSFT(KC_EQUAL) // + -#define KC_RCBR LSFT(KC_RBRC) // } -#define KC_RIGHT_CURLY_BRACE KC_RCBR +#define KC_LEFT_CURLY_BRACE LSFT(KC_LEFT_BRACKET) // { +#define KC_LCBR KC_LEFT_CURLY_BRACE -#define KC_LABK LSFT(KC_COMM) // < -#define KC_LEFT_ANGLE_BRACKET KC_LABK +#define KC_RIGHT_CURLY_BRACE LSFT(KC_RIGHT_BRACKET) // } +#define KC_RCBR KC_RIGHT_CURLY_BRACE -#define KC_RABK LSFT(KC_DOT) // > -#define KC_RIGHT_ANGLE_BRACKET KC_RABK +#define KC_LEFT_ANGLE_BRACKET LSFT(KC_COMMA) // < +#define KC_LABK KC_LEFT_ANGLE_BRACKET +#define KC_LT KC_LEFT_ANGLE_BRACKET -#define KC_COLN LSFT(KC_SCLN) // : -#define KC_COLON KC_COLN +#define KC_RIGHT_ANGLE_BRACKET LSFT(KC_DOT) // > +#define KC_RABK KC_RIGHT_ANGLE_BRACKET +#define KC_GT KC_RIGHT_ANGLE_BRACKET -#define KC_PIPE LSFT(KC_BSLS) // | +#define KC_COLON LSFT(KC_SEMICOLON) // : +#define KC_COLN KC_COLON -#define KC_LT LSFT(KC_COMM) // < +#define KC_PIPE LSFT(KC_BACKSLASH) // | -#define KC_GT LSFT(KC_DOT) // > +#define KC_QUESTION LSFT(KC_SLASH) // ? +#define KC_QUES KC_QUESTION -#define KC_QUES LSFT(KC_SLSH) // ? -#define KC_QUESTION KC_QUES - -#define KC_DQT LSFT(KC_QUOT) // " -#define KC_DOUBLE_QUOTE KC_DQT -#define KC_DQUO KC_DQT +#define KC_DOUBLE_QUOTE LSFT(KC_QUOTE) // " +#define KC_DQUO KC_DOUBLE_QUOTE +#define KC_DQT KC_DOUBLE_QUOTE #define KC_DELT KC_DELETE // Del key (four letter code) @@ -854,3 +886,39 @@ enum quantum_keycodes { #define OS_TOGG ONESHOT_TOGGLE #define OS_ON ONESHOT_ENABLE #define OS_OFF ONESHOT_DISABLE + +// Programmable Button aliases +#define PB_1 PROGRAMMABLE_BUTTON_1 +#define PB_2 PROGRAMMABLE_BUTTON_2 +#define PB_3 PROGRAMMABLE_BUTTON_3 +#define PB_4 PROGRAMMABLE_BUTTON_4 +#define PB_5 PROGRAMMABLE_BUTTON_5 +#define PB_6 PROGRAMMABLE_BUTTON_6 +#define PB_7 PROGRAMMABLE_BUTTON_7 +#define PB_8 PROGRAMMABLE_BUTTON_8 +#define PB_9 PROGRAMMABLE_BUTTON_9 +#define PB_10 PROGRAMMABLE_BUTTON_10 +#define PB_11 PROGRAMMABLE_BUTTON_11 +#define PB_12 PROGRAMMABLE_BUTTON_12 +#define PB_13 PROGRAMMABLE_BUTTON_13 +#define PB_14 PROGRAMMABLE_BUTTON_14 +#define PB_15 PROGRAMMABLE_BUTTON_15 +#define PB_16 PROGRAMMABLE_BUTTON_16 +#define PB_17 PROGRAMMABLE_BUTTON_17 +#define PB_18 PROGRAMMABLE_BUTTON_18 +#define PB_19 PROGRAMMABLE_BUTTON_19 +#define PB_20 PROGRAMMABLE_BUTTON_20 +#define PB_21 PROGRAMMABLE_BUTTON_21 +#define PB_22 PROGRAMMABLE_BUTTON_22 +#define PB_23 PROGRAMMABLE_BUTTON_23 +#define PB_24 PROGRAMMABLE_BUTTON_24 +#define PB_25 PROGRAMMABLE_BUTTON_25 +#define PB_26 PROGRAMMABLE_BUTTON_26 +#define PB_27 PROGRAMMABLE_BUTTON_27 +#define PB_28 PROGRAMMABLE_BUTTON_28 +#define PB_29 PROGRAMMABLE_BUTTON_29 +#define PB_30 PROGRAMMABLE_BUTTON_30 +#define PB_31 PROGRAMMABLE_BUTTON_31 +#define PB_32 PROGRAMMABLE_BUTTON_32 +#define PROGRAMMABLE_BUTTON_MIN PROGRAMMABLE_BUTTON_1 +#define PROGRAMMABLE_BUTTON_MAX PROGRAMMABLE_BUTTON_32 diff --git a/quantum/raw_hid.h b/quantum/raw_hid.h new file mode 100644 index 0000000000..6d60ab2bff --- /dev/null +++ b/quantum/raw_hid.h @@ -0,0 +1,5 @@ +#pragma once + +void raw_hid_receive(uint8_t *data, uint8_t length); + +void raw_hid_send(uint8_t *data, uint8_t length); diff --git a/quantum/rgb_matrix/animations/alpha_mods_anim.h b/quantum/rgb_matrix/animations/alpha_mods_anim.h index 3f2c9b799a..d6136f1ba4 100644 --- a/quantum/rgb_matrix/animations/alpha_mods_anim.h +++ b/quantum/rgb_matrix/animations/alpha_mods_anim.h @@ -19,8 +19,8 @@ bool ALPHAS_MODS(effect_params_t* params) { rgb_matrix_set_color(i, rgb1.r, rgb1.g, rgb1.b); } } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_ALPHAS_MODS +#endif // ENABLE_RGB_MATRIX_ALPHAS_MODS diff --git a/quantum/rgb_matrix/animations/breathing_anim.h b/quantum/rgb_matrix/animations/breathing_anim.h index a00ccb83a2..29187e1543 100644 --- a/quantum/rgb_matrix/animations/breathing_anim.h +++ b/quantum/rgb_matrix/animations/breathing_anim.h @@ -13,8 +13,8 @@ bool BREATHING(effect_params_t* params) { RGB_MATRIX_TEST_LED_FLAGS(); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_BREATHING +#endif // ENABLE_RGB_MATRIX_BREATHING diff --git a/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h index ac95789228..0375d4937d 100644 --- a/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h +++ b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h @@ -10,4 +10,4 @@ static HSV BAND_PINWHEEL_SAT_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time) bool BAND_PINWHEEL_SAT(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_SAT_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT +#endif // ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT diff --git a/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h index f7fe4b76e9..e40bf4cd1f 100644 --- a/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h +++ b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h @@ -10,4 +10,4 @@ static HSV BAND_PINWHEEL_VAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time) bool BAND_PINWHEEL_VAL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_VAL_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL +#endif // ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL diff --git a/quantum/rgb_matrix/animations/colorband_sat_anim.h b/quantum/rgb_matrix/animations/colorband_sat_anim.h index 96a6cbf5cd..1c4f7de575 100644 --- a/quantum/rgb_matrix/animations/colorband_sat_anim.h +++ b/quantum/rgb_matrix/animations/colorband_sat_anim.h @@ -11,4 +11,4 @@ static HSV BAND_SAT_math(HSV hsv, uint8_t i, uint8_t time) { bool BAND_SAT(effect_params_t* params) { return effect_runner_i(params, &BAND_SAT_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_BAND_SAT +#endif // ENABLE_RGB_MATRIX_BAND_SAT diff --git a/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h index 52f6040d81..cdd02b3797 100644 --- a/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h +++ b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h @@ -10,4 +10,4 @@ static HSV BAND_SPIRAL_SAT_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, u bool BAND_SPIRAL_SAT(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_SAT_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT +#endif // ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT diff --git a/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h index d5752e27fb..e1331eaebe 100644 --- a/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h +++ b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h @@ -10,4 +10,4 @@ static HSV BAND_SPIRAL_VAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, u bool BAND_SPIRAL_VAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_VAL_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL +#endif // ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL diff --git a/quantum/rgb_matrix/animations/colorband_val_anim.h b/quantum/rgb_matrix/animations/colorband_val_anim.h index 32bc6f52a5..02ee4add67 100644 --- a/quantum/rgb_matrix/animations/colorband_val_anim.h +++ b/quantum/rgb_matrix/animations/colorband_val_anim.h @@ -11,4 +11,4 @@ static HSV BAND_VAL_math(HSV hsv, uint8_t i, uint8_t time) { bool BAND_VAL(effect_params_t* params) { return effect_runner_i(params, &BAND_VAL_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_BAND_VAL +#endif // ENABLE_RGB_MATRIX_BAND_VAL diff --git a/quantum/rgb_matrix/animations/cycle_all_anim.h b/quantum/rgb_matrix/animations/cycle_all_anim.h index 20af94b6ba..3b73b9d385 100644 --- a/quantum/rgb_matrix/animations/cycle_all_anim.h +++ b/quantum/rgb_matrix/animations/cycle_all_anim.h @@ -10,4 +10,4 @@ static HSV CYCLE_ALL_math(HSV hsv, uint8_t i, uint8_t time) { bool CYCLE_ALL(effect_params_t* params) { return effect_runner_i(params, &CYCLE_ALL_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_CYCLE_ALL +#endif // ENABLE_RGB_MATRIX_CYCLE_ALL diff --git a/quantum/rgb_matrix/animations/cycle_left_right_anim.h b/quantum/rgb_matrix/animations/cycle_left_right_anim.h index 7f84f4bd59..bf6a574069 100644 --- a/quantum/rgb_matrix/animations/cycle_left_right_anim.h +++ b/quantum/rgb_matrix/animations/cycle_left_right_anim.h @@ -10,4 +10,4 @@ static HSV CYCLE_LEFT_RIGHT_math(HSV hsv, uint8_t i, uint8_t time) { bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT +#endif // ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT diff --git a/quantum/rgb_matrix/animations/cycle_out_in_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_anim.h index 2277f16a2f..2bdb9d9375 100644 --- a/quantum/rgb_matrix/animations/cycle_out_in_anim.h +++ b/quantum/rgb_matrix/animations/cycle_out_in_anim.h @@ -10,4 +10,4 @@ static HSV CYCLE_OUT_IN_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_CYCLE_OUT_IN +#endif // ENABLE_RGB_MATRIX_CYCLE_OUT_IN diff --git a/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h index 981c0afd05..51979c44fe 100644 --- a/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h +++ b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h @@ -12,4 +12,4 @@ static HSV CYCLE_OUT_IN_DUAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time) bool CYCLE_OUT_IN_DUAL(effect_params_t* params) { return effect_runner_dx_dy(params, &CYCLE_OUT_IN_DUAL_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL +#endif // ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL diff --git a/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h index 1a7db4a4c7..10ba2b7c2c 100644 --- a/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h +++ b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h @@ -10,4 +10,4 @@ static HSV CYCLE_PINWHEEL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time) { bool CYCLE_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &CYCLE_PINWHEEL_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_CYCLE_PINWHEEL +#endif // ENABLE_RGB_MATRIX_CYCLE_PINWHEEL diff --git a/quantum/rgb_matrix/animations/cycle_spiral_anim.h b/quantum/rgb_matrix/animations/cycle_spiral_anim.h index 245cdc237f..482c7e7da6 100644 --- a/quantum/rgb_matrix/animations/cycle_spiral_anim.h +++ b/quantum/rgb_matrix/animations/cycle_spiral_anim.h @@ -10,4 +10,4 @@ static HSV CYCLE_SPIRAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint bool CYCLE_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_SPIRAL_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_CYCLE_SPIRAL +#endif // ENABLE_RGB_MATRIX_CYCLE_SPIRAL diff --git a/quantum/rgb_matrix/animations/cycle_up_down_anim.h b/quantum/rgb_matrix/animations/cycle_up_down_anim.h index c9b5a54133..277edccb2f 100644 --- a/quantum/rgb_matrix/animations/cycle_up_down_anim.h +++ b/quantum/rgb_matrix/animations/cycle_up_down_anim.h @@ -10,4 +10,4 @@ static HSV CYCLE_UP_DOWN_math(HSV hsv, uint8_t i, uint8_t time) { bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_CYCLE_UP_DOWN +#endif // ENABLE_RGB_MATRIX_CYCLE_UP_DOWN diff --git a/quantum/rgb_matrix/animations/digital_rain_anim.h b/quantum/rgb_matrix/animations/digital_rain_anim.h index 1de45f8e8d..8ce8fd7039 100644 --- a/quantum/rgb_matrix/animations/digital_rain_anim.h +++ b/quantum/rgb_matrix/animations/digital_rain_anim.h @@ -1,4 +1,4 @@ -#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN) +#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_DIGITAL_RAIN) RGB_MATRIX_EFFECT(DIGITAL_RAIN) # ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS @@ -72,4 +72,4 @@ bool DIGITAL_RAIN(effect_params_t* params) { } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN) +#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(ENABLE_RGB_MATRIX_DIGITAL_RAIN) diff --git a/quantum/rgb_matrix/animations/dual_beacon_anim.h b/quantum/rgb_matrix/animations/dual_beacon_anim.h index 5c06080a26..dbe9b3ecf1 100644 --- a/quantum/rgb_matrix/animations/dual_beacon_anim.h +++ b/quantum/rgb_matrix/animations/dual_beacon_anim.h @@ -10,4 +10,4 @@ static HSV DUAL_BEACON_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, uint8_t bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_DUAL_BEACON +#endif // ENABLE_RGB_MATRIX_DUAL_BEACON diff --git a/quantum/rgb_matrix/animations/gradient_left_right_anim.h b/quantum/rgb_matrix/animations/gradient_left_right_anim.h index b4f2752ff7..8bb5e570bd 100644 --- a/quantum/rgb_matrix/animations/gradient_left_right_anim.h +++ b/quantum/rgb_matrix/animations/gradient_left_right_anim.h @@ -15,8 +15,8 @@ bool GRADIENT_LEFT_RIGHT(effect_params_t* params) { RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT +#endif // ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT diff --git a/quantum/rgb_matrix/animations/gradient_up_down_anim.h b/quantum/rgb_matrix/animations/gradient_up_down_anim.h index 3fd45cf99b..a5674583e3 100644 --- a/quantum/rgb_matrix/animations/gradient_up_down_anim.h +++ b/quantum/rgb_matrix/animations/gradient_up_down_anim.h @@ -15,8 +15,8 @@ bool GRADIENT_UP_DOWN(effect_params_t* params) { RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN +#endif // ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN diff --git a/quantum/rgb_matrix/animations/hue_breathing_anim.h b/quantum/rgb_matrix/animations/hue_breathing_anim.h index 6d974b8c39..82be1a4424 100644 --- a/quantum/rgb_matrix/animations/hue_breathing_anim.h +++ b/quantum/rgb_matrix/animations/hue_breathing_anim.h @@ -15,7 +15,7 @@ bool HUE_BREATHING(effect_params_t* params) { RGB_MATRIX_TEST_LED_FLAGS(); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h index 7d8eafffb9..3ffb57eb35 100644 --- a/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h +++ b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h @@ -22,8 +22,8 @@ bool JELLYBEAN_RAINDROPS(effect_params_t* params) { for (int i = led_min; i < led_max; i++) { jellybean_raindrops_set_color(i, params); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS +#endif // ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS diff --git a/quantum/rgb_matrix/animations/pixel_fractal_anim.h b/quantum/rgb_matrix/animations/pixel_fractal_anim.h new file mode 100644 index 0000000000..8e25ec402c --- /dev/null +++ b/quantum/rgb_matrix/animations/pixel_fractal_anim.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2021 @filterpaper + * + * 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/>. + */ + +// Inspired from 4x12 fractal created by @schwarzgrau + +#ifdef ENABLE_RGB_MATRIX_PIXEL_FRACTAL +RGB_MATRIX_EFFECT(PIXEL_FRACTAL) +# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +static bool PIXEL_FRACTAL(effect_params_t* params) { +# define MID_COL MATRIX_COLS / 2 + static bool led[MATRIX_ROWS][MATRIX_COLS]; + + static uint32_t wait_timer = 0; + if (wait_timer > g_rgb_timer) { + return false; + } + + inline uint32_t interval(void) { return 3000 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16); } + + RGB rgb = rgb_matrix_hsv_to_rgb(rgb_matrix_config.hsv); + for (uint8_t h = 0; h < MATRIX_ROWS; ++h) { + for (uint8_t l = 0; l < MID_COL - 1; ++l) { // Light and move left columns outwards + if (led[h][l]) { + rgb_matrix_set_color(g_led_config.matrix_co[h][l], rgb.r, rgb.g, rgb.b); + } else { + rgb_matrix_set_color(g_led_config.matrix_co[h][l], 0, 0, 0); + } + led[h][l] = led[h][l + 1]; + } + + for (uint8_t r = MATRIX_COLS - 1; r > MID_COL; --r) { // Light and move right columns outwards + if (led[h][r]) { + rgb_matrix_set_color(g_led_config.matrix_co[h][r], rgb.r, rgb.g, rgb.b); + } else { + rgb_matrix_set_color(g_led_config.matrix_co[h][r], 0, 0, 0); + } + led[h][r] = led[h][r - 1]; + } + + // Light both middle columns + if (led[h][MID_COL]) { + rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL], rgb.r, rgb.g, rgb.b); + } else { + rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL], 0, 0, 0); + } + if (led[h][MID_COL - 1]) { + rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], rgb.r, rgb.g, rgb.b); + } else { + rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], 0, 0, 0); + } + + // Generate new random fractal columns + led[h][MID_COL] = led[h][MID_COL - 1] = (random8() & 3) ? false : true; + } + + wait_timer = g_rgb_timer + interval(); + return false; +} +# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // ENABLE_RGB_MATRIX_PIXEL_FRACTAL diff --git a/quantum/rgb_matrix/animations/pixel_rain_anim.h b/quantum/rgb_matrix/animations/pixel_rain_anim.h new file mode 100644 index 0000000000..001649aa6e --- /dev/null +++ b/quantum/rgb_matrix/animations/pixel_rain_anim.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2021 @filterpaper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef ENABLE_RGB_MATRIX_PIXEL_RAIN +RGB_MATRIX_EFFECT(PIXEL_RAIN) +# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +static bool PIXEL_RAIN(effect_params_t* params) { + static uint32_t wait_timer = 0; + if (wait_timer > g_rgb_timer) { + return false; + } + + inline uint32_t interval(void) { return 500 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16); } + + bool rain_pixel(uint8_t i, effect_params_t * params, bool off) { + if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) { + return true; + } + if (off) { + rgb_matrix_set_color(i, 0, 0, 0); + } else { + HSV hsv = {random8(), qadd8(random8() >> 1, 127), rgb_matrix_config.hsv.v}; + RGB rgb = rgb_matrix_hsv_to_rgb(hsv); + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } + wait_timer = g_rgb_timer + interval(); + return false; + } + + return rain_pixel(mod8(random8(), DRIVER_LED_TOTAL), params, random8() & 2); +} + +# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // ENABLE_RGB_MATRIX_PIXEL_RAIN diff --git a/quantum/rgb_matrix/animations/rainbow_beacon_anim.h b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h index b54d997f63..cd529958db 100644 --- a/quantum/rgb_matrix/animations/rainbow_beacon_anim.h +++ b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h @@ -10,4 +10,4 @@ static HSV RAINBOW_BEACON_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, uint8 bool RAINBOW_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &RAINBOW_BEACON_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_RAINBOW_BEACON +#endif // ENABLE_RGB_MATRIX_RAINBOW_BEACON diff --git a/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h index 50db922014..2f3de64e9d 100644 --- a/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h +++ b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h @@ -10,4 +10,4 @@ static HSV RAINBOW_MOVING_CHEVRON_math(HSV hsv, uint8_t i, uint8_t time) { bool RAINBOW_MOVING_CHEVRON(effect_params_t* params) { return effect_runner_i(params, &RAINBOW_MOVING_CHEVRON_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON +#endif // ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON diff --git a/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h index 3299f15df1..dae2b5d190 100644 --- a/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h +++ b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h @@ -10,4 +10,4 @@ static HSV RAINBOW_PINWHEELS_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, ui bool RAINBOW_PINWHEELS(effect_params_t* params) { return effect_runner_sin_cos_i(params, &RAINBOW_PINWHEELS_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS +#endif // ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS diff --git a/quantum/rgb_matrix/animations/raindrops_anim.h b/quantum/rgb_matrix/animations/raindrops_anim.h index c01688e2c7..4b1b9dd9ec 100644 --- a/quantum/rgb_matrix/animations/raindrops_anim.h +++ b/quantum/rgb_matrix/animations/raindrops_anim.h @@ -32,8 +32,8 @@ bool RAINDROPS(effect_params_t* params) { for (int i = led_min; i < led_max; i++) { raindrops_set_color(i, params); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_RGB_MATRIX_RAINDROPS +#endif // ENABLE_RGB_MATRIX_RAINDROPS diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc index 302ad79c04..27ce347235 100644 --- a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc +++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc @@ -26,6 +26,8 @@ #include "hue_breathing_anim.h" #include "hue_pendulum_anim.h" #include "hue_wave_anim.h" +#include "pixel_rain_anim.h" +#include "pixel_fractal_anim.h" #include "typing_heatmap_anim.h" #include "digital_rain_anim.h" #include "solid_reactive_simple_anim.h" diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h index 4867609c81..2ad0f22c28 100644 --- a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h @@ -13,5 +13,5 @@ bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) { RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, time)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h index 9545b418d9..bcae7c79b6 100644 --- a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h @@ -14,5 +14,5 @@ bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func) RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, dist, time)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_i.h index 1881cd6c60..b4de2992b6 100644 --- a/quantum/rgb_matrix/animations/runners/effect_runner_i.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_i.h @@ -11,5 +11,5 @@ bool effect_runner_i(effect_params_t* params, i_f effect_func) { RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h index 75b7c0df4e..d5c1a26cef 100644 --- a/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h @@ -23,7 +23,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) { RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, offset)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h index 2e46ffb350..d3a6e4e72f 100644 --- a/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h @@ -23,7 +23,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h index 02351de51e..7776491d51 100644 --- a/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h @@ -13,5 +13,5 @@ bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) { RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, cos_value, sin_value, i, time)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } diff --git a/quantum/rgb_matrix/animations/solid_color_anim.h b/quantum/rgb_matrix/animations/solid_color_anim.h index 79d63cf133..4209959468 100644 --- a/quantum/rgb_matrix/animations/solid_color_anim.h +++ b/quantum/rgb_matrix/animations/solid_color_anim.h @@ -9,7 +9,7 @@ bool SOLID_COLOR(effect_params_t* params) { RGB_MATRIX_TEST_LED_FLAGS(); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } - return led_max < DRIVER_LED_TOTAL; + return rgb_matrix_check_finished_leds(led_max); } #endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/quantum/rgb_matrix/animations/solid_reactive_anim.h b/quantum/rgb_matrix/animations/solid_reactive_anim.h index d45bb961bc..360d05a67a 100644 --- a/quantum/rgb_matrix/animations/solid_reactive_anim.h +++ b/quantum/rgb_matrix/animations/solid_reactive_anim.h @@ -1,5 +1,5 @@ #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE RGB_MATRIX_EFFECT(SOLID_REACTIVE) # ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS @@ -11,5 +11,5 @@ static HSV SOLID_REACTIVE_math(HSV hsv, uint16_t offset) { bool SOLID_REACTIVE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // DISABLE_RGB_MATRIX_SOLID_REACTIVE +# endif // ENABLE_RGB_MATRIX_SOLID_REACTIVE #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/solid_reactive_cross.h b/quantum/rgb_matrix/animations/solid_reactive_cross.h index f76c68e8c7..496651f8a5 100644 --- a/quantum/rgb_matrix/animations/solid_reactive_cross.h +++ b/quantum/rgb_matrix/animations/solid_reactive_cross.h @@ -1,11 +1,11 @@ #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED -# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS) +# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS) -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS RGB_MATRIX_EFFECT(SOLID_REACTIVE_CROSS) # endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTICROSS) # endif @@ -23,14 +23,14 @@ static HSV SOLID_REACTIVE_CROSS_math(HSV hsv, int16_t dx, int16_t dy, uint8_t di return hsv; } -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS bool SOLID_REACTIVE_CROSS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math); } # endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math); } # endif # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS) +# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS) #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/solid_reactive_nexus.h b/quantum/rgb_matrix/animations/solid_reactive_nexus.h index 17f94e3c18..3562e74a72 100644 --- a/quantum/rgb_matrix/animations/solid_reactive_nexus.h +++ b/quantum/rgb_matrix/animations/solid_reactive_nexus.h @@ -1,11 +1,11 @@ #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED -# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS) +# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS) -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS RGB_MATRIX_EFFECT(SOLID_REACTIVE_NEXUS) # endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTINEXUS) # endif @@ -21,14 +21,14 @@ static HSV SOLID_REACTIVE_NEXUS_math(HSV hsv, int16_t dx, int16_t dy, uint8_t di return hsv; } -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS bool SOLID_REACTIVE_NEXUS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math); } # endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math); } # endif # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS) +# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS) #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h index 12eb248cc0..69189f636b 100644 --- a/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h +++ b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h @@ -1,5 +1,5 @@ #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE RGB_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE) # ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS @@ -11,5 +11,5 @@ static HSV SOLID_REACTIVE_SIMPLE_math(HSV hsv, uint16_t offset) { bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE +# endif // ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/solid_reactive_wide.h b/quantum/rgb_matrix/animations/solid_reactive_wide.h index 1cc4dca728..a613c7ff5f 100644 --- a/quantum/rgb_matrix/animations/solid_reactive_wide.h +++ b/quantum/rgb_matrix/animations/solid_reactive_wide.h @@ -1,11 +1,11 @@ #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED -# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE) +# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE) -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE RGB_MATRIX_EFFECT(SOLID_REACTIVE_WIDE) # endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTIWIDE) # endif @@ -18,14 +18,14 @@ static HSV SOLID_REACTIVE_WIDE_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dis return hsv; } -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE bool SOLID_REACTIVE_WIDE(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math); } # endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE +# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math); } # endif # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE) +# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE) #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/solid_splash_anim.h b/quantum/rgb_matrix/animations/solid_splash_anim.h index 99efb4996a..bd9c1cfe2b 100644 --- a/quantum/rgb_matrix/animations/solid_splash_anim.h +++ b/quantum/rgb_matrix/animations/solid_splash_anim.h @@ -1,11 +1,11 @@ #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED -# if !defined(DISABLE_RGB_MATRIX_SOLID_SPLASH) || !defined(DISABLE_RGB_MATRIX_SOLID_MULTISPLASH) +# if defined(ENABLE_RGB_MATRIX_SOLID_SPLASH) || defined(ENABLE_RGB_MATRIX_SOLID_MULTISPLASH) -# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH +# ifdef ENABLE_RGB_MATRIX_SOLID_SPLASH RGB_MATRIX_EFFECT(SOLID_SPLASH) # endif -# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH +# ifdef ENABLE_RGB_MATRIX_SOLID_MULTISPLASH RGB_MATRIX_EFFECT(SOLID_MULTISPLASH) # endif @@ -18,14 +18,14 @@ HSV SOLID_SPLASH_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t ti return hsv; } -# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH +# ifdef ENABLE_RGB_MATRIX_SOLID_SPLASH bool SOLID_SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math); } # endif -# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH +# ifdef ENABLE_RGB_MATRIX_SOLID_MULTISPLASH bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); } # endif # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_RGB_MATRIX_SPLASH) && !defined(DISABLE_RGB_MATRIX_MULTISPLASH) +# endif // !defined(ENABLE_RGB_MATRIX_SPLASH) && !defined(ENABLE_RGB_MATRIX_MULTISPLASH) #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/splash_anim.h b/quantum/rgb_matrix/animations/splash_anim.h index 1415bcc0fa..382355e9ed 100644 --- a/quantum/rgb_matrix/animations/splash_anim.h +++ b/quantum/rgb_matrix/animations/splash_anim.h @@ -1,11 +1,11 @@ #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED -# if !defined(DISABLE_RGB_MATRIX_SPLASH) || !defined(DISABLE_RGB_MATRIX_MULTISPLASH) +# if defined(ENABLE_RGB_MATRIX_SPLASH) || defined(ENABLE_RGB_MATRIX_MULTISPLASH) -# ifndef DISABLE_RGB_MATRIX_SPLASH +# ifdef ENABLE_RGB_MATRIX_SPLASH RGB_MATRIX_EFFECT(SPLASH) # endif -# ifndef DISABLE_RGB_MATRIX_MULTISPLASH +# ifdef ENABLE_RGB_MATRIX_MULTISPLASH RGB_MATRIX_EFFECT(MULTISPLASH) # endif @@ -19,14 +19,14 @@ HSV SPLASH_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { return hsv; } -# ifndef DISABLE_RGB_MATRIX_SPLASH +# ifdef ENABLE_RGB_MATRIX_SPLASH bool SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SPLASH_math); } # endif -# ifndef DISABLE_RGB_MATRIX_MULTISPLASH +# ifdef ENABLE_RGB_MATRIX_MULTISPLASH bool MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SPLASH_math); } # endif # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_RGB_MATRIX_SPLASH) || !defined(DISABLE_RGB_MATRIX_MULTISPLASH) +# endif // !defined(ENABLE_RGB_MATRIX_SPLASH) || !defined(ENABLE_RGB_MATRIX_MULTISPLASH) #endif // RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix/animations/typing_heatmap_anim.h b/quantum/rgb_matrix/animations/typing_heatmap_anim.h index 28f040109d..b66667b9b8 100644 --- a/quantum/rgb_matrix/animations/typing_heatmap_anim.h +++ b/quantum/rgb_matrix/animations/typing_heatmap_anim.h @@ -83,4 +83,4 @@ bool TYPING_HEATMAP(effect_params_t* params) { } # endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_TYPING_HEATMAP) +#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP) diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c index 8f00b40877..558c7bd41a 100644 --- a/quantum/rgb_matrix/rgb_matrix.c +++ b/quantum/rgb_matrix/rgb_matrix.c @@ -31,14 +31,6 @@ const led_point_t k_rgb_matrix_center = {112, 32}; const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; #endif -// clang-format off -#ifndef RGB_MATRIX_IMMEDIATE_EEPROM -# define rgb_eeconfig_update(v) rgb_update_eeprom |= v -#else -# define rgb_eeconfig_update(v) if (v) eeconfig_update_rgb_matrix() -#endif -// clang-format on - __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } // Generic effect runners @@ -128,7 +120,6 @@ last_hit_t g_last_hit_tracker; // internals static bool suspend_state = false; -static bool rgb_update_eeprom = false; static uint8_t rgb_last_enable = UINT8_MAX; static uint8_t rgb_last_effect = UINT8_MAX; static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; @@ -148,9 +139,9 @@ static last_hit_t last_hit_buffer; const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; #endif -void eeconfig_read_rgb_matrix(void) { eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } +EECONFIG_DEBOUNCE_HELPER(rgb_matrix, EECONFIG_RGB_MATRIX, rgb_matrix_config); -void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } +void eeconfig_update_rgb_matrix(void) { eeconfig_flush_rgb_matrix(true); } void eeconfig_update_rgb_matrix_default(void) { dprintf("eeconfig_update_rgb_matrix_default\n"); @@ -159,7 +150,7 @@ void eeconfig_update_rgb_matrix_default(void) { 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; rgb_matrix_config.flags = LED_FLAG_ALL; - eeconfig_update_rgb_matrix(); + eeconfig_flush_rgb_matrix(true); } void eeconfig_debug_rgb_matrix(void) { @@ -187,14 +178,7 @@ uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l void rgb_matrix_update_pwm_buffers(void) { rgb_matrix_driver.flush(); } -void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { -#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) - if (!is_keyboard_left() && index >= k_rgb_matrix_split[0]) - rgb_matrix_driver.set_color(index - k_rgb_matrix_split[0], red, green, blue); - else if (is_keyboard_left() && index < k_rgb_matrix_split[0]) -#endif - rgb_matrix_driver.set_color(index, red, green, blue); -} +void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color(index, red, green, blue); } void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) @@ -314,9 +298,8 @@ static void rgb_task_timers(void) { } static void rgb_task_sync(void) { + eeconfig_flush_rgb_matrix(false); // next task - if (rgb_update_eeprom) eeconfig_update_rgb_matrix(); - rgb_update_eeprom = false; if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; } @@ -491,7 +474,7 @@ void rgb_matrix_init(void) { eeconfig_update_rgb_matrix_default(); } - eeconfig_read_rgb_matrix(); + eeconfig_init_rgb_matrix(); if (!rgb_matrix_config.mode) { dprintf("rgb_matrix_init_drivers rgb_matrix_config.mode = 0. Write default values to EEPROM.\n"); eeconfig_update_rgb_matrix_default(); @@ -514,7 +497,7 @@ bool rgb_matrix_get_suspend_state(void) { return suspend_state; } void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { rgb_matrix_config.enable ^= 1; rgb_task_state = STARTING; - rgb_eeconfig_update(write_to_eeprom); + eeconfig_flag_rgb_matrix(write_to_eeprom); dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable); } void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); } @@ -522,7 +505,7 @@ void rgb_matrix_toggle(void) { rgb_matrix_toggle_eeprom_helper(true); } void rgb_matrix_enable(void) { rgb_matrix_enable_noeeprom(); - rgb_eeconfig_update(true); + eeconfig_flag_rgb_matrix(true); } void rgb_matrix_enable_noeeprom(void) { @@ -532,7 +515,7 @@ void rgb_matrix_enable_noeeprom(void) { void rgb_matrix_disable(void) { rgb_matrix_disable_noeeprom(); - rgb_eeconfig_update(true); + eeconfig_flag_rgb_matrix(true); } void rgb_matrix_disable_noeeprom(void) { @@ -554,7 +537,7 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { rgb_matrix_config.mode = mode; } rgb_task_state = STARTING; - rgb_eeconfig_update(write_to_eeprom); + eeconfig_flag_rgb_matrix(write_to_eeprom); dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode); } void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); } @@ -583,7 +566,7 @@ void rgb_matrix_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, boo rgb_matrix_config.hsv.h = hue; rgb_matrix_config.hsv.s = sat; rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val; - rgb_eeconfig_update(write_to_eeprom); + eeconfig_flag_rgb_matrix(write_to_eeprom); dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v); } void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); } @@ -620,7 +603,7 @@ void rgb_matrix_decrease_val(void) { rgb_matrix_decrease_val_helper(true); } void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { rgb_matrix_config.speed = speed; - rgb_eeconfig_update(write_to_eeprom); + eeconfig_flag_rgb_matrix(write_to_eeprom); dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed); } void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); } diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h index f53e011c1b..a804d99abc 100644 --- a/quantum/rgb_matrix/rgb_matrix.h +++ b/quantum/rgb_matrix/rgb_matrix.h @@ -23,7 +23,6 @@ #include "rgb_matrix_types.h" #include "color.h" #include "quantum.h" -#include "rgb_matrix_legacy_enables.h" #ifdef IS31FL3731 # include "is31fl3731.h" @@ -33,6 +32,8 @@ # include "is31fl3737.h" #elif defined(IS31FL3741) # include "is31fl3741.h" +#elif defined(CKLED2001) +# include "ckled2001.h" #elif defined(AW20216) # include "aw20216.h" #elif defined(WS2812) @@ -48,14 +49,33 @@ #endif #if defined(RGB_MATRIX_LED_PROCESS_LIMIT) && RGB_MATRIX_LED_PROCESS_LIMIT > 0 && RGB_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL -# define RGB_MATRIX_USE_LIMITS(min, max) \ - uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \ - uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \ - if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; +# if defined(RGB_MATRIX_SPLIT) +# define RGB_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \ + uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \ + if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; \ + uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; \ + if (is_keyboard_left() && (max > k_rgb_matrix_split[0])) max = k_rgb_matrix_split[0]; \ + if (!(is_keyboard_left()) && (min < k_rgb_matrix_split[0])) min = k_rgb_matrix_split[0]; +# else +# define RGB_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \ + uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \ + if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; +# endif #else -# define RGB_MATRIX_USE_LIMITS(min, max) \ - uint8_t min = 0; \ - uint8_t max = DRIVER_LED_TOTAL; +# if defined(RGB_MATRIX_SPLIT) +# define RGB_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = 0; \ + uint8_t max = DRIVER_LED_TOTAL; \ + const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; \ + if (is_keyboard_left() && (max > k_rgb_matrix_split[0])) max = k_rgb_matrix_split[0]; \ + if (!(is_keyboard_left()) && (min < k_rgb_matrix_split[0])) min = k_rgb_matrix_split[0]; +# else +# define RGB_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = 0; \ + uint8_t max = DRIVER_LED_TOTAL; +# endif #endif #define RGB_MATRIX_INDICATOR_SET_COLOR(i, r, g, b) \ @@ -214,6 +234,18 @@ typedef struct { void (*flush)(void); } rgb_matrix_driver_t; +static inline bool rgb_matrix_check_finished_leds(uint8_t led_idx) { +#if defined(RGB_MATRIX_SPLIT) + if (is_keyboard_left()) { + uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; + return led_idx < k_rgb_matrix_split[0]; + } else + return led_idx < DRIVER_LED_TOTAL; +#else + return led_idx < DRIVER_LED_TOTAL; +#endif +} + extern const rgb_matrix_driver_t rgb_matrix_driver; extern rgb_config_t rgb_matrix_config; diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c index 2cec162e22..130ca47a63 100644 --- a/quantum/rgb_matrix/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix/rgb_matrix_drivers.c @@ -23,111 +23,153 @@ * be here if shared between boards. */ -#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3737) || defined(IS31FL3741) - +#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3737) || defined(IS31FL3741) || defined(CKLED2001) # include "i2c_master.h" +// TODO: Remove this at some later date +# if defined(DRIVER_ADDR_1) && defined(DRIVER_ADDR_2) +# if DRIVER_ADDR_1 == DRIVER_ADDR_2 +# error "Setting DRIVER_ADDR_2 == DRIVER_ADDR_1 is obsolete. If you are only using one ISSI driver, set DRIVER_COUNT to 1 and remove DRIVER_ADDR_2" +# endif +# endif + static void init(void) { i2c_init(); -# ifdef IS31FL3731 + +# if defined(IS31FL3731) IS31FL3731_init(DRIVER_ADDR_1); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3731_init(DRIVER_ADDR_2); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3731_init(DRIVER_ADDR_3); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3731_init(DRIVER_ADDR_4); +# endif +# endif # endif + # elif defined(IS31FL3733) -# ifndef DRIVER_SYNC_1 +# if !defined(DRIVER_SYNC_1) # define DRIVER_SYNC_1 0 # endif IS31FL3733_init(DRIVER_ADDR_1, DRIVER_SYNC_1); -# if defined DRIVER_ADDR_2 && (DRIVER_ADDR_1 != DRIVER_ADDR_2) -# ifndef DRIVER_SYNC_2 +# if defined(DRIVER_ADDR_2) +# if !defined(DRIVER_SYNC_2) # define DRIVER_SYNC_2 0 # endif IS31FL3733_init(DRIVER_ADDR_2, DRIVER_SYNC_2); -# endif -# ifdef DRIVER_ADDR_3 -# ifndef DRIVER_SYNC_3 -# define DRIVER_SYNC_3 0 -# endif +# if defined(DRIVER_ADDR_3) +# if !defined(DRIVER_SYNC_3) +# define DRIVER_SYNC_3 0 +# endif IS31FL3733_init(DRIVER_ADDR_3, DRIVER_SYNC_3); -# endif -# ifdef DRIVER_ADDR_4 -# ifndef DRIVER_SYNC_4 -# define DRIVER_SYNC_4 0 -# endif +# if defined(DRIVER_ADDR_4) +# if !defined(DRIVER_SYNC_4) +# define DRIVER_SYNC_4 0 +# endif IS31FL3733_init(DRIVER_ADDR_4, DRIVER_SYNC_4); +# endif +# endif # endif + # elif defined(IS31FL3737) IS31FL3737_init(DRIVER_ADDR_1); -# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility +# if defined(DRIVER_ADDR_2) IS31FL3737_init(DRIVER_ADDR_2); # endif -# else + +# elif defined(IS31FL3741) IS31FL3741_init(DRIVER_ADDR_1); + +# elif defined(CKLED2001) + CKLED2001_init(DRIVER_ADDR_1); +# if defined(DRIVER_ADDR_2) + CKLED2001_init(DRIVER_ADDR_2); +# if defined(DRIVER_ADDR_3) + CKLED2001_init(DRIVER_ADDR_3); +# if defined(DRIVER_ADDR_4) + CKLED2001_init(DRIVER_ADDR_4); +# endif +# endif +# endif # endif + for (int index = 0; index < DRIVER_LED_TOTAL; index++) { bool enabled = true; + // This only caches it for later -# ifdef IS31FL3731 +# if defined(IS31FL3731) IS31FL3731_set_led_control_register(index, enabled, enabled, enabled); # elif defined(IS31FL3733) IS31FL3733_set_led_control_register(index, enabled, enabled, enabled); # elif defined(IS31FL3737) IS31FL3737_set_led_control_register(index, enabled, enabled, enabled); -# else +# elif defined(IS31FL3741) IS31FL3741_set_led_control_register(index, enabled, enabled, enabled); +# elif defined(CKLED2001) + CKLED2001_set_led_control_register(index, enabled, enabled, enabled); # endif } + // This actually updates the LED drivers -# ifdef IS31FL3731 +# if defined(IS31FL3731) IS31FL3731_update_led_control_registers(DRIVER_ADDR_1, 0); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3731_update_led_control_registers(DRIVER_ADDR_2, 1); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3731_update_led_control_registers(DRIVER_ADDR_3, 2); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3731_update_led_control_registers(DRIVER_ADDR_4, 3); +# endif +# endif # endif + # elif defined(IS31FL3733) IS31FL3733_update_led_control_registers(DRIVER_ADDR_1, 0); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3733_update_led_control_registers(DRIVER_ADDR_2, 1); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3733_update_led_control_registers(DRIVER_ADDR_3, 2); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3); +# endif +# endif # endif + # elif defined(IS31FL3737) IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, 0); -# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility +# if defined(DRIVER_ADDR_2) IS31FL3737_update_led_control_registers(DRIVER_ADDR_2, 1); # endif -# else + +# elif defined(IS31FL3741) IS31FL3741_update_led_control_registers(DRIVER_ADDR_1, 0); + +# elif defined(CKLED2001) + CKLED2001_update_led_control_registers(DRIVER_ADDR_1, 0); +# if defined(DRIVER_ADDR_2) + CKLED2001_update_led_control_registers(DRIVER_ADDR_2, 1); +# if defined(DRIVER_ADDR_3) + CKLED2001_update_led_control_registers(DRIVER_ADDR_3, 2); +# if defined(DRIVER_ADDR_4) + CKLED2001_update_led_control_registers(DRIVER_ADDR_4, 3); +# endif +# endif +# endif # endif } -# ifdef IS31FL3731 +# if defined(IS31FL3731) static void flush(void) { IS31FL3731_update_pwm_buffers(DRIVER_ADDR_1, 0); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3731_update_pwm_buffers(DRIVER_ADDR_2, 1); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3731_update_pwm_buffers(DRIVER_ADDR_3, 2); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3731_update_pwm_buffers(DRIVER_ADDR_4, 3); +# endif +# endif # endif } @@ -137,17 +179,18 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color = IS31FL3731_set_color, .set_color_all = IS31FL3731_set_color_all, }; + # elif defined(IS31FL3733) static void flush(void) { IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1, 0); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2, 1); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3733_update_pwm_buffers(DRIVER_ADDR_3, 2); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3733_update_pwm_buffers(DRIVER_ADDR_4, 3); +# endif +# endif # endif } @@ -157,10 +200,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color = IS31FL3733_set_color, .set_color_all = IS31FL3733_set_color_all, }; + # elif defined(IS31FL3737) static void flush(void) { IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, 0); -# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility +# if defined(DRIVER_ADDR_2) IS31FL3737_update_pwm_buffers(DRIVER_ADDR_2, 1); # endif } @@ -171,10 +215,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color = IS31FL3737_set_color, .set_color_all = IS31FL3737_set_color_all, }; -# else + +# elif defined(IS31FL3741) static void flush(void) { IS31FL3741_update_pwm_buffers(DRIVER_ADDR_1, 0); -# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility +# if defined(DRIVER_ADDR_2) IS31FL3741_update_pwm_buffers(DRIVER_ADDR_2, 1); # endif } @@ -185,21 +230,44 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color = IS31FL3741_set_color, .set_color_all = IS31FL3741_set_color_all, }; + +# elif defined(CKLED2001) +static void flush(void) { + CKLED2001_update_pwm_buffers(DRIVER_ADDR_1, 0); +# if defined(DRIVER_ADDR_2) + CKLED2001_update_pwm_buffers(DRIVER_ADDR_2, 1); +# if defined(DRIVER_ADDR_3) + CKLED2001_update_pwm_buffers(DRIVER_ADDR_3, 2); +# if defined(DRIVER_ADDR_4) + CKLED2001_update_pwm_buffers(DRIVER_ADDR_4, 3); +# endif +# endif +# endif +} + +const rgb_matrix_driver_t rgb_matrix_driver = { + .init = init, + .flush = flush, + .set_color = CKLED2001_set_color, + .set_color_all = CKLED2001_set_color_all, +}; # endif #elif defined(AW20216) # include "spi_master.h" + static void init(void) { spi_init(); + AW20216_init(DRIVER_1_CS, DRIVER_1_EN); -# ifdef DRIVER_2_CS +# if defined(DRIVER_2_CS) AW20216_init(DRIVER_2_CS, DRIVER_2_EN); # endif } static void flush(void) { AW20216_update_pwm_buffers(DRIVER_1_CS, 0); -# ifdef DRIVER_2_CS +# if defined(DRIVER_2_CS) AW20216_update_pwm_buffers(DRIVER_2_CS, 1); # endif } @@ -229,6 +297,14 @@ static void flush(void) { // Set an led in the buffer to a color static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) { +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; + if (!is_keyboard_left() && (i >= k_rgb_matrix_split[0])) { + i -= k_rgb_matrix_split[0]; + } else if (is_keyboard_left() && (i >= k_rgb_matrix_split[0])) + return; +# endif + rgb_matrix_ws2812_array[i].r = r; rgb_matrix_ws2812_array[i].g = g; rgb_matrix_ws2812_array[i].b = b; diff --git a/quantum/rgb_matrix/rgb_matrix_legacy_enables.h b/quantum/rgb_matrix/rgb_matrix_legacy_enables.h deleted file mode 100644 index 398858ebc8..0000000000 --- a/quantum/rgb_matrix/rgb_matrix_legacy_enables.h +++ /dev/null @@ -1,153 +0,0 @@ -/* Copyright 2021 QMK - * - * 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/>. - */ - -// to-do: remove this - -#pragma once - -#ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS -# define ENABLE_RGB_MATRIX_ALPHAS_MODS -#endif -#ifndef DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN -# define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN -#endif -#ifndef DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT -# define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT -#endif -#ifndef DISABLE_RGB_MATRIX_BREATHING -# define ENABLE_RGB_MATRIX_BREATHING -#endif -#ifndef DISABLE_RGB_MATRIX_BAND_SAT -# define ENABLE_RGB_MATRIX_BAND_SAT -#endif -#ifndef DISABLE_RGB_MATRIX_BAND_VAL -# define ENABLE_RGB_MATRIX_BAND_VAL -#endif -#ifndef DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT -# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT -#endif -#ifndef DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL -# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL -#endif -#ifndef DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT -# define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT -#endif -#ifndef DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL -# define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL -#endif -#ifndef DISABLE_RGB_MATRIX_CYCLE_ALL -# define ENABLE_RGB_MATRIX_CYCLE_ALL -#endif -#ifndef DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT -# define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT -#endif -#ifndef DISABLE_RGB_MATRIX_CYCLE_UP_DOWN -# define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN -#endif -#ifndef DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON -# define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON -#endif -#ifndef DISABLE_RGB_MATRIX_CYCLE_OUT_IN -# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN -#endif -#ifndef DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL -# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL -#endif -#ifndef DISABLE_RGB_MATRIX_CYCLE_PINWHEEL -# define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL -#endif -#ifndef DISABLE_RGB_MATRIX_CYCLE_SPIRAL -# define ENABLE_RGB_MATRIX_CYCLE_SPIRAL -#endif -#ifndef DISABLE_RGB_MATRIX_DUAL_BEACON -# define ENABLE_RGB_MATRIX_DUAL_BEACON -#endif -#ifndef DISABLE_RGB_MATRIX_RAINBOW_BEACON -# define ENABLE_RGB_MATRIX_RAINBOW_BEACON -#endif -#ifndef DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS -# define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS -#endif -#ifndef DISABLE_RGB_MATRIX_RAINDROPS -# define ENABLE_RGB_MATRIX_RAINDROPS -#endif -#ifndef DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS -# define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS -#endif -#ifndef DISABLE_RGB_MATRIX_HUE_BREATHING -# define ENABLE_RGB_MATRIX_HUE_BREATHING -#endif -#ifndef DISABLE_RGB_MATRIX_HUE_PENDULUM -# define ENABLE_RGB_MATRIX_HUE_PENDULUM -#endif -#ifndef DISABLE_RGB_MATRIX_HUE_WAVE -# define ENABLE_RGB_MATRIX_HUE_WAVE -#endif -#ifndef DISABLE_RGB_MATRIX_PIXEL_RAIN -# define ENABLE_RGB_MATRIX_PIXEL_RAIN -#endif -#ifndef DISABLE_RGB_MATRIX_PIXEL_FLOW -# define ENABLE_RGB_MATRIX_PIXEL_FLOW -#endif -#ifndef DISABLE_RGB_MATRIX_PIXEL_FRACTAL -# define ENABLE_RGB_MATRIX_PIXEL_FRACTAL -#endif -#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) -# ifndef DISABLE_RGB_MATRIX_TYPING_HEATMAP -# define ENABLE_RGB_MATRIX_TYPING_HEATMAP -# endif -# ifndef DISABLE_RGB_MATRIX_DIGITAL_RAIN -# define ENABLE_RGB_MATRIX_DIGITAL_RAIN -# endif -#endif -#if defined(RGB_MATRIX_KEYREACTIVE_ENABLED) -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE -# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE -# define ENABLE_RGB_MATRIX_SOLID_REACTIVE -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE -# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE -# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS -# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS -# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS -# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS -# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS -# endif -# ifndef DISABLE_RGB_MATRIX_SPLASH -# define ENABLE_RGB_MATRIX_SPLASH -# endif -# ifndef DISABLE_RGB_MATRIX_MULTISPLASH -# define ENABLE_RGB_MATRIX_MULTISPLASH -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH -# define ENABLE_RGB_MATRIX_SOLID_SPLASH -# endif -# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH -# define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH -# endif -#endif diff --git a/quantum/sequencer/tests/rules.mk b/quantum/sequencer/tests/rules.mk index 76c221cf92..a3bbd80513 100644 --- a/quantum/sequencer/tests/rules.mk +++ b/quantum/sequencer/tests/rules.mk @@ -1,5 +1,5 @@ # The letter case of these variables might seem odd. However: -# - it is consistent with the serial_link example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features) +# - it is consistent with the example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features) # - Neither `make test:sequencer` or `make test:SEQUENCER` work when using SCREAMING_SNAKE_CASE sequencer_DEFS := -DNO_DEBUG -DMIDI_MOCKED @@ -8,4 +8,4 @@ sequencer_SRC := \ $(QUANTUM_PATH)/sequencer/tests/midi_mock.c \ $(QUANTUM_PATH)/sequencer/tests/sequencer_tests.cpp \ $(QUANTUM_PATH)/sequencer/sequencer.c \ - $(TMK_PATH)/common/test/timer.c + $(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c diff --git a/quantum/serial_link/LICENSE b/quantum/serial_link/LICENSE deleted file mode 100644 index d13cc4b26a..0000000000 --- a/quantum/serial_link/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/quantum/serial_link/README.md b/quantum/serial_link/README.md deleted file mode 100644 index 05871dbdf7..0000000000 --- a/quantum/serial_link/README.md +++ /dev/null @@ -1 +0,0 @@ -# qmk_serial_link diff --git a/quantum/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/protocol/byte_stuffer.c deleted file mode 100644 index d3a91d8286..0000000000 --- a/quantum/serial_link/protocol/byte_stuffer.c +++ /dev/null @@ -1,135 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "serial_link/protocol/byte_stuffer.h" -#include "serial_link/protocol/frame_validator.h" -#include "serial_link/protocol/physical.h" -#include <stdbool.h> - -// This implements the "Consistent overhead byte stuffing protocol" -// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing -// http://www.stuartcheshire.org/papers/COBSforToN.pdf - -typedef struct byte_stuffer_state { - uint16_t next_zero; - uint16_t data_pos; - bool long_frame; - uint8_t data[MAX_FRAME_SIZE]; -} byte_stuffer_state_t; - -static byte_stuffer_state_t states[NUM_LINKS]; - -void init_byte_stuffer_state(byte_stuffer_state_t* state) { - state->next_zero = 0; - state->data_pos = 0; - state->long_frame = false; -} - -void init_byte_stuffer(void) { - int i; - for (i = 0; i < NUM_LINKS; i++) { - init_byte_stuffer_state(&states[i]); - } -} - -void byte_stuffer_recv_byte(uint8_t link, uint8_t data) { - byte_stuffer_state_t* state = &states[link]; - // Start of a new frame - if (state->next_zero == 0) { - state->next_zero = data; - state->long_frame = data == 0xFF; - state->data_pos = 0; - return; - } - - state->next_zero--; - if (data == 0) { - if (state->next_zero == 0) { - // The frame is completed - if (state->data_pos > 0) { - validator_recv_frame(link, state->data, state->data_pos); - } - } else { - // The frame is invalid, so reset - init_byte_stuffer_state(state); - } - } else { - if (state->data_pos == MAX_FRAME_SIZE) { - // We exceeded our maximum frame size - // therefore there's nothing else to do than reset to a new frame - state->next_zero = data; - state->long_frame = data == 0xFF; - state->data_pos = 0; - } else if (state->next_zero == 0) { - if (state->long_frame) { - // This is part of a long frame, so continue - state->next_zero = data; - state->long_frame = data == 0xFF; - } else { - // Special case for zeroes - state->next_zero = data; - state->data[state->data_pos++] = 0; - } - } else { - state->data[state->data_pos++] = data; - } - } -} - -static void send_block(uint8_t link, uint8_t* start, uint8_t* end, uint8_t num_non_zero) { - send_data(link, &num_non_zero, 1); - if (end > start) { - send_data(link, start, end - start); - } -} - -void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { - const uint8_t zero = 0; - if (size > 0) { - uint16_t num_non_zero = 1; - uint8_t* end = data + size; - uint8_t* start = data; - while (data < end) { - if (num_non_zero == 0xFF) { - // There's more data after big non-zero block - // So send it, and start a new block - send_block(link, start, data, num_non_zero); - start = data; - num_non_zero = 1; - } else { - if (*data == 0) { - // A zero encountered, so send the block - send_block(link, start, data, num_non_zero); - start = data + 1; - num_non_zero = 1; - } else { - num_non_zero++; - } - ++data; - } - } - send_block(link, start, data, num_non_zero); - send_data(link, &zero, 1); - } -} diff --git a/quantum/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/protocol/byte_stuffer.h deleted file mode 100644 index 397ed3baae..0000000000 --- a/quantum/serial_link/protocol/byte_stuffer.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include <stdint.h> - -#define MAX_FRAME_SIZE 1024 -#define NUM_LINKS 2 - -void init_byte_stuffer(void); -void byte_stuffer_recv_byte(uint8_t link, uint8_t data); -void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size); diff --git a/quantum/serial_link/protocol/frame_router.c b/quantum/serial_link/protocol/frame_router.c deleted file mode 100644 index 5292673700..0000000000 --- a/quantum/serial_link/protocol/frame_router.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "serial_link/protocol/frame_router.h" -#include "serial_link/protocol/transport.h" -#include "serial_link/protocol/frame_validator.h" - -static bool is_master; - -void router_set_master(bool master) { is_master = master; } - -void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { - if (is_master) { - if (link == DOWN_LINK) { - transport_recv_frame(data[size - 1], data, size - 1); - } - } else { - if (link == UP_LINK) { - if (data[size - 1] & 1) { - transport_recv_frame(0, data, size - 1); - } - data[size - 1] >>= 1; - validator_send_frame(DOWN_LINK, data, size); - } else { - data[size - 1]++; - validator_send_frame(UP_LINK, data, size); - } - } -} - -void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { - if (destination == 0) { - if (!is_master) { - data[size] = 1; - validator_send_frame(UP_LINK, data, size + 1); - } - } else { - if (is_master) { - data[size] = destination; - validator_send_frame(DOWN_LINK, data, size + 1); - } - } -} diff --git a/quantum/serial_link/protocol/frame_router.h b/quantum/serial_link/protocol/frame_router.h deleted file mode 100644 index 9325fe4eed..0000000000 --- a/quantum/serial_link/protocol/frame_router.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include <stdint.h> -#include <stdbool.h> - -#define UP_LINK 0 -#define DOWN_LINK 1 - -void router_set_master(bool master); -void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size); -void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size); diff --git a/quantum/serial_link/protocol/frame_validator.c b/quantum/serial_link/protocol/frame_validator.c deleted file mode 100644 index bc9136f70b..0000000000 --- a/quantum/serial_link/protocol/frame_validator.c +++ /dev/null @@ -1,57 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "serial_link/protocol/frame_validator.h" -#include "serial_link/protocol/frame_router.h" -#include "serial_link/protocol/byte_stuffer.h" -#include <string.h> - -const uint32_t poly8_lookup[256] = {0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D}; - -static uint32_t crc32_byte(uint8_t* p, uint32_t bytelength) { - uint32_t crc = 0xffffffff; - while (bytelength-- != 0) crc = poly8_lookup[((uint8_t)crc ^ *(p++))] ^ (crc >> 8); - // return (~crc); also works - return (crc ^ 0xffffffff); -} - -void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) { - if (size > 4) { - uint32_t frame_crc; - memcpy(&frame_crc, data + size - 4, 4); - uint32_t expected_crc = crc32_byte(data, size - 4); - if (frame_crc == expected_crc) { - route_incoming_frame(link, data, size - 4); - } - } -} - -void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size) { - uint32_t crc = crc32_byte(data, size); - memcpy(data + size, &crc, 4); - byte_stuffer_send_frame(link, data, size + 4); -} diff --git a/quantum/serial_link/protocol/frame_validator.h b/quantum/serial_link/protocol/frame_validator.h deleted file mode 100644 index 0f78768a00..0000000000 --- a/quantum/serial_link/protocol/frame_validator.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include <stdint.h> - -void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size); -// The buffer pointed to by the data needs 4 additional bytes -void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size); diff --git a/quantum/serial_link/protocol/physical.h b/quantum/serial_link/protocol/physical.h deleted file mode 100644 index 399c9d1f76..0000000000 --- a/quantum/serial_link/protocol/physical.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -void send_data(uint8_t link, const uint8_t* data, uint16_t size); diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c deleted file mode 100644 index 73b8dc62e9..0000000000 --- a/quantum/serial_link/protocol/transport.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "serial_link/protocol/transport.h" -#include "serial_link/protocol/frame_router.h" -#include "serial_link/protocol/triple_buffered_object.h" -#include <string.h> - -#define MAX_REMOTE_OBJECTS 16 -static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS]; -static uint32_t num_remote_objects = 0; - -void reinitialize_serial_link_transport(void) { num_remote_objects = 0; } - -void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) { - unsigned int i; - for (i = 0; i < _num_remote_objects; i++) { - remote_object_t* obj = _remote_objects[i]; - remote_objects[num_remote_objects++] = obj; - if (obj->object_type == MASTER_TO_ALL_SLAVES) { - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; - triple_buffer_init(tb); - uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); - tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - } else if (obj->object_type == MASTER_TO_SINGLE_SLAVE) { - uint8_t* start = obj->buffer; - unsigned int j; - for (j = 0; j < NUM_SLAVES; j++) { - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - start += LOCAL_OBJECT_SIZE(obj->object_size); - } - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - } else { - uint8_t* start = obj->buffer; - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - start += LOCAL_OBJECT_SIZE(obj->object_size); - unsigned int j; - for (j = 0; j < NUM_SLAVES; j++) { - tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - start += REMOTE_OBJECT_SIZE(obj->object_size); - } - } - } -} - -void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) { - uint8_t id = data[size - 1]; - if (id < num_remote_objects) { - remote_object_t* obj = remote_objects[id]; - if (obj->object_size == size - 1) { - uint8_t* start; - if (obj->object_type == MASTER_TO_ALL_SLAVES) { - start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); - } else if (obj->object_type == SLAVE_TO_MASTER) { - start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); - start += (from - 1) * REMOTE_OBJECT_SIZE(obj->object_size); - } else { - start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size); - } - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - void* ptr = triple_buffer_begin_write_internal(obj->object_size, tb); - memcpy(ptr, data, size - 1); - triple_buffer_end_write_internal(tb); - } - } -} - -void update_transport(void) { - unsigned int i; - for (i = 0; i < num_remote_objects; i++) { - remote_object_t* obj = remote_objects[i]; - if (obj->object_type == MASTER_TO_ALL_SLAVES || obj->object_type == SLAVE_TO_MASTER) { - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; - uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb); - if (ptr) { - ptr[obj->object_size] = i; - uint8_t dest = obj->object_type == MASTER_TO_ALL_SLAVES ? 0xFF : 0; - router_send_frame(dest, ptr, obj->object_size + 1); - } - } else { - uint8_t* start = obj->buffer; - unsigned int j; - for (j = 0; j < NUM_SLAVES; j++) { - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb); - if (ptr) { - ptr[obj->object_size] = i; - uint8_t dest = j + 1; - router_send_frame(dest, ptr, obj->object_size + 1); - } - start += LOCAL_OBJECT_SIZE(obj->object_size); - } - } - } -} diff --git a/quantum/serial_link/protocol/transport.h b/quantum/serial_link/protocol/transport.h deleted file mode 100644 index 3ce0c9fe4e..0000000000 --- a/quantum/serial_link/protocol/transport.h +++ /dev/null @@ -1,139 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include "serial_link/protocol/triple_buffered_object.h" -#include "serial_link/system/serial_link.h" - -#define NUM_SLAVES 8 -#define LOCAL_OBJECT_EXTRA 16 - -// master -> slave = 1 local(target all), 1 remote object -// slave -> master = 1 local(target 0), multiple remote objects -// master -> single slave (multiple local, target id), 1 remote object -typedef enum { - MASTER_TO_ALL_SLAVES, - MASTER_TO_SINGLE_SLAVE, - SLAVE_TO_MASTER, -} remote_object_type; - -typedef struct { - remote_object_type object_type; - uint16_t object_size; - uint8_t buffer[] __attribute__((aligned(4))); -} remote_object_t; - -#define REMOTE_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + objectsize * 3) -#define LOCAL_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + (objectsize + LOCAL_OBJECT_EXTRA) * 3) - -#define REMOTE_OBJECT_HELPER(name, type, num_local, num_remote) \ - typedef struct { \ - remote_object_t object; \ - uint8_t buffer[num_remote * REMOTE_OBJECT_SIZE(sizeof(type)) + num_local * LOCAL_OBJECT_SIZE(sizeof(type))]; \ - } remote_object_##name##_t; - -#define MASTER_TO_ALL_SLAVES_OBJECT(name, type) \ - REMOTE_OBJECT_HELPER(name, type, 1, 1) \ - remote_object_##name##_t remote_object_##name = {.object = { \ - .object_type = MASTER_TO_ALL_SLAVES, \ - .object_size = sizeof(type), \ - }}; \ - type* begin_write_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \ - return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \ - } \ - void end_write_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \ - triple_buffer_end_write_internal(tb); \ - signal_data_written(); \ - } \ - type* read_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - return (type*)triple_buffer_read_internal(obj->object_size, tb); \ - } - -#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \ - REMOTE_OBJECT_HELPER(name, type, NUM_SLAVES, 1) \ - remote_object_##name##_t remote_object_##name = {.object = { \ - .object_type = MASTER_TO_SINGLE_SLAVE, \ - .object_size = sizeof(type), \ - }}; \ - type* begin_write_##name(uint8_t slave) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer; \ - start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \ - } \ - void end_write_##name(uint8_t slave) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer; \ - start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - triple_buffer_end_write_internal(tb); \ - signal_data_written(); \ - } \ - type* read_##name() { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - return (type*)triple_buffer_read_internal(obj->object_size, tb); \ - } - -#define SLAVE_TO_MASTER_OBJECT(name, type) \ - REMOTE_OBJECT_HELPER(name, type, 1, NUM_SLAVES) \ - remote_object_##name##_t remote_object_##name = {.object = { \ - .object_type = SLAVE_TO_MASTER, \ - .object_size = sizeof(type), \ - }}; \ - type* begin_write_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \ - return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \ - } \ - void end_write_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \ - triple_buffer_end_write_internal(tb); \ - signal_data_written(); \ - } \ - type* read_##name(uint8_t slave) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \ - start += slave * REMOTE_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - return (type*)triple_buffer_read_internal(obj->object_size, tb); \ - } - -#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name - -void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects); -void reinitialize_serial_link_transport(void); -void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size); -void update_transport(void); diff --git a/quantum/serial_link/protocol/triple_buffered_object.c b/quantum/serial_link/protocol/triple_buffered_object.c deleted file mode 100644 index e0c6d702a5..0000000000 --- a/quantum/serial_link/protocol/triple_buffered_object.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "serial_link/protocol/triple_buffered_object.h" -#include "serial_link/system/serial_link.h" -#include <stdbool.h> -#include <stddef.h> - -#define GET_READ_INDEX() object->state & 3 -#define GET_WRITE_INDEX() (object->state >> 2) & 3 -#define GET_SHARED_INDEX() (object->state >> 4) & 3 -#define GET_DATA_AVAILABLE() (object->state >> 6) & 1 - -#define SET_READ_INDEX(i) object->state = ((object->state & ~3) | i) -#define SET_WRITE_INDEX(i) object->state = ((object->state & ~(3 << 2)) | (i << 2)) -#define SET_SHARED_INDEX(i) object->state = ((object->state & ~(3 << 4)) | (i << 4)) -#define SET_DATA_AVAILABLE(i) object->state = ((object->state & ~(1 << 6)) | (i << 6)) - -void triple_buffer_init(triple_buffer_object_t* object) { - object->state = 0; - SET_WRITE_INDEX(0); - SET_READ_INDEX(1); - SET_SHARED_INDEX(2); - SET_DATA_AVAILABLE(0); -} - -void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object) { - serial_link_lock(); - if (GET_DATA_AVAILABLE()) { - uint8_t shared_index = GET_SHARED_INDEX(); - uint8_t read_index = GET_READ_INDEX(); - SET_READ_INDEX(shared_index); - SET_SHARED_INDEX(read_index); - SET_DATA_AVAILABLE(false); - serial_link_unlock(); - return object->buffer + object_size * shared_index; - } else { - serial_link_unlock(); - return NULL; - } -} - -void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object) { - uint8_t write_index = GET_WRITE_INDEX(); - return object->buffer + object_size * write_index; -} - -void triple_buffer_end_write_internal(triple_buffer_object_t* object) { - serial_link_lock(); - uint8_t shared_index = GET_SHARED_INDEX(); - uint8_t write_index = GET_WRITE_INDEX(); - SET_SHARED_INDEX(write_index); - SET_WRITE_INDEX(shared_index); - SET_DATA_AVAILABLE(true); - serial_link_unlock(); -} diff --git a/quantum/serial_link/protocol/triple_buffered_object.h b/quantum/serial_link/protocol/triple_buffered_object.h deleted file mode 100644 index 717d6d7b8b..0000000000 --- a/quantum/serial_link/protocol/triple_buffered_object.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include <stdint.h> - -typedef struct { - uint8_t state; - uint8_t buffer[] __attribute__((aligned(4))); -} triple_buffer_object_t; - -void triple_buffer_init(triple_buffer_object_t* object); - -#define triple_buffer_begin_write(object) (typeof(*object.buffer[0])*)triple_buffer_begin_write_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object) - -#define triple_buffer_end_write(object) triple_buffer_end_write_internal((triple_buffer_object_t*)object) - -#define triple_buffer_read(object) (typeof(*object.buffer[0])*)triple_buffer_read_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object) - -void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object); -void triple_buffer_end_write_internal(triple_buffer_object_t* object); -void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object); diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c deleted file mode 100644 index 6363f8ff3b..0000000000 --- a/quantum/serial_link/system/serial_link.c +++ /dev/null @@ -1,250 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -#include "report.h" -#include "host_driver.h" -#include "serial_link/system/serial_link.h" -#include <hal.h> -#include "serial_link/protocol/byte_stuffer.h" -#include "serial_link/protocol/transport.h" -#include "serial_link/protocol/frame_router.h" -#include "matrix.h" -#include "sync_timer.h" -#include <stdbool.h> -#include "print.h" -#include "config.h" - -#define SYNC_TIMER_OFFSET 2 - -static event_source_t new_data_event; -static bool serial_link_connected; -static bool is_master = false; - -static uint8_t keyboard_leds(void); -static void send_keyboard(report_keyboard_t* report); -static void send_mouse(report_mouse_t* report); -static void send_system(uint16_t data); -static void send_consumer(uint16_t data); - -host_driver_t serial_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; - -// Define these in your Config.h file -#ifndef SERIAL_LINK_BAUD -# error "Serial link baud is not set" -#endif - -#ifndef SERIAL_LINK_THREAD_PRIORITY -# error "Serial link thread priority not set" -#endif - -static SerialConfig config = {.sc_speed = SERIAL_LINK_BAUD}; - -//#define DEBUG_LINK_ERRORS - -static uint32_t read_from_serial(SerialDriver* driver, uint8_t link) { - const uint32_t buffer_size = 16; - uint8_t buffer[buffer_size]; - uint32_t bytes_read = sdAsynchronousRead(driver, buffer, buffer_size); - uint8_t* current = buffer; - uint8_t* end = current + bytes_read; - while (current < end) { - byte_stuffer_recv_byte(link, *current); - current++; - } - return bytes_read; -} - -static void print_error(char* str, eventflags_t flags, SerialDriver* driver) { -#ifdef DEBUG_LINK_ERRORS - if (flags & SD_PARITY_ERROR) { - print(str); - print(" Parity error\n"); - } - if (flags & SD_FRAMING_ERROR) { - print(str); - print(" Framing error\n"); - } - if (flags & SD_OVERRUN_ERROR) { - print(str); - uint32_t size = qSpaceI(&(driver->iqueue)); - xprintf(" Overrun error, queue size %d\n", size); - } - if (flags & SD_NOISE_ERROR) { - print(str); - print(" Noise error\n"); - } - if (flags & SD_BREAK_DETECTED) { - print(str); - print(" Break detected\n"); - } -#else - (void)str; - (void)flags; - (void)driver; -#endif -} - -bool is_serial_link_master(void) { return is_master; } - -// TODO: Optimize the stack size, this is probably way too big -static THD_WORKING_AREA(serialThreadStack, 1024); -static THD_FUNCTION(serialThread, arg) { - (void)arg; - event_listener_t new_data_listener; - event_listener_t sd1_listener; - event_listener_t sd2_listener; - chEvtRegister(&new_data_event, &new_data_listener, 0); - eventflags_t events = CHN_INPUT_AVAILABLE | SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR | SD_NOISE_ERROR | SD_BREAK_DETECTED; - chEvtRegisterMaskWithFlags(chnGetEventSource(&SD1), &sd1_listener, EVENT_MASK(1), events); - chEvtRegisterMaskWithFlags(chnGetEventSource(&SD2), &sd2_listener, EVENT_MASK(2), events); - bool need_wait = false; - while (true) { - eventflags_t flags1 = 0; - eventflags_t flags2 = 0; - if (need_wait) { - eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(1000)); - if (mask & EVENT_MASK(1)) { - flags1 = chEvtGetAndClearFlags(&sd1_listener); - print_error("DOWNLINK", flags1, &SD1); - } - if (mask & EVENT_MASK(2)) { - flags2 = chEvtGetAndClearFlags(&sd2_listener); - print_error("UPLINK", flags2, &SD2); - } - } - - // Always stay as master, even if the USB goes into sleep mode - is_master |= usbGetDriverStateI(&USBD1) == USB_ACTIVE; - router_set_master(is_master); - - need_wait = true; - need_wait &= read_from_serial(&SD2, UP_LINK) == 0; - need_wait &= read_from_serial(&SD1, DOWN_LINK) == 0; - update_transport(); - } -} - -void send_data(uint8_t link, const uint8_t* data, uint16_t size) { - if (link == DOWN_LINK) { - sdWrite(&SD1, data, size); - } else { - sdWrite(&SD2, data, size); - } -} - -static systime_t last_update = 0; - -typedef struct { - matrix_row_t rows[MATRIX_ROWS]; -} matrix_object_t; - -static matrix_object_t last_matrix = {}; - -SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t); -MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool); -#ifndef DISABLE_SYNC_TIMER -MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t); -#endif - -static remote_object_t* remote_objects[] = { - REMOTE_OBJECT(serial_link_connected), - REMOTE_OBJECT(keyboard_matrix), -#ifndef DISABLE_SYNC_TIMER - REMOTE_OBJECT(sync_timer), -#endif -}; - -void init_serial_link(void) { - serial_link_connected = false; - init_serial_link_hal(); - add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*)); - init_byte_stuffer(); - sdStart(&SD1, &config); - sdStart(&SD2, &config); - chEvtObjectInit(&new_data_event); - (void)chThdCreateStatic(serialThreadStack, sizeof(serialThreadStack), SERIAL_LINK_THREAD_PRIORITY, serialThread, NULL); -} - -void matrix_set_remote(matrix_row_t* rows, uint8_t index); - -void serial_link_update(void) { - if (read_serial_link_connected()) { - serial_link_connected = true; - } - - matrix_object_t matrix; - bool changed = false; - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - matrix.rows[i] = matrix_get_row(i); - changed |= matrix.rows[i] != last_matrix.rows[i]; - } - - systime_t current_time = chVTGetSystemTimeX(); - systime_t delta = current_time - last_update; - if (changed || delta > TIME_US2I(5000)) { - last_update = current_time; - last_matrix = matrix; - matrix_object_t* m = begin_write_keyboard_matrix(); - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - m->rows[i] = matrix.rows[i]; - } - end_write_keyboard_matrix(); - - *begin_write_serial_link_connected() = true; - end_write_serial_link_connected(); - -#ifndef DISABLE_SYNC_TIMER - *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET; - end_write_sync_timer(); -#endif - } - - matrix_object_t* m = read_keyboard_matrix(0); - if (m) { - matrix_set_remote(m->rows, 0); - } - -#ifndef DISABLE_SYNC_TIMER - uint32_t* t = read_sync_timer(); - if (t) { - sync_timer_update(*t); - } -#endif -} - -void signal_data_written(void) { chEvtBroadcast(&new_data_event); } - -bool is_serial_link_connected(void) { return serial_link_connected; } - -host_driver_t* get_serial_link_driver(void) { return &serial_driver; } - -// NOTE: The driver does nothing, because the master handles everything -uint8_t keyboard_leds(void) { return 0; } - -void send_keyboard(report_keyboard_t* report) { (void)report; } - -void send_mouse(report_mouse_t* report) { (void)report; } - -void send_system(uint16_t data) { (void)data; } - -void send_consumer(uint16_t data) { (void)data; } diff --git a/quantum/serial_link/system/serial_link.h b/quantum/serial_link/system/serial_link.h deleted file mode 100644 index adc1f6e93d..0000000000 --- a/quantum/serial_link/system/serial_link.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include "host_driver.h" -#include <stdbool.h> - -void init_serial_link(void); -void init_serial_link_hal(void); -bool is_serial_link_connected(void); -bool is_serial_link_master(void); -host_driver_t* get_serial_link_driver(void); -void serial_link_update(void); - -#if defined(PROTOCOL_CHIBIOS) -# include <ch.h> - -static inline void serial_link_lock(void) { chSysLock(); } - -static inline void serial_link_unlock(void) { chSysUnlock(); } - -void signal_data_written(void); - -#else - -inline void serial_link_lock(void) {} - -inline void serial_link_unlock(void) {} - -void signal_data_written(void); - -#endif diff --git a/quantum/serial_link/tests/Makefile b/quantum/serial_link/tests/Makefile deleted file mode 100644 index 11dd355b22..0000000000 --- a/quantum/serial_link/tests/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2016 Fred Sundvik -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -CC = gcc -CFLAGS = -INCLUDES = -I. -I../../ -LDFLAGS = -L$(BUILDDIR)/cgreen/build-c/src -shared -LDLIBS = -lcgreen -UNITOBJ = $(BUILDDIR)/serialtest/unitobj -DEPDIR = $(BUILDDIR)/serialtest/unit.d -UNITTESTS = $(BUILDDIR)/serialtest/unittests -DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td -EXT = .so -UNAME := $(shell uname) -ifneq (, $(findstring MINGW, $(UNAME))) - EXT = .dll -endif -ifneq (, $(findstring CYGWIN, $(UNAME))) - EXT = .dll -endif - -SRC = $(wildcard *.c) -TESTFILES = $(patsubst %.c, $(UNITTESTS)/%$(EXT), $(SRC)) -$(shell mkdir -p $(DEPDIR) >/dev/null) - -test: $(TESTFILES) - @$(BUILDDIR)/cgreen/build-c/tools/cgreen-runner --color $(TESTFILES) - -$(UNITTESTS)/%$(EXT): $(UNITOBJ)/%.o - @mkdir -p $(UNITTESTS) - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) - -$(UNITOBJ)/%.o : %.c -$(UNITOBJ)/%.o: %.c $(DEPDIR)/%.d - @mkdir -p $(UNITOBJ) - $(CC) $(CFLAGS) $(DEPFLAGS) $(INCLUDES) -c $< -o $@ - @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d - -$(DEPDIR)/%.d: ; -.PRECIOUS: $(DEPDIR)/%.d - --include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC))) diff --git a/quantum/serial_link/tests/byte_stuffer_tests.cpp b/quantum/serial_link/tests/byte_stuffer_tests.cpp deleted file mode 100644 index 9e4e1768f4..0000000000 --- a/quantum/serial_link/tests/byte_stuffer_tests.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include <vector> -#include <algorithm> -extern "C" { -#include "serial_link/protocol/byte_stuffer.h" -#include "serial_link/protocol/frame_validator.h" -#include "serial_link/protocol/physical.h" -} - -using testing::_; -using testing::Args; -using testing::ElementsAreArray; - -class ByteStuffer : public ::testing::Test { - public: - ByteStuffer() { - Instance = this; - init_byte_stuffer(); - } - - ~ByteStuffer() { Instance = nullptr; } - - MOCK_METHOD3(validator_recv_frame, void(uint8_t link, uint8_t* data, uint16_t size)); - - void send_data(uint8_t link, const uint8_t* data, uint16_t size) { std::copy(data, data + size, std::back_inserter(sent_data)); } - std::vector<uint8_t> sent_data; - - static ByteStuffer* Instance; -}; - -ByteStuffer* ByteStuffer::Instance = nullptr; - -extern "C" { -void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) { ByteStuffer::Instance->validator_recv_frame(link, data, size); } - -void send_data(uint8_t link, const uint8_t* data, uint16_t size) { ByteStuffer::Instance->send_data(link, data, size); } -} - -TEST_F(ByteStuffer, receives_no_frame_for_a_single_zero_byte) { - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_no_frame_for_a_single_FF_byte) { - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - byte_stuffer_recv_byte(0, 0xFF); -} - -TEST_F(ByteStuffer, receives_no_frame_for_a_single_random_byte) { - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - byte_stuffer_recv_byte(0, 0x4A); -} - -TEST_F(ByteStuffer, receives_no_frame_for_a_zero_length_frame) { - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_single_byte_valid_frame) { - uint8_t expected[] = {0x37}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 0x37); - byte_stuffer_recv_byte(0, 0); -} -TEST_F(ByteStuffer, receives_three_bytes_valid_frame) { - uint8_t expected[] = {0x37, 0x99, 0xFF}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 4); - byte_stuffer_recv_byte(0, 0x37); - byte_stuffer_recv_byte(0, 0x99); - byte_stuffer_recv_byte(0, 0xFF); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_single_zero_valid_frame) { - uint8_t expected[] = {0}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_valid_frame_with_zeroes) { - uint8_t expected[] = {5, 0, 3, 0}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 5); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 3); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_two_valid_frames) { - uint8_t expected1[] = {5, 0}; - uint8_t expected2[] = {3}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected1))); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected2))); - byte_stuffer_recv_byte(1, 2); - byte_stuffer_recv_byte(1, 5); - byte_stuffer_recv_byte(1, 1); - byte_stuffer_recv_byte(1, 0); - byte_stuffer_recv_byte(1, 2); - byte_stuffer_recv_byte(1, 3); - byte_stuffer_recv_byte(1, 0); -} - -TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_zero) { - uint8_t expected[] = {5, 7}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(1, 3); - byte_stuffer_recv_byte(1, 1); - byte_stuffer_recv_byte(1, 0); - byte_stuffer_recv_byte(1, 3); - byte_stuffer_recv_byte(1, 5); - byte_stuffer_recv_byte(1, 7); - byte_stuffer_recv_byte(1, 0); -} - -TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) { - uint8_t expected[] = {5, 7}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 9); - byte_stuffer_recv_byte(0, 4); // This should have been zero - byte_stuffer_recv_byte(0, 0); - byte_stuffer_recv_byte(0, 3); - byte_stuffer_recv_byte(0, 5); - byte_stuffer_recv_byte(0, 7); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) { - uint8_t expected[254]; - int i; - for (i = 0; i < 254; i++) { - expected[i] = i + 1; - } - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) { - uint8_t expected[255]; - int i; - for (i = 0; i < 254; i++) { - expected[i] = i + 1; - } - expected[254] = 7; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 7); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) { - uint8_t expected[255]; - int i; - for (i = 0; i < 254; i++) { - expected[i] = i + 1; - } - expected[254] = 0; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_two_long_frames_and_some_more) { - uint8_t expected[515]; - int i; - int j; - for (j = 0; j < 2; j++) { - for (i = 0; i < 254; i++) { - expected[i + 254 * j] = i + 1; - } - } - for (i = 0; i < 7; i++) { - expected[254 * 2 + i] = i + 1; - } - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 8); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 3); - byte_stuffer_recv_byte(0, 4); - byte_stuffer_recv_byte(0, 5); - byte_stuffer_recv_byte(0, 6); - byte_stuffer_recv_byte(0, 7); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) { - uint8_t expected[MAX_FRAME_SIZE] = {}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - int i; - byte_stuffer_recv_byte(0, 1); - for (i = 0; i < MAX_FRAME_SIZE; i++) { - byte_stuffer_recv_byte(0, 1); - } - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) { - uint8_t expected[1] = {0}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - int i; - byte_stuffer_recv_byte(0, 1); - for (i = 0; i < MAX_FRAME_SIZE; i++) { - byte_stuffer_recv_byte(0, 1); - } - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, received_frame_is_aborted_when_its_too_long) { - uint8_t expected[1] = {1}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - int i; - byte_stuffer_recv_byte(0, 1); - for (i = 0; i < MAX_FRAME_SIZE; i++) { - byte_stuffer_recv_byte(0, 1); - } - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, does_nothing_when_sending_zero_size_frame) { - EXPECT_EQ(sent_data.size(), 0); - byte_stuffer_send_frame(0, NULL, 0); -} - -TEST_F(ByteStuffer, send_one_byte_frame) { - uint8_t data[] = {5}; - byte_stuffer_send_frame(1, data, 1); - uint8_t expected[] = {2, 5, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_two_byte_frame) { - uint8_t data[] = {5, 0x77}; - byte_stuffer_send_frame(0, data, 2); - uint8_t expected[] = {3, 5, 0x77, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_one_byte_frame_with_zero) { - uint8_t data[] = {0}; - byte_stuffer_send_frame(0, data, 1); - uint8_t expected[] = {1, 1, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_zero) { - uint8_t data[] = {0, 9}; - byte_stuffer_send_frame(1, data, 2); - uint8_t expected[] = {1, 2, 9, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) { - uint8_t data[] = {9, 0}; - byte_stuffer_send_frame(1, data, 2); - uint8_t expected[] = {2, 9, 1, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) { - uint8_t data[] = {9, 0, 0x68}; - byte_stuffer_send_frame(0, data, 3); - uint8_t expected[] = {2, 9, 2, 0x68, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_three_byte_frame_data_in_the_middle) { - uint8_t data[] = {0, 0x55, 0}; - byte_stuffer_send_frame(0, data, 3); - uint8_t expected[] = {1, 2, 0x55, 1, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_three_byte_frame_with_all_zeroes) { - uint8_t data[] = {0, 0, 0}; - byte_stuffer_send_frame(0, data, 3); - uint8_t expected[] = {1, 1, 1, 1, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes) { - uint8_t data[254]; - int i; - for (i = 0; i < 254; i++) { - data[i] = i + 1; - } - byte_stuffer_send_frame(0, data, 254); - uint8_t expected[256]; - expected[0] = 0xFF; - for (i = 1; i < 255; i++) { - expected[i] = i; - } - expected[255] = 0; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_frame_with_255_non_zeroes) { - uint8_t data[255]; - int i; - for (i = 0; i < 255; i++) { - data[i] = i + 1; - } - byte_stuffer_send_frame(0, data, 255); - uint8_t expected[258]; - expected[0] = 0xFF; - for (i = 1; i < 255; i++) { - expected[i] = i; - } - expected[255] = 2; - expected[256] = 255; - expected[257] = 0; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) { - uint8_t data[255]; - int i; - for (i = 0; i < 254; i++) { - data[i] = i + 1; - } - data[254] = 0; - byte_stuffer_send_frame(0, data, 255); - uint8_t expected[258]; - expected[0] = 0xFF; - for (i = 1; i < 255; i++) { - expected[i] = i; - } - expected[255] = 1; - expected[256] = 1; - expected[257] = 0; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) { - uint8_t original_data[] = {1, 2, 3}; - byte_stuffer_send_frame(0, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - int i; - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) { - uint8_t original_data[] = {1, 0, 3, 0, 0, 9}; - byte_stuffer_send_frame(1, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - int i; - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) { - uint8_t original_data[254]; - int i; - for (i = 0; i < 254; i++) { - original_data[i] = i + 1; - } - byte_stuffer_send_frame(0, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) { - uint8_t original_data[256]; - int i; - for (i = 0; i < 254; i++) { - original_data[i] = i + 1; - } - original_data[254] = 22; - original_data[255] = 23; - byte_stuffer_send_frame(0, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) { - uint8_t original_data[255]; - int i; - for (i = 0; i < 254; i++) { - original_data[i] = i + 1; - } - original_data[254] = 0; - byte_stuffer_send_frame(0, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} diff --git a/quantum/serial_link/tests/frame_router_tests.cpp b/quantum/serial_link/tests/frame_router_tests.cpp deleted file mode 100644 index f76dfb33d6..0000000000 --- a/quantum/serial_link/tests/frame_router_tests.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include <array> -extern "C" { -#include "serial_link/protocol/transport.h" -#include "serial_link/protocol/byte_stuffer.h" -#include "serial_link/protocol/frame_router.h" -} - -using testing::_; -using testing::Args; -using testing::ElementsAreArray; - -class FrameRouter : public testing::Test { - public: - FrameRouter() : current_router_buffer(nullptr) { - Instance = this; - init_byte_stuffer(); - } - - ~FrameRouter() { Instance = nullptr; } - - void send_data(uint8_t link, const uint8_t* data, uint16_t size) { - auto& buffer = current_router_buffer->send_buffers[link]; - std::copy(data, data + size, std::back_inserter(buffer)); - } - - void receive_data(uint8_t link, uint8_t* data, uint16_t size) { - int i; - for (i = 0; i < size; i++) { - byte_stuffer_recv_byte(link, data[i]); - } - } - - void activate_router(uint8_t num) { - current_router_buffer = router_buffers + num; - router_set_master(num == 0); - } - - void simulate_transport(uint8_t from, uint8_t to) { - activate_router(to); - if (from > to) { - receive_data(DOWN_LINK, router_buffers[from].send_buffers[UP_LINK].data(), router_buffers[from].send_buffers[UP_LINK].size()); - } else if (to > from) { - receive_data(UP_LINK, router_buffers[from].send_buffers[DOWN_LINK].data(), router_buffers[from].send_buffers[DOWN_LINK].size()); - } - } - - MOCK_METHOD3(transport_recv_frame, void(uint8_t from, uint8_t* data, uint16_t size)); - - std::vector<uint8_t> received_data; - - struct router_buffer { - std::vector<uint8_t> send_buffers[2]; - }; - - router_buffer router_buffers[8]; - router_buffer* current_router_buffer; - - static FrameRouter* Instance; -}; - -FrameRouter* FrameRouter::Instance = nullptr; - -typedef struct { - std::array<uint8_t, 4> data; - uint8_t extra[16]; -} frame_buffer_t; - -extern "C" { -void send_data(uint8_t link, const uint8_t* data, uint16_t size) { FrameRouter::Instance->send_data(link, data, size); } - -void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) { FrameRouter::Instance->transport_recv_frame(from, data, size); } -} - -TEST_F(FrameRouter, master_broadcast_is_received_by_everyone) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(0); - router_send_frame(0xFF, (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); - EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(0, 1); - EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(1, 2); - EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0); -} - -TEST_F(FrameRouter, master_send_is_received_by_targets) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(0); - router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); - - simulate_transport(0, 1); - EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(1, 2); - EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(2, 3); - EXPECT_GT(router_buffers[3].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[3].send_buffers[UP_LINK].size(), 0); -} - -TEST_F(FrameRouter, first_link_sends_to_master) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(1); - router_send_frame(0, (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(1, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(1, 0); - EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); -} - -TEST_F(FrameRouter, second_link_sends_to_master) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(2); - router_send_frame(0, (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[2].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[2].send_buffers[DOWN_LINK].size(), 0); - - simulate_transport(2, 1); - EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(2, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(1, 0); - EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); -} - -TEST_F(FrameRouter, master_sends_to_master_does_nothing) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(0); - router_send_frame(0, (uint8_t*)&data, 4); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); -} - -TEST_F(FrameRouter, link_sends_to_other_link_does_nothing) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(1); - router_send_frame(2, (uint8_t*)&data, 4); - EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); -} - -TEST_F(FrameRouter, master_receives_on_uplink_does_nothing) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(1); - router_send_frame(0, (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(_, _, _)).Times(0); - activate_router(0); - receive_data(UP_LINK, router_buffers[1].send_buffers[UP_LINK].data(), router_buffers[1].send_buffers[UP_LINK].size()); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); -} diff --git a/quantum/serial_link/tests/frame_validator_tests.cpp b/quantum/serial_link/tests/frame_validator_tests.cpp deleted file mode 100644 index 43dc57b633..0000000000 --- a/quantum/serial_link/tests/frame_validator_tests.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "gtest/gtest.h" -#include "gmock/gmock.h" -extern "C" { -#include "serial_link/protocol/frame_validator.h" -} - -using testing::_; -using testing::Args; -using testing::ElementsAreArray; - -class FrameValidator : public testing::Test { - public: - FrameValidator() { Instance = this; } - - ~FrameValidator() { Instance = nullptr; } - - MOCK_METHOD3(route_incoming_frame, void(uint8_t link, uint8_t* data, uint16_t size)); - MOCK_METHOD3(byte_stuffer_send_frame, void(uint8_t link, uint8_t* data, uint16_t size)); - - static FrameValidator* Instance; -}; - -FrameValidator* FrameValidator::Instance = nullptr; - -extern "C" { -void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->route_incoming_frame(link, data, size); } - -void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->byte_stuffer_send_frame(link, data, size); } -} - -TEST_F(FrameValidator, doesnt_validate_frames_under_5_bytes) { - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0); - uint8_t data[] = {1, 2}; - validator_recv_frame(0, 0, 1); - validator_recv_frame(0, data, 2); - validator_recv_frame(0, data, 3); - validator_recv_frame(0, data, 4); -} - -TEST_F(FrameValidator, validates_one_byte_frame_with_correct_crc) { - uint8_t data[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3}; - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 1))); - validator_recv_frame(0, data, 5); -} - -TEST_F(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) { - uint8_t data[] = {0x44, 0, 0, 0, 0}; - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0); - validator_recv_frame(1, data, 5); -} - -TEST_F(FrameValidator, validates_four_byte_frame_with_correct_crc) { - uint8_t data[] = {0x44, 0x10, 0xFF, 0x00, 0x74, 0x4E, 0x30, 0xBA}; - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 4))); - validator_recv_frame(1, data, 8); -} - -TEST_F(FrameValidator, validates_five_byte_frame_with_correct_crc) { - uint8_t data[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47}; - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 5))); - validator_recv_frame(0, data, 9); -} - -TEST_F(FrameValidator, sends_one_byte_with_correct_crc) { - uint8_t original[] = {0x44, 0, 0, 0, 0}; - uint8_t expected[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3}; - EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - validator_send_frame(0, original, 1); -} - -TEST_F(FrameValidator, sends_five_bytes_with_correct_crc) { - uint8_t original[] = {1, 2, 3, 4, 5, 0, 0, 0, 0}; - uint8_t expected[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47}; - EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - validator_send_frame(0, original, 5); -} diff --git a/quantum/serial_link/tests/rules.mk b/quantum/serial_link/tests/rules.mk deleted file mode 100644 index b81515bc55..0000000000 --- a/quantum/serial_link/tests/rules.mk +++ /dev/null @@ -1,22 +0,0 @@ -serial_link_byte_stuffer_SRC :=\ - $(SERIAL_PATH)/tests/byte_stuffer_tests.cpp \ - $(SERIAL_PATH)/protocol/byte_stuffer.c - -serial_link_frame_validator_SRC := \ - $(SERIAL_PATH)/tests/frame_validator_tests.cpp \ - $(SERIAL_PATH)/protocol/frame_validator.c - -serial_link_frame_router_SRC := \ - $(SERIAL_PATH)/tests/frame_router_tests.cpp \ - $(SERIAL_PATH)/protocol/byte_stuffer.c \ - $(SERIAL_PATH)/protocol/frame_validator.c \ - $(SERIAL_PATH)/protocol/frame_router.c - -serial_link_triple_buffered_object_SRC := \ - $(SERIAL_PATH)/tests/triple_buffered_object_tests.cpp \ - $(SERIAL_PATH)/protocol/triple_buffered_object.c - -serial_link_transport_SRC := \ - $(SERIAL_PATH)/tests/transport_tests.cpp \ - $(SERIAL_PATH)/protocol/transport.c \ - $(SERIAL_PATH)/protocol/triple_buffered_object.c diff --git a/quantum/serial_link/tests/testlist.mk b/quantum/serial_link/tests/testlist.mk deleted file mode 100644 index c5edaf478f..0000000000 --- a/quantum/serial_link/tests/testlist.mk +++ /dev/null @@ -1,6 +0,0 @@ -TEST_LIST +=\ - serial_link_byte_stuffer\ - serial_link_frame_validator\ - serial_link_frame_router\ - serial_link_triple_buffered_object\ - serial_link_transport diff --git a/quantum/serial_link/tests/transport_tests.cpp b/quantum/serial_link/tests/transport_tests.cpp deleted file mode 100644 index cfd1110460..0000000000 --- a/quantum/serial_link/tests/transport_tests.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "gtest/gtest.h" -#include "gmock/gmock.h" - -using testing::_; -using testing::Args; -using testing::ElementsAreArray; - -extern "C" { -#include "serial_link/protocol/transport.h" -} - -struct test_object1 { - uint32_t test; -}; - -struct test_object2 { - uint32_t test1; - uint32_t test2; -}; - -MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1); -MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1); -SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1); - -static remote_object_t* test_remote_objects[] = { - REMOTE_OBJECT(master_to_slave), - REMOTE_OBJECT(master_to_single_slave), - REMOTE_OBJECT(slave_to_master), -}; - -class Transport : public testing::Test { - public: - Transport() { - Instance = this; - add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*)); - } - - ~Transport() { - Instance = nullptr; - reinitialize_serial_link_transport(); - } - - MOCK_METHOD0(signal_data_written, void()); - MOCK_METHOD1(router_send_frame, void(uint8_t destination)); - - void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { - router_send_frame(destination); - std::copy(data, data + size, std::back_inserter(sent_data)); - } - - static Transport* Instance; - - std::vector<uint8_t> sent_data; -}; - -Transport* Transport::Instance = nullptr; - -extern "C" { -void signal_data_written(void) { Transport::Instance->signal_data_written(); } - -void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { Transport::Instance->router_send_frame(destination, data, size); } -} - -TEST_F(Transport, write_to_local_signals_an_event) { - begin_write_master_to_slave(); - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_slave(); - begin_write_slave_to_master(); - EXPECT_CALL(*this, signal_data_written()); - end_write_slave_to_master(); - begin_write_master_to_single_slave(1); - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_single_slave(1); -} - -TEST_F(Transport, writes_from_master_to_all_slaves) { - update_transport(); - test_object1* obj = begin_write_master_to_slave(); - obj->test = 5; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_slave(); - EXPECT_CALL(*this, router_send_frame(0xFF)); - update_transport(); - transport_recv_frame(0, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_master_to_slave(); - EXPECT_NE(obj2, nullptr); - EXPECT_EQ(obj2->test, 5); -} - -TEST_F(Transport, writes_from_slave_to_master) { - update_transport(); - test_object1* obj = begin_write_slave_to_master(); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_slave_to_master(); - EXPECT_CALL(*this, router_send_frame(0)); - update_transport(); - transport_recv_frame(3, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_slave_to_master(2); - EXPECT_EQ(read_slave_to_master(0), nullptr); - EXPECT_NE(obj2, nullptr); - EXPECT_EQ(obj2->test, 7); -} - -TEST_F(Transport, writes_from_master_to_single_slave) { - update_transport(); - test_object1* obj = begin_write_master_to_single_slave(3); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_single_slave(3); - EXPECT_CALL(*this, router_send_frame(4)); - update_transport(); - transport_recv_frame(0, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_master_to_single_slave(); - EXPECT_NE(obj2, nullptr); - EXPECT_EQ(obj2->test, 7); -} - -TEST_F(Transport, ignores_object_with_invalid_id) { - update_transport(); - test_object1* obj = begin_write_master_to_single_slave(3); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_single_slave(3); - EXPECT_CALL(*this, router_send_frame(4)); - update_transport(); - sent_data[sent_data.size() - 1] = 44; - transport_recv_frame(0, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_master_to_single_slave(); - EXPECT_EQ(obj2, nullptr); -} - -TEST_F(Transport, ignores_object_with_size_too_small) { - update_transport(); - test_object1* obj = begin_write_master_to_slave(); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_slave(); - EXPECT_CALL(*this, router_send_frame(_)); - update_transport(); - sent_data[sent_data.size() - 2] = 0; - transport_recv_frame(0, sent_data.data(), sent_data.size() - 1); - test_object1* obj2 = read_master_to_slave(); - EXPECT_EQ(obj2, nullptr); -} - -TEST_F(Transport, ignores_object_with_size_too_big) { - update_transport(); - test_object1* obj = begin_write_master_to_slave(); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_slave(); - EXPECT_CALL(*this, router_send_frame(_)); - update_transport(); - sent_data.resize(sent_data.size() + 22); - sent_data[sent_data.size() - 1] = 0; - transport_recv_frame(0, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_master_to_slave(); - EXPECT_EQ(obj2, nullptr); -} diff --git a/quantum/serial_link/tests/triple_buffered_object_tests.cpp b/quantum/serial_link/tests/triple_buffered_object_tests.cpp deleted file mode 100644 index 8de9bfdebf..0000000000 --- a/quantum/serial_link/tests/triple_buffered_object_tests.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "gtest/gtest.h" -extern "C" { -#include "serial_link/protocol/triple_buffered_object.h" -} - -struct test_object { - uint8_t state; - uint32_t buffer[3]; -}; - -test_object test_object; - -class TripleBufferedObject : public testing::Test { - public: - TripleBufferedObject() { triple_buffer_init((triple_buffer_object_t*)&test_object); } -}; - -TEST_F(TripleBufferedObject, writes_and_reads_object) { - *triple_buffer_begin_write(&test_object) = 0x3456ABCC; - triple_buffer_end_write(&test_object); - EXPECT_EQ(*triple_buffer_read(&test_object), 0x3456ABCC); -} - -TEST_F(TripleBufferedObject, does_not_read_empty) { EXPECT_EQ(triple_buffer_read(&test_object), nullptr); } - -TEST_F(TripleBufferedObject, writes_twice_and_reads_object) { - *triple_buffer_begin_write(&test_object) = 0x3456ABCC; - triple_buffer_end_write(&test_object); - *triple_buffer_begin_write(&test_object) = 0x44778899; - triple_buffer_end_write(&test_object); - EXPECT_EQ(*triple_buffer_read(&test_object), 0x44778899); -} - -TEST_F(TripleBufferedObject, performs_another_write_in_the_middle_of_read) { - *triple_buffer_begin_write(&test_object) = 1; - triple_buffer_end_write(&test_object); - uint32_t* read = triple_buffer_read(&test_object); - *triple_buffer_begin_write(&test_object) = 2; - triple_buffer_end_write(&test_object); - EXPECT_EQ(*read, 1); - EXPECT_EQ(*triple_buffer_read(&test_object), 2); - EXPECT_EQ(triple_buffer_read(&test_object), nullptr); -} - -TEST_F(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) { - *triple_buffer_begin_write(&test_object) = 1; - triple_buffer_end_write(&test_object); - uint32_t* read = triple_buffer_read(&test_object); - *triple_buffer_begin_write(&test_object) = 2; - triple_buffer_end_write(&test_object); - *triple_buffer_begin_write(&test_object) = 3; - triple_buffer_end_write(&test_object); - EXPECT_EQ(*read, 1); - EXPECT_EQ(*triple_buffer_read(&test_object), 3); - EXPECT_EQ(triple_buffer_read(&test_object), nullptr); -} diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h index 1d4f6ed0cd..437d4bc1f6 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h @@ -41,8 +41,13 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length); #ifdef ENCODER_ENABLE +# include "gpio.h" # include "encoder.h" -# define NUMBER_OF_ENCODERS (sizeof((pin_t[])ENCODERS_PAD_A) / sizeof(pin_t)) +// if no pads for right half are defined, we assume the keyboard is symmetric (i.e. same pads) +# ifndef ENCODERS_PAD_A_RIGHT +# define ENCODERS_PAD_A_RIGHT ENCODERS_PAD_A +# endif +# define NUMBER_OF_ENCODERS ((sizeof((pin_t[])ENCODERS_PAD_A) + sizeof((pin_t[])ENCODERS_PAD_A_RIGHT)) / sizeof(pin_t)) #endif // ENCODER_ENABLE #ifdef BACKLIGHT_ENABLE diff --git a/quantum/sync_timer.c b/quantum/sync_timer.c new file mode 100644 index 0000000000..de24b463b6 --- /dev/null +++ b/quantum/sync_timer.c @@ -0,0 +1,58 @@ +/* +Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +If you happen to meet one of the copyright holders in a bar you are obligated +to buy them one pint of beer. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "sync_timer.h" +#include "keyboard.h" + +#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) +volatile int32_t sync_timer_ms; + +void sync_timer_init(void) { sync_timer_ms = 0; } + +void sync_timer_update(uint32_t time) { + if (is_keyboard_master()) return; + sync_timer_ms = time - timer_read32(); +} + +uint16_t sync_timer_read(void) { + if (is_keyboard_master()) return timer_read(); + return sync_timer_read32(); +} + +uint32_t sync_timer_read32(void) { + if (is_keyboard_master()) return timer_read32(); + return sync_timer_ms + timer_read32(); +} + +uint16_t sync_timer_elapsed(uint16_t last) { + if (is_keyboard_master()) return timer_elapsed(last); + return TIMER_DIFF_16(sync_timer_read(), last); +} + +uint32_t sync_timer_elapsed32(uint32_t last) { + if (is_keyboard_master()) return timer_elapsed32(last); + return TIMER_DIFF_32(sync_timer_read32(), last); +} +#endif diff --git a/quantum/sync_timer.h b/quantum/sync_timer.h new file mode 100644 index 0000000000..9ddef45bb2 --- /dev/null +++ b/quantum/sync_timer.h @@ -0,0 +1,54 @@ +/* +Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +If you happen to meet one of the copyright holders in a bar you are obligated +to buy them one pint of beer. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#include <stdint.h> +#include "timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) +void sync_timer_init(void); +void sync_timer_update(uint32_t time); +uint16_t sync_timer_read(void); +uint32_t sync_timer_read32(void); +uint16_t sync_timer_elapsed(uint16_t last); +uint32_t sync_timer_elapsed32(uint32_t last); +#else +# define sync_timer_init() +# define sync_timer_clear() +# define sync_timer_update(t) +# define sync_timer_read() timer_read() +# define sync_timer_read32() timer_read32() +# define sync_timer_elapsed(t) timer_elapsed(t) +# define sync_timer_elapsed32(t) timer_elapsed32(t) +#endif + +#ifdef __cplusplus +} +#endif diff --git a/quantum/via.c b/quantum/via.c index 1b2dbcf08d..7c8aa753e7 100644 --- a/quantum/via.c +++ b/quantum/via.c @@ -44,7 +44,7 @@ #include "raw_hid.h" #include "dynamic_keymap.h" -#include "tmk_core/common/eeprom.h" +#include "eeprom.h" #include "version.h" // for QMK_BUILDDATE used in EEPROM magic #include "via_ensure_keycode.h" diff --git a/quantum/via_ensure_keycode.h b/quantum/via_ensure_keycode.h index a9c1b8ba5d..1aba0cdd2a 100644 --- a/quantum/via_ensure_keycode.h +++ b/quantum/via_ensure_keycode.h @@ -5,362 +5,338 @@ #ifndef VIA_HAS_BROKEN_KEYCODES -_Static_assert(KC_NO == 0, ""); -_Static_assert(KC_TRNS == 1, ""); +// clang-format off -_Static_assert(KC_A == 0x04, ""); -_Static_assert(KC_B == 0x05, ""); -_Static_assert(KC_C == 0x06, ""); -_Static_assert(KC_D == 0x07, ""); -_Static_assert(KC_E == 0x08, ""); -_Static_assert(KC_F == 0x09, ""); -_Static_assert(KC_G == 0x0A, ""); -_Static_assert(KC_H == 0x0B, ""); -_Static_assert(KC_I == 0x0C, ""); -_Static_assert(KC_J == 0x0D, ""); -_Static_assert(KC_K == 0x0E, ""); -_Static_assert(KC_L == 0x0F, ""); -_Static_assert(KC_M == 0x10, ""); -_Static_assert(KC_N == 0x11, ""); -_Static_assert(KC_O == 0x12, ""); -_Static_assert(KC_P == 0x13, ""); -_Static_assert(KC_Q == 0x14, ""); -_Static_assert(KC_R == 0x15, ""); -_Static_assert(KC_S == 0x16, ""); -_Static_assert(KC_T == 0x17, ""); -_Static_assert(KC_U == 0x18, ""); -_Static_assert(KC_V == 0x19, ""); -_Static_assert(KC_W == 0x1A, ""); -_Static_assert(KC_X == 0x1B, ""); -_Static_assert(KC_Y == 0x1C, ""); -_Static_assert(KC_Z == 0x1D, ""); -_Static_assert(KC_1 == 0x1E, ""); -_Static_assert(KC_2 == 0x1F, ""); -_Static_assert(KC_3 == 0x20, ""); -_Static_assert(KC_4 == 0x21, ""); -_Static_assert(KC_5 == 0x22, ""); -_Static_assert(KC_6 == 0x23, ""); -_Static_assert(KC_7 == 0x24, ""); -_Static_assert(KC_8 == 0x25, ""); -_Static_assert(KC_9 == 0x26, ""); -_Static_assert(KC_0 == 0x27, ""); -_Static_assert(KC_ENTER == 0x28, ""); -_Static_assert(KC_ESCAPE == 0x29, ""); -_Static_assert(KC_BSPACE == 0x2A, ""); -_Static_assert(KC_TAB == 0x2B, ""); -_Static_assert(KC_SPACE == 0x2C, ""); -_Static_assert(KC_MINUS == 0x2D, ""); -_Static_assert(KC_EQUAL == 0x2E, ""); -_Static_assert(KC_LBRACKET == 0x2F, ""); -_Static_assert(KC_RBRACKET == 0x30, ""); -_Static_assert(KC_BSLASH == 0x31, ""); -_Static_assert(KC_SCOLON == 0x33, ""); -_Static_assert(KC_QUOTE == 0x34, ""); -_Static_assert(KC_GRAVE == 0x35, ""); -_Static_assert(KC_COMMA == 0x36, ""); -_Static_assert(KC_DOT == 0x37, ""); -_Static_assert(KC_SLASH == 0x38, ""); -_Static_assert(KC_CAPSLOCK == 0x39, ""); -_Static_assert(KC_F1 == 0x3A, ""); -_Static_assert(KC_F2 == 0x3B, ""); -_Static_assert(KC_F3 == 0x3C, ""); -_Static_assert(KC_F4 == 0x3D, ""); -_Static_assert(KC_F5 == 0x3E, ""); -_Static_assert(KC_F6 == 0x3F, ""); -_Static_assert(KC_F7 == 0x40, ""); -_Static_assert(KC_F8 == 0x41, ""); -_Static_assert(KC_F9 == 0x42, ""); -_Static_assert(KC_F10 == 0x43, ""); -_Static_assert(KC_F11 == 0x44, ""); -_Static_assert(KC_F12 == 0x45, ""); -_Static_assert(KC_PSCREEN == 0x46, ""); -_Static_assert(KC_SCROLLLOCK == 0x47, ""); -_Static_assert(KC_PAUSE == 0x48, ""); -_Static_assert(KC_INSERT == 0x49, ""); -_Static_assert(KC_HOME == 0x4A, ""); -_Static_assert(KC_PGUP == 0x4B, ""); -_Static_assert(KC_DELETE == 0x4C, ""); -_Static_assert(KC_END == 0x4D, ""); -_Static_assert(KC_PGDOWN == 0x4E, ""); -_Static_assert(KC_RIGHT == 0x4F, ""); -_Static_assert(KC_LEFT == 0x50, ""); -_Static_assert(KC_DOWN == 0x51, ""); -_Static_assert(KC_UP == 0x52, ""); -_Static_assert(KC_NUMLOCK == 0x53, ""); -_Static_assert(KC_KP_SLASH == 0x54, ""); -_Static_assert(KC_KP_ASTERISK == 0x55, ""); -_Static_assert(KC_KP_MINUS == 0x56, ""); -_Static_assert(KC_KP_PLUS == 0x57, ""); -_Static_assert(KC_KP_ENTER == 0x58, ""); -_Static_assert(KC_KP_1 == 0x59, ""); -_Static_assert(KC_KP_2 == 0x5A, ""); -_Static_assert(KC_KP_3 == 0x5B, ""); -_Static_assert(KC_KP_4 == 0x5C, ""); -_Static_assert(KC_KP_5 == 0x5D, ""); -_Static_assert(KC_KP_6 == 0x5E, ""); -_Static_assert(KC_KP_7 == 0x5F, ""); -_Static_assert(KC_KP_8 == 0x60, ""); -_Static_assert(KC_KP_9 == 0x61, ""); -_Static_assert(KC_KP_0 == 0x62, ""); -_Static_assert(KC_KP_DOT == 0x63, ""); -_Static_assert(KC_APPLICATION == 0x65, ""); -_Static_assert(KC_KP_EQUAL == 0x67, ""); -_Static_assert(KC_KP_COMMA == 0x85, ""); -_Static_assert(KC_LCTRL == 0xE0, ""); -_Static_assert(KC_LSHIFT == 0xE1, ""); -_Static_assert(KC_LALT == 0xE2, ""); -_Static_assert(KC_LGUI == 0xE3, ""); -_Static_assert(KC_RCTRL == 0xE4, ""); -_Static_assert(KC_RSHIFT == 0xE5, ""); -_Static_assert(KC_RALT == 0xE6, ""); -_Static_assert(KC_RGUI == 0xE7, ""); +_Static_assert(KC_NO == 0x0000, ""); +_Static_assert(KC_TRANSPARENT == 0x0001, ""); -_Static_assert(KC_TILD == 0x235, ""); -_Static_assert(KC_EXLM == 0x21E, ""); -_Static_assert(KC_AT == 0x21F, ""); -_Static_assert(KC_HASH == 0x220, ""); -_Static_assert(KC_DLR == 0x221, ""); -_Static_assert(KC_PERC == 0x222, ""); -_Static_assert(KC_CIRC == 0x223, ""); -_Static_assert(KC_AMPR == 0x224, ""); -_Static_assert(KC_ASTR == 0x225, ""); -_Static_assert(KC_LPRN == 0x226, ""); -_Static_assert(KC_RPRN == 0x227, ""); -_Static_assert(KC_UNDS == 0x22D, ""); -_Static_assert(KC_PLUS == 0x22E, ""); -_Static_assert(KC_LCBR == 0x22F, ""); -_Static_assert(KC_RCBR == 0x230, ""); -_Static_assert(KC_LT == 0x236, ""); -_Static_assert(KC_GT == 0x237, ""); -_Static_assert(KC_COLN == 0x233, ""); -_Static_assert(KC_PIPE == 0x231, ""); -_Static_assert(KC_QUES == 0x238, ""); -_Static_assert(KC_DQUO == 0x234, ""); +_Static_assert(KC_A == 0x0004, ""); +_Static_assert(KC_B == 0x0005, ""); +_Static_assert(KC_C == 0x0006, ""); +_Static_assert(KC_D == 0x0007, ""); +_Static_assert(KC_E == 0x0008, ""); +_Static_assert(KC_F == 0x0009, ""); +_Static_assert(KC_G == 0x000A, ""); +_Static_assert(KC_H == 0x000B, ""); +_Static_assert(KC_I == 0x000C, ""); +_Static_assert(KC_J == 0x000D, ""); +_Static_assert(KC_K == 0x000E, ""); +_Static_assert(KC_L == 0x000F, ""); +_Static_assert(KC_M == 0x0010, ""); +_Static_assert(KC_N == 0x0011, ""); +_Static_assert(KC_O == 0x0012, ""); +_Static_assert(KC_P == 0x0013, ""); +_Static_assert(KC_Q == 0x0014, ""); +_Static_assert(KC_R == 0x0015, ""); +_Static_assert(KC_S == 0x0016, ""); +_Static_assert(KC_T == 0x0017, ""); +_Static_assert(KC_U == 0x0018, ""); +_Static_assert(KC_V == 0x0019, ""); +_Static_assert(KC_W == 0x001A, ""); +_Static_assert(KC_X == 0x001B, ""); +_Static_assert(KC_Y == 0x001C, ""); +_Static_assert(KC_Z == 0x001D, ""); +_Static_assert(KC_1 == 0x001E, ""); +_Static_assert(KC_2 == 0x001F, ""); +_Static_assert(KC_3 == 0x0020, ""); +_Static_assert(KC_4 == 0x0021, ""); +_Static_assert(KC_5 == 0x0022, ""); +_Static_assert(KC_6 == 0x0023, ""); +_Static_assert(KC_7 == 0x0024, ""); +_Static_assert(KC_8 == 0x0025, ""); +_Static_assert(KC_9 == 0x0026, ""); +_Static_assert(KC_0 == 0x0027, ""); +_Static_assert(KC_ENTER == 0x0028, ""); +_Static_assert(KC_ESCAPE == 0x0029, ""); +_Static_assert(KC_BACKSPACE == 0x002A, ""); +_Static_assert(KC_TAB == 0x002B, ""); +_Static_assert(KC_SPACE == 0x002C, ""); +_Static_assert(KC_MINUS == 0x002D, ""); +_Static_assert(KC_EQUAL == 0x002E, ""); +_Static_assert(KC_LEFT_BRACKET == 0x002F, ""); +_Static_assert(KC_RIGHT_BRACKET == 0x0030, ""); +_Static_assert(KC_BACKSLASH == 0x0031, ""); +_Static_assert(KC_NONUS_HASH == 0x0032, ""); +_Static_assert(KC_SEMICOLON == 0x0033, ""); +_Static_assert(KC_QUOTE == 0x0034, ""); +_Static_assert(KC_GRAVE == 0x0035, ""); +_Static_assert(KC_COMMA == 0x0036, ""); +_Static_assert(KC_DOT == 0x0037, ""); +_Static_assert(KC_SLASH == 0x0038, ""); +_Static_assert(KC_CAPS_LOCK == 0x0039, ""); +_Static_assert(KC_F1 == 0x003A, ""); +_Static_assert(KC_F2 == 0x003B, ""); +_Static_assert(KC_F3 == 0x003C, ""); +_Static_assert(KC_F4 == 0x003D, ""); +_Static_assert(KC_F5 == 0x003E, ""); +_Static_assert(KC_F6 == 0x003F, ""); +_Static_assert(KC_F7 == 0x0040, ""); +_Static_assert(KC_F8 == 0x0041, ""); +_Static_assert(KC_F9 == 0x0042, ""); +_Static_assert(KC_F10 == 0x0043, ""); +_Static_assert(KC_F11 == 0x0044, ""); +_Static_assert(KC_F12 == 0x0045, ""); +_Static_assert(KC_PRINT_SCREEN == 0x0046, ""); +_Static_assert(KC_SCROLL_LOCK == 0x0047, ""); +_Static_assert(KC_PAUSE == 0x0048, ""); +_Static_assert(KC_INSERT == 0x0049, ""); +_Static_assert(KC_HOME == 0x004A, ""); +_Static_assert(KC_PAGE_UP == 0x004B, ""); +_Static_assert(KC_DELETE == 0x004C, ""); +_Static_assert(KC_END == 0x004D, ""); +_Static_assert(KC_PAGE_DOWN == 0x004E, ""); +_Static_assert(KC_RIGHT == 0x004F, ""); +_Static_assert(KC_LEFT == 0x0050, ""); +_Static_assert(KC_DOWN == 0x0051, ""); +_Static_assert(KC_UP == 0x0052, ""); +_Static_assert(KC_NUM_LOCK == 0x0053, ""); +_Static_assert(KC_KP_SLASH == 0x0054, ""); +_Static_assert(KC_KP_ASTERISK == 0x0055, ""); +_Static_assert(KC_KP_MINUS == 0x0056, ""); +_Static_assert(KC_KP_PLUS == 0x0057, ""); +_Static_assert(KC_KP_ENTER == 0x0058, ""); +_Static_assert(KC_KP_1 == 0x0059, ""); +_Static_assert(KC_KP_2 == 0x005A, ""); +_Static_assert(KC_KP_3 == 0x005B, ""); +_Static_assert(KC_KP_4 == 0x005C, ""); +_Static_assert(KC_KP_5 == 0x005D, ""); +_Static_assert(KC_KP_6 == 0x005E, ""); +_Static_assert(KC_KP_7 == 0x005F, ""); +_Static_assert(KC_KP_8 == 0x0060, ""); +_Static_assert(KC_KP_9 == 0x0061, ""); +_Static_assert(KC_KP_0 == 0x0062, ""); +_Static_assert(KC_KP_DOT == 0x0063, ""); +_Static_assert(KC_NONUS_BACKSLASH == 0x0064, ""); +_Static_assert(KC_APPLICATION == 0x0065, ""); +_Static_assert(KC_KB_POWER == 0x0066, ""); +_Static_assert(KC_KP_EQUAL == 0x0067, ""); +_Static_assert(KC_F13 == 0x0068, ""); +_Static_assert(KC_F14 == 0x0069, ""); +_Static_assert(KC_F15 == 0x006A, ""); +_Static_assert(KC_F16 == 0x006B, ""); +_Static_assert(KC_F17 == 0x006C, ""); +_Static_assert(KC_F18 == 0x006D, ""); +_Static_assert(KC_F19 == 0x006E, ""); +_Static_assert(KC_F20 == 0x006F, ""); +_Static_assert(KC_F21 == 0x0070, ""); +_Static_assert(KC_F22 == 0x0071, ""); +_Static_assert(KC_F23 == 0x0072, ""); +_Static_assert(KC_F24 == 0x0073, ""); +_Static_assert(KC_EXECUTE == 0x0074, ""); +_Static_assert(KC_HELP == 0x0075, ""); +_Static_assert(KC_MENU == 0x0076, ""); +_Static_assert(KC_SELECT == 0x0077, ""); +_Static_assert(KC_STOP == 0x0078, ""); +_Static_assert(KC_AGAIN == 0x0079, ""); +_Static_assert(KC_UNDO == 0x007A, ""); +_Static_assert(KC_CUT == 0x007B, ""); +_Static_assert(KC_COPY == 0x007C, ""); +_Static_assert(KC_PASTE == 0x007D, ""); +_Static_assert(KC_FIND == 0x007E, ""); -_Static_assert(KC_NONUS_HASH == 0x32, ""); -_Static_assert(KC_NONUS_BSLASH == 0x64, ""); -_Static_assert(KC_RO == 0x87, ""); -_Static_assert(KC_KANA == 0x88, ""); -_Static_assert(KC_JYEN == 0x89, ""); -_Static_assert(KC_HENK == 0x8A, ""); -_Static_assert(KC_MHEN == 0x8B, ""); -_Static_assert(KC_LANG1 == 0x90, ""); -_Static_assert(KC_LANG2 == 0x91, ""); +_Static_assert(KC_LOCKING_CAPS_LOCK == 0x0082, ""); +_Static_assert(KC_LOCKING_NUM_LOCK == 0x0083, ""); +_Static_assert(KC_LOCKING_SCROLL_LOCK == 0x0084, ""); +_Static_assert(KC_KP_COMMA == 0x0085, ""); +_Static_assert(KC_KP_EQUAL_AS400 == 0x0086, ""); +_Static_assert(KC_INTERNATIONAL_1 == 0x0087, ""); +_Static_assert(KC_INTERNATIONAL_2 == 0x0088, ""); +_Static_assert(KC_INTERNATIONAL_3 == 0x0089, ""); +_Static_assert(KC_INTERNATIONAL_4 == 0x008A, ""); +_Static_assert(KC_INTERNATIONAL_5 == 0x008B, ""); +_Static_assert(KC_INTERNATIONAL_6 == 0x008C, ""); +_Static_assert(KC_INTERNATIONAL_7 == 0x008D, ""); +_Static_assert(KC_INTERNATIONAL_8 == 0x008E, ""); +_Static_assert(KC_INTERNATIONAL_9 == 0x008F, ""); +_Static_assert(KC_LANGUAGE_1 == 0x0090, ""); +_Static_assert(KC_LANGUAGE_2 == 0x0091, ""); +_Static_assert(KC_LANGUAGE_3 == 0x0092, ""); +_Static_assert(KC_LANGUAGE_4 == 0x0093, ""); +_Static_assert(KC_LANGUAGE_5 == 0x0094, ""); +_Static_assert(KC_LANGUAGE_6 == 0x0095, ""); +_Static_assert(KC_LANGUAGE_7 == 0x0096, ""); +_Static_assert(KC_LANGUAGE_8 == 0x0097, ""); +_Static_assert(KC_LANGUAGE_9 == 0x0098, ""); +_Static_assert(KC_ALTERNATE_ERASE == 0x0099, ""); +_Static_assert(KC_SYSTEM_REQUEST == 0x009A, ""); +_Static_assert(KC_CANCEL == 0x009B, ""); +_Static_assert(KC_CLEAR == 0x009C, ""); +_Static_assert(KC_PRIOR == 0x009D, ""); -_Static_assert(KC_GESC == 0x5C16, ""); -_Static_assert(KC_LSPO == 0x5CD7, ""); -_Static_assert(KC_RSPC == 0x5CD8, ""); -_Static_assert(KC_LCPO == 0x5CF3, ""); -_Static_assert(KC_RCPC == 0x5CF4, ""); -_Static_assert(KC_LAPO == 0x5CF5, ""); -_Static_assert(KC_RAPC == 0x5CF6, ""); -_Static_assert(KC_SFTENT == 0x5CD9, ""); +_Static_assert(KC_OUT == 0x00A0, ""); +_Static_assert(KC_OPER == 0x00A1, ""); +_Static_assert(KC_CLEAR_AGAIN == 0x00A2, ""); +_Static_assert(KC_CRSEL == 0x00A3, ""); +_Static_assert(KC_EXSEL == 0x00A4, ""); -_Static_assert(BL_TOGG == 23743, ""); -_Static_assert(BL_STEP == 23744, ""); -_Static_assert(BL_BRTG == 23745, ""); -_Static_assert(BL_ON == 23739, ""); -_Static_assert(BL_OFF == 23740, ""); -_Static_assert(BL_INC == 23742, ""); -_Static_assert(BL_DEC == 23741, ""); -_Static_assert(RGB_TOG == 23746, ""); -_Static_assert(RGB_MOD == 23747, ""); -_Static_assert(RGB_RMOD == 23748, ""); -_Static_assert(RGB_HUI == 23749, ""); -_Static_assert(RGB_HUD == 23750, ""); -_Static_assert(RGB_SAI == 23751, ""); -_Static_assert(RGB_SAD == 23752, ""); -_Static_assert(RGB_VAI == 23753, ""); -_Static_assert(RGB_VAD == 23754, ""); -_Static_assert(RGB_SPI == 23755, ""); -_Static_assert(RGB_SPD == 23756, ""); -_Static_assert(RGB_M_P == 23757, ""); -_Static_assert(RGB_M_B == 23758, ""); -_Static_assert(RGB_M_R == 23759, ""); -_Static_assert(RGB_M_SW == 23760, ""); -_Static_assert(RGB_M_SN == 23761, ""); -_Static_assert(RGB_M_K == 23762, ""); -_Static_assert(RGB_M_X == 23763, ""); -_Static_assert(RGB_M_G == 23764, ""); -_Static_assert(RGB_M_T == 23765, ""); +_Static_assert(KC_PWR == 0x00A5, ""); +_Static_assert(KC_SLEP == 0x00A6, ""); +_Static_assert(KC_WAKE == 0x00A7, ""); +_Static_assert(KC_MUTE == 0x00A8, ""); +_Static_assert(KC_VOLU == 0x00A9, ""); +_Static_assert(KC_VOLD == 0x00AA, ""); +_Static_assert(KC_MNXT == 0x00AB, ""); +_Static_assert(KC_MPRV == 0x00AC, ""); +_Static_assert(KC_MSTP == 0x00AD, ""); +_Static_assert(KC_MPLY == 0x00AE, ""); +_Static_assert(KC_MSEL == 0x00AF, ""); +_Static_assert(KC_EJCT == 0x00B0, ""); +_Static_assert(KC_MAIL == 0x00B1, ""); +_Static_assert(KC_CALC == 0x00B2, ""); +_Static_assert(KC_MYCM == 0x00B3, ""); +_Static_assert(KC_WSCH == 0x00B4, ""); +_Static_assert(KC_WHOM == 0x00B5, ""); +_Static_assert(KC_WBAK == 0x00B6, ""); +_Static_assert(KC_WFWD == 0x00B7, ""); +_Static_assert(KC_WSTP == 0x00B8, ""); +_Static_assert(KC_WREF == 0x00B9, ""); +_Static_assert(KC_WFAV == 0x00BA, ""); +_Static_assert(KC_MFFD == 0x00BB, ""); +_Static_assert(KC_MRWD == 0x00BC, ""); +_Static_assert(KC_BRIU == 0x00BD, ""); +_Static_assert(KC_BRID == 0x00BE, ""); -_Static_assert(KC_F13 == 104, ""); -_Static_assert(KC_F14 == 105, ""); -_Static_assert(KC_F15 == 106, ""); -_Static_assert(KC_F16 == 107, ""); -_Static_assert(KC_F17 == 108, ""); -_Static_assert(KC_F18 == 109, ""); -_Static_assert(KC_F19 == 110, ""); -_Static_assert(KC_F20 == 111, ""); -_Static_assert(KC_F21 == 112, ""); -_Static_assert(KC_F22 == 113, ""); -_Static_assert(KC_F23 == 114, ""); -_Static_assert(KC_F24 == 115, ""); -_Static_assert(KC_PWR == 165, ""); -_Static_assert(KC_SLEP == 166, ""); -_Static_assert(KC_WAKE == 167, ""); -_Static_assert(KC_EXEC == 116, ""); -_Static_assert(KC_HELP == 117, ""); -_Static_assert(KC_SLCT == 119, ""); -_Static_assert(KC_STOP == 120, ""); -_Static_assert(KC_AGIN == 121, ""); -_Static_assert(KC_UNDO == 122, ""); -_Static_assert(KC_CUT == 123, ""); -_Static_assert(KC_COPY == 124, ""); -_Static_assert(KC_PSTE == 125, ""); -_Static_assert(KC_FIND == 126, ""); -_Static_assert(KC_CALC == 178, ""); -_Static_assert(KC_MAIL == 177, ""); -_Static_assert(KC_MSEL == 175, ""); -_Static_assert(KC_MYCM == 179, ""); -_Static_assert(KC_WSCH == 180, ""); -_Static_assert(KC_WHOM == 181, ""); -_Static_assert(KC_WBAK == 182, ""); -_Static_assert(KC_WFWD == 183, ""); -_Static_assert(KC_WSTP == 184, ""); -_Static_assert(KC_WREF == 185, ""); -_Static_assert(KC_WFAV == 186, ""); -_Static_assert(KC_BRIU == 189, ""); -_Static_assert(KC_BRID == 190, ""); -_Static_assert(KC_MPRV == 172, ""); -_Static_assert(KC_MNXT == 171, ""); -_Static_assert(KC_MUTE == 168, ""); -_Static_assert(KC_VOLD == 170, ""); -_Static_assert(KC_VOLU == 169, ""); -_Static_assert(KC_MSTP == 173, ""); -_Static_assert(KC_MPLY == 174, ""); -_Static_assert(KC_MRWD == 188, ""); -_Static_assert(KC_MFFD == 187, ""); -_Static_assert(KC_EJCT == 176, ""); -_Static_assert(KC_MS_U == 240, ""); -_Static_assert(KC_MS_D == 241, ""); -_Static_assert(KC_MS_L == 242, ""); -_Static_assert(KC_MS_R == 243, ""); -_Static_assert(KC_BTN1 == 244, ""); -_Static_assert(KC_BTN2 == 245, ""); -_Static_assert(KC_BTN3 == 246, ""); -_Static_assert(KC_BTN4 == 247, ""); -_Static_assert(KC_BTN5 == 248, ""); -_Static_assert(KC_WH_U == 249, ""); -_Static_assert(KC_WH_D == 250, ""); -_Static_assert(KC_WH_L == 251, ""); -_Static_assert(KC_WH_R == 252, ""); -_Static_assert(KC_ACL0 == 253, ""); -_Static_assert(KC_ACL1 == 254, ""); -_Static_assert(KC_ACL2 == 255, ""); -_Static_assert(KC_LCAP == 130, ""); -_Static_assert(KC_LNUM == 131, ""); -_Static_assert(KC_LSCR == 132, ""); +_Static_assert(KC_LEFT_CTRL == 0x00E0, ""); +_Static_assert(KC_LEFT_SHIFT == 0x00E1, ""); +_Static_assert(KC_LEFT_ALT == 0x00E2, ""); +_Static_assert(KC_LEFT_GUI == 0x00E3, ""); +_Static_assert(KC_RIGHT_CTRL == 0x00E4, ""); +_Static_assert(KC_RIGHT_SHIFT == 0x00E5, ""); +_Static_assert(KC_RIGHT_ALT == 0x00E6, ""); +_Static_assert(KC_RIGHT_GUI == 0x00E7, ""); -_Static_assert(FN_MO13 == 0x5F10, ""); -_Static_assert(FN_MO23 == 0x5F11, ""); +_Static_assert(KC_MS_U == 0x00F0, ""); +_Static_assert(KC_MS_D == 0x00F1, ""); +_Static_assert(KC_MS_L == 0x00F2, ""); +_Static_assert(KC_MS_R == 0x00F3, ""); +_Static_assert(KC_BTN1 == 0x00F4, ""); +_Static_assert(KC_BTN2 == 0x00F5, ""); +_Static_assert(KC_BTN3 == 0x00F6, ""); +_Static_assert(KC_BTN4 == 0x00F7, ""); +_Static_assert(KC_BTN5 == 0x00F8, ""); +_Static_assert(KC_WH_U == 0x00F9, ""); +_Static_assert(KC_WH_D == 0x00FA, ""); +_Static_assert(KC_WH_L == 0x00FB, ""); +_Static_assert(KC_WH_R == 0x00FC, ""); +_Static_assert(KC_ACL0 == 0x00FD, ""); +_Static_assert(KC_ACL1 == 0x00FE, ""); +_Static_assert(KC_ACL2 == 0x00FF, ""); -_Static_assert(MACRO00 == 0x5F12, ""); -_Static_assert(MACRO01 == 0x5F13, ""); -_Static_assert(MACRO02 == 0x5F14, ""); -_Static_assert(MACRO03 == 0x5F15, ""); -_Static_assert(MACRO04 == 0x5F16, ""); -_Static_assert(MACRO05 == 0x5F17, ""); -_Static_assert(MACRO06 == 0x5F18, ""); -_Static_assert(MACRO07 == 0x5F19, ""); -_Static_assert(MACRO08 == 0x5F1A, ""); -_Static_assert(MACRO09 == 0x5F1B, ""); -_Static_assert(MACRO10 == 0x5F1C, ""); -_Static_assert(MACRO11 == 0x5F1D, ""); -_Static_assert(MACRO12 == 0x5F1E, ""); -_Static_assert(MACRO13 == 0x5F1F, ""); -_Static_assert(MACRO14 == 0x5F20, ""); -_Static_assert(MACRO15 == 0x5F21, ""); +_Static_assert(KC_EXLM == 0x021E, ""); +_Static_assert(KC_AT == 0x021F, ""); +_Static_assert(KC_HASH == 0x0220, ""); +_Static_assert(KC_DLR == 0x0221, ""); +_Static_assert(KC_PERC == 0x0222, ""); +_Static_assert(KC_CIRC == 0x0223, ""); +_Static_assert(KC_AMPR == 0x0224, ""); +_Static_assert(KC_ASTR == 0x0225, ""); +_Static_assert(KC_LPRN == 0x0226, ""); +_Static_assert(KC_RPRN == 0x0227, ""); +_Static_assert(KC_UNDS == 0x022D, ""); +_Static_assert(KC_PLUS == 0x022E, ""); +_Static_assert(KC_LCBR == 0x022F, ""); +_Static_assert(KC_RCBR == 0x0230, ""); +_Static_assert(KC_PIPE == 0x0231, ""); +_Static_assert(KC_COLN == 0x0233, ""); +_Static_assert(KC_DQUO == 0x0234, ""); +_Static_assert(KC_TILD == 0x0235, ""); +_Static_assert(KC_LT == 0x0236, ""); +_Static_assert(KC_GT == 0x0237, ""); +_Static_assert(KC_QUES == 0x0238, ""); -_Static_assert(USER00 == 0x5F80, ""); -_Static_assert(USER01 == 0x5F81, ""); -_Static_assert(USER02 == 0x5F82, ""); -_Static_assert(USER03 == 0x5F83, ""); -_Static_assert(USER04 == 0x5F84, ""); -_Static_assert(USER05 == 0x5F85, ""); -_Static_assert(USER06 == 0x5F86, ""); -_Static_assert(USER07 == 0x5F87, ""); -_Static_assert(USER08 == 0x5F88, ""); -_Static_assert(USER09 == 0x5F89, ""); -_Static_assert(USER10 == 0x5F8A, ""); -_Static_assert(USER11 == 0x5F8B, ""); -_Static_assert(USER12 == 0x5F8C, ""); -_Static_assert(USER13 == 0x5F8D, ""); -_Static_assert(USER14 == 0x5F8E, ""); -_Static_assert(USER15 == 0x5F8F, ""); +_Static_assert(RESET == 0x5C00, ""); +_Static_assert(DEBUG == 0x5C01, ""); -_Static_assert(KC_POWER == 102, ""); -_Static_assert(KC_MENU == 118, ""); -_Static_assert(KC_KP_EQUAL_AS400 == 134, ""); -_Static_assert(KC_INT6 == 140, ""); -_Static_assert(KC_INT7 == 141, ""); -_Static_assert(KC_INT8 == 142, ""); -_Static_assert(KC_INT9 == 143, ""); -_Static_assert(KC_LANG3 == 146, ""); -_Static_assert(KC_LANG4 == 147, ""); -_Static_assert(KC_LANG5 == 148, ""); -_Static_assert(KC_LANG6 == 149, ""); -_Static_assert(KC_LANG7 == 150, ""); -_Static_assert(KC_LANG8 == 151, ""); -_Static_assert(KC_LANG9 == 152, ""); -_Static_assert(KC_ERAS == 153, ""); -_Static_assert(KC_SYSREQ == 154, ""); -_Static_assert(KC_CANCEL == 155, ""); -_Static_assert(KC_CLEAR == 156, ""); -_Static_assert(KC_CLR == 156, ""); -_Static_assert(KC_PRIOR == 157, ""); -_Static_assert(KC_OUT == 160, ""); -_Static_assert(KC_OPER == 161, ""); -_Static_assert(KC_CLEAR_AGAIN == 162, ""); -_Static_assert(KC_CRSEL == 163, ""); -_Static_assert(KC_EXSEL == 164, ""); -_Static_assert(KC_FN0 == 192, ""); -_Static_assert(KC_FN1 == 193, ""); -_Static_assert(KC_FN2 == 194, ""); -_Static_assert(KC_FN3 == 195, ""); -_Static_assert(KC_FN4 == 196, ""); -_Static_assert(KC_FN5 == 197, ""); -_Static_assert(KC_FN6 == 198, ""); -_Static_assert(KC_FN7 == 199, ""); -_Static_assert(KC_FN8 == 200, ""); -_Static_assert(KC_FN9 == 201, ""); -_Static_assert(KC_FN10 == 202, ""); -_Static_assert(KC_FN11 == 203, ""); -_Static_assert(KC_FN12 == 204, ""); -_Static_assert(KC_FN13 == 205, ""); -_Static_assert(KC_FN14 == 206, ""); -_Static_assert(KC_FN15 == 207, ""); -_Static_assert(KC_FN16 == 208, ""); -_Static_assert(KC_FN17 == 209, ""); -_Static_assert(KC_FN18 == 210, ""); -_Static_assert(KC_FN19 == 211, ""); -_Static_assert(KC_FN20 == 212, ""); -_Static_assert(KC_FN21 == 213, ""); -_Static_assert(KC_FN22 == 214, ""); -_Static_assert(KC_FN23 == 215, ""); -_Static_assert(KC_FN24 == 216, ""); -_Static_assert(KC_FN25 == 217, ""); -_Static_assert(KC_FN26 == 218, ""); -_Static_assert(KC_FN27 == 219, ""); -_Static_assert(KC_FN28 == 220, ""); -_Static_assert(KC_FN29 == 221, ""); -_Static_assert(KC_FN30 == 222, ""); -_Static_assert(KC_FN31 == 223, ""); -_Static_assert(RESET == 23552, ""); -_Static_assert(DEBUG == 23553, ""); -_Static_assert(MAGIC_TOGGLE_NKRO == 23572, ""); -_Static_assert(AU_ON == 23581, ""); -_Static_assert(AU_OFF == 23582, ""); -_Static_assert(AU_TOG == 23583, ""); -_Static_assert(CLICKY_TOGGLE == 23584, ""); -_Static_assert(CLICKY_ENABLE == 23585, ""); -_Static_assert(CLICKY_DISABLE == 23586, ""); -_Static_assert(CLICKY_UP == 23587, ""); -_Static_assert(CLICKY_DOWN == 23588, ""); -_Static_assert(CLICKY_RESET == 23589, ""); -_Static_assert(MU_ON == 23590, ""); -_Static_assert(MU_OFF == 23591, ""); -_Static_assert(MU_TOG == 23592, ""); -_Static_assert(MU_MOD == 23593, ""); +_Static_assert(MAGIC_TOGGLE_NKRO == 0x5C14, ""); + +_Static_assert(KC_GESC == 0x5C16, ""); + +_Static_assert(AU_ON == 0x5C1D, ""); +_Static_assert(AU_OFF == 0x5C1E, ""); +_Static_assert(AU_TOG == 0x5C1F, ""); + +_Static_assert(CLICKY_TOGGLE == 0x5C20, ""); +_Static_assert(CLICKY_ENABLE == 0x5C21, ""); +_Static_assert(CLICKY_DISABLE == 0x5C22, ""); +_Static_assert(CLICKY_UP == 0x5C23, ""); +_Static_assert(CLICKY_DOWN == 0x5C24, ""); +_Static_assert(CLICKY_RESET == 0x5C25, ""); +_Static_assert(MU_ON == 0x5C26, ""); +_Static_assert(MU_OFF == 0x5C27, ""); +_Static_assert(MU_TOG == 0x5C28, ""); +_Static_assert(MU_MOD == 0x5C29, ""); + +_Static_assert(BL_ON == 0x5CBB, ""); +_Static_assert(BL_OFF == 0x5CBC, ""); +_Static_assert(BL_DEC == 0x5CBD, ""); +_Static_assert(BL_INC == 0x5CBE, ""); +_Static_assert(BL_TOGG == 0x5CBF, ""); +_Static_assert(BL_STEP == 0x5CC0, ""); +_Static_assert(BL_BRTG == 0x5CC1, ""); +_Static_assert(RGB_TOG == 0x5CC2, ""); +_Static_assert(RGB_MOD == 0x5CC3, ""); +_Static_assert(RGB_RMOD == 0x5CC4, ""); +_Static_assert(RGB_HUI == 0x5CC5, ""); +_Static_assert(RGB_HUD == 0x5CC6, ""); +_Static_assert(RGB_SAI == 0x5CC7, ""); +_Static_assert(RGB_SAD == 0x5CC8, ""); +_Static_assert(RGB_VAI == 0x5CC9, ""); +_Static_assert(RGB_VAD == 0x5CCA, ""); +_Static_assert(RGB_SPI == 0x5CCB, ""); +_Static_assert(RGB_SPD == 0x5CCC, ""); +_Static_assert(RGB_M_P == 0x5CCD, ""); +_Static_assert(RGB_M_B == 0x5CCE, ""); +_Static_assert(RGB_M_R == 0x5CCF, ""); +_Static_assert(RGB_M_SW == 0x5CD0, ""); +_Static_assert(RGB_M_SN == 0x5CD1, ""); +_Static_assert(RGB_M_K == 0x5CD2, ""); +_Static_assert(RGB_M_X == 0x5CD3, ""); +_Static_assert(RGB_M_G == 0x5CD4, ""); +_Static_assert(RGB_M_T == 0x5CD5, ""); + +_Static_assert(KC_LSPO == 0x5CD7, ""); +_Static_assert(KC_RSPC == 0x5CD8, ""); +_Static_assert(KC_SFTENT == 0x5CD9, ""); + +_Static_assert(KC_LCPO == 0x5CF3, ""); +_Static_assert(KC_RCPC == 0x5CF4, ""); +_Static_assert(KC_LAPO == 0x5CF5, ""); +_Static_assert(KC_RAPC == 0x5CF6, ""); + +_Static_assert(FN_MO13 == 0x5F10, ""); +_Static_assert(FN_MO23 == 0x5F11, ""); +_Static_assert(MACRO00 == 0x5F12, ""); +_Static_assert(MACRO01 == 0x5F13, ""); +_Static_assert(MACRO02 == 0x5F14, ""); +_Static_assert(MACRO03 == 0x5F15, ""); +_Static_assert(MACRO04 == 0x5F16, ""); +_Static_assert(MACRO05 == 0x5F17, ""); +_Static_assert(MACRO06 == 0x5F18, ""); +_Static_assert(MACRO07 == 0x5F19, ""); +_Static_assert(MACRO08 == 0x5F1A, ""); +_Static_assert(MACRO09 == 0x5F1B, ""); +_Static_assert(MACRO10 == 0x5F1C, ""); +_Static_assert(MACRO11 == 0x5F1D, ""); +_Static_assert(MACRO12 == 0x5F1E, ""); +_Static_assert(MACRO13 == 0x5F1F, ""); +_Static_assert(MACRO14 == 0x5F20, ""); +_Static_assert(MACRO15 == 0x5F21, ""); + +_Static_assert(USER00 == 0x5F80, ""); +_Static_assert(USER01 == 0x5F81, ""); +_Static_assert(USER02 == 0x5F82, ""); +_Static_assert(USER03 == 0x5F83, ""); +_Static_assert(USER04 == 0x5F84, ""); +_Static_assert(USER05 == 0x5F85, ""); +_Static_assert(USER06 == 0x5F86, ""); +_Static_assert(USER07 == 0x5F87, ""); +_Static_assert(USER08 == 0x5F88, ""); +_Static_assert(USER09 == 0x5F89, ""); +_Static_assert(USER10 == 0x5F8A, ""); +_Static_assert(USER11 == 0x5F8B, ""); +_Static_assert(USER12 == 0x5F8C, ""); +_Static_assert(USER13 == 0x5F8D, ""); +_Static_assert(USER14 == 0x5F8E, ""); +_Static_assert(USER15 == 0x5F8F, ""); #endif diff --git a/quantum/virtser.h b/quantum/virtser.h new file mode 100644 index 0000000000..df7e87984c --- /dev/null +++ b/quantum/virtser.h @@ -0,0 +1,9 @@ +#pragma once + +void virtser_init(void); + +/* Define this function in your code to process incoming bytes */ +void virtser_recv(const uint8_t ch); + +/* Call this to send a character over the Virtual Serial Device */ +void virtser_send(const uint8_t byte); diff --git a/quantum/visualizer/LICENSE.md b/quantum/visualizer/LICENSE.md deleted file mode 100644 index 22d4c3f08b..0000000000 --- a/quantum/visualizer/LICENSE.md +++ /dev/null @@ -1,29 +0,0 @@ -The files in this project are licensed under the MIT license -It uses the following libraries -uGFX - with it's own license, see the license.html file in the uGFX subfolder for more information -tmk_core - is indirectly used and not included in the repository. It's licensed under the GPLv2 license -Chibios - which is used by tmk_core is licensed under GPLv3. - -Therefore the effective license for any project using the library is GPLv3 - -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/quantum/visualizer/common_gfxconf.h b/quantum/visualizer/common_gfxconf.h deleted file mode 100644 index e0735b37d0..0000000000 --- a/quantum/visualizer/common_gfxconf.h +++ /dev/null @@ -1,354 +0,0 @@ -/** - * This file has a different license to the rest of the uGFX system. - * You can copy, modify and distribute this file as you see fit. - * You do not need to publish your source modifications to this file. - * The only thing you are not permitted to do is to relicense it - * under a different license. - */ - -/** - * Copy this file into your project directory and rename it as gfxconf.h - * Edit your copy to turn on the uGFX features you want to use. - * The values below are the defaults. - * - * Only remove the comments from lines where you want to change the - * default value. This allows definitions to be included from - * driver makefiles when required and provides the best future - * compatibility for your project. - * - * Please use spaces instead of tabs in this file. - */ - -#pragma once - -/////////////////////////////////////////////////////////////////////////// -// GFX - Compatibility options // -/////////////////////////////////////////////////////////////////////////// -//#define GFX_COMPAT_V2 GFXON -//#define GFX_COMPAT_OLDCOLORS GFXON - -/////////////////////////////////////////////////////////////////////////// -// GOS - One of these must be defined, preferably in your Makefile // -/////////////////////////////////////////////////////////////////////////// -//#define GFX_USE_OS_CHIBIOS GFXOFF -//#define GFX_USE_OS_FREERTOS GFXOFF -// #define GFX_FREERTOS_USE_TRACE GFXOFF -//#define GFX_USE_OS_WIN32 GFXOFF -//#define GFX_USE_OS_LINUX GFXOFF -//#define GFX_USE_OS_OSX GFXOFF -//#define GFX_USE_OS_ECOS GFXOFF -//#define GFX_USE_OS_RAWRTOS GFXOFF -//#define GFX_USE_OS_ARDUINO GFXOFF -//#define GFX_USE_OS_KEIL GFXOFF -//#define GFX_USE_OS_RTX5 GFXOFF -//#define GFX_USE_OS_CMSIS GFXOFF -//#define GFX_USE_OS_CMSIS2 GFXOFF -//#define GFX_USE_OS_RAW32 GFXOFF -//#define GFX_USE_OS_ZEPHYR GFXOFF -//#define GFX_USE_OS_NIOS GFXOFF -//#define GFX_USE_OS_QT GFXOFF -// #define INTERRUPTS_OFF() optional_code -// #define INTERRUPTS_ON() optional_code - -// Options that (should where relevant) apply to all operating systems -#define GFX_NO_INLINE GFXON -// #define GFX_COMPILER GFX_COMPILER_UNKNOWN -// #define GFX_SHOW_COMPILER GFXOFF -// #define GFX_CPU GFX_CPU_UNKNOWN -// #define GFX_CPU_NO_ALIGNMENT_FAULTS GFXOFF -// #define GFX_CPU_ENDIAN GFX_CPU_ENDIAN_UNKNOWN -// #define GFX_OS_HEAP_SIZE 0 -// #define GFX_OS_NO_INIT GFXOFF -// #define GFX_OS_INIT_NO_WARNING GFXOFF -// #define GFX_OS_PRE_INIT_FUNCTION myHardwareInitRoutine -// #define GFX_OS_EXTRA_INIT_FUNCTION myOSInitRoutine -// #define GFX_OS_EXTRA_DEINIT_FUNCTION myOSDeInitRoutine -// #define GFX_OS_CALL_UGFXMAIN GFXOFF -// #define GFX_OS_UGFXMAIN_STACKSIZE 0 -// #define GFX_EMULATE_MALLOC GFXOFF -// #define GFX_MEM_LT64K GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GDISP // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GDISP GFXON - -//#define GDISP_NEED_AUTOFLUSH GFXOFF -//#define GDISP_NEED_TIMERFLUSH GFXOFF -//#define GDISP_NEED_VALIDATION GFXON -//#define GDISP_NEED_CLIP GFXON -#define GDISP_NEED_CIRCLE GFXON -//#define GDISP_NEED_DUALCIRCLE GFXOFF -#define GDISP_NEED_ELLIPSE GFXON -#define GDISP_NEED_ARC GFXON -#define GDISP_NEED_ARCSECTORS GFXON -#define GDISP_NEED_CONVEX_POLYGON GFXON -//#define GDISP_NEED_SCROLL GFXOFF -#define GDISP_NEED_PIXELREAD GFXON -#define GDISP_NEED_CONTROL GFXON -//#define GDISP_NEED_QUERY GFXOFF -//#define GDISP_NEED_MULTITHREAD GFXOFF -//#define GDISP_NEED_STREAMING GFXOFF -#define GDISP_NEED_TEXT GFXON -// #define GDISP_NEED_TEXT_WORDWRAP GFXOFF -// #define GDISP_NEED_TEXT_BOXPADLR 1 -// #define GDISP_NEED_TEXT_BOXPADTB 1 -// #define GDISP_NEED_ANTIALIAS GFXOFF -// #define GDISP_NEED_UTF8 GFXOFF -#define GDISP_NEED_TEXT_KERNING GFXON -// #define GDISP_INCLUDE_FONT_UI1 GFXOFF -// #define GDISP_INCLUDE_FONT_UI2 GFXOFF // The smallest preferred font. -// #define GDISP_INCLUDE_FONT_LARGENUMBERS GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS10 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS12 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS16 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS20 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS24 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS32 GFXOFF -#define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 GFXON -// #define GDISP_INCLUDE_FONT_FIXED_10X20 GFXOFF -// #define GDISP_INCLUDE_FONT_FIXED_7X14 GFXOFF -#define GDISP_INCLUDE_FONT_FIXED_5X8 GFXON -// #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA GFXOFF -// #define GDISP_INCLUDE_USER_FONTS GFXOFF - -//#define GDISP_NEED_IMAGE GFXOFF -// #define GDISP_NEED_IMAGE_NATIVE GFXOFF -// #define GDISP_NEED_IMAGE_GIF GFXOFF -// #define GDISP_IMAGE_GIF_BLIT_BUFFER_SIZE 32 -// #define GDISP_NEED_IMAGE_BMP GFXOFF -// #define GDISP_NEED_IMAGE_BMP_1 GFXON -// #define GDISP_NEED_IMAGE_BMP_4 GFXON -// #define GDISP_NEED_IMAGE_BMP_4_RLE GFXON -// #define GDISP_NEED_IMAGE_BMP_8 GFXON -// #define GDISP_NEED_IMAGE_BMP_8_RLE GFXON -// #define GDISP_NEED_IMAGE_BMP_16 GFXON -// #define GDISP_NEED_IMAGE_BMP_24 GFXON -// #define GDISP_NEED_IMAGE_BMP_32 GFXON -// #define GDISP_IMAGE_BMP_BLIT_BUFFER_SIZE 32 -// #define GDISP_NEED_IMAGE_JPG GFXOFF -// #define GDISP_NEED_IMAGE_PNG GFXOFF -// #define GDISP_NEED_IMAGE_PNG_INTERLACED GFXOFF -// #define GDISP_NEED_IMAGE_PNG_TRANSPARENCY GFXON -// #define GDISP_NEED_IMAGE_PNG_BACKGROUND GFXON -// #define GDISP_NEED_IMAGE_PNG_ALPHACLIFF 32 -// #define GDISP_NEED_IMAGE_PNG_PALETTE_124 GFXON -// #define GDISP_NEED_IMAGE_PNG_PALETTE_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 GFXON -// #define GDISP_NEED_IMAGE_PNG_RGB_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_RGB_16 GFXON -// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_16 GFXON -// #define GDISP_IMAGE_PNG_BLIT_BUFFER_SIZE 32 -// #define GDISP_IMAGE_PNG_FILE_BUFFER_SIZE 8 -// #define GDISP_IMAGE_PNG_Z_BUFFER_SIZE 32768 -// #define GDISP_NEED_IMAGE_ACCOUNTING GFXOFF - -//#define GDISP_NEED_PIXMAP GFXOFF -// #define GDISP_NEED_PIXMAP_IMAGE GFXOFF - -//#define GDISP_DEFAULT_ORIENTATION gOrientationLandscape // If not defined the native hardware orientation is used. -//#define GDISP_LINEBUF_SIZE 128 -//#define GDISP_STARTUP_COLOR GFX_BLACK -#define GDISP_NEED_STARTUP_LOGO GFXOFF - -//#define GDISP_TOTAL_DISPLAYS 1 - -//#define GDISP_DRIVER_LIST GDISPVMT_Win32, GDISPVMT_Win32 -#ifdef GDISP_DRIVER_LIST -// // For code and speed optimization define as GFXON or GFXOFF if all controllers have the same capability -# define GDISP_HARDWARE_STREAM_WRITE GFXOFF -# define GDISP_HARDWARE_STREAM_READ GFXOFF -# define GDISP_HARDWARE_STREAM_POS GFXOFF -# define GDISP_HARDWARE_DRAWPIXEL GFXON -# define GDISP_HARDWARE_CLEARS GFXOFF -# define GDISP_HARDWARE_FILLS GFXOFF -//#define GDISP_HARDWARE_BITFILLS GFXOFF -# define GDISP_HARDWARE_SCROLL GFXOFF -# define GDISP_HARDWARE_PIXELREAD GFXON -# define GDISP_HARDWARE_CONTROL GFXON -# define GDISP_HARDWARE_QUERY GFXOFF -# define GDISP_HARDWARE_CLIP GFXOFF - -# define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 -#endif - -#define GDISP_USE_GFXNET GFXOFF -// #define GDISP_GFXNET_PORT 13001 -// #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP GFXOFF -// #define GDISP_DONT_WAIT_FOR_NET_DISPLAY GFXOFF -// #define GDISP_GFXNET_UNSAFE_SOCKETS GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GWIN // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GWIN GFXOFF - -//#define GWIN_NEED_WINDOWMANAGER GFXOFF -// #define GWIN_REDRAW_IMMEDIATE GFXOFF -// #define GWIN_REDRAW_SINGLEOP GFXOFF -// #define GWIN_NEED_FLASHING GFXOFF -// #define GWIN_FLASHING_PERIOD 250 - -//#define GWIN_NEED_CONSOLE GFXOFF -// #define GWIN_CONSOLE_USE_HISTORY GFXOFF -// #define GWIN_CONSOLE_HISTORY_AVERAGING GFXOFF -// #define GWIN_CONSOLE_HISTORY_ATCREATE GFXOFF -// #define GWIN_CONSOLE_ESCSEQ GFXOFF -// #define GWIN_CONSOLE_USE_BASESTREAM GFXOFF -// #define GWIN_CONSOLE_USE_FLOAT GFXOFF -//#define GWIN_NEED_GRAPH GFXOFF -//#define GWIN_NEED_GL3D GFXOFF - -//#define GWIN_NEED_WIDGET GFXOFF -//#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1 -// #define GWIN_NEED_LABEL GFXOFF -// #define GWIN_LABEL_ATTRIBUTE GFXOFF -// #define GWIN_NEED_BUTTON GFXOFF -// #define GWIN_BUTTON_LAZY_RELEASE GFXOFF -// #define GWIN_NEED_SLIDER GFXOFF -// #define GWIN_SLIDER_NOSNAP GFXOFF -// #define GWIN_SLIDER_DEAD_BAND 5 -// #define GWIN_SLIDER_TOGGLE_INC 20 -// #define GWIN_NEED_CHECKBOX GFXOFF -// #define GWIN_NEED_IMAGE GFXOFF -// #define GWIN_NEED_IMAGE_ANIMATION GFXOFF -// #define GWIN_NEED_RADIO GFXOFF -// #define GWIN_NEED_LIST GFXOFF -// #define GWIN_NEED_LIST_IMAGES GFXOFF -// #define GWIN_NEED_PROGRESSBAR GFXOFF -// #define GWIN_PROGRESSBAR_AUTO GFXOFF -// #define GWIN_NEED_KEYBOARD GFXOFF -// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1 -// #define GWIN_NEED_KEYBOARD_ENGLISH1 GFXON -// #define GWIN_NEED_TEXTEDIT GFXOFF -// #define GWIN_FLAT_STYLING GFXOFF -// #define GWIN_WIDGET_TAGS GFXOFF - -//#define GWIN_NEED_CONTAINERS GFXOFF -// #define GWIN_NEED_CONTAINER GFXOFF -// #define GWIN_NEED_FRAME GFXOFF -// #define GWIN_NEED_TABSET GFXOFF -// #define GWIN_TABSET_TABHEIGHT 18 - -/////////////////////////////////////////////////////////////////////////// -// GTRANS // -/////////////////////////////////////////////////////////////////////////// -//#define GFX_USE_GTRANS GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GEVENT // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GEVENT GFXON - -//#define GEVENT_ASSERT_NO_RESOURCE GFXOFF -//#define GEVENT_MAXIMUM_SIZE 32 -//#define GEVENT_MAX_SOURCE_LISTENERS 32 - -/////////////////////////////////////////////////////////////////////////// -// GTIMER // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GTIMER GFXOFF - -//#define GTIMER_THREAD_PRIORITY gThreadpriorityHigh -//#define GTIMER_THREAD_WORKAREA_SIZE 2048 - -/////////////////////////////////////////////////////////////////////////// -// GQUEUE // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GQUEUE GFXOFF - -//#define GQUEUE_NEED_ASYNC GFXOFF -//#define GQUEUE_NEED_GSYNC GFXOFF -//#define GQUEUE_NEED_FSYNC GFXOFF -//#define GQUEUE_NEED_BUFFERS GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GINPUT // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GINPUT GFXOFF - -//#define GINPUT_NEED_MOUSE GFXOFF -// #define GINPUT_TOUCH_STARTRAW GFXOFF -// #define GINPUT_TOUCH_NOTOUCH GFXOFF -// #define GINPUT_TOUCH_NOCALIBRATE GFXOFF -// #define GINPUT_TOUCH_NOCALIBRATE_GUI GFXOFF -// #define GINPUT_MOUSE_POLL_PERIOD 25 -// #define GINPUT_MOUSE_CLICK_TIME 300 -// #define GINPUT_TOUCH_CXTCLICK_TIME 700 -// #define GINPUT_TOUCH_USER_CALIBRATION_LOAD GFXOFF -// #define GINPUT_TOUCH_USER_CALIBRATION_SAVE GFXOFF -// #define GMOUSE_DRIVER_LIST GMOUSEVMT_Win32, GMOUSEVMT_Win32 -// #define GINPUT_TOUCH_CALIBRATION_FONT1 "* Double" -// #define GINPUT_TOUCH_CALIBRATION_FONT2 "* Narrow" -// #define GINPUT_TOUCH_CALIBRATION_TITLE "Calibration" -// #define GINPUT_TOUCH_CALIBRATION_ERROR "Calibration Failed!" -//#define GINPUT_NEED_KEYBOARD GFXOFF -// #define GINPUT_KEYBOARD_POLL_PERIOD 200 -// #define GKEYBOARD_DRIVER_LIST GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32 -// #define GKEYBOARD_LAYOUT_OFF GFXOFF -// #define GKEYBOARD_LAYOUT_SCANCODE2_US GFXOFF -//#define GINPUT_NEED_TOGGLE GFXOFF -//#define GINPUT_NEED_DIAL GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GFILE // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GFILE GFXOFF - -//#define GFILE_NEED_PRINTG GFXOFF -//#define GFILE_NEED_SCANG GFXOFF -//#define GFILE_NEED_STRINGS GFXOFF -//#define GFILE_NEED_FILELISTS GFXOFF -//#define GFILE_NEED_STDIO GFXOFF -//#define GFILE_NEED_NOAUTOMOUNT GFXOFF -//#define GFILE_NEED_NOAUTOSYNC GFXOFF - -//#define GFILE_NEED_MEMFS GFXOFF -//#define GFILE_NEED_ROMFS GFXOFF -//#define GFILE_NEED_RAMFS GFXOFF -//#define GFILE_NEED_FATFS GFXOFF -//#define GFILE_NEED_NATIVEFS GFXOFF -//#define GFILE_NEED_CHBIOSFS GFXOFF -//#define GFILE_NEED_USERFS GFXOFF - -//#define GFILE_ALLOW_FLOATS GFXOFF -//#define GFILE_ALLOW_DEVICESPECIFIC GFXOFF -//#define GFILE_MAX_GFILES 3 - -/////////////////////////////////////////////////////////////////////////// -// GADC // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GADC GFXOFF -// #define GADC_MAX_LOWSPEED_DEVICES 4 - -/////////////////////////////////////////////////////////////////////////// -// GAUDIO // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GAUDIO GFXOFF -// #define GAUDIO_NEED_PLAY GFXOFF -// #define GAUDIO_NEED_RECORD GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GMISC // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GMISC GFXON - -//#define GMISC_NEED_ARRAYOPS GFXOFF -//#define GMISC_NEED_FASTTRIG GFXOFF -//#define GMISC_NEED_FIXEDTRIG GFXOFF -//#define GMISC_NEED_INVSQRT GFXOFF -// #define GMISC_INVSQRT_MIXED_ENDIAN GFXOFF -// #define GMISC_INVSQRT_REAL_SLOW GFXOFF -#define GMISC_NEED_MATRIXFLOAT2D GFXON -#define GMISC_NEED_MATRIXFIXED2D GFXOFF -//#define GMISC_NEED_HITTEST_POLY GFXOFF diff --git a/quantum/visualizer/default_animations.c b/quantum/visualizer/default_animations.c deleted file mode 100644 index 2f43c67cc8..0000000000 --- a/quantum/visualizer/default_animations.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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/>. - */ - -#if defined(VISUALIZER_ENABLE) - -# include "default_animations.h" -# include "visualizer.h" -# ifdef LCD_ENABLE -# include "lcd_keyframes.h" -# endif -# ifdef LCD_BACKLIGHT_ENABLE -# include "lcd_backlight_keyframes.h" -# endif - -# ifdef BACKLIGHT_ENABLE -# include "led_backlight_keyframes.h" -# endif - -# include "visualizer_keyframes.h" - -# if defined(LCD_ENABLE) || defined(LCD_BACKLIGHT_ENABLE) || defined(BACKLIGHT_ENABLE) - -static bool keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { -# ifdef LCD_ENABLE - lcd_keyframe_enable(animation, state); -# endif -# ifdef LCD_BACKLIGHT_ENABLE - lcd_backlight_keyframe_enable(animation, state); -# endif -# ifdef BACKLIGHT_ENABLE - led_backlight_keyframe_enable(animation, state); -# endif - return false; -} - -static bool keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { -# ifdef LCD_ENABLE - lcd_keyframe_disable(animation, state); -# endif -# ifdef LCD_BACKLIGHT_ENABLE - lcd_backlight_keyframe_disable(animation, state); -# endif -# ifdef BACKLIGHT_ENABLE - led_backlight_keyframe_disable(animation, state); -# endif - return false; -} - -static bool keyframe_fade_in(keyframe_animation_t* animation, visualizer_state_t* state) { - bool ret = false; -# ifdef LCD_BACKLIGHT_ENABLE - ret |= lcd_backlight_keyframe_animate_color(animation, state); -# endif -# ifdef BACKLIGHT_ENABLE - ret |= led_backlight_keyframe_fade_in_all(animation, state); -# endif - return ret; -} - -static bool keyframe_fade_out(keyframe_animation_t* animation, visualizer_state_t* state) { - bool ret = false; -# ifdef LCD_BACKLIGHT_ENABLE - ret |= lcd_backlight_keyframe_animate_color(animation, state); -# endif -# ifdef BACKLIGHT_ENABLE - ret |= led_backlight_keyframe_fade_out_all(animation, state); -# endif - return ret; -} - -// Don't worry, if the startup animation is long, you can use the keyboard like normal -// during that time -keyframe_animation_t default_startup_animation = { -# if LCD_ENABLE - .num_frames = 3, -# else - .num_frames = 2, -# endif - .loop = false, - .frame_lengths = {0, -# if LCD_ENABLE - 0, -# endif - gfxMillisecondsToTicks(5000)}, - .frame_functions = - { - keyframe_enable, -# if LCD_ENABLE - lcd_keyframe_draw_logo, -# endif - keyframe_fade_in, - }, -}; - -keyframe_animation_t default_suspend_animation = { -# if LCD_ENABLE - .num_frames = 3, -# else - .num_frames = 2, -# endif - .loop = false, - .frame_lengths = - { -# if LCD_ENABLE - 0, -# endif - gfxMillisecondsToTicks(1000), 0}, - .frame_functions = - { -# if LCD_ENABLE - lcd_keyframe_display_layer_text, -# endif - keyframe_fade_out, - keyframe_disable, - }, -}; -# endif - -# if defined(BACKLIGHT_ENABLE) -# define CROSSFADE_TIME 1000 -# define GRADIENT_TIME 3000 - -keyframe_animation_t led_test_animation = { - .num_frames = 14, - .loop = true, - .frame_lengths = - { - gfxMillisecondsToTicks(1000), // fade in - gfxMillisecondsToTicks(1000), // no op (leds on) - gfxMillisecondsToTicks(1000), // fade out - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - gfxMillisecondsToTicks(GRADIENT_TIME), // left to rigt (outside in) - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom - 0, // mirror leds - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - gfxMillisecondsToTicks(GRADIENT_TIME), // left_to_right (mirrored, so inside out) - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom - 0, // normal leds - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - - }, - .frame_functions = - { - led_backlight_keyframe_fade_in_all, - keyframe_no_operation, - led_backlight_keyframe_fade_out_all, - led_backlight_keyframe_crossfade, - led_backlight_keyframe_left_to_right_gradient, - led_backlight_keyframe_crossfade, - led_backlight_keyframe_top_to_bottom_gradient, - led_backlight_keyframe_mirror_orientation, - led_backlight_keyframe_crossfade, - led_backlight_keyframe_left_to_right_gradient, - led_backlight_keyframe_crossfade, - led_backlight_keyframe_top_to_bottom_gradient, - led_backlight_keyframe_normal_orientation, - led_backlight_keyframe_crossfade, - }, -}; -# endif - -#endif diff --git a/quantum/visualizer/default_animations.h b/quantum/visualizer/default_animations.h deleted file mode 100644 index 9accd89774..0000000000 --- a/quantum/visualizer/default_animations.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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 "visualizer.h" - -// You can use these default animations, but of course you can also write your own custom ones instead -extern keyframe_animation_t default_startup_animation; -extern keyframe_animation_t default_suspend_animation; - -// An animation for testing and demonstrating the led support, should probably not be used for real world -// cases -extern keyframe_animation_t led_test_animation; diff --git a/quantum/visualizer/lcd_backlight.c b/quantum/visualizer/lcd_backlight.c deleted file mode 100644 index 23978974e3..0000000000 --- a/quantum/visualizer/lcd_backlight.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "lcd_backlight.h" -#include <math.h> - -static uint8_t current_hue = 0; -static uint8_t current_saturation = 0; -static uint8_t current_intensity = 0; -static uint8_t current_brightness = 0; - -void lcd_backlight_init(void) { - lcd_backlight_hal_init(); - lcd_backlight_color(current_hue, current_saturation, current_intensity); -} - -// This code is based on Brian Neltner's blogpost and example code -// "Why every LED light should be using HSI colorspace". -// http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi -static void hsi_to_rgb(float h, float s, float i, uint16_t* r_out, uint16_t* g_out, uint16_t* b_out) { - unsigned int r, g, b; - h = fmodf(h, 360.0f); // cycle h around to 0-360 degrees - h = 3.14159f * h / 180.0f; // Convert to radians. - s = s > 0.0f ? (s < 1.0f ? s : 1.0f) : 0.0f; // clamp s and i to interval [0,1] - i = i > 0.0f ? (i < 1.0f ? i : 1.0f) : 0.0f; - - // Math! Thanks in part to Kyle Miller. - if (h < 2.09439f) { - r = 65535.0f * i / 3.0f * (1.0f + s * cos(h) / cosf(1.047196667f - h)); - g = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cos(1.047196667f - h))); - b = 65535.0f * i / 3.0f * (1.0f - s); - } else if (h < 4.188787) { - h = h - 2.09439; - g = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h)); - b = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h))); - r = 65535.0f * i / 3.0f * (1.0f - s); - } else { - h = h - 4.188787; - b = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h)); - r = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h))); - g = 65535.0f * i / 3.0f * (1.0f - s); - } - *r_out = r > 65535 ? 65535 : r; - *g_out = g > 65535 ? 65535 : g; - *b_out = b > 65535 ? 65535 : b; -} - -void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity) { - uint16_t r, g, b; - float hue_f = 360.0f * (float)hue / 255.0f; - float saturation_f = (float)saturation / 255.0f; - float intensity_f = (float)intensity / 255.0f; - intensity_f *= (float)current_brightness / 255.0f; - hsi_to_rgb(hue_f, saturation_f, intensity_f, &r, &g, &b); - current_hue = hue; - current_saturation = saturation; - current_intensity = intensity; - lcd_backlight_hal_color(r, g, b); -} - -void lcd_backlight_brightness(uint8_t b) { - current_brightness = b; - lcd_backlight_color(current_hue, current_saturation, current_intensity); -} - -uint8_t lcd_get_backlight_brightness(void) { return current_brightness; } diff --git a/quantum/visualizer/lcd_backlight.h b/quantum/visualizer/lcd_backlight.h deleted file mode 100644 index 4ea5b14639..0000000000 --- a/quantum/visualizer/lcd_backlight.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include <stdint.h> - -// Helper macros for storing hue, staturation and intensity as unsigned integers -#define LCD_COLOR(hue, saturation, intensity) (hue << 16 | saturation << 8 | intensity) -#define LCD_HUE(color) ((color >> 16) & 0xFF) -#define LCD_SAT(color) ((color >> 8) & 0xFF) -#define LCD_INT(color) (color & 0xFF) - -static inline uint32_t change_lcd_color_intensity(uint32_t color, uint8_t new_intensity) { return (color & 0xFFFFFF00) | new_intensity; } - -void lcd_backlight_init(void); -void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity); -void lcd_backlight_brightness(uint8_t b); -uint8_t lcd_get_backlight_brightness(void); - -void lcd_backlight_hal_init(void); -void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b); diff --git a/quantum/visualizer/lcd_backlight_keyframes.c b/quantum/visualizer/lcd_backlight_keyframes.c deleted file mode 100644 index c13cce311d..0000000000 --- a/quantum/visualizer/lcd_backlight_keyframes.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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 "lcd_backlight_keyframes.h" - -bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state) { - int frame_length = animation->frame_lengths[animation->current_frame]; - int current_pos = frame_length - animation->time_left_in_frame; - uint8_t t_h = LCD_HUE(state->target_lcd_color); - uint8_t t_s = LCD_SAT(state->target_lcd_color); - uint8_t t_i = LCD_INT(state->target_lcd_color); - uint8_t p_h = LCD_HUE(state->prev_lcd_color); - uint8_t p_s = LCD_SAT(state->prev_lcd_color); - uint8_t p_i = LCD_INT(state->prev_lcd_color); - - uint8_t d_h1 = t_h - p_h; // Modulo arithmetic since we want to wrap around - int d_h2 = t_h - p_h; - // Chose the shortest way around - int d_h = abs(d_h2) < d_h1 ? d_h2 : d_h1; - int d_s = t_s - p_s; - int d_i = t_i - p_i; - - int hue = (d_h * current_pos) / frame_length; - int sat = (d_s * current_pos) / frame_length; - int intensity = (d_i * current_pos) / frame_length; - // dprintf("%X -> %X = %X\n", p_h, t_h, hue); - hue += p_h; - sat += p_s; - intensity += p_i; - state->current_lcd_color = LCD_COLOR(hue, sat, intensity); - lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color)); - - return true; -} - -bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - state->prev_lcd_color = state->target_lcd_color; - state->current_lcd_color = state->target_lcd_color; - lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color)); - return false; -} - -bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - lcd_backlight_hal_color(0, 0, 0); - return false; -} - -bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color)); - return false; -} diff --git a/quantum/visualizer/lcd_backlight_keyframes.h b/quantum/visualizer/lcd_backlight_keyframes.h deleted file mode 100644 index 88768dd4a5..0000000000 --- a/quantum/visualizer/lcd_backlight_keyframes.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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 "visualizer.h" - -// Animates the LCD backlight color between the current color and the target color (of the state) -bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state); -// Sets the backlight color to the target color -bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state); - -bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); -bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); diff --git a/quantum/visualizer/lcd_keyframes.c b/quantum/visualizer/lcd_keyframes.c deleted file mode 100644 index 1d6f3dca18..0000000000 --- a/quantum/visualizer/lcd_keyframes.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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 "lcd_keyframes.h" -#include <string.h> -#include "action_util.h" -#include "led.h" -#include "resources/resources.h" - -bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - gdispClear(White); - gdispDrawString(0, 10, state->layer_text, state->font_dejavusansbold12, Black); - return false; -} - -static void format_layer_bitmap_string(uint16_t default_layer, uint16_t layer, char* buffer) { - for (int i = 0; i < 16; i++) { - uint32_t mask = (1u << i); - if (default_layer & mask) { - if (layer & mask) { - *buffer = 'B'; - } else { - *buffer = 'D'; - } - } else if (layer & mask) { - *buffer = '1'; - } else { - *buffer = '0'; - } - ++buffer; - - if (i == 3 || i == 7 || i == 11) { - *buffer = ' '; - ++buffer; - } - } - *buffer = 0; -} - -bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - const char* layer_help = "1=On D=Default B=Both"; - char layer_buffer[16 + 4]; // 3 spaces and one null terminator - gdispClear(White); - gdispDrawString(0, 0, layer_help, state->font_fixed5x8, Black); - format_layer_bitmap_string(state->status.default_layer, state->status.layer, layer_buffer); - gdispDrawString(0, 10, layer_buffer, state->font_fixed5x8, Black); - format_layer_bitmap_string(state->status.default_layer >> 16, state->status.layer >> 16, layer_buffer); - gdispDrawString(0, 20, layer_buffer, state->font_fixed5x8, Black); - return false; -} - -static void format_mods_bitmap_string(uint8_t mods, char* buffer) { - *buffer = ' '; - ++buffer; - - for (int i = 0; i < 8; i++) { - uint32_t mask = (1u << i); - if (mods & mask) { - *buffer = '1'; - } else { - *buffer = '0'; - } - ++buffer; - - if (i == 3) { - *buffer = ' '; - ++buffer; - } - } - *buffer = 0; -} - -bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - - const char* title = "Modifier states"; - const char* mods_header = " CSAG CSAG "; - char status_buffer[12]; - - gdispClear(White); - gdispDrawString(0, 0, title, state->font_fixed5x8, Black); - gdispDrawString(0, 10, mods_header, state->font_fixed5x8, Black); - format_mods_bitmap_string(state->status.mods, status_buffer); - gdispDrawString(0, 20, status_buffer, state->font_fixed5x8, Black); - - return false; -} - -#define LED_STATE_STRING_SIZE sizeof("NUM CAPS SCRL COMP KANA") - -static void get_led_state_string(char* output, visualizer_state_t* state) { - uint8_t pos = 0; - - if (state->status.leds & (1u << USB_LED_NUM_LOCK)) { - memcpy(output + pos, "NUM ", 4); - pos += 4; - } - if (state->status.leds & (1u << USB_LED_CAPS_LOCK)) { - memcpy(output + pos, "CAPS ", 5); - pos += 5; - } - if (state->status.leds & (1u << USB_LED_SCROLL_LOCK)) { - memcpy(output + pos, "SCRL ", 5); - pos += 5; - } - if (state->status.leds & (1u << USB_LED_COMPOSE)) { - memcpy(output + pos, "COMP ", 5); - pos += 5; - } - if (state->status.leds & (1u << USB_LED_KANA)) { - memcpy(output + pos, "KANA", 4); - pos += 4; - } - output[pos] = 0; -} - -bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - char output[LED_STATE_STRING_SIZE]; - get_led_state_string(output, state); - gdispClear(White); - gdispDrawString(0, 10, output, state->font_dejavusansbold12, Black); - return false; -} - -bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - gdispClear(White); - uint8_t y = 10; - if (state->status.leds) { - char output[LED_STATE_STRING_SIZE]; - get_led_state_string(output, state); - gdispDrawString(0, 1, output, state->font_dejavusansbold12, Black); - y = 17; - } - gdispDrawString(0, y, state->layer_text, state->font_dejavusansbold12, Black); - return false; -} - -bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - // Read the uGFX documentation for information how to use the displays - // http://wiki.ugfx.org/index.php/Main_Page - gdispClear(Black); - - // You can use static variables for things that can't be found in the animation - // or state structs, here we use the image - - // gdispGBlitArea is a tricky function to use since it supports blitting part of the image - // if you have full screen image, then just use LCD_WIDTH and LCD_HEIGHT for both source and target dimensions - gdispGBlitArea(GDISP, 0, 0, 128, 32, 0, 0, LCD_WIDTH, (pixel_t*)resource_lcd_logo); - - return false; -} - -bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - gdispSetPowerMode(powerOff); - return false; -} - -bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - gdispSetPowerMode(powerOn); - return false; -} diff --git a/quantum/visualizer/lcd_keyframes.h b/quantum/visualizer/lcd_keyframes.h deleted file mode 100644 index b7125e8323..0000000000 --- a/quantum/visualizer/lcd_keyframes.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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 "visualizer.h" - -// Displays the layer text centered vertically on the screen -bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays a bitmap (0/1) of all the currently active layers -bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays a bitmap (0/1) of all the currently active mods -bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays the keyboard led states (CAPS (Caps lock), NUM (Num lock), SCRL (Scroll lock), COMP (Compose), KANA) -bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays both the layer text and the led states -bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays the QMK logo on the LCD screen -bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state); - -bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); -bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); diff --git a/quantum/visualizer/led_backlight_keyframes.c b/quantum/visualizer/led_backlight_keyframes.c deleted file mode 100644 index 338ada5227..0000000000 --- a/quantum/visualizer/led_backlight_keyframes.c +++ /dev/null @@ -1,143 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -#include "gfx.h" -#include <math.h> -#include "led_backlight_keyframes.h" - -static uint8_t fade_led_color(keyframe_animation_t* animation, int from, int to) { - int frame_length = animation->frame_lengths[animation->current_frame]; - int current_pos = frame_length - animation->time_left_in_frame; - int delta = to - from; - int luma = (delta * current_pos) / frame_length; - luma += from; - return luma; -} - -static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint8_t from, uint8_t to) { - uint8_t luma = fade_led_color(animation, from, to); - color_t color = LUMA2COLOR(luma); - gdispGClear(LED_DISPLAY, color); -} - -// TODO: Should be customizable per keyboard -#define NUM_ROWS LED_HEIGHT -#define NUM_COLS LED_WIDTH - -static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS]; -static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS]; - -static uint8_t compute_gradient_color(float t, float index, float num) { - const float two_pi = M_PI * 2.0f; - float normalized_index = (1.0f - index / (num - 1.0f)) * two_pi; - float x = t * two_pi + normalized_index; - float v = 0.5 * (cosf(x) + 1.0f); - return (uint8_t)(255.0f * v); -} - -bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - keyframe_fade_all_leds_from_to(animation, 0, 255); - return true; -} - -bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - keyframe_fade_all_leds_from_to(animation, 255, 0); - return true; -} - -bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - float frame_length = animation->frame_lengths[animation->current_frame]; - float current_pos = frame_length - animation->time_left_in_frame; - float t = current_pos / frame_length; - for (int i = 0; i < NUM_COLS; i++) { - uint8_t color = compute_gradient_color(t, i, NUM_COLS); - gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color)); - } - return true; -} - -bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - float frame_length = animation->frame_lengths[animation->current_frame]; - float current_pos = frame_length - animation->time_left_in_frame; - float t = current_pos / frame_length; - for (int i = 0; i < NUM_ROWS; i++) { - uint8_t color = compute_gradient_color(t, i, NUM_ROWS); - gdispGDrawLine(LED_DISPLAY, 0, i, NUM_COLS - 1, i, LUMA2COLOR(color)); - } - return true; -} - -static void copy_current_led_state(uint8_t* dest) { - for (int i = 0; i < NUM_ROWS; i++) { - for (int j = 0; j < NUM_COLS; j++) { - dest[i * NUM_COLS + j] = gdispGGetPixelColor(LED_DISPLAY, j, i); - } - } -} -bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - if (animation->first_update_of_frame) { - copy_current_led_state(&crossfade_start_frame[0][0]); - run_next_keyframe(animation, state); - copy_current_led_state(&crossfade_end_frame[0][0]); - } - for (int i = 0; i < NUM_ROWS; i++) { - for (int j = 0; j < NUM_COLS; j++) { - color_t color = LUMA2COLOR(fade_led_color(animation, crossfade_start_frame[i][j], crossfade_end_frame[i][j])); - gdispGDrawPixel(LED_DISPLAY, j, i, color); - } - } - return true; -} - -bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180); - return false; -} - -bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0); - return false; -} - -bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - gdispGSetPowerMode(LED_DISPLAY, powerOff); - return false; -} - -bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - gdispGSetPowerMode(LED_DISPLAY, powerOn); - return false; -} diff --git a/quantum/visualizer/led_backlight_keyframes.h b/quantum/visualizer/led_backlight_keyframes.h deleted file mode 100644 index 90153be5eb..0000000000 --- a/quantum/visualizer/led_backlight_keyframes.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include "visualizer.h" - -bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state); - -bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); - -extern keyframe_animation_t led_test_animation; diff --git a/quantum/visualizer/readme.md b/quantum/visualizer/readme.md deleted file mode 100644 index 298efb742f..0000000000 --- a/quantum/visualizer/readme.md +++ /dev/null @@ -1,18 +0,0 @@ -# A visualization library for the TMK keyboard firmware - -This library is designed to work together with the [TMK keyboard firmware](https://github.com/tmk/tmk_keyboard). Currently it only works for [Chibios](http://www.chibios.org/) - flavors, but it would be possible to add support for other configurations as well. The LCD display functionality is provided by the [uGFX library](https://ugfx.io/). - -## To use this library as a user -You can and should modify the visualizer\_user.c file. Check the comments in the file for more information. - -## To add this library to custom keyboard projects - -1. Add tmk_visualizer as a submodule to your project -1. Set VISUALIZER_DIR in the main keyboard project makefile to point to the submodule -1. Define LCD\_ENABLE and/or LCD\_BACKLIGHT\_ENABLE, to enable support -1. Include the visualizer.mk make file -1. Copy the files in the example\_integration folder to your keyboard project -1. All other files than the callback.c file are included automatically, so you will need to add callback.c to your makefile manually. If you already have a similar file in your project, you can just copy the functions instead of the whole file. -1. Edit the files to match your hardware. You might might want to read the Chibios and UGfx documentation, for more information. -1. If you enable LCD support you might also have to write a custom uGFX display driver, check the uGFX documentation for that. You probably also want to enable SPI support in your Chibios configuration. diff --git a/quantum/visualizer/resources/lcd_logo.c b/quantum/visualizer/resources/lcd_logo.c deleted file mode 100644 index 13bf734cb3..0000000000 --- a/quantum/visualizer/resources/lcd_logo.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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 "resources.h" - -// clang-format off - -// To generate an image array like this -// Ensure the image is 128 x 32 or smaller -// Convert the bitmap to a C array using a program like http://www.riuson.com/lcd-image-converter/ -// Ensure the the conversion process produces a monochrome format array - 1 bit/pixel, left to right, top to bottom -// Update array in the source code with the C array produced by the conversion program - -// The image below is generated from lcd_logo.png -__attribute__((weak)) const uint8_t resource_lcd_logo[512] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0xEE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xEE, 0xF0, 0x01, 0xC6, 0x0D, 0x8C, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0xEE, 0xFE, 0x03, 0xE7, 0x1D, 0x9C, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x37, 0x1D, 0xB8, 0x18, 0x0B, 0x59, 0xC8, 0x09, 0xE5, 0x9E, 0x00, - 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x37, 0xBD, 0xF0, 0x18, 0x6F, 0x7F, 0xEC, 0x9B, 0x37, 0xB3, 0x00, 0x00, 0xFE, 0xEE, 0xFE, 0x06, 0x37, 0xBD, 0xE0, 0x1F, 0x6C, 0x66, 0x6D, 0xD8, 0x36, 0x33, 0x00, - 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x36, 0xED, 0xF0, 0x1F, 0x6C, 0x66, 0x6D, 0x59, 0xF6, 0x3E, 0x00, 0x00, 0x1F, 0x6D, 0xF0, 0x06, 0x36, 0xED, 0xB8, 0x18, 0x6C, 0x66, 0x67, 0x73, 0x36, 0x30, 0x00, - 0x00, 0xFF, 0x83, 0xFE, 0x03, 0xE6, 0x4D, 0x9C, 0x18, 0x6C, 0x66, 0x67, 0x73, 0x36, 0x1F, 0x00, 0x00, 0x1F, 0xEF, 0xF0, 0x01, 0xC6, 0x0D, 0x8C, 0x18, 0x6C, 0x66, 0x62, 0x21, 0xD6, 0x0E, 0x00, - 0x00, 0xFF, 0xEF, 0xFE, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; diff --git a/quantum/visualizer/resources/lcd_logo.png b/quantum/visualizer/resources/lcd_logo.png Binary files differdeleted file mode 100644 index 178ef65f15..0000000000 --- a/quantum/visualizer/resources/lcd_logo.png +++ /dev/null diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c deleted file mode 100644 index 709affbb77..0000000000 --- a/quantum/visualizer/visualizer.c +++ /dev/null @@ -1,483 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "config.h" -#include "visualizer.h" -#include <string.h> -#ifdef PROTOCOL_CHIBIOS -# include <ch.h> -#endif - -#include "gfx.h" - -#ifdef LCD_BACKLIGHT_ENABLE -# include "lcd_backlight.h" -#endif - -//#define DEBUG_VISUALIZER - -#ifdef DEBUG_VISUALIZER -# include "debug.h" -#else -# include "nodebug.h" -#endif - -#ifdef SERIAL_LINK_ENABLE -# include "serial_link/protocol/transport.h" -# include "serial_link/system/serial_link.h" -#endif - -#include "action_util.h" - -// Define this in config.h -#ifndef VISUALIZER_THREAD_PRIORITY -// The visualizer needs gfx thread priorities -# define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2) -#endif - -static visualizer_keyboard_status_t current_status = {.layer = 0xFFFFFFFF, - .default_layer = 0xFFFFFFFF, - .leds = 0xFFFFFFFF, -#ifdef BACKLIGHT_ENABLE - .backlight_level = 0, -#endif - .mods = 0xFF, - .suspended = false, -#ifdef VISUALIZER_USER_DATA_SIZE - .user_data = {0} -#endif -}; - -static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { - return status1->layer == status2->layer && status1->default_layer == status2->default_layer && status1->mods == status2->mods && status1->leds == status2->leds && status1->suspended == status2->suspended -#ifdef BACKLIGHT_ENABLE - && status1->backlight_level == status2->backlight_level -#endif -#ifdef VISUALIZER_USER_DATA_SIZE - && memcmp(status1->user_data, status2->user_data, VISUALIZER_USER_DATA_SIZE) == 0 -#endif - ; -} - -static bool visualizer_enabled = false; - -#ifdef VISUALIZER_USER_DATA_SIZE -static uint8_t user_data[VISUALIZER_USER_DATA_SIZE]; -#endif - -#define MAX_SIMULTANEOUS_ANIMATIONS 4 -static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {}; - -#ifdef SERIAL_LINK_ENABLE -MASTER_TO_ALL_SLAVES_OBJECT(current_status, visualizer_keyboard_status_t); - -static remote_object_t* remote_objects[] = { - REMOTE_OBJECT(current_status), -}; - -#endif - -GDisplay* LCD_DISPLAY = 0; -GDisplay* LED_DISPLAY = 0; - -#ifdef LCD_DISPLAY_NUMBER -__attribute__((weak)) GDisplay* get_lcd_display(void) { return gdispGetDisplay(LCD_DISPLAY_NUMBER); } -#endif - -#ifdef LED_DISPLAY_NUMBER -__attribute__((weak)) GDisplay* get_led_display(void) { return gdispGetDisplay(LED_DISPLAY_NUMBER); } -#endif - -void start_keyframe_animation(keyframe_animation_t* animation) { - animation->current_frame = -1; - animation->time_left_in_frame = 0; - animation->need_update = true; - int free_index = -1; - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - if (animations[i] == animation) { - return; - } - if (free_index == -1 && animations[i] == NULL) { - free_index = i; - } - } - if (free_index != -1) { - animations[free_index] = animation; - } -} - -void stop_keyframe_animation(keyframe_animation_t* animation) { - animation->current_frame = animation->num_frames; - animation->time_left_in_frame = 0; - animation->need_update = true; - animation->first_update_of_frame = false; - animation->last_update_of_frame = false; - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - if (animations[i] == animation) { - animations[i] = NULL; - return; - } - } -} - -void stop_all_keyframe_animations(void) { - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - if (animations[i]) { - animations[i]->current_frame = animations[i]->num_frames; - animations[i]->time_left_in_frame = 0; - animations[i]->need_update = true; - animations[i]->first_update_of_frame = false; - animations[i]->last_update_of_frame = false; - animations[i] = NULL; - } - } -} - -static uint8_t get_num_running_animations(void) { - uint8_t count = 0; - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - count += animations[i] ? 1 : 0; - } - return count; -} - -static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systemticks_t delta, systemticks_t* sleep_time) { - // TODO: Clean up this messy code - dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, animation->time_left_in_frame, delta); - if (animation->current_frame == animation->num_frames) { - animation->need_update = false; - return false; - } - if (animation->current_frame == -1) { - animation->current_frame = 0; - animation->time_left_in_frame = animation->frame_lengths[0]; - animation->need_update = true; - animation->first_update_of_frame = true; - } else { - animation->time_left_in_frame -= delta; - while (animation->time_left_in_frame <= 0) { - int left = animation->time_left_in_frame; - if (animation->need_update) { - animation->time_left_in_frame = 0; - animation->last_update_of_frame = true; - (*animation->frame_functions[animation->current_frame])(animation, state); - animation->last_update_of_frame = false; - } - animation->current_frame++; - animation->need_update = true; - animation->first_update_of_frame = true; - if (animation->current_frame == animation->num_frames) { - if (animation->loop) { - animation->current_frame = 0; - } else { - stop_keyframe_animation(animation); - return false; - } - } - delta = -left; - animation->time_left_in_frame = animation->frame_lengths[animation->current_frame]; - animation->time_left_in_frame -= delta; - } - } - if (animation->need_update) { - animation->need_update = (*animation->frame_functions[animation->current_frame])(animation, state); - animation->first_update_of_frame = false; - } - - systemticks_t wanted_sleep = animation->need_update ? gfxMillisecondsToTicks(10) : (unsigned)animation->time_left_in_frame; - if (wanted_sleep < *sleep_time) { - *sleep_time = wanted_sleep; - } - - return true; -} - -void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state) { - int next_frame = animation->current_frame + 1; - if (next_frame == animation->num_frames) { - next_frame = 0; - } - keyframe_animation_t temp_animation = *animation; - temp_animation.current_frame = next_frame; - temp_animation.time_left_in_frame = animation->frame_lengths[next_frame]; - temp_animation.first_update_of_frame = true; - temp_animation.last_update_of_frame = false; - temp_animation.need_update = false; - visualizer_state_t temp_state = *state; - (*temp_animation.frame_functions[next_frame])(&temp_animation, &temp_state); -} - -// TODO: Optimize the stack size, this is probably way too big -static DECLARE_THREAD_STACK(visualizerThreadStack, 1024); -static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { - (void)arg; - - GListener event_listener; - geventListenerInit(&event_listener); - geventAttachSource(&event_listener, (GSourceHandle)¤t_status, 0); - - visualizer_keyboard_status_t initial_status = { - .default_layer = 0xFFFFFFFF, - .layer = 0xFFFFFFFF, - .mods = 0xFF, - .leds = 0xFFFFFFFF, - .suspended = false, -#ifdef BACKLIGHT_ENABLE - .backlight_level = 0, -#endif -#ifdef VISUALIZER_USER_DATA_SIZE - .user_data = {0}, -#endif - }; - - visualizer_state_t state = {.status = initial_status, - .current_lcd_color = 0, -#ifdef LCD_ENABLE - .font_fixed5x8 = gdispOpenFont("fixed_5x8"), - .font_dejavusansbold12 = gdispOpenFont("DejaVuSansBold12") -#endif - }; - initialize_user_visualizer(&state); - state.prev_lcd_color = state.current_lcd_color; - -#ifdef LCD_BACKLIGHT_ENABLE - lcd_backlight_color(LCD_HUE(state.current_lcd_color), LCD_SAT(state.current_lcd_color), LCD_INT(state.current_lcd_color)); -#endif - - systemticks_t sleep_time = TIME_INFINITE; - systemticks_t current_time = gfxSystemTicks(); - bool force_update = true; - - while (true) { - systemticks_t new_time = gfxSystemTicks(); - systemticks_t delta = new_time - current_time; - current_time = new_time; - bool enabled = visualizer_enabled; - if (force_update || !same_status(&state.status, ¤t_status)) { - force_update = false; -#if BACKLIGHT_ENABLE - if (current_status.backlight_level != state.status.backlight_level) { - if (current_status.backlight_level != 0) { - gdispGSetPowerMode(LED_DISPLAY, powerOn); - uint16_t percent = (uint16_t)current_status.backlight_level * 100 / BACKLIGHT_LEVELS; - gdispGSetBacklight(LED_DISPLAY, percent); - } else { - gdispGSetPowerMode(LED_DISPLAY, powerOff); - } - state.status.backlight_level = current_status.backlight_level; - } -#endif - if (visualizer_enabled) { - if (current_status.suspended) { - stop_all_keyframe_animations(); - visualizer_enabled = false; - state.status = current_status; - user_visualizer_suspend(&state); - } else { - visualizer_keyboard_status_t prev_status = state.status; - state.status = current_status; - update_user_visualizer_state(&state, &prev_status); - } - state.prev_lcd_color = state.current_lcd_color; - } - } - if (!enabled && state.status.suspended && current_status.suspended == false) { - // Setting the status to the initial status will force an update - // when the visualizer is enabled again - state.status = initial_status; - state.status.suspended = false; - stop_all_keyframe_animations(); - user_visualizer_resume(&state); - state.prev_lcd_color = state.current_lcd_color; - } - sleep_time = TIME_INFINITE; - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - if (animations[i]) { - update_keyframe_animation(animations[i], &state, delta, &sleep_time); - } - } -#ifdef BACKLIGHT_ENABLE - gdispGFlush(LED_DISPLAY); -#endif - -#ifdef LCD_ENABLE - gdispGFlush(LCD_DISPLAY); -#endif - -#ifdef EMULATOR - draw_emulator(); -#endif - // Enable the visualizer when the startup or the suspend animation has finished - if (!visualizer_enabled && state.status.suspended == false && get_num_running_animations() == 0) { - visualizer_enabled = true; - force_update = true; - sleep_time = 0; - } - - systemticks_t after_update = gfxSystemTicks(); - unsigned update_delta = after_update - current_time; - if (sleep_time != TIME_INFINITE) { - if (sleep_time > update_delta) { - sleep_time -= update_delta; - } else { - sleep_time = 0; - } - } - dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, sleep_time); -#ifdef PROTOCOL_CHIBIOS - // The gEventWait function really takes milliseconds, even if the documentation says ticks. - // Unfortunately there's no generic ugfx conversion from system time to milliseconds, - // so let's do it in a platform dependent way. - - // On windows the system ticks is the same as milliseconds anyway - if (sleep_time != TIME_INFINITE) { - sleep_time = TIME_I2MS(sleep_time); - } -#endif - geventEventWait(&event_listener, sleep_time); - } -#ifdef LCD_ENABLE - gdispCloseFont(state.font_fixed5x8); - gdispCloseFont(state.font_dejavusansbold12); -#endif - - return 0; -} - -void visualizer_init(void) { - gfxInit(); - -#ifdef LCD_BACKLIGHT_ENABLE - lcd_backlight_init(); -#endif - -#ifdef SERIAL_LINK_ENABLE - add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*)); -#endif - -#ifdef LCD_ENABLE - LCD_DISPLAY = get_lcd_display(); -#endif - -#ifdef BACKLIGHT_ENABLE - LED_DISPLAY = get_led_display(); -#endif - - // We are using a low priority thread, the idea is to have it run only - // when the main thread is sleeping during the matrix scanning - gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack), VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL); -} - -void update_status(bool changed) { - if (changed) { - GSourceListener* listener = geventGetSourceListener((GSourceHandle)¤t_status, NULL); - if (listener) { - geventSendEvent(listener); - } - } -#ifdef SERIAL_LINK_ENABLE - static systime_t last_update = 0; - systime_t current_update = chVTGetSystemTimeX(); - systime_t delta = current_update - last_update; - if (changed || delta > TIME_MS2I(10)) { - last_update = current_update; - visualizer_keyboard_status_t* r = begin_write_current_status(); - *r = current_status; - end_write_current_status(); - } -#endif -} - -uint8_t visualizer_get_mods() { - uint8_t mods = get_mods(); - -#ifndef NO_ACTION_ONESHOT - if (!has_oneshot_mods_timed_out()) { - mods |= get_oneshot_mods(); - } -#endif - return mods; -} - -#ifdef VISUALIZER_USER_DATA_SIZE -void visualizer_set_user_data(void* u) { memcpy(user_data, u, VISUALIZER_USER_DATA_SIZE); } -#endif - -void visualizer_update(layer_state_t default_state, layer_state_t state, uint8_t mods, uint32_t leds) { - // Note that there's a small race condition here, the thread could read - // a state where one of these are set but not the other. But this should - // not really matter as it will be fixed during the next loop step. - // Alternatively a mutex could be used instead of the volatile variables - - bool changed = false; -#ifdef SERIAL_LINK_ENABLE - if (is_serial_link_connected()) { - visualizer_keyboard_status_t* new_status = read_current_status(); - if (new_status) { - if (!same_status(¤t_status, new_status)) { - changed = true; - current_status = *new_status; - } - } - } else { -#else - { -#endif - visualizer_keyboard_status_t new_status = { - .layer = state, - .default_layer = default_state, - .mods = mods, - .leds = leds, -#ifdef BACKLIGHT_ENABLE - .backlight_level = current_status.backlight_level, -#endif - .suspended = current_status.suspended, - }; -#ifdef VISUALIZER_USER_DATA_SIZE - memcpy(new_status.user_data, user_data, VISUALIZER_USER_DATA_SIZE); -#endif - if (!same_status(¤t_status, &new_status)) { - changed = true; - current_status = new_status; - } - } - update_status(changed); -} - -void visualizer_suspend(void) { - current_status.suspended = true; - update_status(true); -} - -void visualizer_resume(void) { - current_status.suspended = false; - update_status(true); -} - -#ifdef BACKLIGHT_ENABLE -void backlight_set(uint8_t level) { - current_status.backlight_level = level; - update_status(true); -} -#endif diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h deleted file mode 100644 index 627c80a305..0000000000 --- a/quantum/visualizer/visualizer.h +++ /dev/null @@ -1,154 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include <stdlib.h> -#include <stdint.h> -#include <stdbool.h> - -#include "config.h" -#include "gfx.h" -#include "action_layer.h" - -#ifdef LCD_BACKLIGHT_ENABLE -# include "lcd_backlight.h" -#endif - -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" -#endif - -// use this function to merge both real_mods and oneshot_mods in a uint16_t -uint8_t visualizer_get_mods(void); - -// This need to be called once at the start -void visualizer_init(void); -// This should be called at every matrix scan -void visualizer_update(layer_state_t default_state, layer_state_t state, uint8_t mods, uint32_t leds); - -// This should be called when the keyboard goes to suspend state -void visualizer_suspend(void); -// This should be called when the keyboard wakes up from suspend state -void visualizer_resume(void); - -// These functions are week, so they can be overridden by the keyboard -// if needed -GDisplay* get_lcd_display(void); -GDisplay* get_led_display(void); - -// For emulator builds, this function need to be implemented -#ifdef EMULATOR -void draw_emulator(void); -#endif - -// If you need support for more than 16 keyframes per animation, you can change this -#define MAX_VISUALIZER_KEY_FRAMES 16 - -struct keyframe_animation_t; - -typedef struct { - layer_state_t layer; - layer_state_t default_layer; - uint32_t leds; // See led.h for available statuses - uint8_t mods; - bool suspended; -#ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; -#endif -#ifdef VISUALIZER_USER_DATA_SIZE - uint8_t user_data[VISUALIZER_USER_DATA_SIZE]; -#endif -} visualizer_keyboard_status_t; - -// The state struct is used by the various keyframe functions -// It's also used for setting the LCD color and layer text -// from the user customized code -typedef struct visualizer_state_t { - // The user code should primarily be modifying these - uint32_t target_lcd_color; - const char* layer_text; - - // The user visualizer(and animation functions) can read these - visualizer_keyboard_status_t status; - - // These are used by the animation functions - uint32_t current_lcd_color; - uint32_t prev_lcd_color; -#ifdef LCD_ENABLE - gFont font_fixed5x8; - gFont font_dejavusansbold12; -#endif -} visualizer_state_t; - -// Any custom keyframe function should have this signature -// return true to get continuous updates, otherwise you will only get one -// update per frame -typedef bool (*frame_func)(struct keyframe_animation_t*, visualizer_state_t*); - -// Represents a keyframe animation, so fields are internal to the system -// while others are meant to be initialized by the user code -typedef struct keyframe_animation_t { - // These should be initialized - int num_frames; - bool loop; - int frame_lengths[MAX_VISUALIZER_KEY_FRAMES]; - frame_func frame_functions[MAX_VISUALIZER_KEY_FRAMES]; - - // Used internally by the system, and can also be read by - // keyframe update functions - int current_frame; - int time_left_in_frame; - bool first_update_of_frame; - bool last_update_of_frame; - bool need_update; - -} keyframe_animation_t; - -extern GDisplay* LCD_DISPLAY; -extern GDisplay* LED_DISPLAY; - -void start_keyframe_animation(keyframe_animation_t* animation); -void stop_keyframe_animation(keyframe_animation_t* animation); -// This runs the next keyframe, but does not update the animation state -// Useful for crossfades for example -void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state); - -// The master can set userdata which will be transferred to the slave -#ifdef VISUALIZER_USER_DATA_SIZE -void visualizer_set_user_data(void* user_data); -#endif - -// These functions have to be implemented by the user -// Called regularly each time the state has changed (but not every scan loop) -void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status); -// Called when the computer goes to suspend, will also stop calling update_user_visualizer_state -void user_visualizer_suspend(visualizer_state_t* state); -// You have to start at least one animation as a response to the following two functions -// When the animation has finished the visualizer will resume normal operation and start calling the -// update_user_visualizer_state again -// Called when the keyboard boots up -void initialize_user_visualizer(visualizer_state_t* state); -// Called when the computer resumes from a suspend -void user_visualizer_resume(visualizer_state_t* state); diff --git a/quantum/visualizer/visualizer.mk b/quantum/visualizer/visualizer.mk deleted file mode 100644 index 4c961ac59d..0000000000 --- a/quantum/visualizer/visualizer.mk +++ /dev/null @@ -1,123 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2016 Fred Sundvik -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -define ADD_DRIVER - $(1)_DRIVER:=$(strip $($(1)_DRIVER)) - $(1)_WIDTH:=$(strip $($(1)_WIDTH)) - $(1)_HEIGHT:=$(strip $($(1)_HEIGHT)) - ifeq ($($(1)_DRIVER),) - $$(error $(1)_DRIVER is not defined) - endif - ifeq ($($(1)_WIDTH),) - $$(error $(1)_WIDTH is not defined) - endif - ifeq ($($(1)_HEIGHT),) - $$(error $(1)_HEIGHT is not defined) - endif - OPT_DEFS+=-D$(1)_WIDTH=$($(1)_WIDTH) - OPT_DEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT) - GFXDEFS+=-D$(1)_WIDTH=$($(1)_WIDTH) - GFXDEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT) - $(1)_DISPLAY_NUMBER:=$$(words $$(GDISP_DRIVER_LIST)) - OPT_DEFS+=-D$(1)_DISPLAY_NUMBER=$$($(1)_DISPLAY_NUMBER) - include $(TOP_DIR)/drivers/ugfx/gdisp/$($(1)_DRIVER)/driver.mk -endef - -GDISP_DRIVER_LIST:= - -SRC += $(VISUALIZER_DIR)/visualizer.c \ - $(VISUALIZER_DIR)/visualizer_keyframes.c -EXTRAINCDIRS += $(GFXINC) $(VISUALIZER_DIR) -GFXLIB = $(LIB_PATH)/ugfx -VPATH += $(VISUALIZER_PATH) - -OPT_DEFS += -DVISUALIZER_ENABLE - -ifdef LCD_ENABLE -OPT_DEFS += -DLCD_ENABLE -ULIBS += -lm -endif - -ifeq ($(strip $(LCD_ENABLE)), yes) - SRC += $(VISUALIZER_DIR)/lcd_keyframes.c - ifeq ($(strip $(LCD_BACKLIGHT_ENABLE)), yes) - OPT_DEFS += -DLCD_BACKLIGHT_ENABLE - SRC += $(VISUALIZER_DIR)/lcd_backlight.c - SRC += $(VISUALIZER_DIR)/lcd_backlight_keyframes.c - endif -# Note, that the linker will strip out any resources that are not actually in use -SRC += $(VISUALIZER_DIR)/resources/lcd_logo.c -$(eval $(call ADD_DRIVER,LCD)) -endif - -ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) -SRC += $(VISUALIZER_DIR)/led_backlight_keyframes.c -$(eval $(call ADD_DRIVER,LED)) -endif - -SRC += $(VISUALIZER_DIR)/default_animations.c - -include $(GFXLIB)/gfx.mk -# For the common_gfxconf.h -GFXINC += quantum/visualizer - -GFXSRC := $(patsubst $(TOP_DIR)/%,%,$(GFXSRC)) -GFXDEFS := $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS))) - -GDISP_LIST_COMMA=, -GDISP_LIST_EMPTY= -GDISP_LIST_SPACE=$(GDISP_LIST_EMPTY) $(GDISP_LIST_EMPTY) - -GDISP_DRIVER_LIST := $(strip $(GDISP_DRIVER_LIST)) -GDISP_DRIVER_LIST := $(subst $(GDISP_LIST_SPACE),$(GDISP_LIST_COMMA),$(GDISP_DRIVER_LIST)) - -GFXDEFS +=-DGDISP_DRIVER_LIST="$(GDISP_DRIVER_LIST)" - -ifneq ("$(wildcard $(KEYMAP_PATH)/visualizer.c)","") - SRC += $(KEYMAP_PATH)/visualizer.c -else - VISUALIZER_1 := $(KEYBOARD_PATH_1)/visualizer.c - VISUALIZER_2 := $(KEYBOARD_PATH_2)/visualizer.c - VISUALIZER_3 := $(KEYBOARD_PATH_3)/visualizer.c - VISUALIZER_4 := $(KEYBOARD_PATH_4)/visualizer.c - VISUALIZER_5 := $(KEYBOARD_PATH_5)/visualizer.c - - ifneq ("$(wildcard $(VISUALIZER_5))","") - SRC += $(VISUALIZER_5) - endif - ifneq ("$(wildcard $(VISUALIZER_4))","") - SRC += $(VISUALIZER_4) - endif - ifneq ("$(wildcard $(VISUALIZER_3))","") - SRC += $(VISUALIZER_3) - endif - ifneq ("$(wildcard $(VISUALIZER_2))","") - SRC += $(VISUALIZER_2) - endif - ifneq ("$(wildcard $(VISUALIZER_1))","") - SRC += $(VISUALIZER_1) - endif -endif - -ifdef EMULATOR -UINCDIR += $(TMK_DIR)/common -endif diff --git a/quantum/visualizer/visualizer_keyframes.h b/quantum/visualizer/visualizer_keyframes.h deleted file mode 100644 index c92ff16113..0000000000 --- a/quantum/visualizer/visualizer_keyframes.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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 "visualizer.h" - -// Some predefined keyframe functions that can be used by the user code -// Does nothing, useful for adding delays -bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state); diff --git a/quantum/wpm.c b/quantum/wpm.c index e711e9fe73..925e2c416e 100644 --- a/quantum/wpm.c +++ b/quantum/wpm.c @@ -21,13 +21,37 @@ // WPM Stuff static uint8_t current_wpm = 0; -static uint16_t wpm_timer = 0; +static uint32_t wpm_timer = 0; +#ifndef WPM_UNFILTERED +static uint32_t smoothing_timer = 0; +#endif -// This smoothing is 40 keystrokes -static const float wpm_smoothing = WPM_SMOOTHING; +/* The WPM calculation works by specifying a certain number of 'periods' inside + * a ring buffer, and we count the number of keypresses which occur in each of + * those periods. Then to calculate WPM, we add up all of the keypresses in + * the whole ring buffer, divide by the number of keypresses in a 'word', and + * then adjust for how much time is captured by our ring buffer. Right now + * the ring buffer is hardcoded below to be six half-second periods, accounting + * for a total WPM sampling period of up to three seconds of typing. + * + * Whenever our WPM drops to absolute zero due to no typing occurring within + * any contiguous three seconds, we reset and start measuring fresh, + * which lets our WPM immediately reach the correct value even before a full + * three second sampling buffer has been filled. + */ +#define MAX_PERIODS (WPM_SAMPLE_PERIODS) +#define PERIOD_DURATION (1000 * WPM_SAMPLE_SECONDS / MAX_PERIODS) +#define LATENCY (100) +static int8_t period_presses[MAX_PERIODS] = {0}; +static uint8_t current_period = 0; +static uint8_t periods = 1; -void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; } +#if !defined(WPM_UNFILTERED) +static uint8_t prev_wpm = 0; +static uint8_t next_wpm = 0; +#endif +void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; } uint8_t get_current_wpm(void) { return current_wpm; } bool wpm_keycode(uint16_t keycode) { return wpm_keycode_kb(keycode); } @@ -56,7 +80,7 @@ __attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) { } else if (keycode > 0xFF) { keycode = 0; } - if (keycode == KC_DEL || keycode == KC_BSPC) { + if (keycode == KC_DELETE || keycode == KC_BACKSPACE) { if (((get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) || weak_modded) { return WPM_ESTIMATED_WORD_SIZE; } else { @@ -68,33 +92,65 @@ __attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) { } #endif +// Outside 'raw' mode we smooth results over time. + void update_wpm(uint16_t keycode) { if (wpm_keycode(keycode)) { - if (wpm_timer > 0) { - uint16_t latest_wpm = 60000 / timer_elapsed(wpm_timer) / WPM_ESTIMATED_WORD_SIZE; - if (latest_wpm > UINT8_MAX) { - latest_wpm = UINT8_MAX; - } - current_wpm += ceilf((latest_wpm - current_wpm) * wpm_smoothing); - } - wpm_timer = timer_read(); + period_presses[current_period]++; } #ifdef WPM_ALLOW_COUNT_REGRESSION uint8_t regress = wpm_regress_count(keycode); if (regress) { - if (current_wpm < regress) { - current_wpm = 0; - } else { - current_wpm -= regress; - } - wpm_timer = timer_read(); + period_presses[current_period]--; } #endif } void decay_wpm(void) { - if (timer_elapsed(wpm_timer) > 1000) { - current_wpm += (-current_wpm) * wpm_smoothing; - wpm_timer = timer_read(); + int32_t presses = period_presses[0]; + for (int i = 1; i <= periods; i++) { + presses += period_presses[i]; + } + if (presses < 0) { + presses = 0; } + int32_t elapsed = timer_elapsed32(wpm_timer); + uint32_t duration = (((periods)*PERIOD_DURATION) + elapsed); + uint32_t wpm_now = (60000 * presses) / (duration * WPM_ESTIMATED_WORD_SIZE); + wpm_now = (wpm_now > 240) ? 240 : wpm_now; + + if (elapsed > PERIOD_DURATION) { + current_period = (current_period + 1) % MAX_PERIODS; + period_presses[current_period] = 0; + periods = (periods < MAX_PERIODS - 1) ? periods + 1 : MAX_PERIODS - 1; + elapsed = 0; + /* if (wpm_timer == 0) { */ + wpm_timer = timer_read32(); + /* } else { */ + /* wpm_timer += PERIOD_DURATION; */ + /* } */ + } + if (presses < 2) // don't guess high WPM based on a single keypress. + wpm_now = 0; + +#if defined WPM_LAUNCH_CONTROL + if (presses == 0) { + current_period = 0; + periods = 0; + wpm_now = 0; + } +#endif // WPM_LAUNCH_CONTROL + +#ifndef WPM_UNFILTERED + int32_t latency = timer_elapsed32(smoothing_timer); + if (latency > LATENCY) { + smoothing_timer = timer_read32(); + prev_wpm = current_wpm; + next_wpm = wpm_now; + } + + current_wpm = prev_wpm + (latency * ((int)next_wpm - (int)prev_wpm) / LATENCY); +#else + current_wpm = wpm_now; +#endif } diff --git a/quantum/wpm.h b/quantum/wpm.h index 4af52d2b98..c8e7d26684 100644 --- a/quantum/wpm.h +++ b/quantum/wpm.h @@ -22,8 +22,11 @@ #ifndef WPM_ESTIMATED_WORD_SIZE # define WPM_ESTIMATED_WORD_SIZE 5 #endif -#ifndef WPM_SMOOTHING -# define WPM_SMOOTHING 0.0487 +#ifndef WPM_SAMPLE_SECONDS +# define WPM_SAMPLE_SECONDS 5 +#endif +#ifndef WPM_SAMPLE_PERIODS +# define WPM_SAMPLE_PERIODS 50 #endif bool wpm_keycode(uint16_t keycode); |